Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 42 additions & 55 deletions arch/x86_64/interrupts/Interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
#include "PS2.h"
#include "Panic.h"
#include "Process.h"
#include "Serial.h"
#include "MemOps.h"

// The C-level interrupt handler, called from the assembly stub
void InterruptHandler(Registers* regs) {
ASSERT(regs != NULL);
Expand Down Expand Up @@ -50,73 +51,59 @@ void InterruptHandler(Registers* regs) {

// Handle CPU exceptions (0-31)

// Buffer for creating descriptive panic messages.
// Made static to reside in .bss rather than on a potentially corrupt stack.
static char panic_message[256];

switch (regs->interrupt_number) {
case 6: // Invalid Opcode
PrintKernelError(" TYPE: Invalid Opcode (UD)\n");
PrintKernelError(" RIP: ");
PrintKernelHex(regs->rip);
PrintKernelError("\n");
PANIC("Invalid Opcode");
{
char rip_str[20];
htoa(regs->rip, rip_str);
strcpy(panic_message, "Invalid Opcode at ");
strcat(panic_message, rip_str);
PanicFromInterrupt(panic_message, regs);
break;
}

case 13: // General Protection Fault
PrintKernelError(" TYPE: General Protection Fault (GPF)\n");
PrintKernelError(" RIP: ");
PrintKernelHex(regs->rip);
PrintKernelError("\n Error Code: ");
PrintKernelHex(regs->error_code);
PANIC_CODE(" General Protection Fault\n", regs->error_code);
{
char ec_str[20];
htoa(regs->error_code, ec_str);
strcpy(panic_message, "General Protection Fault. Selector: ");
strcat(panic_message, ec_str);
PanicFromInterrupt(panic_message, regs);
break;
}

case 14: // Page Fault
{
uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));

// Serial logging for debugging
SerialWrite("\n[PAGEFAULT] CR2: 0x");
SerialWriteHex(cr2);
SerialWrite(" RIP: 0x");
SerialWriteHex(regs->rip);
SerialWrite(" RSP: 0x");
SerialWriteHex(regs->rsp);
SerialWrite(" Error: 0x");
SerialWriteHex(regs->error_code);
SerialWrite("\n");

PrintKernelError(" TYPE: Page Fault (PF)\n");
PrintKernelError(" Faulting Address: ");
PrintKernelHex(cr2);
PrintKernelError("\n RIP: ");
PrintKernelHex(regs->rip);
PrintKernelError("\n Error Code: ");
PrintKernelHex(regs->error_code);
PrintKernelError("\n Details:\n");

if (!(regs->error_code & 0x1)) PrintKernelError(" - Reason: Page Not Present\n");
else PrintKernelError(" - Reason: Protection Violation\n");

if (regs->error_code & 0x2) PrintKernelError(" - Operation: Write\n");
else PrintKernelError(" - Operation: Read\n");

if (regs->error_code & 0x4) PrintKernelError(" - Mode: User\n");
else PrintKernelError(" - Mode: Supervisor\n");

if (regs->error_code & 0x8) PrintKernelError(" - Cause: Reserved bit set\n");
if (regs->error_code & 0x10) PrintKernelError(" - Cause: Instruction Fetch\n");

PANIC_CODE("Page Fault", regs->error_code);
char cr2_str[20], rip_str[20];
htoa(cr2, cr2_str);
htoa(regs->rip, rip_str);

strcpy(panic_message, "Page Fault accessing ");
strcat(panic_message, cr2_str);
strcat(panic_message, " from instruction at ");
strcat(panic_message, rip_str);
PanicFromInterrupt(panic_message, regs);
break;
}

default: // All other exceptions
PrintKernelError(" TYPE: Unhandled Exception\n");
PrintKernelError(" Interrupt Number: ");
PrintKernelInt(regs->interrupt_number);
PrintKernelError("\n RIP: ");
PrintKernelHex(regs->rip);
PrintKernelError("\n Error Code: ");
PrintKernelHex(regs->error_code);
PrintKernelError("\n");
PANIC("Unhandled CPU Exception");
{
char int_str[20], rip_str[20];
itoa(regs->interrupt_number, int_str);
htoa(regs->rip, rip_str);

strcpy(panic_message, "Unhandled Exception #");
strcat(panic_message, int_str);
strcat(panic_message, " at ");
strcat(panic_message, rip_str);
PanicFromInterrupt(panic_message, regs);
break;
}
}
}
21 changes: 19 additions & 2 deletions drivers/VesaBIOSExtension.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern const uint32_t _binary_splash7_32_raw_start[];
extern const uint32_t _binary_splash8_32_raw_start[];
extern const uint32_t _binary_splash9_32_raw_start[];
extern const uint32_t _binary_splash10_32_raw_start[];
extern const uint32_t _binary_panic_32_raw_start[];

// Update your array of pointers
const uint32_t* splash_images[] = {
Expand All @@ -30,6 +31,12 @@ const uint32_t* splash_images[] = {
};

const unsigned int num_splash_images = sizeof(splash_images) / sizeof(uint32_t*);

const uint32_t* panic_images[] = {
_binary_panic_32_raw_start
};

const unsigned int num_panic_images = sizeof(panic_images) / sizeof(uint32_t*);
// Multiboot2 tag types
#define MULTIBOOT_TAG_FRAMEBUFFER 8
#define MULTIBOOT_TAG_VBE 7
Expand Down Expand Up @@ -323,12 +330,11 @@ void VBEDrawStringCentered(uint32_t center_x, uint32_t center_y, const char* str
VBEDrawString(start_x, start_y, str, fg_color, bg_color);
}


// Create a simple splash screen
void VBEShowSplash(void) {
if (!vbe_initialized) return;

for (unsigned int i = 0; i < num_splash_images * 10; i++) { // Loop
for (unsigned int i = 0; i < num_splash_images * 6; i++) { // Loop
const uint32_t* image_data = (const uint32_t*)splash_images[i % num_splash_images];

for (uint32_t y = 0; y < vbe_info.height; y++) {
Expand All @@ -340,6 +346,17 @@ void VBEShowSplash(void) {
}
}

void VBEShowPanic(void) {
if (!vbe_initialized) return;
const uint32_t* image_data = (const uint32_t*)panic_images[0];

for (uint32_t y = 0; y < vbe_info.height; y++) {
for (uint32_t x = 0; x < vbe_info.width; x++) {
VBEPutPixel(x, y, image_data[y * vbe_info.width + x]);
}
}
}

vbe_info_t* VBEGetInfo(void) {
return vbe_initialized ? &vbe_info : NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/VesaBIOSExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ void VBEDrawLine(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t co
void VBEDrawChar(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_color);
void VBEDrawString(uint32_t x, uint32_t y, const char* str, uint32_t fg_color, uint32_t bg_color);
void VBEShowSplash(void);
void VBEShowPanic(void);
void delay(uint32_t ms);
Comment on lines +45 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Clarify delay units & namespace the helper

delay(uint32_t ms) implies time in ms yet the implementation takes an iteration count. Either rename to VBEBusyWait(uint32_t loops) or scale the loop to approximate milliseconds and document the approximation.
This avoids misuse elsewhere in the kernel.

🤖 Prompt for AI Agents
In drivers/VesaBIOSExtension.h at lines 45-46, the function delay(uint32_t ms)
is misleading because it suggests a delay in milliseconds, but the
implementation uses an iteration count. Rename the function to
VBEBusyWait(uint32_t loops) to reflect its actual behavior or modify the
implementation to scale the loops to approximate milliseconds and add
documentation explaining the approximation. This change will prevent misuse and
clarify the function's purpose.

// Utility functions
vbe_info_t* VBEGetInfo(void);
int VBEIsInitialized(void);
Expand Down
8 changes: 3 additions & 5 deletions kernel/core/Kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ static void PrintBootstrapSummary(void) {
if (addr < (uint64_t)_kernel_phys_start ||
addr >= (uint64_t)_kernel_phys_end) {
pt_pages++;
}
}
}
}

Expand Down Expand Up @@ -531,13 +531,11 @@ void KernelMainHigherHalf(void) {
SystemInitS2();

PrintKernelSuccess("[SYSTEM] Kernel initialization complete\n");
PrintKernelSuccess("[SYSTEM] Initializing interrupts...\n\n");
PrintKernelSuccess("[SYSTEM] Initializing interrupts...\n");

asm volatile("sti");

while (1) {
if (ShouldSchedule()) {
RequestSchedule();
}
asm volatile("hlt");
}
}
Loading