From 6d2e453d274c54b42dc2913429441ee279c9fc70 Mon Sep 17 00:00:00 2001 From: cowmonk Date: Thu, 16 Oct 2025 13:53:36 -0700 Subject: [PATCH] Added Memory Paging + Formating Fixes Memory paging was "fixed", there was previously a stub because I was working out some compilation issue. Turns out, I had extern keyword called to the structs. Stupidly, I forgot to declare the struct in the header the whole time. Luckily that worked itself out, and now vga memory is mapped. --- .gitignore | 1 + kernel/drivers/video/framebuffer.c | 525 +++++++++++++++-------------- kernel/drivers/video/vga.c | 138 ++++---- kernel/include/mm/paging.h | 11 + kernel/init/kernel.c | 2 + kernel/klibc/string.c | 2 +- kernel/mm/paging.c | 125 +++++++ kernel/mm/paging.stub | 119 ------- 8 files changed, 477 insertions(+), 446 deletions(-) create mode 100644 kernel/include/mm/paging.h create mode 100644 kernel/mm/paging.c delete mode 100644 kernel/mm/paging.stub diff --git a/.gitignore b/.gitignore index c925249..1377575 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ isodir/boot/limine/limine-bios-cd.bin isodir/boot/limine/limine-uefi-cd.bin isodir/EFI/BOOT/BOOTX64.EFI isodir/EFI/BOOT/BOOTIA32.EFI +compile_flags.txt diff --git a/kernel/drivers/video/framebuffer.c b/kernel/drivers/video/framebuffer.c index 2f64757..c96218e 100644 --- a/kernel/drivers/video/framebuffer.c +++ b/kernel/drivers/video/framebuffer.c @@ -7,279 +7,290 @@ static fb_console_t console; -void fb_init(void) +void +fb_init(void) { - if (framebuffer_request.response == NULL || - framebuffer_request.response->framebuffer_count < 1) { - return; - } - - console.fb = framebuffer_request.response->framebuffers[0]; - console.fg_color = 0xFFFFFF; // White - console.bg_color = 0x000000; // Black - console.cursor_x = 0; - console.cursor_y = 0; - console.cols = console.fb->width / FB_CHAR_WIDTH; - console.rows = console.fb->height / FB_CHAR_HEIGHT; - - fb_clear(); -} - -void fb_clear(void) -{ - if (!console.fb) return; - - uint32_t *fb = (uint32_t *)console.fb->address; - size_t pixels = (console.fb->pitch / 4) * console.fb->height; - - for (size_t i = 0; i < pixels; i++) { - fb[i] = console.bg_color; - } - - console.cursor_x = 0; - console.cursor_y = 0; -} - -void fb_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) -{ - if (!console.fb) return; - - uint32_t *fb = (uint32_t *)console.fb->address; - uint32_t pitch_pixels = console.fb->pitch / 4; - - for (uint32_t row = y; row < y + h && row < console.fb->height; row++) { - for (uint32_t col = x; col < x + w && col < console.fb->width; col++) { - fb[row * pitch_pixels + col] = color; + if (framebuffer_request.response == NULL || + framebuffer_request.response->framebuffer_count < 1) { + return; } - } -} - -void fb_set_color(uint32_t fg, uint32_t bg) -{ - console.fg_color = fg; - console.bg_color = bg; -} - -static void draw_char(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_color) -{ - if (!console.fb) return; - - uint32_t *fb = (uint32_t *)console.fb->address; - uint32_t pitch_pixels = console.fb->pitch / 4; - - // Get the font data for this character - const uint8_t *char_data = &IBM_VGA_8x16[c * 16]; - - // Draw each row of the character - for (uint32_t row = 0; row < FB_CHAR_HEIGHT; row++) { - uint8_t font_row = char_data[row]; - // Draw each pixel in the row - for (uint32_t col = 0; col < FB_CHAR_WIDTH; col++) { - uint32_t px = x + col; - uint32_t py = y + row; - - // Check bounds - if (px >= console.fb->width || py >= console.fb->height) continue; - - // Check if this pixel should be set (bit test) - if (font_row & (0x80 >> col)) { - fb[py * pitch_pixels + px] = fg_color; - } else { - fb[py * pitch_pixels + px] = bg_color; - } - } - } -} - -static void scroll_up(void) -{ - if (!console.fb) return; - - uint32_t *fb = (uint32_t *)console.fb->address; - uint32_t pitch_pixels = console.fb->pitch / 4; - - // Move all lines up by one character height - for (uint32_t y = 0; y < console.fb->height - FB_CHAR_HEIGHT; y++) { - for (uint32_t x = 0; x < console.fb->width; x++) { - fb[y * pitch_pixels + x] = fb[(y + FB_CHAR_HEIGHT) * pitch_pixels + x]; - } - } - - // Clear the last line - for (uint32_t y = console.fb->height - FB_CHAR_HEIGHT; y < console.fb->height; y++) { - for (uint32_t x = 0; x < console.fb->width; x++) { - fb[y * pitch_pixels + x] = console.bg_color; - } - } -} - -void fb_putchar(char c) -{ - if (!console.fb) return; - - // Handle special characters - switch (c) { - case '\n': - console.cursor_x = 0; - console.cursor_y++; - break; - case '\r': - console.cursor_x = 0; - break; - case '\t': - console.cursor_x = (console.cursor_x + 8) & ~7; - break; - case '\b': - if (console.cursor_x > 0) { - console.cursor_x--; - draw_char(console.cursor_x * FB_CHAR_WIDTH, - console.cursor_y * FB_CHAR_HEIGHT, - ' ', console.fg_color, console.bg_color); - } - break; - default: - // Draw the character - draw_char(console.cursor_x * FB_CHAR_WIDTH, - console.cursor_y * FB_CHAR_HEIGHT, - c, console.fg_color, console.bg_color); - console.cursor_x++; - break; - } - - // Handle line wrapping - if (console.cursor_x >= console.cols) { + console.fb = framebuffer_request.response->framebuffers[0]; + console.fg_color = 0xFFFFFF; // White + console.bg_color = 0x000000; // Black console.cursor_x = 0; - console.cursor_y++; - } - - // Handle scrolling - if (console.cursor_y >= console.rows) { - scroll_up(); - console.cursor_y = console.rows - 1; - } + console.cursor_y = 0; + console.cols = console.fb->width / FB_CHAR_WIDTH; + console.rows = console.fb->height / FB_CHAR_HEIGHT; + + fb_clear(); } -void fb_puts(const char *str) +void +fb_clear(void) { - while (*str) { - fb_putchar(*str++); - } -} - -static void print_number(unsigned long num, int base, int width, char pad) -{ - char digits[] = "0123456789ABCDEF"; - char buffer[32]; - int pos = 0; - - // Convert number to string (reversed) - if (num == 0) { - buffer[pos++] = '0'; - } else { - while (num > 0) { - buffer[pos++] = digits[num % base]; - num /= base; + if (!console.fb) return; + + uint32_t *fb = (uint32_t *)console.fb->address; + size_t pixels = (console.fb->pitch / 4) * console.fb->height; + + for (size_t i = 0; i < pixels; i++) { + fb[i] = console.bg_color; } - } - - // Add padding if needed - while (pos < width) { - buffer[pos++] = pad; - } - - // Print reversed - while (pos > 0) { - fb_putchar(buffer[--pos]); - } + + console.cursor_x = 0; + console.cursor_y = 0; } -static void print_signed(long num, int width, char pad) +void +fb_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) { - if (num < 0) { - fb_putchar('-'); - print_number(-num, 10, width, pad); - } else { - print_number(num, 10, width, pad); - } + if (!console.fb) return; + + uint32_t *fb = (uint32_t *)console.fb->address; + uint32_t pitch_pixels = console.fb->pitch / 4; + + for (uint32_t row = y; row < y + h && row < console.fb->height; row++) { + for (uint32_t col = x; col < x + w && col < console.fb->width; col++) { + fb[row * pitch_pixels + col] = color; + } + } } -void fb_printf(const char *fmt, ...) +void +fb_set_color(uint32_t fg, uint32_t bg) { - va_list args; - va_start(args, fmt); - - while (*fmt) { - if (*fmt == '%') { - fmt++; - - // Handle width and padding - char pad = ' '; - int width = 0; - - if (*fmt == '0') { - pad = '0'; - fmt++; - } - - while (*fmt >= '0' && *fmt <= '9') { - width = width * 10 + (*fmt - '0'); - fmt++; - } - - // Handle format specifiers - switch (*fmt) { - case 'd': - case 'i': - print_signed(va_arg(args, int), width, pad); - break; + console.fg_color = fg; + console.bg_color = bg; +} + +static void +draw_char(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_color) +{ + if (!console.fb) return; + + uint32_t *fb = (uint32_t *)console.fb->address; + uint32_t pitch_pixels = console.fb->pitch / 4; + + // Get the font data for this character + const uint8_t *char_data = &IBM_VGA_8x16[c * 16]; + + // Draw each row of the character + for (uint32_t row = 0; row < FB_CHAR_HEIGHT; row++) { + uint8_t font_row = char_data[row]; + + // Draw each pixel in the row + for (uint32_t col = 0; col < FB_CHAR_WIDTH; col++) { + uint32_t px = x + col; + uint32_t py = y + row; - case 'u': - print_number(va_arg(args, unsigned int), 10, width, pad); - break; - - case 'x': - print_number(va_arg(args, unsigned int), 16, width, pad); - break; - - case 'X': - print_number(va_arg(args, unsigned int), 16, width, pad); - break; - - case 'p': - fb_puts("0x"); - print_number((unsigned long)va_arg(args, void*), 16, 16, '0'); - break; - - case 'c': - fb_putchar(va_arg(args, int)); - break; - - case 's': - { - const char *str = va_arg(args, const char*); - if (str) { - fb_puts(str); + // Check bounds + if (px >= console.fb->width || py >= console.fb->height) continue; + + // Check if this pixel should be set (bit test) + if (font_row & (0x80 >> col)) { + fb[py * pitch_pixels + px] = fg_color; } else { - fb_puts("(null)"); + fb[py * pitch_pixels + px] = bg_color; } - } - break; - - case '%': - fb_putchar('%'); - break; - - default: - fb_putchar('%'); - fb_putchar(*fmt); - break; - } - } else { - fb_putchar(*fmt); + } } - fmt++; - } - - va_end(args); +} + +static void +scroll_up(void) +{ + if (!console.fb) return; + + uint32_t *fb = (uint32_t *)console.fb->address; + uint32_t pitch_pixels = console.fb->pitch / 4; + + // Move all lines up by one character height + for (uint32_t y = 0; y < console.fb->height - FB_CHAR_HEIGHT; y++) { + for (uint32_t x = 0; x < console.fb->width; x++) { + fb[y * pitch_pixels + x] = fb[(y + FB_CHAR_HEIGHT) * pitch_pixels + x]; + } + } + + // Clear the last line + for (uint32_t y = console.fb->height - FB_CHAR_HEIGHT; y < console.fb->height; y++) { + for (uint32_t x = 0; x < console.fb->width; x++) { + fb[y * pitch_pixels + x] = console.bg_color; + } + } +} + +void +fb_putchar(char c) +{ + if (!console.fb) return; + + // Handle special characters + switch (c) { + case '\n': + console.cursor_x = 0; + console.cursor_y++; + break; + case '\r': + console.cursor_x = 0; + break; + case '\t': + console.cursor_x = (console.cursor_x + 8) & ~7; + break; + case '\b': + if (console.cursor_x > 0) { + console.cursor_x--; + draw_char(console.cursor_x * FB_CHAR_WIDTH, + console.cursor_y * FB_CHAR_HEIGHT, + ' ', console.fg_color, console.bg_color); + } + break; + default: + // Draw the character + draw_char(console.cursor_x * FB_CHAR_WIDTH, + console.cursor_y * FB_CHAR_HEIGHT, + c, console.fg_color, console.bg_color); + console.cursor_x++; + break; + } + + // Handle line wrapping + if (console.cursor_x >= console.cols) { + console.cursor_x = 0; + console.cursor_y++; + } + + // Handle scrolling + if (console.cursor_y >= console.rows) { + scroll_up(); + console.cursor_y = console.rows - 1; + } +} + +void +fb_puts(const char *str) +{ + while (*str) { + fb_putchar(*str++); + } +} + +static void +print_number(unsigned long num, int base, int width, char pad) +{ + char digits[] = "0123456789ABCDEF"; + char buffer[32]; + int pos = 0; + + // Convert number to string (reversed) + if (num == 0) { + buffer[pos++] = '0'; + } else { + while (num > 0) { + buffer[pos++] = digits[num % base]; + num /= base; + } + } + + // Add padding if needed + while (pos < width) { + buffer[pos++] = pad; + } + + // Print reversed + while (pos > 0) { + fb_putchar(buffer[--pos]); + } +} + +static void +print_signed(long num, int width, char pad) +{ + if (num < 0) { + fb_putchar('-'); + print_number(-num, 10, width, pad); + } else { + print_number(num, 10, width, pad); + } +} + +void +fb_printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + while (*fmt) { + if (*fmt == '%') { + fmt++; + + // Handle width and padding + char pad = ' '; + int width = 0; + + if (*fmt == '0') { + pad = '0'; + fmt++; + } + + while (*fmt >= '0' && *fmt <= '9') { + width = width * 10 + (*fmt - '0'); + fmt++; + } + + // Handle format specifiers + switch (*fmt) { + case 'd': + case 'i': + print_signed(va_arg(args, int), width, pad); + break; + + case 'u': + print_number(va_arg(args, unsigned int), 10, width, pad); + break; + + case 'x': + print_number(va_arg(args, unsigned int), 16, width, pad); + break; + + case 'X': + print_number(va_arg(args, unsigned int), 16, width, pad); + break; + + case 'p': + fb_puts("0x"); + print_number((unsigned long)va_arg(args, void*), 16, 16, '0'); + break; + + case 'c': + fb_putchar(va_arg(args, int)); + break; + + case 's': + { + const char *str = va_arg(args, const char*); + if (str) { + fb_puts(str); + } else { + fb_puts("(null)"); + } + } + break; + + case '%': + fb_putchar('%'); + break; + + default: + fb_putchar('%'); + fb_putchar(*fmt); + break; + } + } else { + fb_putchar(*fmt); + } + fmt++; + } + + va_end(args); } diff --git a/kernel/drivers/video/vga.c b/kernel/drivers/video/vga.c index 9cf1715..e44f1d0 100644 --- a/kernel/drivers/video/vga.c +++ b/kernel/drivers/video/vga.c @@ -4,69 +4,69 @@ static inline void outb(uint16_t port, uint8_t val) { - __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); + __asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port)); } static inline uint8_t inb(uint16_t port) { - uint8_t ret; - __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); - return ret; + uint8_t ret; + __asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port)); + return ret; } // Write vga registers for mode change static void write_regs(uint8_t *regs) { - unsigned i; - - // Write misc output register - outb(VGA_MISC_WRITE, *regs); - regs++; - - // Write sequencer registers (5 registers) - for (i = 0; i < 5; i++) { - outb(VGA_SEQ_INDEX, i); - outb(VGA_SEQ_DATA, *regs); - regs++; - } - - // Unlock CRTC registers 0-7 by clearing protect bit - outb(VGA_CRTC_INDEX, 0x03); - outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80); - outb(VGA_CRTC_INDEX, 0x11); - outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80); - - // Update the register values to match - regs[0x03] = regs[0x03] | 0x80; - regs[0x11] = regs[0x11] & ~0x80; - - // Write CRTC registers (25 registers) - for (i = 0; i < 25; i++) { - outb(VGA_CRTC_INDEX, i); - outb(VGA_CRTC_DATA, *regs); - regs++; - } - - // Write graphics controller registers (9 registers) - for (i = 0; i < 9; i++) { - outb(VGA_GC_INDEX, i); - outb(VGA_GC_DATA, *regs); - regs++; - } - - // Write attribute controller registers (21 registers) - for (i = 0; i < 21; i++) { - inb(VGA_INSTAT_READ); // Reset flip-flop - outb(VGA_AC_INDEX, i); - outb(VGA_AC_WRITE, *regs); - regs++; - } - - // Enable video display - inb(VGA_INSTAT_READ); - outb(VGA_AC_INDEX, 0x20); + unsigned i; + + // Write misc output register + outb(VGA_MISC_WRITE, *regs); + regs++; + + // Write sequencer registers (5 registers) + for (i = 0; i < 5; i++) { + outb(VGA_SEQ_INDEX, i); + outb(VGA_SEQ_DATA, *regs); + regs++; + } + + // Unlock CRTC registers 0-7 by clearing protect bit + outb(VGA_CRTC_INDEX, 0x03); + outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80); + outb(VGA_CRTC_INDEX, 0x11); + outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & ~0x80); + + // Update the register values to match + regs[0x03] = regs[0x03] | 0x80; + regs[0x11] = regs[0x11] & ~0x80; + + // Write CRTC registers (25 registers) + for (i = 0; i < 25; i++) { + outb(VGA_CRTC_INDEX, i); + outb(VGA_CRTC_DATA, *regs); + regs++; + } + + // Write graphics controller registers (9 registers) + for (i = 0; i < 9; i++) { + outb(VGA_GC_INDEX, i); + outb(VGA_GC_DATA, *regs); + regs++; + } + + // Write attribute controller registers (21 registers) + for (i = 0; i < 21; i++) { + inb(VGA_INSTAT_READ); // Reset flip-flop + outb(VGA_AC_INDEX, i); + outb(VGA_AC_WRITE, *regs); + regs++; + } + + // Enable video display + inb(VGA_INSTAT_READ); + outb(VGA_AC_INDEX, 0x20); } void @@ -75,22 +75,22 @@ vga_set_mode_13h(void) // Register values for VGA mode 13h (320x200, 256 colors) // Order: Misc, Seq[5], CRTC[25], GC[9], AC[21] static uint8_t mode_320x200x256[] = { - // Misc output register - 0x63, - // Sequencer registers - 0x03, 0x01, 0x0F, 0x00, 0x0E, - // CRTC registers - 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, - 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, - 0xFF, - // Graphics controller registers - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, - 0xFF, - // Attribute controller registers - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x41, 0x00, 0x0F, 0x00, 0x00 + // Misc output register + 0x63, + // Sequencer registers + 0x03, 0x01, 0x0F, 0x00, 0x0E, + // CRTC registers + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, + 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, + 0xFF, + // Graphics controller registers + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + // Attribute controller registers + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00 }; write_regs(mode_320x200x256); @@ -113,6 +113,6 @@ vga_clear_screen(uint8_t color) uint8_t *vga = (uint8_t *)VGA_GRAPHICS_BUFFER; // fill entire buffer (64k pixels) for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { - vga[i] = color; + vga[i] = color; } } diff --git a/kernel/include/mm/paging.h b/kernel/include/mm/paging.h new file mode 100644 index 0000000..bbe8085 --- /dev/null +++ b/kernel/include/mm/paging.h @@ -0,0 +1,11 @@ +#ifndef PAGING_H +#define PAGING_H + +#include + +volatile struct limine_hhdm_request hhdm_request; +volatile struct limine_kernel_address_request kernel_address_request; + +void map_vga_memory(void); + +#endif /* ifndef PAGING_H */ diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c index 1883bdf..ecb9192 100644 --- a/kernel/init/kernel.c +++ b/kernel/init/kernel.c @@ -3,6 +3,7 @@ #include #include #include +#include static void hcf(void) @@ -20,6 +21,7 @@ kernel_main(void) /* Initialize framebuffer console */ fb_init(); + map_vga_memory(); /* Test print */ fb_puts("Hello World\n"); diff --git a/kernel/klibc/string.c b/kernel/klibc/string.c index b512017..75ad9d1 100644 --- a/kernel/klibc/string.c +++ b/kernel/klibc/string.c @@ -1,4 +1,4 @@ -#include +#include size_t strlen(const char* str) diff --git a/kernel/mm/paging.c b/kernel/mm/paging.c new file mode 100644 index 0000000..d854ff1 --- /dev/null +++ b/kernel/mm/paging.c @@ -0,0 +1,125 @@ +#include +#include +#include +#include + +#define PAGE_PRESENT (1ULL << 0) +#define PAGE_WRITABLE (1ULL << 1) +#define PAGE_USER (1ULL << 2) +#define PAGE_SIZE_2MB (1ULL << 7) +#define PAGE_SIZE 4096 + +// Get hhdm offset +extern volatile struct limine_hhdm_request hhdm_request; +extern volatile struct limine_kernel_address_request kernel_address_request; + +// Static storage for page tables +static uint64_t pdpt[512] __attribute__((aligned(4096))); +static uint64_t pd[512] __attribute__((aligned(4096))); + +// Get current cr3 value (PML address) +static uint64_t +get_cr3(void) +{ + uint64_t cr3; + __asm__ volatile("mov %%cr3, %0" : "=r"(cr3)); + return cr3; +} + +// Set cr3 to flush TLB +static void +set_cr3(uint64_t cr3) +{ + __asm__ volatile("mov %0, %%cr3" : : "r"(cr3) : "memory"); +} + +// Convert physical address to virt address using hhdm +static void* +phys_to_virt(uint64_t phys) +{ + if (hhdm_request.response == NULL) { + // Fallback if hhdm is not available + return (void *)(phys + 0xffff800000000000ULL); + } + return (void *)(phys + hhdm_request.response->offset); +} + +// Convert virt address to physical address +static uint64_t +virt_to_phys(void *virt) +{ + uint64_t addr = (uint64_t)virt; + + // Check if this is a kernel address + if (kernel_address_request.response != NULL) { + uint64_t kernel_virt_base = kernel_address_request.response->virtual_base; + uint64_t kernel_phys_base = kernel_address_request.response->physical_base; + + // If address is in kernel space, convert using kernel base + if (addr >= kernel_virt_base && addr < kernel_virt_base + 0x200000) { + return kernel_phys_base + (addr - kernel_virt_base); + } + } + + // Otherwise, in hhdm range + if (hhdm_request.response == NULL) { + // Fallback to default if hhdm not avail + return (addr - 0xffff800000000000ULL); + } + return (addr - hhdm_request.response->offset); +} + +void +map_vga_memory(void) +{ + // Get current PML4 from cr3 + uint64_t cr3 = get_cr3(); + uint64_t *pml4 = (uint64_t *)phys_to_virt(cr3 & ~0xFFF); + + // VGA memory starts at 0xA0000 (640KB) + // Map entire lower 1MB region for simplcity + + /* For address 0xA0000: + * PML4 index = 0 (bits 47-39) + * PDPT index = 0 (bits 38-30) + * PD index = 0 (bits 29-21) + * PT index = 160 (0xA0) (bits 20-12) + */ + + // Check if PML4[0] is present + if (!(pml4[0] & PAGE_PRESENT)) { + // Clear PDPT + for (int i = 0; i < 512; i++) { + pdpt[i] = 0; + } + // Install PDPT (use physical address) + pml4[0] = virt_to_phys(pdpt) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; + } + + // Get PDPT (convert physical address from entry to virt for access) + uint64_t *pdpt_ptr = (uint64_t *)phys_to_virt(pml4[0] & ~0xFFF); + + // Check if PDPT[0] is present + if (!(pdpt_ptr[0] & PAGE_PRESENT)) { + // Clear pd + for (int i = 0; i < 512; i++) { + pd[i] = 0; + } + // Install pd (use physical address) + pdpt_ptr[0] = virt_to_phys(pd) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; + } + + // Get pd (convert physical address from entry to virt for access) + uint64_t *pd_ptr = (uint64_t *)phys_to_virt(pdpt_ptr[0] & ~0xFFF); + + // Check if we can use 2MB pages + if (!(pd_ptr[0] & PAGE_PRESENT)) { + // Map the first 2MB as a large page (0x0 - 0x200000) + // This include VGA memory at 0xA0000-0xBFFFF + pd_ptr[0] = 0x0 | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER | PAGE_SIZE_2MB; + } + + // Flush TLB + set_cr3(cr3); + +} diff --git a/kernel/mm/paging.stub b/kernel/mm/paging.stub deleted file mode 100644 index c0ad428..0000000 --- a/kernel/mm/paging.stub +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include - -#define PAGE_PRESENT (1ULL << 0) -#define PAGE_WRITABLE (1ULL << 1) -#define PAGE_USER (1ULL << 2) -#define PAGE_SIZE_2MB (1ULL << 7) -#define PAGE_SIZE 4096 - -// Get hhdm offset -extern volatile struct limine_hhdm_request hhdm_request; -extern volatile struct limine_kernel_address_request kernel_address_request; - -// Static storage for page tables -static uint64_t pdpt[512] __attribute__((aligned(4096))); -static uint64_t pd[512] __attribute__((aligned(4096))); - -// Get current cr3 value (PML address) -static uint64_t get_cr3(void) -{ - uint64_t cr3; - __asm__ volatile("mov %%cr3, %0" : "=r"(cr3)); - return cr3; -} - -// Set cr3 to flush TLB -static void set_cr3(uint64_t cr3) -{ - __asm__ volatile("mov %0, %%cr3" : : "r"(cr3) : "memory"); -} - -// Convert physical address to virt address using hhdm -static inline void *phys_to_virt(uint64_t phys) -{ - if (hhdm_request.response == NULL) { - // Fallback if hhdm is not available - return (void *)(phys + 0xffff800000000000ULL); - } - return (void *)(phys + hhdm_request.response->offset); -} - -// Convert virt address to physical address -static inline uint64_t virt_to_phys(void *virt) -{ - uint64_t addr = (uint64_t)virt; - - // Check if this is a kernel address - if (kernel_address_request.response != NULL) { - uint64_t kernel_virt_base = kernel_address_request.response->virtual_base; - uint64_t kernel_phys_base = kernel_address_request.response->physical_base; - - // If address is in kernel space, convert using kernel base - if (addr >= kernel_virt_base && addr < kernel_virt_base + 0x200000) { - return kernel_phys_base + (addr - kernel_virt_base); - } - } - - // Otherwise, in hhdm range - if (hhdm_request.response == NULL) { - // Fallback to default if hhdm not avail - return (addr - 0xffff800000000000ULL); - } - return (addr - hhdm_request.response->offset); -} - -void map_vga_memory(void) -{ - // Get current PML4 from cr3 - uint64_t cr3 = get_cr3(); - uint64_t *pml4 = (uint64_t *)phys_to_virt(cr3 & ~0xFFF); - - // VGA memory starts at 0xA0000 (640KB) - // Map entire lower 1MB region for simplcity - - /* For address 0xA0000: - * PML4 index = 0 (bits 47-39) - * PDPT index = 0 (bits 38-30) - * PD index = 0 (bits 29-21) - * PT index = 160 (0xA0) (bits 20-12) - */ - - // Check if PML4[0] is present - if (!(pml4[0] & PAGE_PRESENT)) { - // Clear PDPT - for (int i = 0; i < 512; i++) { - pdpt[i] = 0; - } - // Install PDPT (use physical address) - pml4[0] = virt_to_phys(pdpt) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; - } - - // Get PDPT (convert physical address from entry to virt for access) - uint64_t *pdpt_ptr = (uint64_t *)phys_to_virt(pml4[0] & ~0xFFF); - - // Check if PDPT[0] is present - if (!(pdpt_ptr[0] & PAGE_PRESENT)) { - // Clear pd - for (int i = 0; i < 512; i++) { - pd[i] = 0; - } - // Install pd (use physical address) - pdpt_ptr[0] = virt_to_phys(pd) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; - } - - // Get pd (convert physical address from entry to virt for access) - uint64_t *pd_ptr = (uint64_t *)phys_to_virt(pdpt_ptr[0] & ~0xFFF); - - // Check if we can use 2MB pages - if (!(pd_ptr[0] & PAGE_PRESENT)) { - // Map the first 2MB as a large page (0x0 - 0x200000) - // This include VGA memory at 0xA0000-0xBFFFF - pd_ptr[0] = 0x0 | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER | PAGE_SIZE_2MB; - } - - // Flush TLB - set_cr3(cr3); - -}