Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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