]>
Commit | Line | Data |
---|---|---|
fe8c2806 WD |
1 | /* |
2 | * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> | |
3 | * | |
4 | * (C) Copyright 2000 | |
5 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
fe8c2806 WD |
8 | */ |
9 | #include <common.h> | |
10 | ||
11 | /* | |
12 | * The exception table consists of pairs of addresses: the first is the | |
13 | * address of an instruction that is allowed to fault, and the second is | |
14 | * the address at which the program should continue. No registers are | |
15 | * modified, so it is entirely up to the continuation code to figure out | |
16 | * what to do. | |
17 | * | |
18 | * All the routines below use bits of fixup code that are out of line | |
19 | * with the main instruction path. This means when everything is well, | |
20 | * we don't even have to jump over them. Further, they do not intrude | |
21 | * on our cache or tlb entries. | |
22 | */ | |
23 | ||
9d27b3a0 | 24 | DECLARE_GLOBAL_DATA_PTR; |
25 | ||
fe8c2806 WD |
26 | struct exception_table_entry |
27 | { | |
28 | unsigned long insn, fixup; | |
29 | }; | |
30 | ||
31 | extern const struct exception_table_entry __start___ex_table[]; | |
32 | extern const struct exception_table_entry __stop___ex_table[]; | |
33 | ||
34 | static inline unsigned long | |
35 | search_one_table(const struct exception_table_entry *first, | |
36 | const struct exception_table_entry *last, | |
37 | unsigned long value) | |
38 | { | |
1b305bdc | 39 | long diff; |
e6b05e77 PT |
40 | while (first <= last) { |
41 | diff = first->insn - value; | |
42 | if (diff == 0) | |
43 | return first->fixup; | |
44 | first++; | |
8bde7f77 | 45 | } |
e6b05e77 | 46 | |
8bde7f77 | 47 | return 0; |
fe8c2806 WD |
48 | } |
49 | ||
fe8c2806 WD |
50 | unsigned long |
51 | search_exception_table(unsigned long addr) | |
52 | { | |
53 | unsigned long ret; | |
54 | ||
55 | /* There is only the kernel to search. */ | |
56 | ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); | |
c9c1eeed | 57 | /* if the serial port does not hang in exception, printf can be used */ |
6d0f6bcf | 58 | #if !defined(CONFIG_SYS_SERIAL_HANG_IN_EXCEPTION) |
fe44f452 | 59 | debug("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret); |
4c52783b | 60 | #endif |
fe8c2806 WD |
61 | if (ret) return ret; |
62 | ||
63 | return 0; | |
64 | } |