13using namespace MaxOS::common;
14using namespace MaxOS::hardwarecommunication;
15using namespace MaxOS::system;
25: m_interrupt_number(interrupt_number)
30 ASSERT(interrupt_manager !=
nullptr,
"No active interrupt manager");
42 .
type = (uint8_t) redirect,
43 .index = (uint8_t) redirect_index,
59 if (interrupt_manager ==
nullptr)
return;
110 return "Unimplemented message for exception\n";
127 if (can_avoid !=
nullptr)
143 return StringBuilder() <<
"Division by 0 executed at 0x" << status->rip <<
"\n";
153 return StringBuilder() <<
"Invaild opcode executed at 0x" << status->rip <<
"\n";
165 uint64_t core_id = core ? core->id : 0;
167 uint64_t error_code = status->error_code;
168 return StringBuilder() <<
"General Protection Fault: (0x" << status->rip <<
"): " << (error_code & 0x1 ?
"Protection-Exception" :
"Not a Protection Exception") <<
" cid: " << core_id <<
"\n";
179 bool present = (status->error_code & 0x1) != 0;
180 bool write = (status->error_code & 0x2) != 0;
181 bool user_mode = (status->error_code & 0x4) != 0;
182 bool reserved_write = (status->error_code & 0x8) != 0;
183 bool instruction_fetch = (status->error_code & 0x10) != 0;
184 uint64_t faulting_address;
185 asm volatile(
"movq %%cr2, %0" :
"=r" (faulting_address));
187 return StringBuilder() <<
"Page Fault: " << (user_mode ?
"user" :
"kernel") <<
" code at 0x" << status->rip <<
" tried to " << (write ?
"write" :
"read") <<
" address 0x" << faulting_address <<
" which is " << (present ?
"" :
"not") <<
" mapped and " << (reserved_write ?
"" :
"not") <<
" reserved. " <<
" (instruction fetch: " << (instruction_fetch ?
"Yes" :
"No") <<
")\n";
212 descriptor.address_low_bits = 0;
213 descriptor.address_mid_bits = 0;
214 descriptor.address_high_bits = 0;
215 descriptor.segment_selector = 0;
217 descriptor.flags = 0;
286 auto handler_address = (uint64_t) handler;
298 interrupt_descriptor->
ist = 0;
301 interrupt_descriptor->
flags = 0b1110 | (((uint8_t)descriptor_privilege_level & 0b11) << 5) | (1 << 7);
312 asm volatile(
"lidt %0" : :
"m" (idt));
392 ASSERT(
m_interrupt_handlers[status->interrupt_number] !=
nullptr,
"Interrupt 0x%x not handled\n", status->interrupt_number);
414ExceptionHandlers::ExceptionHandlers() =
default;
415ExceptionHandlers::~ExceptionHandlers() =
default;
static LogRecord INFO()
Gets the active logger for info logs.
Handles both the Local APIC (boot core) and IO APIC.
IOAPIC * io_apic() const
Get the io apic.
string get_message(system::cpu_status_t *status) final
Get an human readable error message explaining this exception.
ExceptionHandler(uint8_t interrupt_number)
Create a new base exception handler for an interrupt.
virtual string get_message(system::cpu_status_t *status)
Get an human readable error message explaining this exception.
string get_message(system::cpu_status_t *status) final
Get an human readable error message explaining this exception.
Handles the IO APIC in the system (one per system)
void set_redirect(interrupt_redirect_t *redirect)
Redirect a system interrupt to a different IRQ.
Handles a certain interrupt number.
virtual ~InterruptHandler()
Destroys the interrupt handler and unregisters it from the interrupt manager.
InterruptHandler(uint8_t interrupt_number, int64_t redirect=-1, uint64_t redirect_index=0)
Creates a new interrupt handler and registers it with the interrupt manager.
uint8_t m_interrupt_number
The interrupt number this handler handles.
virtual void handle_interrupt()
Handles an interrupt.
Handles all interrupts and passes them to the correct handler.
static InterruptManager * s_active_interrupt_manager
The interrupt manger that is currently handling interrupts and is loaded into the IDTR.
static void HandleException0x15()
Stub (see interrupts.s)
static void HandleInterruptError0x0A()
Stub (see interrupts.s)
static void deactivate()
Deactivates the interrupt manager and stops interrupts.
static void HandleException0x14()
Stub (see interrupts.s)
system::cpu_status_t * handle_interrupt_request(system::cpu_status_t *status)
Handles the interrupt request by passing it to the appropriate handler.
static void HandleException0x00()
Stub (see interrupts.s)
static void HandleInterruptRequest0x0C()
Stub (see interrupts.s)
static void HandleException0x07()
Stub (see interrupts.s)
static void HandleInterruptError0x0D()
Stub (see interrupts.s)
static InterruptManager * active_interrupt_manager()
Gets the active interrupt manager.
static void HandleInterruptError0x08()
Stub (see interrupts.s)
static void HandleException0x13()
Stub (see interrupts.s)
static void HandleInterruptError0x0C()
Stub (see interrupts.s)
static void HandleException0x04()
Stub (see interrupts.s)
static void HandleException0x02()
Stub (see interrupts.s)
static void HandleException0x17()
Stub (see interrupts.s)
static void HandleException0x10()
Stub (see interrupts.s)
static void HandleInterruptRequest0x01()
Stub (see interrupts.s)
void set_apic(AdvancedProgrammableInterruptController *apic)
Sets the APIC.
static void HandleInterruptError0x11()
Stub (see interrupts.s)
static void set_interrupt_descriptor_table_entry(uint8_t interrupt, void(*handler)(), InterruptPrivilegeLevel descriptor_privilege_level)
Sets an entry in the Interrupt Descriptor Table.
static void HandleException0x1E()
Stub (see interrupts.s)
static void HandleInterruptRequest0x60()
Stub (see interrupts.s)
static void HandleException0x1F()
Stub (see interrupts.s)
void remove_interrupt_handler(uint8_t interrupt)
Removes the interrupt handler for the interrupt.
static void load_current()
Tell the processor to use the current InterruptManager.
static void HandleException0x05()
Stub (see interrupts.s)
static void HandleInterruptError0x0B()
Stub (see interrupts.s)
static void HandleException0x19()
Stub (see interrupts.s)
~InterruptManager()
Destroys the Interrupt Manager and deactivates interrupts.
static void HandleException0x1A()
Stub (see interrupts.s)
static void HandleException0x01()
Stub (see interrupts.s)
static void HandleException0x18()
Stub (see interrupts.s)
static void HandleException0x1B()
Stub (see interrupts.s)
InterruptManager()
Constructs the Interrupt Manager and sets up the interrupt descriptor table (does not activate interr...
void activate()
Activates the interrupt manager and starts interrupts (also deactivates the current interrupt manager...
void set_interrupt_handler(uint8_t interrupt, InterruptHandler *handler)
Sets the interrupt handler for the interrupt.
static InterruptDescriptor s_interrupt_descriptor_table[MAX_INTERRUPT_HANDLERS]
The Interrupt Descriptor Table (IDT)
static void HandleException0x12()
Stub (see interrupts.s)
static void HandleInterruptRequest0x00()
Stub (see interrupts.s)
static void HandleException0x09()
Stub (see interrupts.s)
static void HandleException0x16()
Stub (see interrupts.s)
static void HandleInterruptError0x0E()
Stub (see interrupts.s)
static void HandleInterruptRequest0x61()
Stub (see interrupts.s)
static system::cpu_status_t * HandleInterrupt(system::cpu_status_t *status)
Handles the interrupt request by passing it to the interrupt manager.
static void HandleException0x06()
Stub (see interrupts.s)
static void HandleException0x03()
Stub (see interrupts.s)
static void HandleException0x0F()
Stub (see interrupts.s)
static void HandleInterruptRequest0x04()
Stub (see interrupts.s)
static void HandleException0x1C()
Stub (see interrupts.s)
static void HandleInterruptRequest0x02()
Stub (see interrupts.s)
AdvancedProgrammableInterruptController * active_apic()
Gets the APIC.
static void HandleException0x1D()
Stub (see interrupts.s)
InterruptHandler * m_interrupt_handlers[MAX_INTERRUPT_HANDLERS]
A map of index-to-interrupt of interrupt handlers to fire when an interrupt occurs.
string get_message(system::cpu_status_t *status) final
Get an human readable error message explaining this exception.
void send_eoi() const
Acknowledge that the interrupt has been handled, allowing the PIC to process the next interrupt.
string get_message(system::cpu_status_t *status) final
Get an human readable error message explaining this exception.
static void PANIC(const char *message, cpu_status_t *status=nullptr)
Puts the CPU into a panic state and halts it. Dumps the stack trace and registers.
static void halt()
Halts the CPU indefinitely.
static cpu_status_t * prepare_for_panic(cpu_status_t *status=nullptr, const string &msg="")
Ensure the CPU must panic and prepare for it if so.
static Core * executing_core()
Gets the core that is currently executing.
hardwarecommunication::LocalAPIC * local_apic
The local APIC for this core.
struct PACKED MaxOS::system::CPUStatus cpu_status_t
Alias for CPUStatus struct.
Defines a InterruptManager and InterruptHandler for managing hardware and software interrupts.
constexpr uint16_t HARDWARE_INTERRUPT_OFFSET
The offset in the IDT where interrupts from hardware start.
InterruptPrivilegeLevel
Represents the CPU ring level that a interrupt is handler is executed in.
Defines a Logger class for logging messages with different severity levels to multiple output streams...
A struct that holds the Interrupt Descriptor Table Register (IDTR)
uint16_t limit
The size of the IDT.
uint64_t base
The start address of the IDT.
An entry in the Interrupt Descriptor Table (IDT)
uint16_t segment_selector
The code segment selector in the GDT to use when this interrupt fires.
uint32_t address_high_bits
The high bits of the handler function address.
uint8_t ist
The offset into the Interrupt Stack Table (0 if not used) (see TSS)
uint16_t address_mid_bits
The middle bits of the handler function address.
uint16_t address_low_bits
The low bits of the handler function address.
uint8_t flags
Flags: The type of gate this entry represents (0xE for interrupt gate, 0xF for trap gate),...
Defines how an interrupt input is redirected to a specific processor via the I/O APIC.
uint8_t type
The type of redirect (should be 0 for normal interrupts)