| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /* |
| * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com) |
| * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
| */ |
| |
| #ifndef __ASM_ARC_ENTRY_H |
| #define __ASM_ARC_ENTRY_H |
| |
| #include <asm/unistd.h> /* For NR_syscalls definition */ |
| #include <asm/arcregs.h> |
| #include <asm/ptrace.h> |
| #include <asm/processor.h> /* For VMALLOC_START */ |
| #include <asm/mmu.h> |
| |
| #ifdef __ASSEMBLY__ |
| |
| #ifdef CONFIG_ISA_ARCOMPACT |
| #include <asm/entry-compact.h> /* ISA specific bits */ |
| #else |
| #include <asm/entry-arcv2.h> |
| #endif |
| |
| /* |
| * save user mode callee regs as struct callee_regs |
| * - needed by fork/do_signal/unaligned-access-emulation. |
| */ |
| .macro SAVE_CALLEE_SAVED_USER |
| SAVE_ABI_CALLEE_REGS |
| .endm |
| |
| /* |
| * restore user mode callee regs as struct callee_regs |
| * - could have been changed by ptrace tracer or unaligned-access fixup |
| */ |
| .macro RESTORE_CALLEE_SAVED_USER |
| RESTORE_ABI_CALLEE_REGS |
| .endm |
| |
| /* |
| * save/restore kernel mode callee regs at the time of context switch |
| */ |
| .macro SAVE_CALLEE_SAVED_KERNEL |
| SAVE_ABI_CALLEE_REGS |
| .endm |
| |
| .macro RESTORE_CALLEE_SAVED_KERNEL |
| RESTORE_ABI_CALLEE_REGS |
| .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 its 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 |
| * - loads it from backing _current_task[] (and can't use the |
| * caching reg for 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 gp, \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 gp, \tsk |
| #endif |
| .endm |
| |
| #endif /* SMP / UNI */ |
| |
| /* |
| * Get the ptr to some field of Current Task at @off in task struct |
| * - Uses current task cached in reg if enabled |
| */ |
| #ifdef CONFIG_ARC_CURR_IN_REG |
| |
| .macro GET_CURR_TASK_FIELD_PTR off, reg |
| add \reg, gp, \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 */ |
| |
| #else /* !__ASSEMBLY__ */ |
| |
| extern void do_signal(struct pt_regs *); |
| extern void do_notify_resume(struct pt_regs *); |
| extern int do_privilege_fault(unsigned long, struct pt_regs *); |
| extern int do_extension_fault(unsigned long, struct pt_regs *); |
| extern int insterror_is_error(unsigned long, struct pt_regs *); |
| extern int do_memory_error(unsigned long, struct pt_regs *); |
| extern int trap_is_brkpt(unsigned long, struct pt_regs *); |
| extern int do_misaligned_error(unsigned long, struct pt_regs *); |
| extern int do_trap5_error(unsigned long, struct pt_regs *); |
| extern int do_misaligned_access(unsigned long, struct pt_regs *, struct callee_regs *); |
| extern void do_machine_check_fault(unsigned long, struct pt_regs *); |
| extern void do_non_swi_trap(unsigned long, struct pt_regs *); |
| extern void do_insterror_or_kprobe(unsigned long, struct pt_regs *); |
| extern void do_page_fault(unsigned long, struct pt_regs *); |
| |
| #endif |
| |
| #endif /* __ASM_ARC_ENTRY_H */ |