228 lines
6.6 KiB
C
228 lines
6.6 KiB
C
#include <paging.h>
|
|
|
|
u32int page_directory[1024] __attribute__((aligned(4096)));
|
|
u32int first_page_table[1024] __attribute__((aligned(4096)));
|
|
|
|
page_directory_t *current_directory = NULL;
|
|
page_directory_t *kernel_directory = NULL;
|
|
u32int nframes;
|
|
u32int *frames;
|
|
u32int full_end = 0;
|
|
|
|
u32int max(u32int a, u32int b) {
|
|
return a > b ? a : b;
|
|
}
|
|
|
|
u32int min(u32int a, u32int b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
u32int c_log_phys(u32int logical) {
|
|
page_t *page = get_page(logical, 0, current_directory);
|
|
u32int logical_frame = logical & 0xFFFFF000;
|
|
u32int offset = logical - logical_frame;
|
|
u32int real_address = page->frame * 0x1000 + offset;
|
|
return real_address;
|
|
}
|
|
|
|
void initialise_paging2() {
|
|
u32int mem_end_page = mem_upper * 1024;
|
|
nframes = mem_end_page / 0x1000;
|
|
printf("Mem upper: 0x%xu\n", mem_upper);
|
|
printf("Available memory: %uMB, NFRAMES: %u\n",
|
|
(u32int)(mem_upper / 1024 ),
|
|
nframes);
|
|
|
|
full_end = (u32int)&end;
|
|
multiboot_module_t *modules = (multiboot_module_t *)m->mods_addr;
|
|
full_end = max(full_end,modules[0].mod_end);
|
|
u32int tables = nframes / 1024;
|
|
full_end = ((full_end - 1) / 0x1000 + 1) * 0x1000;
|
|
|
|
printf("Full end: 0x%x\n", full_end);
|
|
u32int full_end_pages = full_end + 0x1000 * tables;
|
|
printf("Full end with pages: 0x%x\n", full_end_pages);
|
|
|
|
u32int frames_size = ((nframes - 1) / 32 + 1 * 32) * sizeof(u32int);
|
|
u32int frames_start = full_end_pages;
|
|
u32int frames_end = frames_start + frames_size;
|
|
|
|
frames = (u32int *)frames_start;
|
|
memset((unsigned char *)frames, 0, frames_size);
|
|
|
|
u32int pd_start = ((frames_end - 1) / 0x1000 + 1) * 0x1000;
|
|
u32int pd_size = sizeof(page_directory_t);
|
|
u32int pd_end = pd_start + pd_size;
|
|
|
|
page_directory_t *page_directory =
|
|
(page_directory_t *)pd_start;
|
|
memset((unsigned char *)page_directory, 0, sizeof(page_directory_t));
|
|
|
|
log("page_directory: 0x%x\r\n", page_directory);
|
|
unsigned int i = 0;
|
|
for (i = 0; i < 1024; i++) {
|
|
page_directory->tablesPhysical[i] = 0 | 2;
|
|
}
|
|
|
|
page_directory->physicalAddr = (u32int)page_directory->tablesPhysical;
|
|
init_heap(&kernel_heap, pd_end,
|
|
min(mem_end_page, pd_end + 0x5000),
|
|
mem_end_page, 1,1);
|
|
|
|
printf("Inicjalizacja\n");
|
|
|
|
dump_heap(&kernel_heap);
|
|
|
|
|
|
unsigned int address = 0;
|
|
|
|
current_directory = page_directory;
|
|
kernel_directory = page_directory;
|
|
|
|
//we will fill all 1024 entries, mapping 4 megabytes
|
|
|
|
log("Tworzenie mapy 1-1 dla stronnicowania\r\n");
|
|
|
|
for(address = 0; address < kernel_heap.max_address; address += 0x1000)
|
|
{
|
|
page_t *page = get_page(address, 1, page_directory);
|
|
page->frame = address >> 12;
|
|
page->present = 1;; // attributes: supervisor level,
|
|
page->rw = 1;
|
|
page->user = 0;
|
|
// read/write, present.
|
|
}
|
|
|
|
log("Oznaczenie ramek kernel + reserved as used\r\n");
|
|
log("Ramek pamięci jest: 0x%x\n", full_end_pages / 0x1000);
|
|
|
|
dump_frames();
|
|
|
|
for (u32int i = 0; i < kernel_heap.max_address; i += 0x1000) {
|
|
set_frame(i);
|
|
}
|
|
|
|
log("Zakonczono oznaczenie\r\n");
|
|
|
|
dump_frames();
|
|
|
|
/** zapisujemy, które ramki adresów fizycznych są już zajęte */
|
|
|
|
idt_set_gate(14, (unsigned)page_fault, 0x08, 0X8E);
|
|
log("Ustawiono nowy handler page fault\r\n");
|
|
|
|
switch_page_directory(page_directory);
|
|
log("Uaktywniono stronnicowanie\r\n");
|
|
|
|
printf("Slotow: 0x%x\n", kernel_heap.max_id);
|
|
|
|
}
|
|
|
|
|
|
void switch_page_directory(page_directory_t *dir) {
|
|
current_directory = dir;
|
|
asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));
|
|
u32int cr0;
|
|
asm volatile("mov %%cr0, %0": "=r"(cr0));
|
|
cr0 |= 0x80000000; // uaktywniamy stronnicowanie
|
|
asm volatile("mov %0, %%cr0":: "r"(cr0));
|
|
}
|
|
|
|
page_t *get_page(u32int address, int make, page_directory_t *dir) {
|
|
// przekształcamy adres w indeks
|
|
// log("get_page, address: 0x%x, make: %d, dir: 0x%x\r\n", address,
|
|
// make, dir);
|
|
address /= 0x1000;
|
|
// znajdujemy tablicę stron zawierający dany adres
|
|
u32int table_idx = address / 1024;
|
|
if (dir->table[table_idx]) {
|
|
// jeżeli tablica jest już aktualnie przypisana
|
|
return &dir->table[table_idx]->pages[address % 1024];
|
|
} else if(make) {
|
|
// adres podany nie jest zmapowany, ale możemy go utworzyć
|
|
dir->table[table_idx] = (page_table_t *)(full_end + 0x1000 * table_idx);
|
|
memset((unsigned char *)dir->table[table_idx], 0, sizeof(page_table_t));
|
|
dir->tablesPhysical[table_idx] = (u32int)dir->table[table_idx] | 0x3;
|
|
// PRESENT | RW | US
|
|
// log("Table: 0x%x, page: 0x%x\n", table_idx, address % 1024);
|
|
return &dir->table[table_idx]->pages[address % 1024];
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int page_fault(struct regs *r) {
|
|
u32int faulting_address;
|
|
asm volatile("mov %%cr2, %0" : "=r" (faulting_address));
|
|
|
|
|
|
int present = !(r->err_code & 0x1); // strona nie istnieje
|
|
int rw = r->err_code & 0x2; // czy strona zapisywalna
|
|
int us = r->err_code & 0x4; // czy procesor w user-mode
|
|
int reserved = r->err_code & 0x8; // nadpisywane przez cpu zarezerwowane
|
|
// bity
|
|
int id = r->err_code & 0x10; // czy spowodowane przez
|
|
// pobranie rozkazu
|
|
log("Page fault! ( ");
|
|
if (present) {
|
|
log("present");
|
|
}
|
|
if (rw) {
|
|
log("read-only ");
|
|
}
|
|
if (us) {
|
|
log("user-mode ");
|
|
}
|
|
if (reserved) {
|
|
log("reserved ");
|
|
}
|
|
if (id) {
|
|
log("instr_fetch ");
|
|
}
|
|
log(") at 0x%x\r\n", faulting_address);
|
|
|
|
printf("Page fault! ( ");
|
|
if (present) {
|
|
printf("present");
|
|
}
|
|
if (rw) {
|
|
printf("read-only ");
|
|
}
|
|
if (us) {
|
|
printf("user-mode ");
|
|
}
|
|
if (reserved) {
|
|
printf("reserved ");
|
|
}
|
|
if (id) {
|
|
printf("instr_fetch ");
|
|
}
|
|
printf(") at 0x%x\r\n", faulting_address);
|
|
|
|
PANIC("PAGE FAULT");
|
|
|
|
}
|
|
|
|
u32int* init_paging3() {
|
|
for (int i = 0; i < 1024; i++) {
|
|
page_directory[i] = 0x00000002;
|
|
}
|
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
first_page_table[i] = (i * 0x1000) | 3;
|
|
// attributes - supervisor, read/write, present
|
|
}
|
|
|
|
page_directory[0] = ((unsigned int)first_page_table) | 3;
|
|
|
|
idt_set_gate(14, (unsigned)page_fault, 0x08, 0X8E);
|
|
log("Ustawiono nowy handler page fault\r\n");
|
|
|
|
//switch_page_directory(page_directory);
|
|
log("Uaktywniono stronnicowanie\r\n");
|
|
|
|
loadPageDirectory(page_directory);
|
|
enablePaging();
|
|
return page_directory;
|
|
}
|