Fixed bugs about kheap, paging and ordered list
Furthermore, added Heap kernel driver code for both allocation and deallocation free() does not works yet: `ASSERTION-FAILED(head->magic == HEAP_MAGIC) at kheap.c:261`
This commit is contained in:
parent
a378ca4061
commit
3c574238cf
|
@ -251,7 +251,7 @@ void *alloc(uint32_t size, uint8_t page_align, heap_t *heap) {
|
||||||
|
|
||||||
void free(void *p, heap_t *heap) {
|
void free(void *p, heap_t *heap) {
|
||||||
// Exit for null pointer
|
// Exit for null pointer
|
||||||
if(p == NULL)
|
if(p == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Retrieve the header and the footer for this pointer
|
// Retrieve the header and the footer for this pointer
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#include "ordered_list.h"
|
#include "ordered_list.h"
|
||||||
|
#include "kheap.h"
|
||||||
|
#include "../cpu/assert.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
|
||||||
uint8_t standard_lessthan_predicate(type_t a, type_t b) {
|
uint8_t standard_lessthan_predicate(type_t a, type_t b) {
|
||||||
if(a < b)
|
if(a < b)
|
||||||
|
|
|
@ -9,9 +9,6 @@
|
||||||
#define ORDERED_LIST_H
|
#define ORDERED_LIST_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kheap.h"
|
|
||||||
#include "../cpu/assert.h"
|
|
||||||
#include "../libc/string.h"
|
|
||||||
|
|
||||||
/* Our list is always in a 'sorted state',
|
/* Our list is always in a 'sorted state',
|
||||||
* it can store anything that can be casted
|
* it can store anything that can be casted
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
|
#include "kheap.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
|
||||||
// Macros for bitset algorithms
|
// Macros for bitset algorithms
|
||||||
#define INDEX_FROM_BIT(a) (a/(8*4))
|
#define INDEX_FROM_BIT(a) (a/(8*4))
|
||||||
|
@ -14,10 +16,9 @@ uint32_t *frames;
|
||||||
uint32_t nframes;
|
uint32_t nframes;
|
||||||
|
|
||||||
// From kheap.c
|
// From kheap.c
|
||||||
extern uint32_t placement_address;
|
extern uint32_t placement_addr;
|
||||||
extern heap_t *kheap;
|
extern heap_t *kheap;
|
||||||
|
|
||||||
|
|
||||||
// Set a bit in the frame bitset
|
// Set a bit in the frame bitset
|
||||||
static void set_frame(uint32_t frame_addr) {
|
static void set_frame(uint32_t frame_addr) {
|
||||||
uint32_t frame = frame_addr / 0x1000;
|
uint32_t frame = frame_addr / 0x1000;
|
||||||
|
@ -34,40 +35,35 @@ static void clear_frame(uint32_t frame_addr) {
|
||||||
frames[idx] &= ~(0x1 << off);
|
frames[idx] &= ~(0x1 << off);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if a bit is set
|
// Find the first free frames
|
||||||
static uint32_t test_frame(uint32_t frame_addr) {
|
|
||||||
uint32_t frame = frame_addr / 0x1000;
|
|
||||||
uint32_t idx = INDEX_FROM_BIT(frame);
|
|
||||||
uint32_t off = OFFSET_FROM_BIT(frame);
|
|
||||||
return (frames[idx] & (0x1 << off));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first three frames
|
|
||||||
static uint32_t first_frame() {
|
static uint32_t first_frame() {
|
||||||
for(uint32_t i = 0; i < INDEX_FROM_BIT(nframes); i++) {
|
uint32_t nsections = nframes / FRAME_ALLOCATION_SECTION_SIZE;
|
||||||
if(frames[i] != 0xFFFFFFFF) { // If nothing is free, exit
|
for(uint32_t section = 0; section < INDEX_FROM_BIT(nframes); section++)
|
||||||
for(uint32_t j = 0; j < 32; j++) {
|
if(frames[section] != 0xFFFFFFFF) // If nothing is free, exit
|
||||||
uint32_t to_test = 0x1 << j;
|
for(uint32_t idx = 0; idx < FRAME_ALLOCATION_SECTION_SIZE; idx++)
|
||||||
if (!(frames[i]&to_test))
|
if (!(frames[idx] & (0x1 << idx)))
|
||||||
return i*4*8+j;
|
return (section * FRAME_ALLOCATION_SECTION_SIZE) + idx;
|
||||||
}
|
return nsections * FRAME_ALLOCATION_SECTION_SIZE;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void alloc_frame(page_t *page, int32_t is_kernel, int32_t is_writeable) {
|
void alloc_frame(page_t *page, int32_t is_supervisored, int32_t is_writeable) {
|
||||||
if(page->frame != 0)
|
if(page->frame != 0)
|
||||||
return;
|
return; // Frame already allocated
|
||||||
else {
|
else {
|
||||||
uint32_t idx = first_frame();
|
uint32_t free_frame = first_frame();
|
||||||
if(idx == (uint32_t)-1) {
|
if(free_frame == (uint32_t)-1) {
|
||||||
// panic
|
PANIC("No free frames found!");
|
||||||
|
} else {
|
||||||
|
// Set free frames to page
|
||||||
|
page->present = PAGE_PRESENT;
|
||||||
|
page->rw = (is_writeable) ? PAGE_READ_WRITE : PAGE_READ_ONLY;
|
||||||
|
page->user = (is_supervisored) ? PAGE_SUPERVISOR : PAGE_USER;
|
||||||
|
page->frame = free_frame;
|
||||||
|
|
||||||
|
// Set new frames as used
|
||||||
|
uint32_t physical_address = free_frame * FRAME_SIZE;
|
||||||
|
set_frame(physical_address);
|
||||||
}
|
}
|
||||||
set_frame(idx*0x1000);
|
|
||||||
page->present = 1;
|
|
||||||
page->rw = (is_writeable) ? 1 : 0;
|
|
||||||
page->user = (is_kernel) ? 1 : 0;
|
|
||||||
page->frame = idx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,46 +78,45 @@ void free_frame(page_t *page) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_paging() {
|
void init_paging() {
|
||||||
uint32_t mem_end_page = 0x1000000; // Physical address memory(16MiB big)
|
uint32_t nframes = PHYSICAL_MEMORY_SIZE / FRAME_SIZE;
|
||||||
nframes = mem_end_page / 0x1000;
|
|
||||||
frames = (uint32_t*)kmalloc(INDEX_FROM_BIT(nframes));
|
frames = (uint32_t*)kmalloc(INDEX_FROM_BIT(nframes));
|
||||||
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
|
||||||
|
|
||||||
// Create a page directory
|
// Create a page directory
|
||||||
kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
|
kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
|
||||||
|
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
||||||
current_directory = kernel_directory;
|
current_directory = kernel_directory;
|
||||||
|
|
||||||
/* Map pages in the kernel heap area.
|
/* Map pages in the kernel heap area.
|
||||||
* We only call get_page and not alloc_frame to create a new page_table_t
|
* We only call get_page and not alloc_frame to create a new page_table_t
|
||||||
* only where necessary.*/
|
* only where necessary.*/
|
||||||
for(int32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
for(int32_t i = KHEAP_START; i < (int32_t)KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
||||||
get_page(i, 1, kernel_directory);
|
get_page(i, 1, kernel_directory);
|
||||||
|
|
||||||
/* We have eto identify map from 0x0 to the end of the use memory
|
/* We have eto identify map from 0x0 to the end of the use memory
|
||||||
* so we can use this memory region as if paging was not enabled. */
|
* so we can use this memory region as if paging was not enabled. */
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
while(i < placement_address+0x1000) {
|
while(i < (int32_t)placement_addr+0x1000) {
|
||||||
// Kernel code is read only from userspace
|
// Kernel code is read only from userspace
|
||||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
i += 0x1000;
|
i += 0x1000;
|
||||||
}
|
}
|
||||||
// Perform the real allocation of what we have done so far
|
// Perform the real allocation of what we have done so far
|
||||||
for(i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
for(i = KHEAP_START; i < (int32_t)KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
||||||
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
|
|
||||||
// Register a new ISR to handle page faults
|
// Register a new ISR to handle page faults
|
||||||
register_interrupt_handler(14, page_fault);
|
register_interrupt_handler(14, page_fault);
|
||||||
|
|
||||||
// Enable paging
|
// Enable paging
|
||||||
switch_page_directory(kernel_directory);
|
enable_paging(kernel_directory);
|
||||||
|
|
||||||
// Set up kernel heap
|
// Set up kernel heap
|
||||||
kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
|
kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void switch_page_directory(page_directory_t *dir) {
|
void enable_paging(page_directory_t *dir) {
|
||||||
current_directory = dir;
|
current_directory = dir;
|
||||||
asm volatile("mov %0, %%cr3" :: "r"(&dir->tables_physical));
|
asm volatile("mov %0, %%cr3" :: "r"(&dir->page_table_physical));
|
||||||
uint32_t cr0;
|
uint32_t cr0;
|
||||||
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
||||||
cr0 |= 0x80000000; // code to enable paging
|
cr0 |= 0x80000000; // code to enable paging
|
||||||
|
@ -133,14 +128,14 @@ page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) {
|
||||||
address /= 0x1000;
|
address /= 0x1000;
|
||||||
// Find page table that contains this index
|
// Find page table that contains this index
|
||||||
uint32_t table_idx = address / 1024;
|
uint32_t table_idx = address / 1024;
|
||||||
if(dir->tables[table_idx]) // If current table is already assigned
|
if(dir->page_table_virtual[table_idx]) // If current table is already assigned
|
||||||
return &dir->tables[table_idx]->pages[address%1024];
|
return &dir->page_table_virtual[table_idx]->pages[address%1024];
|
||||||
else if(make) {
|
else if(make) {
|
||||||
uint32_t tmp;
|
uint32_t tmp;
|
||||||
dir->tables[table_idx] = (page_table_t*)kmalloc_p(sizeof(page_table_t), &tmp);
|
dir->page_table_virtual[table_idx] = (page_table_t*)kmalloc_p(sizeof(page_table_t), &tmp);
|
||||||
memset(dir->tables[table_idx], 0, 0x1000);
|
memset(dir->page_table_virtual[table_idx], 0, 0x1000);
|
||||||
dir->tables_physical[table_idx] = tmp | 0x7;
|
dir->page_table_physical[table_idx] = tmp | 0x7;
|
||||||
return &dir->tables[table_idx]->pages[address%1024];
|
return &dir->page_table_virtual[table_idx]->pages[address%1024];
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -155,20 +150,19 @@ void page_fault(registers_t regs) {
|
||||||
int32_t rw = regs.err_code & 0x2; // Write operation
|
int32_t rw = regs.err_code & 0x2; // Write operation
|
||||||
int32_t us = regs.err_code & 0x4; // CPU mode(kernel or user mode)
|
int32_t us = regs.err_code & 0x4; // CPU mode(kernel or user mode)
|
||||||
int32_t reserved = regs.err_code & 0x8;
|
int32_t reserved = regs.err_code & 0x8;
|
||||||
int32_t id = regs.err_code & 0x10;
|
|
||||||
|
|
||||||
// Output of those informations
|
// Output of those informations
|
||||||
kprint("Page fault! ( ");
|
kprint((uint8_t*)"Page fault! ( ");
|
||||||
if(present)
|
if(present)
|
||||||
kprint("present ");
|
kprint((uint8_t*)"present ");
|
||||||
if(rw)
|
if(rw)
|
||||||
kprint("read-only");
|
kprint((uint8_t*)"read-only");
|
||||||
if(us)
|
if(us)
|
||||||
kprint("user-mode");
|
kprint((uint8_t*)"user-mode");
|
||||||
if(reserved)
|
if(reserved)
|
||||||
kprint("reserved");
|
kprint((uint8_t*)"reserved");
|
||||||
kprint(") at 0x");
|
kprint((uint8_t*)") at 0x");
|
||||||
kprint_hex(fault_addr);
|
kprint_hex(fault_addr);
|
||||||
kprint("\n");
|
kprint((uint8_t*)"\n");
|
||||||
PANIC("Page fault");
|
PANIC("Page fault");
|
||||||
}
|
}
|
|
@ -1,41 +1,67 @@
|
||||||
#ifndef PAGING_H
|
#ifndef PAGING_H
|
||||||
#define PAGING_G
|
#define PAGING_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "isr.h"
|
#include "isr.h"
|
||||||
#include "tty.h"
|
|
||||||
#include "kheap.h"
|
|
||||||
|
|
||||||
typedef struct page {
|
#define FRAME_SIZE 4096
|
||||||
uint32_t present : 1; // Presence in memory of single page
|
#define PAGE_TABLE_SIZE 1024
|
||||||
uint32_t rw : 1; // if set read write otherwise read only
|
#define PAGE_DIRECTORY_SIZE 1024
|
||||||
uint32_t user : 1; // Supervisored mode only if cleared
|
#define PAGE_NOT_PRESENT 0
|
||||||
uint32_t accessed : 1; // true if page has been accessed since last refresh
|
#define PAGE_PRESENT 1
|
||||||
uint32_t dirty : 1; // Same as above for write.
|
#define PAGE_READ_ONLY 0
|
||||||
uint32_t unused : 7; // unused bits
|
#define PAGE_READ_WRITE 1
|
||||||
uint32_t frame : 20; // Frame address (shifted to the right)
|
#define PAGE_USER 0
|
||||||
} page_t;
|
#define PAGE_SUPERVISOR 0
|
||||||
|
#define PAGE_SIZE_4KB 0
|
||||||
|
#define PAGE_SIZE_4MB 1
|
||||||
|
#define FRAME_ALLOCATION_SECTION_SIZE 32
|
||||||
|
#define USED_FRAME_ALLOCATIONS_SECTION 0xFFFFFFFF
|
||||||
|
#define FREE_FRAME_ALLOCATIONS_SECTION 0x00000000
|
||||||
|
|
||||||
typedef struct page_table {
|
// Reserve 16 MiB of physical memory
|
||||||
page_t pages[1024];
|
#define PHYSICAL_MEMORY_SIZE 0x10000000
|
||||||
} page_table_t;
|
|
||||||
|
|
||||||
typedef struct page_directory {
|
struct page { // Page structure from Intel's developer manual
|
||||||
page_table_t *tables[1024]; // array of pointers to page tables
|
uint8_t present : 1;
|
||||||
uint32_t tables_physical[1024]; // address of tables physical.
|
uint8_t rw : 1;
|
||||||
uint32_t physical_addr;
|
uint8_t user : 1;
|
||||||
} page_directory_t;
|
uint8_t pwt : 1;
|
||||||
|
uint8_t pcd : 1;
|
||||||
|
uint8_t a : 1;
|
||||||
|
uint8_t d : 1;
|
||||||
|
uint8_t pat : 1;
|
||||||
|
uint8_t g : 1;
|
||||||
|
uint8_t unused : 3;
|
||||||
|
uint32_t frame : 20;
|
||||||
|
} __attribute__((packed));
|
||||||
|
typedef struct page page_t;
|
||||||
|
|
||||||
|
struct page_table {
|
||||||
|
page_t pages[PAGE_TABLE_SIZE];
|
||||||
|
};
|
||||||
|
typedef struct page_table page_table_t;
|
||||||
|
|
||||||
|
/* For each page we hold two arrays:
|
||||||
|
* one is used by the CPU to hold the physical address
|
||||||
|
* the other is used to hold the virtual address to actual read
|
||||||
|
* or write to it. */
|
||||||
|
struct page_directory {
|
||||||
|
page_table_t *page_table_virtual[PAGE_DIRECTORY_SIZE];
|
||||||
|
uint32_t page_table_physical[PAGE_DIRECTORY_SIZE];
|
||||||
|
};
|
||||||
|
typedef struct page_directory page_directory_t;
|
||||||
|
|
||||||
// Setup the environment
|
// Setup the environment
|
||||||
void init_paging();
|
void init_paging();
|
||||||
// Load specified page directory into CR3 register
|
// Load specified page directory into CR3 register
|
||||||
void switch_page_directory(page_directory_t *new);
|
void enable_paging(page_directory_t *new);
|
||||||
// Retrieve pointer to specified page address
|
// Retrieve pointer to specified page address
|
||||||
page_t *get_page(uint32_t addr, int32_t make, page_directory_t *dir);
|
page_t *get_page(uint32_t addr, int32_t make, page_directory_t *dir);
|
||||||
// Handle page faults
|
// Handle page faults
|
||||||
void page_fault(registers_t regs);
|
void page_fault(registers_t regs);
|
||||||
// Allocate a new frame
|
// Allocate a new frame
|
||||||
void alloc_frame(page_t *page, int32_t is_kernel, int32_t is_writeable);
|
void alloc_frame(page_t *page, int32_t is_supervisored, int32_t is_writeable);
|
||||||
// Deallocate frame
|
// Deallocate frame
|
||||||
void free_frame(page_t *page);
|
void free_frame(page_t *page);
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,13 @@
|
||||||
#include "drivers/idt.h"
|
#include "drivers/idt.h"
|
||||||
#include "drivers/timer.h"
|
#include "drivers/timer.h"
|
||||||
#include "drivers/keyboard.h"
|
#include "drivers/keyboard.h"
|
||||||
|
#include "drivers/paging.h"
|
||||||
|
#include "drivers/kheap.h"
|
||||||
#include "shell/shell.h"
|
#include "shell/shell.h"
|
||||||
#include "libc/stdio.h"
|
#include "libc/stdio.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void kernel_main() {
|
void kernel_main() {
|
||||||
printf_color("\n[STATUS]", LIGHT_GREEN, BLACK);
|
printf_color("\n[STATUS]", LIGHT_GREEN, BLACK);
|
||||||
printf_color(" - Loading kernel, wait please...", WHITE, BLACK);
|
printf_color(" - Loading kernel, wait please...", WHITE, BLACK);
|
||||||
|
@ -33,6 +37,19 @@ void kernel_main() {
|
||||||
printf_color("\n[INFO]", LIGHT_CYAN, BLACK);
|
printf_color("\n[INFO]", LIGHT_CYAN, BLACK);
|
||||||
printf_color(" - Loaded PS/2 driver", WHITE, BLACK);
|
printf_color(" - Loaded PS/2 driver", WHITE, BLACK);
|
||||||
|
|
||||||
|
printf_color("\n[TEST]", LIGHT_BROWN, BLACK); // Testing heap
|
||||||
|
printf_color(" - Allocating heap blocks..\n", LIGHT_BROWN, BLACK);
|
||||||
|
|
||||||
|
uint32_t x = kmalloc(8), y = kmalloc(16), z = kmalloc(32);
|
||||||
|
printf("x: %x, y: %x, z: %x", x, y, z);
|
||||||
|
|
||||||
|
printf_color("\n[TEST]", LIGHT_BROWN, BLACK); // Testing heap
|
||||||
|
printf_color(" - Freeing heap blocks..\n", LIGHT_BROWN, BLACK);
|
||||||
|
kfree((void*)x), kfree((void*)y), kfree((void*)z);
|
||||||
|
|
||||||
|
printf_color("\n[STATUS]", LIGHT_GREEN, BLACK);
|
||||||
|
printf_color(" - Heap worked successfullt!", WHITE, BLACK);
|
||||||
|
|
||||||
iceos_ascii_logo();
|
iceos_ascii_logo();
|
||||||
init_prompt(); // Initialize frame buffer
|
init_prompt(); // Initialize frame buffer
|
||||||
}
|
}
|
Loading…
Reference in New Issue