mirror of
https://github.com/cowmonk/cowos.git
synced 2025-12-26 11:16:50 +00:00
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.
This commit is contained in:
parent
0d3653c970
commit
6d2e453d27
8 changed files with 477 additions and 446 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,3 +7,4 @@ isodir/boot/limine/limine-bios-cd.bin
|
||||||
isodir/boot/limine/limine-uefi-cd.bin
|
isodir/boot/limine/limine-uefi-cd.bin
|
||||||
isodir/EFI/BOOT/BOOTX64.EFI
|
isodir/EFI/BOOT/BOOTX64.EFI
|
||||||
isodir/EFI/BOOT/BOOTIA32.EFI
|
isodir/EFI/BOOT/BOOTIA32.EFI
|
||||||
|
compile_flags.txt
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
static fb_console_t console;
|
static fb_console_t console;
|
||||||
|
|
||||||
void fb_init(void)
|
void
|
||||||
|
fb_init(void)
|
||||||
{
|
{
|
||||||
if (framebuffer_request.response == NULL ||
|
if (framebuffer_request.response == NULL ||
|
||||||
framebuffer_request.response->framebuffer_count < 1) {
|
framebuffer_request.response->framebuffer_count < 1) {
|
||||||
|
|
@ -25,7 +26,8 @@ void fb_init(void)
|
||||||
fb_clear();
|
fb_clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_clear(void)
|
void
|
||||||
|
fb_clear(void)
|
||||||
{
|
{
|
||||||
if (!console.fb) return;
|
if (!console.fb) return;
|
||||||
|
|
||||||
|
|
@ -40,7 +42,8 @@ void fb_clear(void)
|
||||||
console.cursor_y = 0;
|
console.cursor_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color)
|
void
|
||||||
|
fb_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color)
|
||||||
{
|
{
|
||||||
if (!console.fb) return;
|
if (!console.fb) return;
|
||||||
|
|
||||||
|
|
@ -54,13 +57,15 @@ void fb_draw_rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_set_color(uint32_t fg, uint32_t bg)
|
void
|
||||||
|
fb_set_color(uint32_t fg, uint32_t bg)
|
||||||
{
|
{
|
||||||
console.fg_color = fg;
|
console.fg_color = fg;
|
||||||
console.bg_color = bg;
|
console.bg_color = bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_char(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_color)
|
static void
|
||||||
|
draw_char(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_t bg_color)
|
||||||
{
|
{
|
||||||
if (!console.fb) return;
|
if (!console.fb) return;
|
||||||
|
|
||||||
|
|
@ -92,7 +97,8 @@ static void draw_char(uint32_t x, uint32_t y, char c, uint32_t fg_color, uint32_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scroll_up(void)
|
static void
|
||||||
|
scroll_up(void)
|
||||||
{
|
{
|
||||||
if (!console.fb) return;
|
if (!console.fb) return;
|
||||||
|
|
||||||
|
|
@ -114,7 +120,8 @@ static void scroll_up(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_putchar(char c)
|
void
|
||||||
|
fb_putchar(char c)
|
||||||
{
|
{
|
||||||
if (!console.fb) return;
|
if (!console.fb) return;
|
||||||
|
|
||||||
|
|
@ -160,14 +167,16 @@ void fb_putchar(char c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_puts(const char *str)
|
void
|
||||||
|
fb_puts(const char *str)
|
||||||
{
|
{
|
||||||
while (*str) {
|
while (*str) {
|
||||||
fb_putchar(*str++);
|
fb_putchar(*str++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_number(unsigned long num, int base, int width, char pad)
|
static void
|
||||||
|
print_number(unsigned long num, int base, int width, char pad)
|
||||||
{
|
{
|
||||||
char digits[] = "0123456789ABCDEF";
|
char digits[] = "0123456789ABCDEF";
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
|
|
@ -194,7 +203,8 @@ static void print_number(unsigned long num, int base, int width, char pad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_signed(long num, int width, char pad)
|
static void
|
||||||
|
print_signed(long num, int width, char pad)
|
||||||
{
|
{
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
fb_putchar('-');
|
fb_putchar('-');
|
||||||
|
|
@ -204,7 +214,8 @@ static void print_signed(long num, int width, char pad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fb_printf(const char *fmt, ...)
|
void
|
||||||
|
fb_printf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
|
||||||
11
kernel/include/mm/paging.h
Normal file
11
kernel/include/mm/paging.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef PAGING_H
|
||||||
|
#define PAGING_H
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <bootloader.h>
|
#include <bootloader.h>
|
||||||
#include <drivers/video/framebuffer.h>
|
#include <drivers/video/framebuffer.h>
|
||||||
|
#include <mm/paging.h>
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hcf(void)
|
hcf(void)
|
||||||
|
|
@ -20,6 +21,7 @@ kernel_main(void)
|
||||||
|
|
||||||
/* Initialize framebuffer console */
|
/* Initialize framebuffer console */
|
||||||
fb_init();
|
fb_init();
|
||||||
|
map_vga_memory();
|
||||||
|
|
||||||
/* Test print */
|
/* Test print */
|
||||||
fb_puts("Hello World\n");
|
fb_puts("Hello World\n");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include <string.h>
|
#include <klibc/string.h>
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
strlen(const char* str)
|
strlen(const char* str)
|
||||||
|
|
|
||||||
125
kernel/mm/paging.c
Normal file
125
kernel/mm/paging.c
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limine.h>
|
||||||
|
#include <mm/paging.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <limine.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue