diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 15:29:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 15:29:46 -0400 |
| commit | d9dc089583ebf28d6f02b995e2d71c85965660f9 (patch) | |
| tree | 8e2beb1719d8891d6eec2bbdc809fc0997ba29f6 | |
| parent | 70ef8f0d37573079e093305214d0cc9eb71100f7 (diff) | |
| parent | 2a4e669dd611855d89d938063c10f44cb67ce65d (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
| -rw-r--r-- | arch/xtensa/include/asm/processor.h | 15 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/ptrace.h | 39 | ||||
| -rw-r--r-- | arch/xtensa/include/uapi/asm/ptrace.h | 40 | ||||
| -rw-r--r-- | arch/xtensa/kernel/coprocessor.S | 24 | ||||
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 3 | ||||
| -rw-r--r-- | arch/xtensa/kernel/process.c | 8 | ||||
| -rw-r--r-- | arch/xtensa/kernel/ptrace.c | 170 | ||||
| -rw-r--r-- | arch/xtensa/kernel/setup.c | 9 | ||||
| -rw-r--r-- | arch/xtensa/kernel/signal.c | 10 | ||||
| -rw-r--r-- | arch/xtensa/kernel/stacktrace.c | 35 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/include/platform/simcall.h | 20 | ||||
| -rw-r--r-- | arch/xtensa/platforms/iss/setup.c | 43 |
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 @@ | |||
| 113 | */ | 113 | */ |
| 114 | #define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) | 114 | #define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000)) |
| 115 | 115 | ||
| 116 | /* Spill slot location for the register reg in the spill area under the stack | ||
| 117 | * pointer sp. reg must be in the range [0..4). | ||
| 118 | */ | ||
| 119 | #define SPILL_SLOT(sp, reg) (*(((unsigned long *)(sp)) - 4 + (reg))) | ||
| 120 | |||
| 121 | /* Spill slot location for the register reg in the spill area under the stack | ||
| 122 | * pointer sp for the call8. reg must be in the range [4..8). | ||
| 123 | */ | ||
| 124 | #define SPILL_SLOT_CALL8(sp, reg) (*(((unsigned long *)(sp)) - 12 + (reg))) | ||
| 125 | |||
| 126 | /* Spill slot location for the register reg in the spill area under the stack | ||
| 127 | * pointer sp for the call12. reg must be in the range [4..12). | ||
| 128 | */ | ||
| 129 | #define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg))) | ||
| 130 | |||
| 116 | typedef struct { | 131 | typedef struct { |
| 117 | unsigned long seg; | 132 | unsigned long seg; |
| 118 | } mm_segment_t; | 133 | } 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 @@ | |||
| 12 | 12 | ||
| 13 | #include <uapi/asm/ptrace.h> | 13 | #include <uapi/asm/ptrace.h> |
| 14 | 14 | ||
| 15 | /* | ||
| 16 | * Kernel stack | ||
| 17 | * | ||
| 18 | * +-----------------------+ -------- STACK_SIZE | ||
| 19 | * | register file | | | ||
| 20 | * +-----------------------+ | | ||
| 21 | * | struct pt_regs | | | ||
| 22 | * +-----------------------+ | ------ PT_REGS_OFFSET | ||
| 23 | * double : 16 bytes spill area : | ^ | ||
| 24 | * excetion :- - - - - - - - - - - -: | | | ||
| 25 | * frame : struct pt_regs : | | | ||
| 26 | * :- - - - - - - - - - - -: | | | ||
| 27 | * | | | | | ||
| 28 | * | memory stack | | | | ||
| 29 | * | | | | | ||
| 30 | * ~ ~ ~ ~ | ||
| 31 | * ~ ~ ~ ~ | ||
| 32 | * | | | | | ||
| 33 | * | | | | | ||
| 34 | * +-----------------------+ | | --- STACK_BIAS | ||
| 35 | * | struct task_struct | | | ^ | ||
| 36 | * current --> +-----------------------+ | | | | ||
| 37 | * | struct thread_info | | | | | ||
| 38 | * +-----------------------+ -------- | ||
| 39 | */ | ||
| 40 | |||
| 41 | #define KERNEL_STACK_SIZE (2 * PAGE_SIZE) | ||
| 42 | |||
| 43 | /* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ | ||
| 44 | |||
| 45 | #define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ | ||
| 46 | #define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ | ||
| 47 | #define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ | ||
| 48 | #define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ | ||
| 49 | #define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ | ||
| 50 | #define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ | ||
| 51 | #define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ | ||
| 52 | #define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ | ||
| 53 | #define EXC_TABLE_SIZE 0x400 | ||
| 15 | 54 | ||
| 16 | #ifndef __ASSEMBLY__ | 55 | #ifndef __ASSEMBLY__ |
| 17 | 56 | ||
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 @@ | |||
| 11 | #ifndef _UAPI_XTENSA_PTRACE_H | 11 | #ifndef _UAPI_XTENSA_PTRACE_H |
| 12 | #define _UAPI_XTENSA_PTRACE_H | 12 | #define _UAPI_XTENSA_PTRACE_H |
| 13 | 13 | ||
| 14 | /* | ||
| 15 | * Kernel stack | ||
| 16 | * | ||
| 17 | * +-----------------------+ -------- STACK_SIZE | ||
| 18 | * | register file | | | ||
| 19 | * +-----------------------+ | | ||
| 20 | * | struct pt_regs | | | ||
| 21 | * +-----------------------+ | ------ PT_REGS_OFFSET | ||
| 22 | * double : 16 bytes spill area : | ^ | ||
| 23 | * excetion :- - - - - - - - - - - -: | | | ||
| 24 | * frame : struct pt_regs : | | | ||
| 25 | * :- - - - - - - - - - - -: | | | ||
| 26 | * | | | | | ||
| 27 | * | memory stack | | | | ||
| 28 | * | | | | | ||
| 29 | * ~ ~ ~ ~ | ||
| 30 | * ~ ~ ~ ~ | ||
| 31 | * | | | | | ||
| 32 | * | | | | | ||
| 33 | * +-----------------------+ | | --- STACK_BIAS | ||
| 34 | * | struct task_struct | | | ^ | ||
| 35 | * current --> +-----------------------+ | | | | ||
| 36 | * | struct thread_info | | | | | ||
| 37 | * +-----------------------+ -------- | ||
| 38 | */ | ||
| 39 | |||
| 40 | #define KERNEL_STACK_SIZE (2 * PAGE_SIZE) | ||
| 41 | |||
| 42 | /* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */ | ||
| 43 | |||
| 44 | #define EXC_TABLE_KSTK 0x004 /* Kernel Stack */ | ||
| 45 | #define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */ | ||
| 46 | #define EXC_TABLE_FIXUP 0x00c /* Fixup handler */ | ||
| 47 | #define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */ | ||
| 48 | #define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */ | ||
| 49 | #define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */ | ||
| 50 | #define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */ | ||
| 51 | #define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */ | ||
| 52 | #define EXC_TABLE_SIZE 0x400 | ||
| 53 | |||
| 54 | /* Registers used by strace */ | 14 | /* Registers used by strace */ |
| 55 | 15 | ||
| 56 | #define REG_A_BASE 0x0000 | 16 | #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 @@ | |||
| 26 | #include <asm/signal.h> | 26 | #include <asm/signal.h> |
| 27 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
| 28 | 28 | ||
| 29 | /* | ||
| 30 | * Entry condition: | ||
| 31 | * | ||
| 32 | * a0: trashed, original value saved on stack (PT_AREG0) | ||
| 33 | * a1: a1 | ||
| 34 | * a2: new stack pointer, original in DEPC | ||
| 35 | * a3: a3 | ||
| 36 | * depc: a2, original value saved on stack (PT_DEPC) | ||
| 37 | * excsave_1: dispatch table | ||
| 38 | * | ||
| 39 | * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC | ||
| 40 | * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception | ||
| 41 | */ | ||
| 42 | |||
| 43 | /* IO protection is currently unsupported. */ | ||
| 44 | |||
| 45 | ENTRY(fast_io_protect) | ||
| 46 | |||
| 47 | wsr a0, excsave1 | ||
| 48 | movi a0, unrecoverable_exception | ||
| 49 | callx0 a0 | ||
| 50 | |||
| 51 | ENDPROC(fast_io_protect) | ||
| 52 | |||
| 53 | #if XTENSA_HAVE_COPROCESSORS | 29 | #if XTENSA_HAVE_COPROCESSORS |
| 54 | 30 | ||
| 55 | /* | 31 | /* |
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) | |||
| 1899 | movi a4, do_syscall_trace_enter | 1899 | movi a4, do_syscall_trace_enter |
| 1900 | s32i a3, a2, PT_SYSCALL | 1900 | s32i a3, a2, PT_SYSCALL |
| 1901 | callx4 a4 | 1901 | callx4 a4 |
| 1902 | mov a3, a6 | ||
| 1902 | 1903 | ||
| 1903 | /* syscall = sys_call_table[syscall_nr] */ | 1904 | /* syscall = sys_call_table[syscall_nr] */ |
| 1904 | 1905 | ||
| 1905 | movi a4, sys_call_table; | 1906 | movi a4, sys_call_table |
| 1906 | movi a5, __NR_syscall_count | 1907 | movi a5, __NR_syscall_count |
| 1907 | movi a6, -ENOSYS | 1908 | movi a6, -ENOSYS |
| 1908 | bgeu a3, a5, 1f | 1909 | 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, | |||
| 204 | #endif | 204 | #endif |
| 205 | 205 | ||
| 206 | /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ | 206 | /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */ |
| 207 | *((int*)childregs - 3) = (unsigned long)childregs; | 207 | SPILL_SLOT(childregs, 1) = (unsigned long)childregs; |
| 208 | *((int*)childregs - 4) = 0; | 208 | SPILL_SLOT(childregs, 0) = 0; |
| 209 | 209 | ||
| 210 | p->thread.sp = (unsigned long)childregs; | 210 | p->thread.sp = (unsigned long)childregs; |
| 211 | 211 | ||
| @@ -266,8 +266,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, | |||
| 266 | /* pass parameters to ret_from_kernel_thread: | 266 | /* pass parameters to ret_from_kernel_thread: |
| 267 | * a2 = thread_fn, a3 = thread_fn arg | 267 | * a2 = thread_fn, a3 = thread_fn arg |
| 268 | */ | 268 | */ |
| 269 | *((int *)childregs - 1) = thread_fn_arg; | 269 | SPILL_SLOT(childregs, 3) = thread_fn_arg; |
| 270 | *((int *)childregs - 2) = usp_thread_fn; | 270 | SPILL_SLOT(childregs, 2) = usp_thread_fn; |
| 271 | 271 | ||
| 272 | /* Childregs are only used when we're going to userspace | 272 | /* Childregs are only used when we're going to userspace |
| 273 | * in which case start_thread will set them up. | 273 | * 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 @@ | |||
| 1 | // TODO some minor issues | ||
| 2 | /* | 1 | /* |
| 3 | * This file is subject to the terms and conditions of the GNU General Public | 2 | * This file is subject to the terms and conditions of the GNU General Public |
| 4 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
| @@ -24,13 +23,14 @@ | |||
| 24 | #include <linux/security.h> | 23 | #include <linux/security.h> |
| 25 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
| 26 | #include <linux/smp.h> | 25 | #include <linux/smp.h> |
| 26 | #include <linux/tracehook.h> | ||
| 27 | #include <linux/uaccess.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/coprocessor.h> | 29 | #include <asm/coprocessor.h> |
| 29 | #include <asm/elf.h> | 30 | #include <asm/elf.h> |
| 30 | #include <asm/page.h> | 31 | #include <asm/page.h> |
| 31 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
| 32 | #include <asm/ptrace.h> | 33 | #include <asm/ptrace.h> |
| 33 | #include <linux/uaccess.h> | ||
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | void user_enable_single_step(struct task_struct *child) | 36 | void user_enable_single_step(struct task_struct *child) |
| @@ -52,7 +52,7 @@ void ptrace_disable(struct task_struct *child) | |||
| 52 | /* Nothing to do.. */ | 52 | /* Nothing to do.. */ |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | int ptrace_getregs(struct task_struct *child, void __user *uregs) | 55 | static int ptrace_getregs(struct task_struct *child, void __user *uregs) |
| 56 | { | 56 | { |
| 57 | struct pt_regs *regs = task_pt_regs(child); | 57 | struct pt_regs *regs = task_pt_regs(child); |
| 58 | xtensa_gregset_t __user *gregset = uregs; | 58 | xtensa_gregset_t __user *gregset = uregs; |
| @@ -73,12 +73,12 @@ int ptrace_getregs(struct task_struct *child, void __user *uregs) | |||
| 73 | 73 | ||
| 74 | for (i = 0; i < XCHAL_NUM_AREGS; i++) | 74 | for (i = 0; i < XCHAL_NUM_AREGS; i++) |
| 75 | __put_user(regs->areg[i], | 75 | __put_user(regs->areg[i], |
| 76 | gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); | 76 | gregset->a + ((wb * 4 + i) % XCHAL_NUM_AREGS)); |
| 77 | 77 | ||
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | int ptrace_setregs(struct task_struct *child, void __user *uregs) | 81 | static int ptrace_setregs(struct task_struct *child, void __user *uregs) |
| 82 | { | 82 | { |
| 83 | struct pt_regs *regs = task_pt_regs(child); | 83 | struct pt_regs *regs = task_pt_regs(child); |
| 84 | xtensa_gregset_t *gregset = uregs; | 84 | xtensa_gregset_t *gregset = uregs; |
| @@ -107,7 +107,7 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) | |||
| 107 | unsigned long rotws, wmask; | 107 | unsigned long rotws, wmask; |
| 108 | 108 | ||
| 109 | rotws = (((ws | (ws << WSBITS)) >> wb) & | 109 | rotws = (((ws | (ws << WSBITS)) >> wb) & |
| 110 | ((1 << WSBITS) - 1)) & ~1; | 110 | ((1 << WSBITS) - 1)) & ~1; |
| 111 | wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | | 111 | wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) | |
| 112 | (rotws & 0xF) | 1; | 112 | (rotws & 0xF) | 1; |
| 113 | regs->windowbase = wb; | 113 | regs->windowbase = wb; |
| @@ -115,19 +115,19 @@ int ptrace_setregs(struct task_struct *child, void __user *uregs) | |||
| 115 | regs->wmask = wmask; | 115 | regs->wmask = wmask; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, | 118 | if (wb != 0 && __copy_from_user(regs->areg + XCHAL_NUM_AREGS - wb * 4, |
| 119 | gregset->a, wb * 16)) | 119 | gregset->a, wb * 16)) |
| 120 | return -EFAULT; | 120 | return -EFAULT; |
| 121 | 121 | ||
| 122 | if (__copy_from_user(regs->areg, gregset->a + wb * 4, | 122 | if (__copy_from_user(regs->areg, gregset->a + wb * 4, |
| 123 | (WSBITS - wb) * 16)) | 123 | (WSBITS - wb) * 16)) |
| 124 | return -EFAULT; | 124 | return -EFAULT; |
| 125 | 125 | ||
| 126 | return 0; | 126 | return 0; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | 129 | ||
| 130 | int ptrace_getxregs(struct task_struct *child, void __user *uregs) | 130 | static int ptrace_getxregs(struct task_struct *child, void __user *uregs) |
| 131 | { | 131 | { |
| 132 | struct pt_regs *regs = task_pt_regs(child); | 132 | struct pt_regs *regs = task_pt_regs(child); |
| 133 | struct thread_info *ti = task_thread_info(child); | 133 | struct thread_info *ti = task_thread_info(child); |
| @@ -151,7 +151,7 @@ int ptrace_getxregs(struct task_struct *child, void __user *uregs) | |||
| 151 | return ret ? -EFAULT : 0; | 151 | return ret ? -EFAULT : 0; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | int ptrace_setxregs(struct task_struct *child, void __user *uregs) | 154 | static int ptrace_setxregs(struct task_struct *child, void __user *uregs) |
| 155 | { | 155 | { |
| 156 | struct thread_info *ti = task_thread_info(child); | 156 | struct thread_info *ti = task_thread_info(child); |
| 157 | struct pt_regs *regs = task_pt_regs(child); | 157 | struct pt_regs *regs = task_pt_regs(child); |
| @@ -177,7 +177,8 @@ int ptrace_setxregs(struct task_struct *child, void __user *uregs) | |||
| 177 | return ret ? -EFAULT : 0; | 177 | return ret ? -EFAULT : 0; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) | 180 | static int ptrace_peekusr(struct task_struct *child, long regno, |
| 181 | long __user *ret) | ||
| 181 | { | 182 | { |
| 182 | struct pt_regs *regs; | 183 | struct pt_regs *regs; |
| 183 | unsigned long tmp; | 184 | unsigned long tmp; |
| @@ -186,86 +187,87 @@ int ptrace_peekusr(struct task_struct *child, long regno, long __user *ret) | |||
| 186 | tmp = 0; /* Default return value. */ | 187 | tmp = 0; /* Default return value. */ |
| 187 | 188 | ||
| 188 | switch(regno) { | 189 | switch(regno) { |
| 190 | case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: | ||
| 191 | tmp = regs->areg[regno - REG_AR_BASE]; | ||
| 192 | break; | ||
| 189 | 193 | ||
| 190 | case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: | 194 | case REG_A_BASE ... REG_A_BASE + 15: |
| 191 | tmp = regs->areg[regno - REG_AR_BASE]; | 195 | tmp = regs->areg[regno - REG_A_BASE]; |
| 192 | break; | 196 | break; |
| 193 | |||
| 194 | case REG_A_BASE ... REG_A_BASE + 15: | ||
| 195 | tmp = regs->areg[regno - REG_A_BASE]; | ||
| 196 | break; | ||
| 197 | 197 | ||
| 198 | case REG_PC: | 198 | case REG_PC: |
| 199 | tmp = regs->pc; | 199 | tmp = regs->pc; |
| 200 | break; | 200 | break; |
| 201 | 201 | ||
| 202 | case REG_PS: | 202 | case REG_PS: |
| 203 | /* Note: PS.EXCM is not set while user task is running; | 203 | /* Note: PS.EXCM is not set while user task is running; |
| 204 | * its being set in regs is for exception handling | 204 | * its being set in regs is for exception handling |
| 205 | * convenience. */ | 205 | * convenience. |
| 206 | tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); | 206 | */ |
| 207 | break; | 207 | tmp = (regs->ps & ~(1 << PS_EXCM_BIT)); |
| 208 | break; | ||
| 208 | 209 | ||
| 209 | case REG_WB: | 210 | case REG_WB: |
| 210 | break; /* tmp = 0 */ | 211 | break; /* tmp = 0 */ |
| 211 | 212 | ||
| 212 | case REG_WS: | 213 | case REG_WS: |
| 213 | { | 214 | { |
| 214 | unsigned long wb = regs->windowbase; | 215 | unsigned long wb = regs->windowbase; |
| 215 | unsigned long ws = regs->windowstart; | 216 | unsigned long ws = regs->windowstart; |
| 216 | tmp = ((ws>>wb) | (ws<<(WSBITS-wb))) & ((1<<WSBITS)-1); | 217 | tmp = ((ws >> wb) | (ws << (WSBITS - wb))) & |
| 218 | ((1 << WSBITS) - 1); | ||
| 217 | break; | 219 | break; |
| 218 | } | 220 | } |
| 219 | case REG_LBEG: | 221 | case REG_LBEG: |
| 220 | tmp = regs->lbeg; | 222 | tmp = regs->lbeg; |
| 221 | break; | 223 | break; |
| 222 | 224 | ||
| 223 | case REG_LEND: | 225 | case REG_LEND: |
| 224 | tmp = regs->lend; | 226 | tmp = regs->lend; |
| 225 | break; | 227 | break; |
| 226 | 228 | ||
| 227 | case REG_LCOUNT: | 229 | case REG_LCOUNT: |
| 228 | tmp = regs->lcount; | 230 | tmp = regs->lcount; |
| 229 | break; | 231 | break; |
| 230 | 232 | ||
| 231 | case REG_SAR: | 233 | case REG_SAR: |
| 232 | tmp = regs->sar; | 234 | tmp = regs->sar; |
| 233 | break; | 235 | break; |
| 234 | 236 | ||
| 235 | case SYSCALL_NR: | 237 | case SYSCALL_NR: |
| 236 | tmp = regs->syscall; | 238 | tmp = regs->syscall; |
| 237 | break; | 239 | break; |
| 238 | 240 | ||
| 239 | default: | 241 | default: |
| 240 | return -EIO; | 242 | return -EIO; |
| 241 | } | 243 | } |
| 242 | return put_user(tmp, ret); | 244 | return put_user(tmp, ret); |
| 243 | } | 245 | } |
| 244 | 246 | ||
| 245 | int ptrace_pokeusr(struct task_struct *child, long regno, long val) | 247 | static int ptrace_pokeusr(struct task_struct *child, long regno, long val) |
| 246 | { | 248 | { |
| 247 | struct pt_regs *regs; | 249 | struct pt_regs *regs; |
| 248 | regs = task_pt_regs(child); | 250 | regs = task_pt_regs(child); |
| 249 | 251 | ||
| 250 | switch (regno) { | 252 | switch (regno) { |
| 251 | case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: | 253 | case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1: |
| 252 | regs->areg[regno - REG_AR_BASE] = val; | 254 | regs->areg[regno - REG_AR_BASE] = val; |
| 253 | break; | 255 | break; |
| 254 | 256 | ||
| 255 | case REG_A_BASE ... REG_A_BASE + 15: | 257 | case REG_A_BASE ... REG_A_BASE + 15: |
| 256 | regs->areg[regno - REG_A_BASE] = val; | 258 | regs->areg[regno - REG_A_BASE] = val; |
| 257 | break; | 259 | break; |
| 258 | 260 | ||
| 259 | case REG_PC: | 261 | case REG_PC: |
| 260 | regs->pc = val; | 262 | regs->pc = val; |
| 261 | break; | 263 | break; |
| 262 | 264 | ||
| 263 | case SYSCALL_NR: | 265 | case SYSCALL_NR: |
| 264 | regs->syscall = val; | 266 | regs->syscall = val; |
| 265 | break; | 267 | break; |
| 266 | 268 | ||
| 267 | default: | 269 | default: |
| 268 | return -EIO; | 270 | return -EIO; |
| 269 | } | 271 | } |
| 270 | return 0; | 272 | return 0; |
| 271 | } | 273 | } |
| @@ -467,39 +469,21 @@ long arch_ptrace(struct task_struct *child, long request, | |||
| 467 | return ret; | 469 | return ret; |
| 468 | } | 470 | } |
| 469 | 471 | ||
| 470 | void do_syscall_trace(void) | 472 | unsigned long do_syscall_trace_enter(struct pt_regs *regs) |
| 471 | { | ||
| 472 | /* | ||
| 473 | * The 0x80 provides a way for the tracing parent to distinguish | ||
| 474 | * between a syscall stop and SIGTRAP delivery | ||
| 475 | */ | ||
| 476 | ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); | ||
| 477 | |||
| 478 | /* | ||
| 479 | * this isn't the same as continuing with a signal, but it will do | ||
| 480 | * for normal use. strace only continues with a signal if the | ||
| 481 | * stopping signal is not SIGTRAP. -brl | ||
| 482 | */ | ||
| 483 | if (current->exit_code) { | ||
| 484 | send_sig(current->exit_code, current, 1); | ||
| 485 | current->exit_code = 0; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | void do_syscall_trace_enter(struct pt_regs *regs) | ||
| 490 | { | 473 | { |
| 491 | if (test_thread_flag(TIF_SYSCALL_TRACE) | 474 | if (test_thread_flag(TIF_SYSCALL_TRACE) && |
| 492 | && (current->ptrace & PT_PTRACED)) | 475 | tracehook_report_syscall_entry(regs)) |
| 493 | do_syscall_trace(); | 476 | return -1; |
| 494 | 477 | ||
| 495 | #if 0 | 478 | return regs->areg[2]; |
| 496 | audit_syscall_entry(...); | ||
| 497 | #endif | ||
| 498 | } | 479 | } |
| 499 | 480 | ||
| 500 | void do_syscall_trace_leave(struct pt_regs *regs) | 481 | void do_syscall_trace_leave(struct pt_regs *regs) |
| 501 | { | 482 | { |
| 502 | if ((test_thread_flag(TIF_SYSCALL_TRACE)) | 483 | int step; |
| 503 | && (current->ptrace & PT_PTRACED)) | 484 | |
| 504 | do_syscall_trace(); | 485 | step = test_thread_flag(TIF_SINGLESTEP); |
| 486 | |||
| 487 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) | ||
| 488 | tracehook_report_syscall_exit(regs, step); | ||
| 505 | } | 489 | } |
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) | |||
| 317 | 317 | ||
| 318 | void __init setup_arch(char **cmdline_p) | 318 | void __init setup_arch(char **cmdline_p) |
| 319 | { | 319 | { |
| 320 | strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
| 321 | *cmdline_p = command_line; | 320 | *cmdline_p = command_line; |
| 321 | platform_setup(cmdline_p); | ||
| 322 | strlcpy(boot_command_line, *cmdline_p, COMMAND_LINE_SIZE); | ||
| 322 | 323 | ||
| 323 | /* Reserve some memory regions */ | 324 | /* Reserve some memory regions */ |
| 324 | 325 | ||
| @@ -382,8 +383,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 382 | 383 | ||
| 383 | unflatten_and_copy_device_tree(); | 384 | unflatten_and_copy_device_tree(); |
| 384 | 385 | ||
| 385 | platform_setup(cmdline_p); | ||
| 386 | |||
| 387 | #ifdef CONFIG_SMP | 386 | #ifdef CONFIG_SMP |
| 388 | smp_init_cpus(); | 387 | smp_init_cpus(); |
| 389 | #endif | 388 | #endif |
| @@ -453,9 +452,9 @@ void cpu_reset(void) | |||
| 453 | tmpaddr += SZ_512M; | 452 | tmpaddr += SZ_512M; |
| 454 | 453 | ||
| 455 | /* Invalidate mapping in the selected temporary area */ | 454 | /* Invalidate mapping in the selected temporary area */ |
| 456 | if (itlb_probe(tmpaddr) & 0x8) | 455 | if (itlb_probe(tmpaddr) & BIT(ITLB_HIT_BIT)) |
| 457 | invalidate_itlb_entry(itlb_probe(tmpaddr)); | 456 | invalidate_itlb_entry(itlb_probe(tmpaddr)); |
| 458 | if (itlb_probe(tmpaddr + PAGE_SIZE) & 0x8) | 457 | if (itlb_probe(tmpaddr + PAGE_SIZE) & BIT(ITLB_HIT_BIT)) |
| 459 | invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE)); | 458 | invalidate_itlb_entry(itlb_probe(tmpaddr + PAGE_SIZE)); |
| 460 | 459 | ||
| 461 | /* | 460 | /* |
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) | |||
| 91 | inc = 1; | 91 | inc = 1; |
| 92 | 92 | ||
| 93 | } else if (m & 4) { /* call8 */ | 93 | } else if (m & 4) { /* call8 */ |
| 94 | if (copy_to_user((void*)(sp - 32), | 94 | if (copy_to_user(&SPILL_SLOT_CALL8(sp, 4), |
| 95 | ®s->areg[(base + 1) * 4], 16)) | 95 | ®s->areg[(base + 1) * 4], 16)) |
| 96 | goto errout; | 96 | goto errout; |
| 97 | inc = 2; | 97 | inc = 2; |
| 98 | 98 | ||
| 99 | } else if (m & 8) { /* call12 */ | 99 | } else if (m & 8) { /* call12 */ |
| 100 | if (copy_to_user((void*)(sp - 48), | 100 | if (copy_to_user(&SPILL_SLOT_CALL12(sp, 4), |
| 101 | ®s->areg[(base + 1) * 4], 32)) | 101 | ®s->areg[(base + 1) * 4], 32)) |
| 102 | goto errout; | 102 | goto errout; |
| 103 | inc = 3; | 103 | inc = 3; |
| 104 | } | 104 | } |
| @@ -106,7 +106,7 @@ flush_window_regs_user(struct pt_regs *regs) | |||
| 106 | /* Save current frame a0..a3 under next SP */ | 106 | /* Save current frame a0..a3 under next SP */ |
| 107 | 107 | ||
| 108 | sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; | 108 | sp = regs->areg[((base + inc) * 4 + 1) % XCHAL_NUM_AREGS]; |
| 109 | if (copy_to_user((void*)(sp - 16), ®s->areg[base * 4], 16)) | 109 | if (copy_to_user(&SPILL_SLOT(sp, 0), ®s->areg[base * 4], 16)) |
| 110 | goto errout; | 110 | goto errout; |
| 111 | 111 | ||
| 112 | /* Get current stack pointer for next loop iteration. */ | 112 | /* 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 @@ | |||
| 23 | */ | 23 | */ |
| 24 | extern int common_exception_return; | 24 | extern int common_exception_return; |
| 25 | 25 | ||
| 26 | /* A struct that maps to the part of the frame containing the a0 and | ||
| 27 | * a1 registers. | ||
| 28 | */ | ||
| 29 | struct frame_start { | ||
| 30 | unsigned long a0; | ||
| 31 | unsigned long a1; | ||
| 32 | }; | ||
| 33 | |||
| 34 | void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, | 26 | void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, |
| 35 | int (*ufn)(struct stackframe *frame, void *data), | 27 | int (*ufn)(struct stackframe *frame, void *data), |
| 36 | void *data) | 28 | void *data) |
| @@ -96,26 +88,16 @@ void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth, | |||
| 96 | /* Start from the a1 register. */ | 88 | /* Start from the a1 register. */ |
| 97 | /* a1 = regs->areg[1]; */ | 89 | /* a1 = regs->areg[1]; */ |
| 98 | while (a0 != 0 && depth--) { | 90 | while (a0 != 0 && depth--) { |
| 99 | struct frame_start frame_start; | 91 | pc = MAKE_PC_FROM_RA(a0, pc); |
| 100 | /* Get the location for a1, a0 for the | ||
| 101 | * previous frame from the current a1. | ||
| 102 | */ | ||
| 103 | unsigned long *psp = (unsigned long *)a1; | ||
| 104 | |||
| 105 | psp -= 4; | ||
| 106 | 92 | ||
| 107 | /* Check if the region is OK to access. */ | 93 | /* Check if the region is OK to access. */ |
| 108 | if (!access_ok(VERIFY_READ, psp, sizeof(frame_start))) | 94 | if (!access_ok(VERIFY_READ, &SPILL_SLOT(a1, 0), 8)) |
| 109 | return; | 95 | return; |
| 110 | /* Copy a1, a0 from user space stack frame. */ | 96 | /* Copy a1, a0 from user space stack frame. */ |
| 111 | if (__copy_from_user_inatomic(&frame_start, psp, | 97 | if (__get_user(a0, &SPILL_SLOT(a1, 0)) || |
| 112 | sizeof(frame_start))) | 98 | __get_user(a1, &SPILL_SLOT(a1, 1))) |
| 113 | return; | 99 | return; |
| 114 | 100 | ||
| 115 | pc = MAKE_PC_FROM_RA(a0, pc); | ||
| 116 | a0 = frame_start.a0; | ||
| 117 | a1 = frame_start.a1; | ||
| 118 | |||
| 119 | frame.pc = pc; | 101 | frame.pc = pc; |
| 120 | frame.sp = a1; | 102 | frame.sp = a1; |
| 121 | 103 | ||
| @@ -147,7 +129,6 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, | |||
| 147 | */ | 129 | */ |
| 148 | while (a1 > sp_start && a1 < sp_end && depth--) { | 130 | while (a1 > sp_start && a1 < sp_end && depth--) { |
| 149 | struct stackframe frame; | 131 | struct stackframe frame; |
| 150 | unsigned long *psp = (unsigned long *)a1; | ||
| 151 | 132 | ||
| 152 | frame.pc = pc; | 133 | frame.pc = pc; |
| 153 | frame.sp = a1; | 134 | frame.sp = a1; |
| @@ -171,8 +152,8 @@ void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth, | |||
| 171 | sp_start = a1; | 152 | sp_start = a1; |
| 172 | 153 | ||
| 173 | pc = MAKE_PC_FROM_RA(a0, pc); | 154 | pc = MAKE_PC_FROM_RA(a0, pc); |
| 174 | a0 = *(psp - 4); | 155 | a0 = SPILL_SLOT(a1, 0); |
| 175 | a1 = *(psp - 3); | 156 | a1 = SPILL_SLOT(a1, 1); |
| 176 | } | 157 | } |
| 177 | } | 158 | } |
| 178 | EXPORT_SYMBOL(xtensa_backtrace_kernel); | 159 | EXPORT_SYMBOL(xtensa_backtrace_kernel); |
| @@ -196,8 +177,8 @@ void walk_stackframe(unsigned long *sp, | |||
| 196 | 177 | ||
| 197 | sp = (unsigned long *)a1; | 178 | sp = (unsigned long *)a1; |
| 198 | 179 | ||
| 199 | a0 = *(sp - 4); | 180 | a0 = SPILL_SLOT(a1, 0); |
| 200 | a1 = *(sp - 3); | 181 | a1 = SPILL_SLOT(a1, 1); |
| 201 | 182 | ||
| 202 | if (a1 <= (unsigned long)sp) | 183 | if (a1 <= (unsigned long)sp) |
| 203 | break; | 184 | 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 @@ | |||
| 6 | * for more details. | 6 | * for more details. |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2001 Tensilica Inc. | 8 | * Copyright (C) 2001 Tensilica Inc. |
| 9 | * Copyright (C) 2017 Cadence Design Systems Inc. | ||
| 9 | */ | 10 | */ |
| 10 | 11 | ||
| 11 | #ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H | 12 | #ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H |
| @@ -49,6 +50,10 @@ | |||
| 49 | #define SYS_bind 30 | 50 | #define SYS_bind 30 |
| 50 | #define SYS_ioctl 31 | 51 | #define SYS_ioctl 31 |
| 51 | 52 | ||
| 53 | #define SYS_iss_argc 1000 /* returns value of argc */ | ||
| 54 | #define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */ | ||
| 55 | #define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */ | ||
| 56 | |||
| 52 | /* | 57 | /* |
| 53 | * SYS_select_one specifiers | 58 | * SYS_select_one specifiers |
| 54 | */ | 59 | */ |
| @@ -118,5 +123,20 @@ static inline int simc_lseek(int fd, uint32_t off, int whence) | |||
| 118 | return __simc(SYS_lseek, fd, off, whence); | 123 | return __simc(SYS_lseek, fd, off, whence); |
| 119 | } | 124 | } |
| 120 | 125 | ||
| 126 | static inline int simc_argc(void) | ||
| 127 | { | ||
| 128 | return __simc(SYS_iss_argc, 0, 0, 0); | ||
| 129 | } | ||
| 130 | |||
| 131 | static inline int simc_argv_size(void) | ||
| 132 | { | ||
| 133 | return __simc(SYS_iss_argv_size, 0, 0, 0); | ||
| 134 | } | ||
| 135 | |||
| 136 | static inline void simc_argv(void *buf) | ||
| 137 | { | ||
| 138 | __simc(SYS_iss_set_argv, (int)buf, 0, 0); | ||
| 139 | } | ||
| 140 | |||
| 121 | #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */ | 141 | #endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */ |
| 122 | 142 | ||
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 @@ | |||
| 8 | * Joe Taylor <joe@tensilica.com> | 8 | * Joe Taylor <joe@tensilica.com> |
| 9 | * | 9 | * |
| 10 | * Copyright 2001 - 2005 Tensilica Inc. | 10 | * Copyright 2001 - 2005 Tensilica Inc. |
| 11 | * Copyright 2017 Cadence Design Systems Inc. | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
| 13 | * under the terms of the GNU General Public License as published by the | 14 | * under the terms of the GNU General Public License as published by the |
| @@ -15,6 +16,7 @@ | |||
| 15 | * option) any later version. | 16 | * option) any later version. |
| 16 | * | 17 | * |
| 17 | */ | 18 | */ |
| 19 | #include <linux/bootmem.h> | ||
| 18 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
| 19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 20 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| @@ -31,13 +33,13 @@ | |||
| 31 | 33 | ||
| 32 | #include <asm/platform.h> | 34 | #include <asm/platform.h> |
| 33 | #include <asm/bootparam.h> | 35 | #include <asm/bootparam.h> |
| 36 | #include <asm/setup.h> | ||
| 34 | 37 | ||
| 35 | #include <platform/simcall.h> | 38 | #include <platform/simcall.h> |
| 36 | 39 | ||
| 37 | 40 | ||
| 38 | void __init platform_init(bp_tag_t* bootparam) | 41 | void __init platform_init(bp_tag_t* bootparam) |
| 39 | { | 42 | { |
| 40 | |||
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | void platform_halt(void) | 45 | void platform_halt(void) |
| @@ -59,26 +61,10 @@ void platform_restart(void) | |||
| 59 | /* control never gets here */ | 61 | /* control never gets here */ |
| 60 | } | 62 | } |
| 61 | 63 | ||
| 62 | extern void iss_net_poll(void); | ||
| 63 | |||
| 64 | const char twirl[]="|/-\\|/-\\"; | ||
| 65 | |||
| 66 | void platform_heartbeat(void) | 64 | void platform_heartbeat(void) |
| 67 | { | 65 | { |
| 68 | #if 0 | ||
| 69 | static int i = 0, j = 0; | ||
| 70 | |||
| 71 | if (--i < 0) { | ||
| 72 | i = 99; | ||
| 73 | printk("\r%c\r", twirl[j++]); | ||
| 74 | if (j == 8) | ||
| 75 | j = 0; | ||
| 76 | } | ||
| 77 | #endif | ||
| 78 | } | 66 | } |
| 79 | 67 | ||
| 80 | |||
| 81 | |||
| 82 | static int | 68 | static int |
| 83 | iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) | 69 | iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) |
| 84 | { | 70 | { |
| @@ -87,12 +73,29 @@ iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr) | |||
| 87 | } | 73 | } |
| 88 | 74 | ||
| 89 | static struct notifier_block iss_panic_block = { | 75 | static struct notifier_block iss_panic_block = { |
| 90 | iss_panic_event, | 76 | .notifier_call = iss_panic_event, |
| 91 | NULL, | ||
| 92 | 0 | ||
| 93 | }; | 77 | }; |
| 94 | 78 | ||
| 95 | void __init platform_setup(char **p_cmdline) | 79 | void __init platform_setup(char **p_cmdline) |
| 96 | { | 80 | { |
| 81 | int argc = simc_argc(); | ||
| 82 | int argv_size = simc_argv_size(); | ||
| 83 | |||
| 84 | if (argc > 1) { | ||
| 85 | void **argv = alloc_bootmem(argv_size); | ||
| 86 | char *cmdline = alloc_bootmem(argv_size); | ||
| 87 | int i; | ||
| 88 | |||
| 89 | cmdline[0] = 0; | ||
| 90 | simc_argv((void *)argv); | ||
| 91 | |||
| 92 | for (i = 1; i < argc; ++i) { | ||
| 93 | if (i > 1) | ||
| 94 | strcat(cmdline, " "); | ||
| 95 | strcat(cmdline, argv[i]); | ||
| 96 | } | ||
| 97 | *p_cmdline = cmdline; | ||
| 98 | } | ||
| 99 | |||
| 97 | atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); | 100 | atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); |
| 98 | } | 101 | } |
