mirror of
https://github.com/gbowne1/ClassicOS.git
synced 2026-01-29 16:15:20 -08:00
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:
@@ -1,21 +1,17 @@
|
||||
#include "paging.h"
|
||||
#include "io.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_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
|
||||
void set_page_directory(page_directory_entry_t *dir) {
|
||||
for (int i = 0; i < PAGE_DIRECTORY_SIZE; i++) {
|
||||
dir[i].present = 0;
|
||||
}
|
||||
// Set first PDE
|
||||
dir[0].present = 1;
|
||||
dir[0].rw = 1;
|
||||
dir[0].user = 0;
|
||||
dir[0].frame = (uint32_t)page_table >> 12;
|
||||
dir[0].addr = (uint32_t)page_table >> 12;
|
||||
}
|
||||
|
||||
// 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
|
||||
table[i].present = 1;
|
||||
table[i].rw = 1; // Read/Write
|
||||
table[i].user = 0; // Kernel mode
|
||||
table[i].write_through = 0;
|
||||
table[i].cache_disabled = 0;
|
||||
table[i].accessed = 0;
|
||||
table[i].frame = i; // Identity mapping
|
||||
table[i].addr = i; // Identity mapping
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,26 +39,13 @@ void enable_paging() {
|
||||
|
||||
// Initialize paging: set up the page directory and enable paging
|
||||
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_page_directory(page_directory);
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -16,25 +16,25 @@ typedef struct {
|
||||
uint32_t write_through : 1; // Write-through cache
|
||||
uint32_t cache_disabled : 1; // Cache disabled
|
||||
uint32_t accessed : 1; // Accessed bit
|
||||
uint32_t reserved : 1; // Reserved bit
|
||||
uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB)
|
||||
uint32_t dirty : 1; // Dirty bit
|
||||
uint32_t attribute : 1; // Page size (0: 4KB, 1: 4MB)
|
||||
uint32_t global : 1; // Global page (can be used across different processes)
|
||||
uint32_t available : 3; // Available bits for the system
|
||||
uint32_t frame : 20; // Frame address (physical address)
|
||||
uint32_t reserved : 3; // Unused
|
||||
uint32_t addr : 20; // Page frame address (physical address)
|
||||
} __attribute__((packed)) page_table_entry_t;
|
||||
|
||||
// Define page directory entry
|
||||
typedef struct {
|
||||
uint32_t present : 1;
|
||||
uint32_t rw : 1;
|
||||
uint32_t user : 1;
|
||||
uint32_t write_through : 1;
|
||||
uint32_t cache_disabled : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t reserved : 1;
|
||||
uint32_t zero : 5; // Must be zero for page directory
|
||||
uint32_t reserved_2 : 7; // Reserved bits
|
||||
uint32_t frame : 20; // Frame address of the page table
|
||||
uint32_t present : 1; // Present bit (1: PTE is present in memory)
|
||||
uint32_t rw : 1; // Read-Write bit (1: pages are read-write)
|
||||
uint32_t user : 1; // User-supervisor bit (1: user mode access)
|
||||
uint32_t write_through : 1; // Write-through cache
|
||||
uint32_t cache_disabled : 1; // Cache disabled
|
||||
uint32_t accessed : 1; // Accessed bit
|
||||
uint32_t available : 1; // Unused
|
||||
uint32_t page_size : 1; // Page size (0: 4KB, 1: 4MB)
|
||||
uint32_t available_2 : 4; // Unused
|
||||
uint32_t addr : 20; // Page table address
|
||||
} __attribute__((packed)) page_directory_entry_t;
|
||||
|
||||
extern page_directory_entry_t *page_directory;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#include "threading.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "malloc.h"
|
||||
#include "print.h"
|
||||
#include "threading.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define MAX_THREADS 16 // Maximum number of threads
|
||||
#define THREAD_STACK_SIZE 8192 // Stack size for each thread
|
||||
@@ -26,7 +27,8 @@ void thread_init(void) {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
my_printf("Error: Maximum thread count reached.\n");
|
||||
return;
|
||||
@@ -41,11 +43,13 @@ void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)
|
||||
thread_table[index].arg = arg;
|
||||
thread_table[index].stack_size = 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)
|
||||
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
|
||||
|
||||
// Set the thread's state to ready
|
||||
@@ -61,7 +65,8 @@ void thread_create(Thread *thread __attribute__((unused)), void (*start_routine)
|
||||
void thread_yield(void) {
|
||||
// Find the next thread in a round-robin manner
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -73,7 +78,8 @@ void thread_yield(void) {
|
||||
|
||||
// Exit the current thread
|
||||
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
|
||||
num_threads--; // Decrease thread count
|
||||
|
||||
@@ -95,18 +101,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
|
||||
// registers)
|
||||
void context_switch(Thread* next) {
|
||||
// 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.
|
||||
// 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");
|
||||
next->start_routine(next->arg); // Start running the next thread
|
||||
}
|
||||
|
||||
// Simple mutex functions (spinlock)
|
||||
void mutex_init(void) {
|
||||
mutex_locked = 0;
|
||||
}
|
||||
void mutex_init(void) { mutex_locked = 0; }
|
||||
|
||||
void mutex_lock(void) {
|
||||
while (__sync_lock_test_and_set(&mutex_locked, 1)) {
|
||||
@@ -114,6 +120,4 @@ void mutex_lock(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void mutex_unlock(void) {
|
||||
__sync_lock_release(&mutex_locked);
|
||||
}
|
||||
void mutex_unlock(void) { __sync_lock_release(&mutex_locked); }
|
||||
|
||||
@@ -9,6 +9,4 @@ char* itoa(int value, char* str, int base);
|
||||
// Convert unsigned integer to string (base is typically 10, 16, etc.)
|
||||
char* utoa(unsigned int value, char* str, int base);
|
||||
|
||||
void *memset(void *dest, int value, size_t len);
|
||||
|
||||
#endif // UTILS_H
|
||||
|
||||
Reference in New Issue
Block a user