162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
462306a36Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __ASM_ARC_ENTRY_H
862306a36Sopenharmony_ci#define __ASM_ARC_ENTRY_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <asm/unistd.h>		/* For NR_syscalls defination */
1162306a36Sopenharmony_ci#include <asm/arcregs.h>
1262306a36Sopenharmony_ci#include <asm/ptrace.h>
1362306a36Sopenharmony_ci#include <asm/processor.h>	/* For VMALLOC_START */
1462306a36Sopenharmony_ci#include <asm/mmu.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#ifdef __ASSEMBLY__
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#ifdef CONFIG_ISA_ARCOMPACT
1962306a36Sopenharmony_ci#include <asm/entry-compact.h>	/* ISA specific bits */
2062306a36Sopenharmony_ci#else
2162306a36Sopenharmony_ci#include <asm/entry-arcv2.h>
2262306a36Sopenharmony_ci#endif
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/* Note on the LD/ST addr modes with addr reg wback
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * LD.a same as LD.aw
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * LD.a    reg1, [reg2, x]  => Pre Incr
2962306a36Sopenharmony_ci *      Eff Addr for load = [reg2 + x]
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * LD.ab   reg1, [reg2, x]  => Post Incr
3262306a36Sopenharmony_ci *      Eff Addr for load = [reg2]
3362306a36Sopenharmony_ci */
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci.macro PUSH reg
3662306a36Sopenharmony_ci	st.a	\reg, [sp, -4]
3762306a36Sopenharmony_ci.endm
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci.macro PUSHAX aux
4062306a36Sopenharmony_ci	lr	r9, [\aux]
4162306a36Sopenharmony_ci	PUSH	r9
4262306a36Sopenharmony_ci.endm
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci.macro POP reg
4562306a36Sopenharmony_ci	ld.ab	\reg, [sp, 4]
4662306a36Sopenharmony_ci.endm
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci.macro POPAX aux
4962306a36Sopenharmony_ci	POP	r9
5062306a36Sopenharmony_ci	sr	r9, [\aux]
5162306a36Sopenharmony_ci.endm
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/*--------------------------------------------------------------
5462306a36Sopenharmony_ci * Helpers to save/restore Scratch Regs:
5562306a36Sopenharmony_ci * used by Interrupt/Exception Prologue/Epilogue
5662306a36Sopenharmony_ci *-------------------------------------------------------------*/
5762306a36Sopenharmony_ci.macro  SAVE_R0_TO_R12
5862306a36Sopenharmony_ci	PUSH	r0
5962306a36Sopenharmony_ci	PUSH	r1
6062306a36Sopenharmony_ci	PUSH	r2
6162306a36Sopenharmony_ci	PUSH	r3
6262306a36Sopenharmony_ci	PUSH	r4
6362306a36Sopenharmony_ci	PUSH	r5
6462306a36Sopenharmony_ci	PUSH	r6
6562306a36Sopenharmony_ci	PUSH	r7
6662306a36Sopenharmony_ci	PUSH	r8
6762306a36Sopenharmony_ci	PUSH	r9
6862306a36Sopenharmony_ci	PUSH	r10
6962306a36Sopenharmony_ci	PUSH	r11
7062306a36Sopenharmony_ci	PUSH	r12
7162306a36Sopenharmony_ci.endm
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci.macro RESTORE_R12_TO_R0
7462306a36Sopenharmony_ci	POP	r12
7562306a36Sopenharmony_ci	POP	r11
7662306a36Sopenharmony_ci	POP	r10
7762306a36Sopenharmony_ci	POP	r9
7862306a36Sopenharmony_ci	POP	r8
7962306a36Sopenharmony_ci	POP	r7
8062306a36Sopenharmony_ci	POP	r6
8162306a36Sopenharmony_ci	POP	r5
8262306a36Sopenharmony_ci	POP	r4
8362306a36Sopenharmony_ci	POP	r3
8462306a36Sopenharmony_ci	POP	r2
8562306a36Sopenharmony_ci	POP	r1
8662306a36Sopenharmony_ci	POP	r0
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci.endm
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/*--------------------------------------------------------------
9162306a36Sopenharmony_ci * Helpers to save/restore callee-saved regs:
9262306a36Sopenharmony_ci * used by several macros below
9362306a36Sopenharmony_ci *-------------------------------------------------------------*/
9462306a36Sopenharmony_ci.macro SAVE_R13_TO_R25
9562306a36Sopenharmony_ci	PUSH	r13
9662306a36Sopenharmony_ci	PUSH	r14
9762306a36Sopenharmony_ci	PUSH	r15
9862306a36Sopenharmony_ci	PUSH	r16
9962306a36Sopenharmony_ci	PUSH	r17
10062306a36Sopenharmony_ci	PUSH	r18
10162306a36Sopenharmony_ci	PUSH	r19
10262306a36Sopenharmony_ci	PUSH	r20
10362306a36Sopenharmony_ci	PUSH	r21
10462306a36Sopenharmony_ci	PUSH	r22
10562306a36Sopenharmony_ci	PUSH	r23
10662306a36Sopenharmony_ci	PUSH	r24
10762306a36Sopenharmony_ci	PUSH	r25
10862306a36Sopenharmony_ci.endm
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci.macro RESTORE_R25_TO_R13
11162306a36Sopenharmony_ci	POP	r25
11262306a36Sopenharmony_ci	POP	r24
11362306a36Sopenharmony_ci	POP	r23
11462306a36Sopenharmony_ci	POP	r22
11562306a36Sopenharmony_ci	POP	r21
11662306a36Sopenharmony_ci	POP	r20
11762306a36Sopenharmony_ci	POP	r19
11862306a36Sopenharmony_ci	POP	r18
11962306a36Sopenharmony_ci	POP	r17
12062306a36Sopenharmony_ci	POP	r16
12162306a36Sopenharmony_ci	POP	r15
12262306a36Sopenharmony_ci	POP	r14
12362306a36Sopenharmony_ci	POP	r13
12462306a36Sopenharmony_ci.endm
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci/*
12762306a36Sopenharmony_ci * save user mode callee regs as struct callee_regs
12862306a36Sopenharmony_ci *  - needed by fork/do_signal/unaligned-access-emulation.
12962306a36Sopenharmony_ci */
13062306a36Sopenharmony_ci.macro SAVE_CALLEE_SAVED_USER
13162306a36Sopenharmony_ci	SAVE_R13_TO_R25
13262306a36Sopenharmony_ci.endm
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * restore user mode callee regs as struct callee_regs
13662306a36Sopenharmony_ci *  - could have been changed by ptrace tracer or unaligned-access fixup
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_ci.macro RESTORE_CALLEE_SAVED_USER
13962306a36Sopenharmony_ci	RESTORE_R25_TO_R13
14062306a36Sopenharmony_ci.endm
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci/*
14362306a36Sopenharmony_ci * save/restore kernel mode callee regs at the time of context switch
14462306a36Sopenharmony_ci */
14562306a36Sopenharmony_ci.macro SAVE_CALLEE_SAVED_KERNEL
14662306a36Sopenharmony_ci	SAVE_R13_TO_R25
14762306a36Sopenharmony_ci.endm
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci.macro RESTORE_CALLEE_SAVED_KERNEL
15062306a36Sopenharmony_ci	RESTORE_R25_TO_R13
15162306a36Sopenharmony_ci.endm
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/*--------------------------------------------------------------
15462306a36Sopenharmony_ci * Super FAST Restore callee saved regs by simply re-adjusting SP
15562306a36Sopenharmony_ci *-------------------------------------------------------------*/
15662306a36Sopenharmony_ci.macro DISCARD_CALLEE_SAVED_USER
15762306a36Sopenharmony_ci	add     sp, sp, SZ_CALLEE_REGS
15862306a36Sopenharmony_ci.endm
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/*-------------------------------------------------------------
16162306a36Sopenharmony_ci * given a tsk struct, get to the base of it's kernel mode stack
16262306a36Sopenharmony_ci * tsk->thread_info is really a PAGE, whose bottom hoists stack
16362306a36Sopenharmony_ci * which grows upwards towards thread_info
16462306a36Sopenharmony_ci *------------------------------------------------------------*/
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci.macro GET_TSK_STACK_BASE tsk, out
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	/* Get task->thread_info (this is essentially start of a PAGE) */
16962306a36Sopenharmony_ci	ld  \out, [\tsk, TASK_THREAD_INFO]
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	/* Go to end of page where stack begins (grows upwards) */
17262306a36Sopenharmony_ci	add2 \out, \out, (THREAD_SIZE)/4
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci.endm
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/*
17762306a36Sopenharmony_ci * @reg [OUT] thread_info->flags of "current"
17862306a36Sopenharmony_ci */
17962306a36Sopenharmony_ci.macro GET_CURR_THR_INFO_FLAGS  reg
18062306a36Sopenharmony_ci	GET_CURR_THR_INFO_FROM_SP  \reg
18162306a36Sopenharmony_ci	ld  \reg, [\reg, THREAD_INFO_FLAGS]
18262306a36Sopenharmony_ci.endm
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci#ifdef CONFIG_SMP
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/*
18762306a36Sopenharmony_ci * Retrieve the current running task on this CPU
18862306a36Sopenharmony_ci *  - loads it from backing _current_task[] (and can't use the
18962306a36Sopenharmony_ci *    caching reg for current task
19062306a36Sopenharmony_ci */
19162306a36Sopenharmony_ci.macro  GET_CURR_TASK_ON_CPU   reg
19262306a36Sopenharmony_ci	GET_CPU_ID  \reg
19362306a36Sopenharmony_ci	ld.as  \reg, [@_current_task, \reg]
19462306a36Sopenharmony_ci.endm
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci/*-------------------------------------------------
19762306a36Sopenharmony_ci * Save a new task as the "current" task on this CPU
19862306a36Sopenharmony_ci * 1. Determine curr CPU id.
19962306a36Sopenharmony_ci * 2. Use it to index into _current_task[ ]
20062306a36Sopenharmony_ci *
20162306a36Sopenharmony_ci * Coded differently than GET_CURR_TASK_ON_CPU (which uses LD.AS)
20262306a36Sopenharmony_ci * because ST r0, [r1, offset] can ONLY have s9 @offset
20362306a36Sopenharmony_ci * while   LD can take s9 (4 byte insn) or LIMM (8 byte insn)
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
20762306a36Sopenharmony_ci	GET_CPU_ID  \tmp
20862306a36Sopenharmony_ci	add2 \tmp, @_current_task, \tmp
20962306a36Sopenharmony_ci	st   \tsk, [\tmp]
21062306a36Sopenharmony_ci#ifdef CONFIG_ARC_CURR_IN_REG
21162306a36Sopenharmony_ci	mov gp, \tsk
21262306a36Sopenharmony_ci#endif
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci.endm
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci#else   /* Uniprocessor implementation of macros */
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci.macro  GET_CURR_TASK_ON_CPU    reg
22062306a36Sopenharmony_ci	ld  \reg, [@_current_task]
22162306a36Sopenharmony_ci.endm
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci.macro  SET_CURR_TASK_ON_CPU    tsk, tmp
22462306a36Sopenharmony_ci	st  \tsk, [@_current_task]
22562306a36Sopenharmony_ci#ifdef CONFIG_ARC_CURR_IN_REG
22662306a36Sopenharmony_ci	mov gp, \tsk
22762306a36Sopenharmony_ci#endif
22862306a36Sopenharmony_ci.endm
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#endif /* SMP / UNI */
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/*
23362306a36Sopenharmony_ci * Get the ptr to some field of Current Task at @off in task struct
23462306a36Sopenharmony_ci *  - Uses current task cached in reg if enabled
23562306a36Sopenharmony_ci */
23662306a36Sopenharmony_ci#ifdef CONFIG_ARC_CURR_IN_REG
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci.macro GET_CURR_TASK_FIELD_PTR  off,  reg
23962306a36Sopenharmony_ci	add \reg, gp, \off
24062306a36Sopenharmony_ci.endm
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci#else
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci.macro GET_CURR_TASK_FIELD_PTR  off,  reg
24562306a36Sopenharmony_ci	GET_CURR_TASK_ON_CPU  \reg
24662306a36Sopenharmony_ci	add \reg, \reg, \off
24762306a36Sopenharmony_ci.endm
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci#endif	/* CONFIG_ARC_CURR_IN_REG */
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci#else	/* !__ASSEMBLY__ */
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ciextern void do_signal(struct pt_regs *);
25462306a36Sopenharmony_ciextern void do_notify_resume(struct pt_regs *);
25562306a36Sopenharmony_ciextern int do_privilege_fault(unsigned long, struct pt_regs *);
25662306a36Sopenharmony_ciextern int do_extension_fault(unsigned long, struct pt_regs *);
25762306a36Sopenharmony_ciextern int insterror_is_error(unsigned long, struct pt_regs *);
25862306a36Sopenharmony_ciextern int do_memory_error(unsigned long, struct pt_regs *);
25962306a36Sopenharmony_ciextern int trap_is_brkpt(unsigned long, struct pt_regs *);
26062306a36Sopenharmony_ciextern int do_misaligned_error(unsigned long, struct pt_regs *);
26162306a36Sopenharmony_ciextern int do_trap5_error(unsigned long, struct pt_regs *);
26262306a36Sopenharmony_ciextern int do_misaligned_access(unsigned long, struct pt_regs *, struct callee_regs *);
26362306a36Sopenharmony_ciextern void do_machine_check_fault(unsigned long, struct pt_regs *);
26462306a36Sopenharmony_ciextern void do_non_swi_trap(unsigned long, struct pt_regs *);
26562306a36Sopenharmony_ciextern void do_insterror_or_kprobe(unsigned long, struct pt_regs *);
26662306a36Sopenharmony_ciextern void do_page_fault(unsigned long, struct pt_regs *);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci#endif
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#endif  /* __ASM_ARC_ENTRY_H */
271