xref: /linux/arch/xtensa/include/asm/traps.h (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
1  /*
2   * arch/xtensa/include/asm/traps.h
3   *
4   * This file is subject to the terms and conditions of the GNU General Public
5   * License.  See the file "COPYING" in the main directory of this archive
6   * for more details.
7   *
8   * Copyright (C) 2012 Tensilica Inc.
9   */
10  #ifndef _XTENSA_TRAPS_H
11  #define _XTENSA_TRAPS_H
12  
13  #include <asm/ptrace.h>
14  
15  typedef void xtensa_exception_handler(struct pt_regs *regs);
16  
17  /*
18   * Per-CPU exception handling data structure.
19   * EXCSAVE1 points to it.
20   */
21  struct exc_table {
22  	/* Kernel Stack */
23  	void *kstk;
24  	/* Double exception save area for a0 */
25  	unsigned long double_save;
26  	/* Fixup handler */
27  	void *fixup;
28  	/* For passing a parameter to fixup */
29  	void *fixup_param;
30  #if XTENSA_HAVE_COPROCESSORS
31  	/* Pointers to owner struct thread_info */
32  	struct thread_info *coprocessor_owner[XCHAL_CP_MAX];
33  #endif
34  	/* Fast user exception handlers */
35  	void *fast_user_handler[EXCCAUSE_N];
36  	/* Fast kernel exception handlers */
37  	void *fast_kernel_handler[EXCCAUSE_N];
38  	/* Default C-Handlers */
39  	xtensa_exception_handler *default_handler[EXCCAUSE_N];
40  };
41  
42  DECLARE_PER_CPU(struct exc_table, exc_table);
43  
44  xtensa_exception_handler *
45  __init trap_set_handler(int cause, xtensa_exception_handler *handler);
46  
47  asmlinkage void fast_illegal_instruction_user(void);
48  asmlinkage void fast_syscall_user(void);
49  asmlinkage void fast_alloca(void);
50  asmlinkage void fast_load_store(void);
51  asmlinkage void fast_unaligned(void);
52  asmlinkage void fast_second_level_miss(void);
53  asmlinkage void fast_store_prohibited(void);
54  asmlinkage void fast_coprocessor(void);
55  
56  asmlinkage void kernel_exception(void);
57  asmlinkage void user_exception(void);
58  asmlinkage void system_call(struct pt_regs *regs);
59  
60  void do_IRQ(int hwirq, struct pt_regs *regs);
61  void do_page_fault(struct pt_regs *regs);
62  void do_unhandled(struct pt_regs *regs);
63  
64  /* Initialize minimal exc_table structure sufficient for basic paging */
early_trap_init(void)65  static inline void __init early_trap_init(void)
66  {
67  	static struct exc_table init_exc_table __initdata = {
68  #ifdef CONFIG_XTENSA_LOAD_STORE
69  		.fast_kernel_handler[EXCCAUSE_LOAD_STORE_ERROR] =
70  			fast_load_store,
71  #endif
72  #ifdef CONFIG_MMU
73  		.fast_kernel_handler[EXCCAUSE_DTLB_MISS] =
74  			fast_second_level_miss,
75  #endif
76  	};
77  	xtensa_set_sr(&init_exc_table, excsave1);
78  }
79  
80  void secondary_trap_init(void);
81  
spill_registers(void)82  static inline void spill_registers(void)
83  {
84  #if defined(__XTENSA_WINDOWED_ABI__)
85  #if XCHAL_NUM_AREGS > 16
86  	__asm__ __volatile__ (
87  		"	call8	1f\n"
88  		"	_j	2f\n"
89  		"	retw\n"
90  		"	.align	4\n"
91  		"1:\n"
92  #if XCHAL_NUM_AREGS == 32
93  		"	_entry	a1, 32\n"
94  		"	addi	a8, a0, 3\n"
95  		"	_entry	a1, 16\n"
96  		"	mov	a12, a12\n"
97  		"	retw\n"
98  #else
99  		"	_entry	a1, 48\n"
100  		"	call12	1f\n"
101  		"	retw\n"
102  		"	.align	4\n"
103  		"1:\n"
104  		"	.rept	(" __stringify(XCHAL_NUM_AREGS) " - 16) / 12\n"
105  		"	_entry	a1, 48\n"
106  		"	mov	a12, a0\n"
107  		"	.endr\n"
108  		"	_entry	a1, 16\n"
109  #if XCHAL_NUM_AREGS % 12 == 0
110  		"	mov	a12, a12\n"
111  #elif XCHAL_NUM_AREGS % 12 == 4
112  		"	mov	a4, a4\n"
113  #elif XCHAL_NUM_AREGS % 12 == 8
114  		"	mov	a8, a8\n"
115  #endif
116  		"	retw\n"
117  #endif
118  		"2:\n"
119  		: : : "a8", "a9", "memory");
120  #else
121  	__asm__ __volatile__ (
122  		"	mov	a12, a12\n"
123  		: : : "memory");
124  #endif
125  #endif
126  }
127  
128  struct debug_table {
129  	/* Pointer to debug exception handler */
130  	void (*debug_exception)(void);
131  	/* Temporary register save area */
132  	unsigned long debug_save[1];
133  #ifdef CONFIG_HAVE_HW_BREAKPOINT
134  	/* Save area for DBREAKC registers */
135  	unsigned long dbreakc_save[XCHAL_NUM_DBREAK];
136  	/* Saved ICOUNT register */
137  	unsigned long icount_save;
138  	/* Saved ICOUNTLEVEL register */
139  	unsigned long icount_level_save;
140  #endif
141  };
142  
143  void debug_exception(void);
144  
145  #endif /* _XTENSA_TRAPS_H */
146