blob: f2b10359f6682a5c57ea66cd55ce5f9169b66a4a [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <trace.h>
24#include <debug.h>
25#include <assert.h>
26#include <stdint.h>
27#include <bits.h>
28#include <kernel/thread.h>
29#include <kernel/debug.h>
30#include <arch/mips.h>
31
32#define LOCAL_TRACE 0
33
34extern enum handler_return platform_irq(struct mips_iframe *iframe, uint num);
35
36void mips_gen_exception(struct mips_iframe *iframe)
37{
38 uint32_t excode = BITS_SHIFT(iframe->cause, 6, 2);
39 if (excode == 0x8) {
40 LTRACEF("SYSCALL, EPC 0x%x\n", iframe->epc);
41 iframe->epc += 4;
42 } else {
43 LTRACEF("status 0x%x\n", iframe->status);
44 LTRACEF("cause 0x%x\n", iframe->cause);
45 LTRACEF("\texcode 0x%x\n", excode);
46 LTRACEF("epc 0x%x\n", iframe->epc);
47 for (;;);
48 }
49}
50
51void mips_irq(struct mips_iframe *iframe, uint num)
52{
53 // unset IE and clear EXL
54 mips_write_c0_status(mips_read_c0_status() & ~(3<<0));
55
56 THREAD_STATS_INC(interrupts);
57 KEVLOG_IRQ_ENTER(num);
58
59 LTRACEF("IRQ %u, EPC 0x%x, old status 0x%x, status 0x%x\n",
60 num, iframe->epc, iframe->status, mips_read_c0_status());
61
62 enum handler_return ret = INT_NO_RESCHEDULE;
63
64 // figure out which interrupt the timer is set to
65 uint32_t ipti = BITS_SHIFT(mips_read_c0_intctl(), 31, 29);
66 if (ipti >= 2 && ipti == num) {
67 // builtin timer
68 ret = mips_timer_irq();
69#if PLATFORM_QEMU_MIPS
70 } else if (num == 2) {
71 ret = platform_irq(iframe, num);
72#endif
73 } else {
74 panic("mips: unhandled irq\n");
75 }
76
77 KEVLOG_IRQ_EXIT(num);
78
79 if (ret != INT_NO_RESCHEDULE)
80 thread_preempt();
81}
82