Fix PDE/PTE definitions, header cleanup

- Fixes PDE/PTE definitions in kernel/paging.h
- removes memset declaration from kernel/utils.h, uses klibc string.h as
needed
This commit is contained in:
vmttmv
2026-01-12 03:48:02 +02:00
committed by Borna Šoštarić
parent d0c9c9c4e0
commit d480fbcc80
4 changed files with 107 additions and 125 deletions

View File

@@ -1,21 +1,17 @@
#include "paging.h"
#include "io.h"
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <string.h>
#include "io.h"
#include "paging.h"
page_directory_entry_t *page_directory = (page_directory_entry_t *)0x200000; page_directory_entry_t *page_directory = (page_directory_entry_t *)0x200000;
page_table_entry_t *page_table = (page_table_entry_t *)0x201000; page_table_entry_t *page_table = (page_table_entry_t *)0x201000;
page_table_entry_t *heap_page_table = (page_table_entry_t *)0x202000;
// Helper function to set up the page directory entry // Helper function to set up the page directory entry
void set_page_directory(page_directory_entry_t *dir) { void set_page_directory(page_directory_entry_t *dir) {
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) { // Set first PDE
dir[i].present = 0;
}
dir[0].present = 1; dir[0].present = 1;
dir[0].rw = 1; dir[0].rw = 1;
dir[0].user = 0; dir[0].addr = (uint32_t)page_table >> 12;
dir[0].frame = (uint32_t)page_table >> 12;
} }
// Helper function to set up the page table entry // Helper function to set up the page table entry
@@ -24,11 +20,7 @@ void set_page_table(page_table_entry_t *table) {
// Set up page table entries with identity mapping // Set up page table entries with identity mapping
table[i].present = 1; table[i].present = 1;
table[i].rw = 1; // Read/Write table[i].rw = 1; // Read/Write
table[i].user = 0; // Kernel mode table[i].addr = i; // Identity mapping
table[i].write_through = 0;
table[i].cache_disabled = 0;
table[i].accessed = 0;
table[i].frame = i; // Identity mapping
} }
} }
@@ -47,26 +39,13 @@ void enable_paging() {
// Initialize paging: set up the page directory and enable paging // Initialize paging: set up the page directory and enable paging
void paging_init() { void paging_init() {
// Zero out the tables
memset(page_directory, 0x00, PAGE_DIRECTORY_SIZE * sizeof *page_directory);
memset(page_table, 0x00, PAGE_TABLE_SIZE * sizeof *page_table);
// Set up identity-mapped page directory + table // Set up identity-mapped page directory + table
set_page_directory(page_directory); set_page_directory(page_directory);
set_page_table(page_table); set_page_table(page_table);
// === Set up heap mapping at 0xC0100000 ===
for (int i = 0; i < PAGE_TABLE_SIZE; i++) {
heap_page_table[i].present = 1;
heap_page_table[i].rw = 1;
heap_page_table[i].user = 0;
heap_page_table[i].write_through = 0;
heap_page_table[i].cache_disabled = 0;
heap_page_table[i].accessed = 0;
heap_page_table[i].frame = (256 + i); // Start physical heap at 1MB (256*4KB = 1MB)
}
// Index 772 = 0xC0100000 / 4MB
page_directory[772].present = 1;
page_directory[772].rw = 1;
page_directory[772].user = 0;
page_directory[772].frame = (uint32_t)heap_page_table >> 12;
enable_paging(); enable_paging();
} }

View File

@@ -16,25 +16,25 @@ typedef struct {
uint32_t write_through : 1; // Write-through cache uint32_t write_through : 1; // Write-through cache
uint32_t cache_disabled : 1; // Cache disabled uint32_t cache_disabled : 1; // Cache disabled
uint32_t accessed : 1; // Accessed bit uint32_t accessed : 1; // Accessed bit
uint32_t reserved : 1; // Reserved bit uint32_t dirty : 1; // Dirty bit
uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB) uint32_t attribute : 1; // Page size (0: 4KB, 1: 4MB)
uint32_t global : 1; // Global page (can be used across different processes) uint32_t global : 1; // Global page (can be used across different processes)
uint32_t available : 3; // Available bits for the system uint32_t reserved : 3; // Unused
uint32_t frame : 20; // Frame address (physical address) uint32_t addr : 20; // Page frame address (physical address)
} __attribute__((packed)) page_table_entry_t; } __attribute__((packed)) page_table_entry_t;
// Define page directory entry // Define page directory entry
typedef struct { typedef struct {
uint32_t present : 1; uint32_t present : 1; // Present bit (1: PTE is present in memory)
uint32_t rw : 1; uint32_t rw : 1; // Read-Write bit (1: pages are read-write)
uint32_t user : 1; uint32_t user : 1; // User-supervisor bit (1: user mode access)
uint32_t write_through : 1; uint32_t write_through : 1; // Write-through cache
uint32_t cache_disabled : 1; uint32_t cache_disabled : 1; // Cache disabled
uint32_t accessed : 1; uint32_t accessed : 1; // Accessed bit
uint32_t reserved : 1; uint32_t available : 1; // Unused
uint32_t zero : 5; // Must be zero for page directory uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB)
uint32_t reserved_2 : 7; // Reserved bits uint32_t available_2 : 4; // Unused
uint32_t frame : 20; // Frame address of the page table uint32_t addr : 20; // Page table address
} __attribute__((packed)) page_directory_entry_t; } __attribute__((packed)) page_directory_entry_t;
extern page_directory_entry_t *page_directory; extern page_directory_entry_t *page_directory;

View File

@@ -1,8 +1,10 @@
#include "threading.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <string.h>
#include "malloc.h" #include "malloc.h"
#include "print.h" #include "print.h"
#include "threading.h"
#include "utils.h" #include "utils.h"
#define MAX_THREADS 16 // Maximum number of threads #define MAX_THREADS 16 // Maximum number of threads
@@ -17,7 +19,7 @@ static uint32_t num_threads = 0; // Number of active threads
static volatile int mutex_locked = 0; static volatile int mutex_locked = 0;
// Function declaration for context_switch // Function declaration for context_switch
void context_switch(Thread *next); void context_switch(Thread* next);
// Initialize the threading system // Initialize the threading system
void thread_init(void) { void thread_init(void) {
@@ -26,7 +28,8 @@ void thread_init(void) {
} }
// Create a new thread // Create a new thread
void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)(void *), void *arg) { void thread_create(Thread* thread __attribute__((unused)),
void (*start_routine)(void*), void* arg) {
if (num_threads >= MAX_THREADS) { if (num_threads >= MAX_THREADS) {
my_printf("Error: Maximum thread count reached.\n"); my_printf("Error: Maximum thread count reached.\n");
return; return;
@@ -41,11 +44,13 @@ void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)
thread_table[index].arg = arg; thread_table[index].arg = arg;
thread_table[index].stack_size = THREAD_STACK_SIZE; thread_table[index].stack_size = THREAD_STACK_SIZE;
thread_table[index].stack = (uint32_t*)malloc(THREAD_STACK_SIZE); thread_table[index].stack = (uint32_t*)malloc(THREAD_STACK_SIZE);
thread_table[index].stack_top = thread_table[index].stack + THREAD_STACK_SIZE / sizeof(uint32_t); thread_table[index].stack_top =
thread_table[index].stack + THREAD_STACK_SIZE / sizeof(uint32_t);
// Initialize the stack (simulate pushing the function's return address) // Initialize the stack (simulate pushing the function's return address)
uint32_t *stack_top = thread_table[index].stack_top; uint32_t* stack_top = thread_table[index].stack_top;
*(--stack_top) = (uint32_t)start_routine; // Return address (the thread's entry point) *(--stack_top) =
(uint32_t)start_routine; // Return address (the thread's entry point)
*(--stack_top) = (uint32_t)arg; // Argument to pass to the thread *(--stack_top) = (uint32_t)arg; // Argument to pass to the thread
// Set the thread's state to ready // Set the thread's state to ready
@@ -61,7 +66,8 @@ void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)
void thread_yield(void) { void thread_yield(void) {
// Find the next thread in a round-robin manner // Find the next thread in a round-robin manner
uint32_t next_thread = (current_thread + 1) % num_threads; uint32_t next_thread = (current_thread + 1) % num_threads;
while (next_thread != current_thread && thread_table[next_thread].state != THREAD_READY) { while (next_thread != current_thread &&
thread_table[next_thread].state != THREAD_READY) {
next_thread = (next_thread + 1) % num_threads; next_thread = (next_thread + 1) % num_threads;
} }
@@ -73,7 +79,8 @@ void thread_yield(void) {
// Exit the current thread // Exit the current thread
void thread_exit(void) { void thread_exit(void) {
thread_table[current_thread].state = THREAD_BLOCKED; // Mark the thread as blocked (finished) thread_table[current_thread].state =
THREAD_BLOCKED; // Mark the thread as blocked (finished)
free(thread_table[current_thread].stack); // Free the thread's stack free(thread_table[current_thread].stack); // Free the thread's stack
num_threads--; // Decrease thread count num_threads--; // Decrease thread count
@@ -95,18 +102,18 @@ void scheduler(void) {
} }
} }
// Context switch to the next thread (assembly would go here to save/load registers) // Context switch to the next thread (assembly would go here to save/load
void context_switch(Thread *next) { // registers)
// For simplicity, context switching in this example would involve saving/restoring registers. void context_switch(Thread* next) {
// In a real system, you would need to save the CPU state (registers) and restore the next thread's state. // For simplicity, context switching in this example would involve
// saving/restoring registers. In a real system, you would need to save the
// CPU state (registers) and restore the next thread's state.
my_printf("Switching to thread...\n"); my_printf("Switching to thread...\n");
next->start_routine(next->arg); // Start running the next thread next->start_routine(next->arg); // Start running the next thread
} }
// Simple mutex functions (spinlock) // Simple mutex functions (spinlock)
void mutex_init(void) { void mutex_init(void) { mutex_locked = 0; }
mutex_locked = 0;
}
void mutex_lock(void) { void mutex_lock(void) {
while (__sync_lock_test_and_set(&mutex_locked, 1)) { while (__sync_lock_test_and_set(&mutex_locked, 1)) {
@@ -114,6 +121,4 @@ void mutex_lock(void) {
} }
} }
void mutex_unlock(void) { void mutex_unlock(void) { __sync_lock_release(&mutex_locked); }
__sync_lock_release(&mutex_locked);
}

View File

@@ -9,6 +9,4 @@ char* itoa(int value, char* str, int base);
// Convert unsigned integer to string (base is typically 10, 16, etc.) // Convert unsigned integer to string (base is typically 10, 16, etc.)
char* utoa(unsigned int value, char* str, int base); char* utoa(unsigned int value, char* str, int base);
void *memset(void *dest, int value, size_t len);
#endif // UTILS_H #endif // UTILS_H