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
2 changes: 0 additions & 2 deletions .cargo/config.toml

This file was deleted.

188 changes: 88 additions & 100 deletions arch/x86_64/interrupts/Interrupts.c
Original file line number Diff line number Diff line change
@@ -1,110 +1,98 @@
#include "Interrupts.h"
#include "Console.h"
#include "Io.h"
#include "Kernel.h"
#include "Keyboard.h"
#include "Panic.h"
#include "Process.h"
#include "VMem.h"
#include "stdint.h"

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

static uint64_t tick_count = 0;

// Fast tick display using direct memory write
static void FastDisplayTicks(uint64_t ticks) {
uint16_t *vidptr = (uint16_t*)(0xb8000 + KERNEL_VIRTUAL_OFFSET);
int pos = 20 * 80; // Line 20

// Write "Ticks: "
vidptr[pos++] = (0x03 << 8) | 'T';
vidptr[pos++] = (0x03 << 8) | 'i';
vidptr[pos++] = (0x03 << 8) | 'c';
vidptr[pos++] = (0x03 << 8) | 'k';
vidptr[pos++] = (0x03 << 8) | 's';
vidptr[pos++] = (0x03 << 8) | ':';
vidptr[pos++] = (0x03 << 8) | ' ';

// Fast number display
if (ticks == 0) {
vidptr[pos] = (0x03 << 8) | '0';
return;
}

char buf[20];
int i = 0;
uint64_t temp = ticks;

while (temp > 0) {
buf[i++] = '0' + (temp % 10);
temp /= 10;
}

while (i > 0) {
vidptr[pos++] = (0x03 << 8) | buf[--i];
}
}


static void FatalExceptionHandler(const char* message, uint64_t interrupt_number) {
PrintKernelWarning(message);
PrintKernelWarning(" at interrupt: ");
PrintKernelInt(interrupt_number);
PrintKernelWarning("\n");
PANIC(message);
}


// The C-level interrupt handler
void InterruptHandler(struct Registers* regs) {
// The C-level interrupt handler, called from the assembly stub
void InterruptHandler(Registers* regs) {
ASSERT(regs != NULL);
if (regs->interrupt_number == 32 || regs->interrupt_number == 33) { // Force ignore keyboard interrupt
tick_count++;
// FastDisplayTicks(tick_count);
FastSchedule(regs);
outb(0x20, 0x20); // EOI to master PIC
return;
}

uint64_t cr2;
asm volatile("mov %%cr2, %0" : "=r"(cr2));

PrintKernelError("PAGE FAULT\n");
PrintKernelError(" Address: ");
PrintKernelHex(cr2);
PrintKernelError("\n Error Code: ");
PrintKernelHex(regs->error_code);
PrintKernelError("\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");
// Handle hardware interrupts first
switch (regs->interrupt_number) {
case 32: // Timer interrupt
FastSchedule(regs);
outb(0x20, 0x20); // EOI to master PIC
return;

case 33: // Keyboard interrupt
KeyboardHandler();
outb(0x20, 0x20); // EOI to master PIC
return;

// Handle other hardware interrupts (34-47)
case 34 ... 47:
PrintKernelWarning("[IRQ] Unhandled hardware interrupt: ");
PrintKernelInt(regs->interrupt_number - 32);
PrintKernelWarning("\n");

// Send EOI to the appropriate PIC
if (regs->interrupt_number >= 40) {
outb(0xA0, 0x20); // EOI to slave PIC
}
outb(0x20, 0x20); // EOI to master PIC
return;
}

if (regs->error_code & 0x4) {
PrintKernelError(" Mode: User\n");
}
else {
PrintKernelError(" Mode: Supervisor\n");
// Handle CPU exceptions (0-31)
PrintKernelError("\n!! CPU EXCEPTION !!\n");

switch (regs->interrupt_number) {
case 6: // Invalid Opcode
PrintKernelError(" TYPE: Invalid Opcode (UD)\n");
PrintKernelError(" RIP: ");
PrintKernelHex(regs->rip);
PrintKernelError("\n");
PANIC("Invalid Opcode");
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);
PrintKernelError(" (often segment related)\n");
PANIC_CODE("General Protection Fault", regs->error_code);
break;

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

PrintKernelError(" TYPE: Page Fault (PF)\n");
PrintKernelError(" Faulting Address: ");
PrintKernelHex(cr2);
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);
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");
break;
}

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);
}

// The C-level interrupt handler
}
4 changes: 4 additions & 0 deletions arch/x86_64/interrupts/Interrupts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#ifndef INTERRUPTS_H
#define INTERRUPTS_H

#endif // INTERRUPTS_H
Comment on lines +1 to +4
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding interrupt-related declarations.

This header appears to be a placeholder with only include guards. Given the significant interrupt handling refactoring mentioned in the AI summary, consider adding appropriate function declarations, constants, or type definitions that should be exposed from the interrupt subsystem.

For example, if KeyboardHandler or other interrupt handlers are called from external code, their declarations should be present here:

 #ifndef INTERRUPTS_H
 #define INTERRUPTS_H
 
+// Function declarations for interrupt handlers
+void KeyboardHandler(void);
+void TimerHandler(void);
+// Add other interrupt-related declarations as needed
+
 #endif // INTERRUPTS_H
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#ifndef INTERRUPTS_H
#define INTERRUPTS_H
#endif // INTERRUPTS_H
#ifndef INTERRUPTS_H
#define INTERRUPTS_H
// Function declarations for interrupt handlers
void KeyboardHandler(void);
void TimerHandler(void);
// Add other interrupt-related declarations as needed
#endif // INTERRUPTS_H
🤖 Prompt for AI Agents
In arch/x86_64/interrupts/Interrupts.h at lines 1 to 4, the file currently only
contains include guards and lacks any interrupt-related declarations. Add
function declarations, constants, or type definitions relevant to the interrupt
subsystem that need to be accessed externally, such as declarations for
KeyboardHandler or other interrupt handlers used outside this module. This will
ensure proper interface exposure for the interrupt handling functionality.

3 changes: 1 addition & 2 deletions arch/x86_64/syscall/Syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
#include "Gdt.h"
#include "Idt.h"
#include "Ipc.h"
#include "Kernel.h"
#include "MemOps.h" // For FastMemcpy
#include "MemOps.h"
#include "Panic.h"
#include "Process.h"
#define likely(x) __builtin_expect(!!(x), 1)
Expand Down
54 changes: 54 additions & 0 deletions drivers/Keyboard.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "Keyboard.h"
#include "Io.h"
#include "Console.h"

#define KEYBOARD_DATA_PORT 0x60
#define KEYBOARD_STATUS_PORT 0x64

static volatile char input_buffer[256];
static volatile int buffer_head = 0;
static volatile int buffer_tail = 0;
static volatile int buffer_count = 0;

static char scancode_to_ascii[] = {
0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0,
'*', 0, ' '
};
Comment on lines +13 to +19
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Incomplete keyboard mapping

The scancode mapping table only covers a subset of keys and doesn't handle modifier keys (Shift, Ctrl, Alt) or different keyboard states (Caps Lock, Num Lock). This limits the keyboard functionality significantly.

Consider implementing a more complete keyboard driver with state tracking:

  • Add support for shift states to handle uppercase/special characters
  • Track Caps Lock, Num Lock, and Scroll Lock states
  • Handle extended scancodes (0xE0 prefix) for arrow keys, Page Up/Down, etc.
  • Support function keys (F1-F12)
🤖 Prompt for AI Agents
In drivers/Keyboard.c around lines 13 to 19, the scancode_to_ascii array only
maps a limited set of keys and does not account for modifier keys or keyboard
states. To fix this, expand the scancode mapping to include all standard keys
including function keys, arrow keys, and extended scancodes with 0xE0 prefix.
Implement state tracking variables for Shift, Ctrl, Alt, Caps Lock, Num Lock,
and Scroll Lock to modify the output characters accordingly. Update the keyboard
input handling logic to use these states and produce correct ASCII output for
uppercase letters and special characters.


void KeyboardInit(void) {
buffer_head = buffer_tail = buffer_count = 0;
}

void KeyboardHandler(void) {
// Check if data is available
uint8_t status = inb(KEYBOARD_STATUS_PORT);
if (!(status & 0x01)) return; // No data available

uint8_t scancode = inb(KEYBOARD_DATA_PORT);

if (scancode & 0x80) return; // Key release
if (scancode >= sizeof(scancode_to_ascii)) return; // Invalid scancode

char c = scancode_to_ascii[scancode];
if (c && buffer_count < 256) {
input_buffer[buffer_tail] = c;
buffer_tail = (buffer_tail + 1) % 256;
buffer_count++;
}
}

char GetChar(void) {
if (buffer_count == 0) return 0;

char c = input_buffer[buffer_head];
buffer_head = (buffer_head + 1) % 256;
buffer_count--;
return c;
}

int HasInput(void) {
return buffer_count > 0;
}
11 changes: 11 additions & 0 deletions drivers/Keyboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H

#include "stdint.h"

void KeyboardInit(void);
void KeyboardHandler(void);
char GetChar(void);
int HasInput(void);

#endif
Loading