Added last part of paging, print_hex function and updated linker script
This commit is contained in:
parent
3eacf3ea21
commit
9b5bf087b5
@ -1,8 +1,8 @@
|
|||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
|
|
||||||
// Extern variables are declared in the linker script
|
// end is declared in the linker script
|
||||||
extern uint32_t end;
|
extern uint32_t end;
|
||||||
extern page_directory_t *kernel_directory; // FIXME:
|
extern page_directory_t *kernel_directory;
|
||||||
uint32_t placement_addr = (uint32_t)&end;
|
uint32_t placement_addr = (uint32_t)&end;
|
||||||
heap_t *kheap = 0;
|
heap_t *kheap = 0;
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ordered_list.h"
|
#include "ordered_list.h"
|
||||||
|
#include "paging.h"
|
||||||
|
|
||||||
// Data structure for single block/hole
|
// Data structure for single block/hole
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -53,4 +53,122 @@ static uint32_t first_frame() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void alloc_frame(page_t *page, int32_t is_kernel, int32_t is_writeable) {
|
||||||
|
if(page->frame != 0)
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
uint32_t idx = first_frame();
|
||||||
|
if(idx == (uint32_t)-1) {
|
||||||
|
// panic
|
||||||
|
}
|
||||||
|
set_frame(idx*0x1000);
|
||||||
|
page->present = 1;
|
||||||
|
page->rw = (is_writeable) ? 1 : 0;
|
||||||
|
page->user = (is_kernel) ? 1 : 0;
|
||||||
|
page->frame = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_frame(page_t *page) {
|
||||||
|
uint32_t frame;
|
||||||
|
if(!(frame=page->frame))
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
clear_frame(frame);
|
||||||
|
page->frame = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_paging() {
|
||||||
|
uint32_t mem_end_page = 0x1000000; // Physical address memory(16MiB big)
|
||||||
|
nframes = mem_end_page / 0x1000;
|
||||||
|
frames = (uint32_t*)kmalloc(INDEX_FROM_BIT(nframes));
|
||||||
|
memset(frames, 0, INDEX_FROM_BIT(nframes));
|
||||||
|
|
||||||
|
// Create a page directory
|
||||||
|
kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
|
||||||
|
current_directory = kernel_directory;
|
||||||
|
|
||||||
|
/* Map pages in the kernel heap area.
|
||||||
|
* We only call get_page and not alloc_frame to create a new page_table_t
|
||||||
|
* only where necessary.*/
|
||||||
|
for(int32_t i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
||||||
|
get_page(i, 1, kernel_directory);
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
int32_t i = 0;
|
||||||
|
while(i < placement_address+0x1000) {
|
||||||
|
// Kernel code is read only from userspace
|
||||||
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
|
i += 0x1000;
|
||||||
|
}
|
||||||
|
// Perform the real allocation of what we have done so far
|
||||||
|
for(i = KHEAP_START; i < KHEAP_START+KHEAP_INITIAL_SIZE; i += 0x1000)
|
||||||
|
alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
|
||||||
|
|
||||||
|
// Register a new ISR to handle page faults
|
||||||
|
register_interrupt_handler(14, page_fault);
|
||||||
|
|
||||||
|
// Enable paging
|
||||||
|
switch_page_directory(kernel_directory);
|
||||||
|
|
||||||
|
// Set up kernel heap
|
||||||
|
kheap = create_heap(KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_page_directory(page_directory_t *dir) {
|
||||||
|
current_directory = dir;
|
||||||
|
asm volatile("mov %0, %%cr3" :: "r"(&dir->tables_physical));
|
||||||
|
uint32_t cr0;
|
||||||
|
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
||||||
|
cr0 |= 0x80000000; // code to enable paging
|
||||||
|
asm volatile("mov %0, %%cr0":: "r"(cr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
page_t *get_page(uint32_t address, int32_t make, page_directory_t *dir) {
|
||||||
|
// Turn address into an index
|
||||||
|
address /= 0x1000;
|
||||||
|
// Find page table that contains this index
|
||||||
|
uint32_t table_idx = address / 1024;
|
||||||
|
if(dir->tables[table_idx]) // If current table is already assigned
|
||||||
|
return &dir->tables[table_idx]->pages[address%1024];
|
||||||
|
else if(make) {
|
||||||
|
uint32_t tmp;
|
||||||
|
dir->tables[table_idx] = (page_table_t*)kmalloc_p(sizeof(page_table_t), &tmp);
|
||||||
|
memset(dir->tables[table_idx], 0, 0x1000);
|
||||||
|
dir->tables_physical[table_idx] = tmp | 0x7;
|
||||||
|
return &dir->tables[table_idx]->pages[address%1024];
|
||||||
|
} else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void page_fault(registers_t regs) {
|
||||||
|
// Retrieve faulted address from CR2 register
|
||||||
|
uint32_t fault_addr;
|
||||||
|
asm volatile("mov %%cr2, %0" : "=r"(fault_addr));
|
||||||
|
|
||||||
|
// Retrieve other infos about the error
|
||||||
|
int32_t present = !(regs.err_code & 0x1); // Page not present
|
||||||
|
int32_t rw = regs.err_code & 0x2; // Write operation
|
||||||
|
int32_t us = regs.err_code & 0x4; // CPU mode(kernel or user mode)
|
||||||
|
int32_t reserved = regs.err_code & 0x8;
|
||||||
|
int32_t id = regs.err_code & 0x10;
|
||||||
|
|
||||||
|
// Output of those informations
|
||||||
|
kprint("Page fault! ( ");
|
||||||
|
if(present)
|
||||||
|
kprint("present ");
|
||||||
|
if(rw)
|
||||||
|
kprint("read-only");
|
||||||
|
if(us)
|
||||||
|
kprint("user-mode");
|
||||||
|
if(reserved)
|
||||||
|
kprint("reserved");
|
||||||
|
kprint(") at 0x");
|
||||||
|
kprint_hex(fault_addr);
|
||||||
|
kprint("\n");
|
||||||
|
PANIC("Page fault");
|
||||||
}
|
}
|
@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "isr.h"
|
#include "isr.h"
|
||||||
|
#include "tty.h"
|
||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
|
|
||||||
typedef struct page {
|
typedef struct page {
|
||||||
uint32_t present : 1; // Presence in memory of single page
|
uint32_t present : 1; // Presence in memory of single page
|
||||||
uint32_t fw : 1; // if set read write otherwise read only
|
uint32_t rw : 1; // if set read write otherwise read only
|
||||||
uint32_t user : 1; // Supervisored mode only if cleared
|
uint32_t user : 1; // Supervisored mode only if cleared
|
||||||
uint32_t accessed : 1; // true if page has been accessed since last refresh
|
uint32_t accessed : 1; // true if page has been accessed since last refresh
|
||||||
uint32_t dirty : 1; // Same as above for write.
|
uint32_t dirty : 1; // Same as above for write.
|
||||||
|
@ -92,6 +92,37 @@ void kprint_dec(uint32_t num) {
|
|||||||
kprint(c2);
|
kprint(c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void kprint_hex(uint32_t num) {
|
||||||
|
int32_t tmp;
|
||||||
|
uint8_t no_zeros = 1;
|
||||||
|
|
||||||
|
kprint((uint8_t*)"0x");
|
||||||
|
|
||||||
|
for(int32_t i = 28; i > 0; i -= 4) {
|
||||||
|
tmp = (num >> i) & 0xF;
|
||||||
|
if(tmp == 0 && no_zeros != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(tmp >= 0xA) {
|
||||||
|
no_zeros = 0;
|
||||||
|
uint8_t *buf = (uint8_t*)tmp-0xA+'a';
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
|
} else {
|
||||||
|
uint8_t *buf = (uint8_t*)tmp+'a';
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = num & 0xF;
|
||||||
|
if(tmp >= 0xA) {
|
||||||
|
uint8_t *buf = (uint8_t*)tmp-0xA+'a';
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
|
} else {
|
||||||
|
uint8_t *buf = (uint8_t*)tmp+'a';
|
||||||
|
kprint_c(buf, strlen(buf), WHITE, BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init_prompt() {
|
void init_prompt() {
|
||||||
uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ ";
|
uint8_t *prompt = (uint8_t*)"\nring0@iceOS-$ ";
|
||||||
kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK);
|
kprint_c(prompt, strlen(prompt), LIGHT_RED, BLACK);
|
||||||
|
@ -54,6 +54,7 @@ void backspace();
|
|||||||
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
|
void kprint_c(uint8_t *buf, uint32_t len, uint8_t fg, uint8_t bg);
|
||||||
void kprint(uint8_t *buf);
|
void kprint(uint8_t *buf);
|
||||||
void kprint_dec(uint32_t num);
|
void kprint_dec(uint32_t num);
|
||||||
|
void kprint_hex(uint32_t num);
|
||||||
void init_prompt();
|
void init_prompt();
|
||||||
void clear_prompt();
|
void clear_prompt();
|
||||||
void clear_row(uint8_t row);
|
void clear_row(uint8_t row);
|
||||||
|
33
link.ld
33
link.ld
@ -1,35 +1,28 @@
|
|||||||
ENTRY(kernel_loader)
|
ENTRY(kernel_loader)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
|
||||||
. = 0x00100000;
|
.text 0x100000 :
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
|
|
||||||
.boot ALIGN (0x1000):
|
|
||||||
{
|
|
||||||
*(.multiboot)
|
|
||||||
}
|
|
||||||
|
|
||||||
.text ALIGN (0x1000):
|
|
||||||
{
|
{
|
||||||
|
code = .; _code = .; __code = .;
|
||||||
*(.text)
|
*(.text)
|
||||||
|
. = ALIGN(4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rodata ALIGN (0x1000):
|
.data :
|
||||||
{
|
|
||||||
*(.rodata*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.data ALIGN (0x1000):
|
|
||||||
{
|
{
|
||||||
|
data = .; _data = .; __data = .;
|
||||||
*(.data)
|
*(.data)
|
||||||
|
*(.rodata)
|
||||||
|
. = ALIGN(4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bss ALIGN (0x1000):
|
.bss :
|
||||||
{
|
{
|
||||||
*(COMMON)
|
bss = .; _bss = .; __bss = .;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
|
. = ALIGN(4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end = .; _end = .; __end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = .;
|
|
Loading…
Reference in New Issue
Block a user