Updated ISR code to properly handle interrupts with error codes. Fixed bug where page faults would clobber the kernel stack

This commit is contained in:
Xnoe 2022-01-09 12:10:57 +00:00
parent 2825c1ff5e
commit fc2c73225b
Signed by: xnoe
GPG Key ID: 45AC398F44F0DAFE
6 changed files with 31 additions and 25 deletions

View File

@ -4,13 +4,14 @@ test -f isr.S && rm isr.S
cp isr.S.base isr.S
for i ({0..255}); do
cat >> isr.S << EOF
isr$i:
push ebp
mov ebp, esp
push $i
jmp catchall
EOF
echo "isr$i:" >> isr.S
echo " push ebp" >> isr.S
echo " mov ebp, esp" >> isr.S
if (( !(i == 8 || i == 17 || (i >= 10 && i <= 14) ) )); then
echo " push 0" >> isr.S
fi
echo " push $i" >> isr.S
echo " jmp catchall" >> isr.S
done
x=""

View File

@ -21,37 +21,36 @@ void set_entry(uint8_t interrupt_number, uint16_t code_segment, void(*handler)()
};
}
void page_fault(frame_struct* frame, uint32_t err_code) {
void page_fault(frame_struct* frame) {
// Clear interrupts, we don't want to perform a context switch during a page fault.
asm ("cli");
uint32_t problem_address;
asm("mov %%cr2, %0" : "=a" (problem_address) :);
Global::kernel->terminal->printf("(EIP %x): Page Fault at %x\n", frame->eip, problem_address);
if (frame->cs & 3 == 0) {
Global::kernel->terminal->printf("(CS %x EIP %x): Page Fault at %x Error Code: %x Gate: %d\n", frame->cs, frame->eip, problem_address, frame->errcode, frame->gate);
if (!(frame->cs & 3)) {
Global::kernel->terminal->printf("[FATAL] Kernel Page Fault!!!\n");
while (1) asm("hlt");
} else {
// Print an error message.
Global::kernel->terminal->printf("PID %d Terminated due to page fault!\n", Global::currentProc->PID);
// We are currently in the kernel stack for the current process so we need to load the main kernel stack in to esp.
//Global::kernel->loadPrimaryStack();
asm volatile ("mov %0, %%esp" ::"m"(Global::kernel->stack));
asm volatile ("mov %0, %%esp" ::"m"(Global::kernel->globalISRStack));
Global::kernel->PD->select();
// We can now safely delete the current process
Global::kernel->destroyProcess(Global::currentProc);
// We want to load the kernel's page directory too.
//Global::kernel->PD->select();
Global::currentProcValid = false;
//Global::currentProcValid = false;
asm ("int $0x20"); // Call context switch.
while (1) asm("hlt");
// Go in to an infinite loop
asm ("sti");
while (1) asm ("hlt");
}
}
void ignore_interrupt(frame_struct* frame) {}
void gpf(frame_struct* frame, uint32_t err_code) {
printf("General Protection Fault %x\n", err_code);
void gpf(frame_struct* frame) {
printf("(EIP %x) General Protection Fault %x\n", frame->eip, frame->errcode);
while (1) asm("hlt");
}

View File

@ -16,6 +16,11 @@ struct __attribute__((packed)) frame_struct {
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t gate;
uint32_t __ignored2;
uint32_t errcode;
uint32_t eip;
uint16_t cs;
uint16_t _ignored0;

View File

@ -16,6 +16,7 @@ Kernel::Kernel(PageDirectory* page_directory, PageMap* phys, PageMap* virt, uint
void Kernel::init_kernel() {
this->pid_map = new xnoe::hashtable<uint32_t, Process*>();
this->globalISRStack = (new uint8_t[0x8000]) + 0x8000;
}
Process* Kernel::createProcess(char* filename) {

View File

@ -10,6 +10,7 @@ class Kernel : public Process {
public:
uint32_t currentPID;
uint32_t stack;
uint32_t globalISRStack;
Terminal* terminal;
xnoe::hashtable<uint32_t, Process*>* pid_map; // Map of PIDs -> Process*s

View File

@ -186,4 +186,3 @@ uint32_t Process::count_allocations(uint32_t address) {
else
return 0;
}