source: mainline/kernel/arch/arm32/src/exception.c@ 3bacee1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3bacee1 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2007 Petr Stepan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup arm32
30 * @{
31 */
32/** @file
33 * @brief Exception handlers and exception initialization routines.
34 */
35
36#include <arch/exception.h>
37#include <arch/regutils.h>
38#include <arch/machine_func.h>
39#include <interrupt.h>
40#include <arch/mm/page_fault.h>
41#include <arch/cp15.h>
42#include <arch/barrier.h>
43#include <print.h>
44#include <syscall/syscall.h>
45#include <stacktrace.h>
46
47/** Offset used in calculation of exception handler's relative address.
48 *
49 * @see install_handler()
50 */
51#define PREFETCH_OFFSET 0x8
52
53/** LDR instruction's code */
54#define LDR_OPCODE 0xe59ff000
55
56/** Number of exception vectors. */
57#define EXC_VECTORS 8
58
59/** Size of memory block occupied by exception vectors. */
60#define EXC_VECTORS_SIZE (EXC_VECTORS * 4)
61
62/** Updates specified exception vector to jump to given handler.
63 *
64 * Addresses of handlers are stored in memory following exception vectors.
65 */
66static void install_handler(unsigned handler_addr, unsigned *vector)
67{
68 /* relative address (related to exc. vector) of the word
69 * where handler's address is stored
70 */
71 volatile uint32_t handler_address_ptr = EXC_VECTORS_SIZE -
72 PREFETCH_OFFSET;
73
74 /* make it LDR instruction and store at exception vector */
75 *vector = handler_address_ptr | LDR_OPCODE;
76 smc_coherence(vector);
77
78 /* store handler's address */
79 *(vector + EXC_VECTORS) = handler_addr;
80
81}
82
83/** Software Interrupt handler.
84 *
85 * Dispatches the syscall.
86 *
87 */
88static void swi_exception(unsigned int exc_no, istate_t *istate)
89{
90 interrupts_enable();
91 istate->r0 = syscall_handler(istate->r0, istate->r1, istate->r2,
92 istate->r3, istate->r4, istate->r5, istate->r6);
93 interrupts_disable();
94}
95
96/** Fills exception vectors with appropriate exception handlers. */
97void install_exception_handlers(void)
98{
99 install_handler((unsigned) reset_exception_entry,
100 (unsigned *) EXC_RESET_VEC);
101
102 install_handler((unsigned) undef_instr_exception_entry,
103 (unsigned *) EXC_UNDEF_INSTR_VEC);
104
105 install_handler((unsigned) swi_exception_entry,
106 (unsigned *) EXC_SWI_VEC);
107
108 install_handler((unsigned) prefetch_abort_exception_entry,
109 (unsigned *) EXC_PREFETCH_ABORT_VEC);
110
111 install_handler((unsigned) data_abort_exception_entry,
112 (unsigned *) EXC_DATA_ABORT_VEC);
113
114 install_handler((unsigned) irq_exception_entry,
115 (unsigned *) EXC_IRQ_VEC);
116
117 install_handler((unsigned) fiq_exception_entry,
118 (unsigned *) EXC_FIQ_VEC);
119}
120
121#ifdef HIGH_EXCEPTION_VECTORS
122/** Activates use of high exception vectors addresses.
123 *
124 * "High vectors were introduced into some implementations of ARMv4 and are
125 * required in ARMv6 implementations. High vectors allow the exception vector
126 * locations to be moved from their normal address range 0x00000000-0x0000001C
127 * at the bottom of the 32-bit address space, to an alternative address range
128 * 0xFFFF0000-0xFFFF001C near the top of the address space. These alternative
129 * locations are known as the high vectors.
130 *
131 * Prior to ARMv6, it is IMPLEMENTATION DEFINED whether the high vectors are
132 * supported. When they are, a hardware configuration input selects whether
133 * the normal vectors or the high vectors are to be used from
134 * reset." ARM Architecture Reference Manual A2.6.11 (p. 64 in the PDF).
135 *
136 * ARM920T (gta02) TRM A2.3.5 (PDF p. 36) and ARM926EJ-S (icp) 2.3.2 (PDF p. 42)
137 * say that armv4 an armv5 chips that we support implement this.
138 */
139static void high_vectors(void)
140{
141 uint32_t control_reg = SCTLR_read();
142
143 /* switch on the high vectors bit */
144 control_reg |= SCTLR_HIGH_VECTORS_EN_FLAG;
145
146 SCTLR_write(control_reg);
147}
148#endif
149
150/** Interrupt Exception handler.
151 *
152 * Determines the sources of interrupt and calls their handlers.
153 */
154static void irq_exception(unsigned int exc_no, istate_t *istate)
155{
156 machine_irq_exception(exc_no, istate);
157}
158
159/** Undefined instruction exception handler.
160 *
161 * Calls scheduler_fpu_lazy_request
162 */
163static void undef_insn_exception(unsigned int exc_no, istate_t *istate)
164{
165#ifdef CONFIG_FPU
166 if (handle_if_fpu_exception()) {
167 /*
168 * Retry the failing instruction,
169 * ARM Architecture Reference Manual says on p.B1-1169
170 * that offset for undef instruction exception is 4
171 */
172 istate->pc -= 4;
173 return;
174 }
175#endif
176 fault_if_from_uspace(istate, "Undefined instruction.");
177 panic_badtrap(istate, exc_no, "Undefined instruction.");
178}
179
180/** Initializes exception handling.
181 *
182 * Installs low-level exception handlers and then registers
183 * exceptions and their handlers to kernel exception dispatcher.
184 */
185void exception_init(void)
186{
187 // TODO check for availability of high vectors for <= armv5
188#ifdef HIGH_EXCEPTION_VECTORS
189 high_vectors();
190#endif
191 install_exception_handlers();
192
193 exc_register(EXC_UNDEF_INSTR, "undefined instruction", true,
194 (iroutine_t) undef_insn_exception);
195 exc_register(EXC_IRQ, "interrupt", true,
196 (iroutine_t) irq_exception);
197 exc_register(EXC_PREFETCH_ABORT, "prefetch abort", true,
198 (iroutine_t) prefetch_abort);
199 exc_register(EXC_DATA_ABORT, "data abort", true,
200 (iroutine_t) data_abort);
201 exc_register(EXC_SWI, "software interrupt", true,
202 (iroutine_t) swi_exception);
203}
204
205/** Prints #istate_t structure content.
206 *
207 * @param istate Structure to be printed.
208 */
209void istate_decode(istate_t *istate)
210{
211 printf("r0 =%0#10" PRIx32 "\tr1 =%0#10" PRIx32 "\t"
212 "r2 =%0#10" PRIx32 "\tr3 =%0#10" PRIx32 "\n",
213 istate->r0, istate->r1, istate->r2, istate->r3);
214 printf("r4 =%0#10" PRIx32 "\tr5 =%0#10" PRIx32 "\t"
215 "r6 =%0#10" PRIx32 "\tr7 =%0#10" PRIx32 "\n",
216 istate->r4, istate->r5, istate->r6, istate->r7);
217 printf("r8 =%0#10" PRIx32 "\tr9 =%0#10" PRIx32 "\t"
218 "r10=%0#10" PRIx32 "\tfp =%0#10" PRIx32 "\n",
219 istate->r8, istate->r9, istate->r10, istate->fp);
220 printf("r12=%0#10" PRIx32 "\tsp =%0#10" PRIx32 "\t"
221 "lr =%0#10" PRIx32 "\tspsr=%0#10" PRIx32 "\n",
222 istate->r12, istate->sp, istate->lr, istate->spsr);
223}
224
225/** @}
226 */
Note: See TracBrowser for help on using the repository browser.