The Pedigree Project  0.1
arm_926e/InterruptManager.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "InterruptManager.h"
21 #include "pedigree/kernel/machine/Machine.h"
22 #include "pedigree/kernel/machine/types.h"
23 #include "pedigree/kernel/panic.h"
24 #include "pedigree/kernel/processor/Processor.h"
25 #include "pedigree/kernel/utilities/utility.h"
26 #ifdef DEBUGGER
27 #include "pedigree/kernel/debugger/Debugger.h"
28 #endif
29 
30 #define SYSCALL_INTERRUPT_NUMBER 8
31 #define BREAKPOINT_INTERRUPT_NUMBER 9
32 
33 const char *g_ExceptionNames[32] = {
34  "Interrupt",
35  "TLB modification exception",
36  "TLB exception (load or instruction fetch)",
37  "TLB exception (store)",
38  "Address error exception (load or instruction fetch)",
39  "Address error exception (store)",
40  "Bus error exception (instruction fetch)",
41  "Bus error exception (data: load or store)",
42  "Syscall exception",
43  "Breakpoint exception",
44  "Reserved instruction exception",
45  "Coprocessor unusable exception",
46  "Arithmetic overflow exception",
47  "Trap exception",
48  "LDCz/SDCz to uncached address",
49  "Virtual coherency exception",
50  "Machine check exception",
51  "Floating point exception",
52  "Reserved",
53  "Reserved",
54  "Reserved",
55  "Reserved",
56  "Reserved",
57  "Watchpoint exception",
58  "Reserved",
59  "Reserved",
60  "Reserved",
61  "Reserved",
62  "Reserved",
63  "Reserved",
64  "Reserved",
65  "Reserved",
66 };
67 
69 
71 {
73 }
75 {
77 }
78 
80  size_t interruptNumber, InterruptHandler *handler)
81 {
82  // TODO: Needs locking
83  if (UNLIKELY(interruptNumber >= 256))
84  return false;
85  if (UNLIKELY(handler != 0 && m_Handler[interruptNumber] != 0))
86  return false;
87  if (UNLIKELY(handler == 0 && m_Handler[interruptNumber] == 0))
88  return false;
89 
90  m_Handler[interruptNumber] = handler;
91  return true;
92 }
93 
94 #ifdef DEBUGGER
95 
97  size_t interruptNumber, InterruptHandler *handler)
98 {
99  // TODO: Needs locking
100  if (UNLIKELY(interruptNumber >= 256))
101  return false;
102  if (UNLIKELY(handler != 0 && m_DbgHandler[interruptNumber] != 0))
103  return false;
104  if (UNLIKELY(handler == 0 && m_DbgHandler[interruptNumber] == 0))
105  return false;
106 
107  m_DbgHandler[interruptNumber] = handler;
108  return true;
109 }
111 {
112  return 3;
113 }
115 {
116  return 1;
117 }
118 
119 #endif
120 
122  Service_t Service, SyscallHandler *handler)
123 {
124  // TODO: Needs locking
125 
126  if (UNLIKELY(Service >= serviceEnd))
127  return false;
128  if (UNLIKELY(handler != 0 && m_SyscallHandler[Service] != 0))
129  return false;
130  if (UNLIKELY(handler == 0 && m_SyscallHandler[Service] == 0))
131  return false;
132 
133  m_SyscallHandler[Service] = handler;
134  return true;
135 }
136 
138  Service_t service, uintptr_t function, uintptr_t p1, uintptr_t p2,
139  uintptr_t p3, uintptr_t p4, uintptr_t p5)
140 {
142  return 0;
143 }
144 
145 // extern "C" void mips32_exception(void);
147 {
148  // TODO: implement
149 }
150 
151 void ARM926EInterruptManager::interrupt(InterruptState &interruptState)
152 {
153  // TODO: Needs locking
154  size_t intNumber = interruptState.getInterruptNumber();
155 
156 #ifdef DEBUGGER
157  // Call the kernel debugger's handler, if any
158  if (m_Instance.m_DbgHandler[intNumber] != 0)
159  m_Instance.m_DbgHandler[intNumber]->interrupt(
160  intNumber, interruptState);
161 #endif
162 
163  // Call the syscall handler, if it is the syscall interrupt
164  if (intNumber == SYSCALL_INTERRUPT_NUMBER)
165  {
166  size_t serviceNumber = interruptState.getSyscallService();
167  if (LIKELY(
168  serviceNumber < serviceEnd &&
169  m_Instance.m_SyscallHandler[serviceNumber] != 0))
170  m_Instance.m_SyscallHandler[serviceNumber]->syscall(interruptState);
171  }
172  // Call the normal interrupt handler, if any, otherwise
173  else if (m_Instance.m_Handler[intNumber] != 0)
174  m_Instance.m_Handler[intNumber]->interrupt(intNumber, interruptState);
175  else
176  {
177  // TODO:: Check for debugger initialisation.
178  static LargeStaticString e;
179  e.clear();
180  e.append("Exception #");
181  e.append(intNumber, 10);
182  e.append(": \"");
183  e.append(g_ExceptionNames[intNumber]);
184  e.append("\"");
185 #ifdef DEBUGGER
186  Debugger::instance().start(interruptState, e);
187 #else
188  panic(e);
189 #endif
190  }
191 
192  // If this was a trap or breakpoint instruction, we need to increase the
193  // program counter a bit.
194  // if (intNumber == 9 || intNumber == 13)
195  // {
196  // ...Unless we were in a branch delay slot!
197  /*if (!interruptState.branchDelay())
198  {
199  interruptState.m_Pc += 4;
200  }*/
201  // }
202 }
203 
205 {
206  // Initialise the pointers to the interrupt handler
207  for (size_t i = 0; i < 256; i++)
208  {
209  m_Handler[i] = 0;
210 #ifdef DEBUGGER
211  m_DbgHandler[i] = 0;
212 #endif
213  }
214 
215  // Initialise the pointers to the syscall handler
216  for (size_t i = 0; i < serviceEnd; i++)
217  m_SyscallHandler[i] = 0;
218 }
220 {
221 }
static EXPORTED_PUBLIC SyscallManager & instance()
static Debugger & instance()
Definition: Debugger.h:48
Handles interrupts and interrupt registrations from kernel components.
virtual bool registerSyscallHandler(Service_t Service, SyscallHandler *handler)
virtual size_t getDebugInterruptNumber() PURE
void start(InterruptState &state, LargeStaticString &description)
Definition: Debugger.cc:121
virtual size_t getBreakpointInterruptNumber() PURE
virtual bool registerInterruptHandlerDebugger(size_t interruptNumber, InterruptHandler *handler)
virtual uintptr_t syscall(Service_t service, uintptr_t function, uintptr_t p1=0, uintptr_t p2=0, uintptr_t p3=0, uintptr_t p4=0, uintptr_t p5=0)
virtual bool registerInterruptHandler(size_t interruptNumber, InterruptHandler *handler)
Abstract base class for interrupt-handlers.
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
static void interrupt(InterruptState &interruptState)
static InterruptManager & instance()