source: mainline/kernel/arch/mips32/src/exception.c@ f1380b7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 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.0 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2003-2004 Jakub Jermar
[f761f1eb]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
[da1bafb]29/** @addtogroup mips32
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[f761f1eb]35#include <arch/exception.h>
[9c0a9b3]36#include <arch/interrupt.h>
[b3f8fb7]37#include <arch/mm/tlb.h>
[f761f1eb]38#include <panic.h>
39#include <arch/cp0.h>
40#include <arch.h>
[63e27ef]41#include <assert.h>
[1084a784]42#include <proc/thread.h>
[7a8c866a]43#include <print.h>
44#include <interrupt.h>
[b2e121a]45#include <halt.h>
[7688b5d]46#include <ddi/irq.h>
[5bb8e45]47#include <arch/debugger.h>
[e2b762ec]48#include <symtab.h>
[b2fa1204]49#include <log.h>
[e2b762ec]50
[a000878c]51static const char *exctable[] = {
[2f40fe4]52 "Interrupt",
53 "TLB Modified",
54 "TLB Invalid",
55 "TLB Invalid Store",
56 "Address Error - load/instr. fetch",
57 "Address Error - store",
58 "Bus Error - fetch instruction",
59 "Bus Error - data reference",
60 "Syscall",
61 "BreakPoint",
62 "Reserved Instruction",
63 "Coprocessor Unusable",
64 "Arithmetic Overflow",
65 "Trap",
66 "Virtual Coherency - instruction",
67 "Floating Point",
68 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
[da1bafb]69 "WatchHi/WatchLo", /* 23 */
[2f40fe4]70 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71 "Virtual Coherency - data",
[7a8c866a]72};
73
[22a28a69]74void istate_decode(istate_t *istate)
[7a8c866a]75{
[b2fa1204]76 log_printf("epc=%#010" PRIx32 "\tsta=%#010" PRIx32 "\t"
[41a7f62]77 "lo =%#010" PRIx32 "\thi =%#010" PRIx32 "\n",
[8469c53]78 istate->epc, istate->status, istate->lo, istate->hi);
[a35b458]79
[b2fa1204]80 log_printf("a0 =%#010" PRIx32 "\ta1 =%#010" PRIx32 "\t"
[41a7f62]81 "a2 =%#010" PRIx32 "\ta3 =%#010" PRIx32 "\n",
[0c61955]82 istate->a0, istate->a1, istate->a2, istate->a3);
[a35b458]83
[b2fa1204]84 log_printf("t0 =%#010" PRIx32 "\tt1 =%#010" PRIx32 "\t"
[41a7f62]85 "t2 =%#010" PRIx32 "\tt3 =%#010" PRIx32 "\n",
[0c61955]86 istate->t0, istate->t1, istate->t2, istate->t3);
[a35b458]87
[b2fa1204]88 log_printf("t4 =%#010" PRIx32 "\tt5 =%#010" PRIx32 "\t"
[41a7f62]89 "t6 =%#010" PRIx32 "\tt7 =%#010" PRIx32 "\n",
[0c61955]90 istate->t4, istate->t5, istate->t6, istate->t7);
[a35b458]91
[b2fa1204]92 log_printf("t8 =%#010" PRIx32 "\tt9 =%#010" PRIx32 "\t"
[41a7f62]93 "v0 =%#010" PRIx32 "\tv1 =%#010" PRIx32 "\n",
[0c61955]94 istate->t8, istate->t9, istate->v0, istate->v1);
[a35b458]95
[b2fa1204]96 log_printf("s0 =%#010" PRIx32 "\ts1 =%#010" PRIx32 "\t"
[41a7f62]97 "s2 =%#010" PRIx32 "\ts3 =%#010" PRIx32 "\n",
[0c61955]98 istate->s0, istate->s1, istate->s2, istate->s3);
[a35b458]99
[b2fa1204]100 log_printf("s4 =%#010" PRIx32 "\ts5 =%#010" PRIx32 "\t"
[41a7f62]101 "s6 =%#010" PRIx32 "\ts7 =%#010" PRIx32 "\n",
[0c61955]102 istate->s4, istate->s5, istate->s6, istate->s7);
[a35b458]103
[b2fa1204]104 log_printf("s8 =%#010" PRIx32 "\tat =%#010" PRIx32 "\t"
[41a7f62]105 "kt0=%#010" PRIx32 "\tkt1=%#010" PRIx32 "\n",
[0c61955]106 istate->s8, istate->at, istate->kt0, istate->kt1);
[a35b458]107
[b2fa1204]108 log_printf("sp =%#010" PRIx32 "\tra =%#010" PRIx32 "\t"
[8469c53]109 "gp =%#010" PRIx32 "\n",
110 istate->sp, istate->ra, istate->gp);
[7a8c866a]111}
112
[214ec25c]113static void unhandled_exception(unsigned int n, istate_t *istate)
[7a8c866a]114{
[f651e80]115 fault_if_from_uspace(istate, "Unhandled exception %s.", exctable[n]);
[ac11ac7]116 panic_badtrap(istate, n, "Unhandled exception %s.", exctable[n]);
[7a8c866a]117}
118
[214ec25c]119static void reserved_instr_exception(unsigned int n, istate_t *istate)
[3b712407]120{
[a000878c]121 if (*((uint32_t *) istate->epc) == 0x7c03e83b) {
[63e27ef]122 assert(THREAD);
[3b712407]123 istate->epc += 4;
[ce890ec9]124 istate->v1 = istate->kt1;
[a000878c]125 } else
[5201199]126 unhandled_exception(n, istate);
[3b712407]127}
128
[214ec25c]129static void breakpoint_exception(unsigned int n, istate_t *istate)
[7a8c866a]130{
[5bb8e45]131#ifdef CONFIG_DEBUG
[25d7709]132 debugger_bpoint(istate);
[5bb8e45]133#else
[1b20da0]134 /* it is necessary to not re-execute BREAK instruction after
[7a8c866a]135 returning from Exception handler
136 (see page 138 in R4000 Manual for more information) */
[25d7709]137 istate->epc += 4;
[5bb8e45]138#endif
[7a8c866a]139}
140
[214ec25c]141static void tlbmod_exception(unsigned int n, istate_t *istate)
[7a8c866a]142{
[25d7709]143 tlb_modified(istate);
[7a8c866a]144}
145
[214ec25c]146static void tlbinv_exception(unsigned int n, istate_t *istate)
[7a8c866a]147{
[25d7709]148 tlb_invalid(istate);
[7a8c866a]149}
150
[5a95b25]151#ifdef CONFIG_FPU_LAZY
[214ec25c]152static void cpuns_exception(unsigned int n, istate_t *istate)
[7a8c866a]153{
154 if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
155 scheduler_fpu_lazy_request();
[874621f]156 else {
[ac11ac7]157 fault_if_from_uspace(istate,
158 "Unhandled Coprocessor Unusable Exception.");
159 panic_badtrap(istate, n,
160 "Unhandled Coprocessor Unusable Exception.");
[874621f]161 }
[7a8c866a]162}
[5a95b25]163#endif
[7a8c866a]164
[214ec25c]165static void interrupt_exception(unsigned int n, istate_t *istate)
[7a8c866a]166{
[7be6379]167 uint32_t ip;
168 uint32_t im;
169
[da1bafb]170 /* Decode interrupt number and process the interrupt */
[7be6379]171 ip = (cp0_cause_read() & cp0_cause_ip_mask) >> cp0_cause_ip_shift;
172 im = (cp0_status_read() & cp0_status_im_mask) >> cp0_status_im_shift;
[a35b458]173
[da1bafb]174 unsigned int i;
[7688b5d]175 for (i = 0; i < 8; i++) {
[7be6379]176
177 /*
178 * The interrupt could only occur if it is unmasked in the
179 * status register. On the other hand, an interrupt can be
180 * apparently pending even if it is masked, so we need to
181 * check both the masked and pending interrupts.
182 */
183 if (im & ip & (1 << i)) {
[7688b5d]184 irq_t *irq = irq_dispatch_and_lock(i);
185 if (irq) {
186 /*
187 * The IRQ handler was found.
188 */
[6cd9aa6]189 irq->handler(irq);
[da1bafb]190 irq_spinlock_unlock(&irq->lock, false);
[7688b5d]191 } else {
192 /*
193 * Spurious interrupt.
194 */
195#ifdef CONFIG_DEBUG
[b2fa1204]196 log(LF_ARCH, LVL_DEBUG,
197 "cpu%u: spurious interrupt (inum=%u)",
[6cd9aa6]198 CPU->id, i);
[7688b5d]199#endif
200 }
201 }
202 }
[7a8c866a]203}
204
[1b109cb]205/** Handle syscall userspace call */
[214ec25c]206static void syscall_exception(unsigned int n, istate_t *istate)
[f761f1eb]207{
[ac11ac7]208 fault_if_from_uspace(istate, "Syscall is handled through shortcut.");
[f761f1eb]209}
[7a8c866a]210
211void exception_init(void)
212{
[b3b7e14a]213 unsigned int i;
[a35b458]214
[7a8c866a]215 /* Clear exception table */
[7688b5d]216 for (i = 0; i < IVT_ITEMS; i++)
[b3b7e14a]217 exc_register(i, "undef", false,
218 (iroutine_t) unhandled_exception);
[a35b458]219
[b3b7e14a]220 exc_register(EXC_Bp, "bkpoint", true,
221 (iroutine_t) breakpoint_exception);
222 exc_register(EXC_RI, "resinstr", true,
223 (iroutine_t) reserved_instr_exception);
224 exc_register(EXC_Mod, "tlb_mod", true,
225 (iroutine_t) tlbmod_exception);
226 exc_register(EXC_TLBL, "tlbinvl", true,
227 (iroutine_t) tlbinv_exception);
228 exc_register(EXC_TLBS, "tlbinvl", true,
229 (iroutine_t) tlbinv_exception);
230 exc_register(EXC_Int, "interrupt", true,
231 (iroutine_t) interrupt_exception);
[a35b458]232
[7a8c866a]233#ifdef CONFIG_FPU_LAZY
[b3b7e14a]234 exc_register(EXC_CpU, "cpunus", true,
235 (iroutine_t) cpuns_exception);
[7a8c866a]236#endif
[a35b458]237
[b3b7e14a]238 exc_register(EXC_Sys, "syscall", true,
239 (iroutine_t) syscall_exception);
[7a8c866a]240}
[b45c443]241
[3c5006a0]242/** @}
[b45c443]243 */
Note: See TracBrowser for help on using the repository browser.