|  | /* | 
|  | * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) | 
|  | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or modify | 
|  | * it under the terms of the GNU General Public License version 2 as | 
|  | * published by the Free Software Foundation. | 
|  | */ | 
|  |  | 
|  | #ifndef __ASM_ARC_ENTRY_H | 
|  | #define __ASM_ARC_ENTRY_H | 
|  |  | 
|  | #include <asm/unistd.h>		/* For NR_syscalls defination */ | 
|  | #include <asm/arcregs.h> | 
|  | #include <asm/ptrace.h> | 
|  | #include <asm/processor.h>	/* For VMALLOC_START */ | 
|  | #include <asm/mmu.h> | 
|  |  | 
|  | #ifdef CONFIG_ISA_ARCOMPACT | 
|  | #include <asm/entry-compact.h>	/* ISA specific bits */ | 
|  | #else | 
|  | #include <asm/entry-arcv2.h> | 
|  | #endif | 
|  |  | 
|  | /* Note on the LD/ST addr modes with addr reg wback | 
|  | * | 
|  | * LD.a same as LD.aw | 
|  | * | 
|  | * LD.a    reg1, [reg2, x]  => Pre Incr | 
|  | *      Eff Addr for load = [reg2 + x] | 
|  | * | 
|  | * LD.ab   reg1, [reg2, x]  => Post Incr | 
|  | *      Eff Addr for load = [reg2] | 
|  | */ | 
|  |  | 
|  | .macro PUSH reg | 
|  | st.a	\reg, [sp, -4] | 
|  | .endm | 
|  |  | 
|  | .macro PUSHAX aux | 
|  | lr	r9, [\aux] | 
|  | PUSH	r9 | 
|  | .endm | 
|  |  | 
|  | .macro POP reg | 
|  | ld.ab	\reg, [sp, 4] | 
|  | .endm | 
|  |  | 
|  | .macro POPAX aux | 
|  | POP	r9 | 
|  | sr	r9, [\aux] | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Helpers to save/restore Scratch Regs: | 
|  | * used by Interrupt/Exception Prologue/Epilogue | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro  SAVE_R0_TO_R12 | 
|  | PUSH	r0 | 
|  | PUSH	r1 | 
|  | PUSH	r2 | 
|  | PUSH	r3 | 
|  | PUSH	r4 | 
|  | PUSH	r5 | 
|  | PUSH	r6 | 
|  | PUSH	r7 | 
|  | PUSH	r8 | 
|  | PUSH	r9 | 
|  | PUSH	r10 | 
|  | PUSH	r11 | 
|  | PUSH	r12 | 
|  | .endm | 
|  |  | 
|  | .macro RESTORE_R12_TO_R0 | 
|  | POP	r12 | 
|  | POP	r11 | 
|  | POP	r10 | 
|  | POP	r9 | 
|  | POP	r8 | 
|  | POP	r7 | 
|  | POP	r6 | 
|  | POP	r5 | 
|  | POP	r4 | 
|  | POP	r3 | 
|  | POP	r2 | 
|  | POP	r1 | 
|  | POP	r0 | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | ld	r25, [sp, 12] | 
|  | #endif | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Helpers to save/restore callee-saved regs: | 
|  | * used by several macros below | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro SAVE_R13_TO_R24 | 
|  | PUSH	r13 | 
|  | PUSH	r14 | 
|  | PUSH	r15 | 
|  | PUSH	r16 | 
|  | PUSH	r17 | 
|  | PUSH	r18 | 
|  | PUSH	r19 | 
|  | PUSH	r20 | 
|  | PUSH	r21 | 
|  | PUSH	r22 | 
|  | PUSH	r23 | 
|  | PUSH	r24 | 
|  | .endm | 
|  |  | 
|  | .macro RESTORE_R24_TO_R13 | 
|  | POP	r24 | 
|  | POP	r23 | 
|  | POP	r22 | 
|  | POP	r21 | 
|  | POP	r20 | 
|  | POP	r19 | 
|  | POP	r18 | 
|  | POP	r17 | 
|  | POP	r16 | 
|  | POP	r15 | 
|  | POP	r14 | 
|  | POP	r13 | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Collect User Mode callee regs as struct callee_regs - needed by | 
|  | * fork/do_signal/unaligned-access-emulation. | 
|  | * (By default only scratch regs are saved on entry to kernel) | 
|  | * | 
|  | * Special handling for r25 if used for caching Task Pointer. | 
|  | * It would have been saved in task->thread.user_r25 already, but to keep | 
|  | * the interface same it is copied into regular r25 placeholder in | 
|  | * struct callee_regs. | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro SAVE_CALLEE_SAVED_USER | 
|  |  | 
|  | mov	r12, sp		; save SP as ref to pt_regs | 
|  | SAVE_R13_TO_R24 | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | ; Retrieve orig r25 and save it with rest of callee_regs | 
|  | ld.as   r12, [r12, PT_user_r25] | 
|  | PUSH	r12 | 
|  | #else | 
|  | PUSH	r25 | 
|  | #endif | 
|  |  | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Save kernel Mode callee regs at the time of Contect Switch. | 
|  | * | 
|  | * Special handling for r25 if used for caching Task Pointer. | 
|  | * Kernel simply skips saving it since it will be loaded with | 
|  | * incoming task pointer anyways | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro SAVE_CALLEE_SAVED_KERNEL | 
|  |  | 
|  | SAVE_R13_TO_R24 | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | sub     sp, sp, 4 | 
|  | #else | 
|  | PUSH	r25 | 
|  | #endif | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Opposite of SAVE_CALLEE_SAVED_KERNEL | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro RESTORE_CALLEE_SAVED_KERNEL | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | add     sp, sp, 4  /* skip usual r25 placeholder */ | 
|  | #else | 
|  | POP	r25 | 
|  | #endif | 
|  | RESTORE_R24_TO_R13 | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Opposite of SAVE_CALLEE_SAVED_USER | 
|  | * | 
|  | * ptrace tracer or unaligned-access fixup might have changed a user mode | 
|  | * callee reg which is saved back to usual r25 storage location | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro RESTORE_CALLEE_SAVED_USER | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | POP	r12 | 
|  | #else | 
|  | POP	r25 | 
|  | #endif | 
|  | RESTORE_R24_TO_R13 | 
|  |  | 
|  | ; SP is back to start of pt_regs | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | st.as   r12, [sp, PT_user_r25] | 
|  | #endif | 
|  | .endm | 
|  |  | 
|  | /*-------------------------------------------------------------- | 
|  | * Super FAST Restore callee saved regs by simply re-adjusting SP | 
|  | *-------------------------------------------------------------*/ | 
|  | .macro DISCARD_CALLEE_SAVED_USER | 
|  | add     sp, sp, SZ_CALLEE_REGS | 
|  | .endm | 
|  |  | 
|  | /*------------------------------------------------------------- | 
|  | * given a tsk struct, get to the base of it's kernel mode stack | 
|  | * tsk->thread_info is really a PAGE, whose bottom hoists stack | 
|  | * which grows upwards towards thread_info | 
|  | *------------------------------------------------------------*/ | 
|  |  | 
|  | .macro GET_TSK_STACK_BASE tsk, out | 
|  |  | 
|  | /* Get task->thread_info (this is essentially start of a PAGE) */ | 
|  | ld  \out, [\tsk, TASK_THREAD_INFO] | 
|  |  | 
|  | /* Go to end of page where stack begins (grows upwards) */ | 
|  | add2 \out, \out, (THREAD_SIZE)/4 | 
|  |  | 
|  | .endm | 
|  |  | 
|  | /* | 
|  | * @reg [OUT] thread_info->flags of "current" | 
|  | */ | 
|  | .macro GET_CURR_THR_INFO_FLAGS  reg | 
|  | GET_CURR_THR_INFO_FROM_SP  \reg | 
|  | ld  \reg, [\reg, THREAD_INFO_FLAGS] | 
|  | .endm | 
|  |  | 
|  | #ifdef CONFIG_SMP | 
|  |  | 
|  | /*------------------------------------------------- | 
|  | * Retrieve the current running task on this CPU | 
|  | * 1. Determine curr CPU id. | 
|  | * 2. Use it to index into _current_task[ ] | 
|  | */ | 
|  | .macro  GET_CURR_TASK_ON_CPU   reg | 
|  | GET_CPU_ID  \reg | 
|  | ld.as  \reg, [@_current_task, \reg] | 
|  | .endm | 
|  |  | 
|  | /*------------------------------------------------- | 
|  | * Save a new task as the "current" task on this CPU | 
|  | * 1. Determine curr CPU id. | 
|  | * 2. Use it to index into _current_task[ ] | 
|  | * | 
|  | * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS) | 
|  | * because ST r0, [r1, offset] can ONLY have s9 @offset | 
|  | * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn) | 
|  | */ | 
|  |  | 
|  | .macro  SET_CURR_TASK_ON_CPU    tsk, tmp | 
|  | GET_CPU_ID  \tmp | 
|  | add2 \tmp, @_current_task, \tmp | 
|  | st   \tsk, [\tmp] | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | mov r25, \tsk | 
|  | #endif | 
|  |  | 
|  | .endm | 
|  |  | 
|  |  | 
|  | #else   /* Uniprocessor implementation of macros */ | 
|  |  | 
|  | .macro  GET_CURR_TASK_ON_CPU    reg | 
|  | ld  \reg, [@_current_task] | 
|  | .endm | 
|  |  | 
|  | .macro  SET_CURR_TASK_ON_CPU    tsk, tmp | 
|  | st  \tsk, [@_current_task] | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  | mov r25, \tsk | 
|  | #endif | 
|  | .endm | 
|  |  | 
|  | #endif /* SMP / UNI */ | 
|  |  | 
|  | /* ------------------------------------------------------------------ | 
|  | * Get the ptr to some field of Current Task at @off in task struct | 
|  | *  -Uses r25 for Current task ptr if that is enabled | 
|  | */ | 
|  |  | 
|  | #ifdef CONFIG_ARC_CURR_IN_REG | 
|  |  | 
|  | .macro GET_CURR_TASK_FIELD_PTR  off,  reg | 
|  | add \reg, r25, \off | 
|  | .endm | 
|  |  | 
|  | #else | 
|  |  | 
|  | .macro GET_CURR_TASK_FIELD_PTR  off,  reg | 
|  | GET_CURR_TASK_ON_CPU  \reg | 
|  | add \reg, \reg, \off | 
|  | .endm | 
|  |  | 
|  | #endif	/* CONFIG_ARC_CURR_IN_REG */ | 
|  |  | 
|  | #endif  /* __ASM_ARC_ENTRY_H */ |