Handout
This commit is contained in:
134
kernel/interrupt/handlers.cc
Normal file
134
kernel/interrupt/handlers.cc
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "./handlers.h"
|
||||
|
||||
#include "../arch/core_cr.h"
|
||||
#include "../arch/idt.h"
|
||||
#include "../arch/lapic.h"
|
||||
#include "../arch/system.h"
|
||||
#include "../debug/kernelpanic.h"
|
||||
#include "../debug/output.h"
|
||||
#include "../device/ps2controller.h"
|
||||
#include "./epilogues.h"
|
||||
#include "./guard.h"
|
||||
|
||||
static void printContext(const InterruptContext *context) {
|
||||
DBG << "ip: " << hex << context->cs << ':' << context->ip
|
||||
<< " sp: " << context->ss << ':' << context->sp << " flags" << bin
|
||||
<< context->flags << endl;
|
||||
}
|
||||
|
||||
[[gnu::interrupt]] static void handle_invalid_opcode(
|
||||
InterruptContext *context) {
|
||||
DBG << "Invalid opcode encountered" << endl;
|
||||
printContext(context);
|
||||
kernelpanic("Invalid opcode!");
|
||||
}
|
||||
|
||||
[[gnu::interrupt]] static void handle_double_fault(InterruptContext *context,
|
||||
uint64_t error) {
|
||||
DBG << "Double fault encountered. Error code: " << dec << error << endl;
|
||||
printContext(context);
|
||||
kernelpanic("Double fault!");
|
||||
}
|
||||
|
||||
[[gnu::interrupt]] static void handle_invalid_tss(InterruptContext *context,
|
||||
uint64_t error) {
|
||||
DBG << "Invalid tss encountered. Offending selector idx: " << dec << error
|
||||
<< endl;
|
||||
printContext(context);
|
||||
kernelpanic("Invalid TSS!");
|
||||
}
|
||||
|
||||
[[gnu::interrupt]] static void handle_general_protection_fault(
|
||||
InterruptContext *context, uint64_t error) {
|
||||
DBG << "General protection fault encountered. Error code: " << dec << error
|
||||
<< endl;
|
||||
printContext(context);
|
||||
kernelpanic("General protection fault!");
|
||||
}
|
||||
|
||||
[[gnu::interrupt]] static void handle_page_fault(InterruptContext *context,
|
||||
uint64_t error) {
|
||||
DBG << "Page fault encountered at linear address " << hex
|
||||
<< Core::CR<2>::read() << endl
|
||||
<< PageFaultError(error) << endl;
|
||||
printContext(context);
|
||||
kernelpanic("Page fault!");
|
||||
}
|
||||
|
||||
/*! \brief Assembly interrupt handler for the keyboard.
|
||||
*
|
||||
* On keyboard interrupt, the register state is saved to and restored from the
|
||||
* stack. This function wraps the handle_keyboard C-function.
|
||||
*
|
||||
*/
|
||||
extern "C" [[gnu::interrupt]] void handle_keyboard_asm(
|
||||
InterruptContext *context);
|
||||
|
||||
/*! \brief Higher-level Interrupt handler for the keyboard.
|
||||
*
|
||||
* On keyboard interrupt, the PS2-Controller may contain a valid Key that has to
|
||||
* be fetched.
|
||||
*
|
||||
*/
|
||||
extern "C" void handle_keyboard() {
|
||||
// DBG_VERBOSE << "Keyboard interrupt" << endl;
|
||||
Key key;
|
||||
if (PS2Controller::fetch(key)) {
|
||||
// Ctrl-Alt-Delete should perform a reboot. This should still be done in
|
||||
// prologue, to ensure that rebooting still works reliably in case of
|
||||
// broken epilogues.
|
||||
if (key.ctrl() && key.alt() && key.scancode == Key::Scancode::KEY_DEL) {
|
||||
System::reboot();
|
||||
}
|
||||
|
||||
// Check if the last key was processed by the epilogue
|
||||
if (!Epilogues::key.valid()) {
|
||||
// Make sure we can receive new interrupts
|
||||
LAPIC::endOfInterrupt();
|
||||
// Enqueue new epilogue
|
||||
Epilogues::key = key;
|
||||
Guard::relay(Epilogues::keyboard);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LAPIC::endOfInterrupt();
|
||||
}
|
||||
|
||||
[[maybe_unused, gnu::interrupt]] static void handle_panic(
|
||||
InterruptContext *context) {
|
||||
(void)context;
|
||||
kernelpanic("Panic interrupt triggered!");
|
||||
}
|
||||
|
||||
[[maybe_unused, gnu::interrupt]] static void handle_timer(
|
||||
InterruptContext *context) {
|
||||
// DBG_VERBOSE << "Timer interrupt" << endl;
|
||||
(void)context;
|
||||
LAPIC::endOfInterrupt();
|
||||
Guard::relay(Epilogues::timer);
|
||||
}
|
||||
|
||||
void initInterruptHandlers() {
|
||||
// Some handlers that are useful for debugging
|
||||
IDT::set(Core::Interrupt::Vector::INVALID_OPCODE,
|
||||
IDT::InterruptDescriptor::Returning(handle_invalid_opcode));
|
||||
IDT::set(Core::Interrupt::Vector::DOUBLE_FAULT,
|
||||
IDT::InterruptDescriptor::DivergingWithError(handle_double_fault));
|
||||
IDT::set(Core::Interrupt::Vector::INVALID_TSS,
|
||||
IDT::InterruptDescriptor::ReturningWithError(handle_invalid_tss));
|
||||
IDT::set(Core::Interrupt::Vector::GENERAL_PROTECTION_FAULT,
|
||||
IDT::InterruptDescriptor::ReturningWithError(
|
||||
handle_general_protection_fault));
|
||||
IDT::set(Core::Interrupt::Vector::PAGE_FAULT,
|
||||
IDT::InterruptDescriptor::ReturningWithError(handle_page_fault));
|
||||
|
||||
// TODO: Add more handlers here
|
||||
IDT::set(Core::Interrupt::Vector::KEYBOARD,
|
||||
IDT::InterruptDescriptor::Returning(handle_keyboard_asm));
|
||||
IDT::set(Core::Interrupt::Vector::PANIC,
|
||||
IDT::InterruptDescriptor::Returning(handle_panic));
|
||||
IDT::set(Core::Interrupt::Vector::TIMER,
|
||||
IDT::InterruptDescriptor::Returning(handle_timer));
|
||||
// Load the idt pointer
|
||||
IDT::load();
|
||||
}
|
||||
Reference in New Issue
Block a user