20 #include "InterruptManager.h" 21 #include "pedigree/kernel/Log.h" 22 #include "pedigree/kernel/debugger/Debugger.h" 23 #include "pedigree/kernel/machine/Machine.h" 24 #include "pedigree/kernel/machine/types.h" 25 #include "pedigree/kernel/processor/Processor.h" 26 #include "pedigree/kernel/processor/TlbManager.h" 27 #include "pedigree/kernel/utilities/utility.h" 29 #define SYSCALL_INTERRUPT_NUMBER 8 30 #define BREAKPOINT_INTERRUPT_NUMBER 9 32 const char *g_ExceptionNames[32] = {
34 "TLB modification exception",
35 "TLB exception (load or instruction fetch)",
36 "TLB exception (store)",
37 "Address error exception (load or instruction fetch)",
38 "Address error exception (store)",
39 "Bus error exception (instruction fetch)",
40 "Bus error exception (data: load or store)",
42 "Breakpoint exception",
43 "Reserved instruction exception",
44 "Coprocessor unusable exception",
45 "Arithmetic overflow exception",
47 "LDCz/SDCz to uncached address",
48 "Virtual coherency exception",
49 "Machine check exception",
50 "Floating point exception",
56 "Watchpoint exception",
82 if (
UNLIKELY(interruptNumber >= 256))
84 if (
UNLIKELY(handler != 0 && m_Handler[interruptNumber] != 0))
86 if (
UNLIKELY(handler == 0 && m_Handler[interruptNumber] == 0))
89 m_Handler[interruptNumber] = handler;
93 bool MIPS32InterruptManager::registerExternalInterruptHandler(
99 if (
UNLIKELY(handler != 0 && m_ExternalHandler[interruptNumber] != 0))
101 if (
UNLIKELY(handler == 0 && m_ExternalHandler[interruptNumber] == 0))
104 m_ExternalHandler[interruptNumber] = handler;
114 if (
UNLIKELY(interruptNumber >= 256))
116 if (
UNLIKELY(handler != 0 && m_DbgHandler[interruptNumber] != 0))
118 if (
UNLIKELY(handler == 0 && m_DbgHandler[interruptNumber] == 0))
121 m_DbgHandler[interruptNumber] = handler;
140 if (
UNLIKELY(Service >= serviceEnd))
142 if (
UNLIKELY(handler != 0 && m_SyscallHandler[Service] != 0))
144 if (
UNLIKELY(handler == 0 && m_SyscallHandler[Service] == 0))
147 m_SyscallHandler[Service] = handler;
150 extern "C" void mips32_exception(
void);
159 0x3c1a0000 | (
reinterpret_cast<uint32_t
>(&mips32_exception) >> 16);
161 pCode[1] = 0x375a0000 |
162 (
reinterpret_cast<uint32_t
>(&mips32_exception) & 0x0000FFFF);
164 pCode[2] = 0x03400008;
166 pCode[3] = 0x00000000;
170 reinterpret_cast<void *>(KSEG1(0x80)), reinterpret_cast<void *>(pCode),
173 reinterpret_cast<void *>(KSEG1(0x100)), reinterpret_cast<void *>(pCode),
176 reinterpret_cast<void *>(KSEG1(0x180)), reinterpret_cast<void *>(pCode),
179 reinterpret_cast<void *>(KSEG1(0x200)), reinterpret_cast<void *>(pCode),
185 pCode[0] = 0x3c1a0000 |
186 (
reinterpret_cast<uint32_t
>(&TlbManager::interruptAsm) >> 16);
190 (
reinterpret_cast<uint32_t
>(&TlbManager::interruptAsm) & 0x0000FFFF);
192 pCode[2] = 0x03400008;
194 pCode[3] = 0x00000000;
197 reinterpret_cast<void *>(KSEG1(0x0)), reinterpret_cast<void *>(pCode),
202 for (uintptr_t i = KSEG0(0); i < KSEG0(0x200); i += 0x80)
203 Processor::invalidateICache(i);
209 uintptr_t sr = interruptState.m_Sr;
213 asm volatile(
"mtc0 %0, $12" ::
"r"(sr));
217 asm volatile(
"mtc0 %0, $13" :
"=r"(cause));
220 cause &= interruptState.m_Sr;
223 cause = (cause >> 8) & 0xFF;
226 uint32_t externalInt = 0xFF;
227 for (
int i = 0; i < 8; i++)
229 if (cause & (1 << i))
237 size_t intNumber = interruptState.getInterruptNumber();
241 if (m_Instance.m_DbgHandler[intNumber] != 0)
242 m_Instance.m_DbgHandler[intNumber]->interrupt(
243 intNumber, interruptState);
247 if (intNumber == SYSCALL_INTERRUPT_NUMBER)
249 size_t serviceNumber = interruptState.getSyscallService();
251 serviceNumber < serviceEnd &&
252 m_Instance.m_SyscallHandler[serviceNumber] != 0))
253 m_Instance.m_SyscallHandler[serviceNumber]->syscall(interruptState);
256 else if (intNumber == 0 && m_Instance.m_ExternalHandler[externalInt])
257 m_Instance.m_ExternalHandler[externalInt]->interrupt(
258 externalInt, interruptState);
260 else if (m_Instance.m_Handler[intNumber] != 0)
261 m_Instance.m_Handler[intNumber]->interrupt(intNumber, interruptState);
267 e.append(
"Exception #");
268 e.append(intNumber, 10);
270 e.append(g_ExceptionNames[intNumber]);
277 if (intNumber == 9 || intNumber == 13)
280 if (!interruptState.branchDelay())
282 interruptState.m_Epc += 4;
290 for (
size_t i = 0; i < 64; i++)
294 m_ExternalHandler[i] = 0;
301 for (
size_t i = 0; i < serviceEnd; i++)
302 m_SyscallHandler[i] = 0;
static MIPS32InterruptManager & instance()
static void initialiseProcessor()
static EXPORTED_PUBLIC SyscallManager & instance()
static Debugger & instance()
Handles interrupts and interrupt registrations from kernel components.
virtual size_t getDebugInterruptNumber() PURE
static MIPS32InterruptManager m_Instance
static void interrupt(InterruptState &interruptState)
void start(InterruptState &state, LargeStaticString &description)
virtual bool registerInterruptHandler(size_t interruptNumber, InterruptHandler *handler)
virtual bool registerInterruptHandlerDebugger(size_t interruptNumber, InterruptHandler *handler)
virtual size_t getBreakpointInterruptNumber() PURE
virtual ~MIPS32InterruptManager()
Abstract base class for interrupt-handlers.
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *handler)
static InterruptManager & instance()