120 lines
No EOL
3.4 KiB
C
120 lines
No EOL
3.4 KiB
C
#include "paging.h"
|
|
#include "libc/stdio.h"
|
|
|
|
/// Use a bitmap to keep track of allocated pages
|
|
char pages_status[PAGING_MAX_PAGES/8];
|
|
/// Kernel page directory (ATTENTION need to be 4096)
|
|
u32 k_pd[PAGING_MAX_DIR_ENTRY] __attribute__((aligned(4096)));
|
|
/// Kernel page table
|
|
u32 k_pt[PAGING_MAX_DIR_ENTRY][1024] __attribute__((aligned(4096)));
|
|
|
|
void paging_enable(){
|
|
// Init pages status
|
|
for(int i=0;i<PAGING_MAX_PAGES/8;i++)
|
|
pages_status[i]=0;
|
|
|
|
// Init page directory
|
|
for(int i=0;i<PAGING_MAX_DIR_ENTRY;i++){
|
|
k_pd[i]=0;
|
|
}
|
|
k_pd[0]=((int)&k_pt[0][0]);
|
|
k_pd[0]|=7; // Permissions
|
|
|
|
// Init page table 0
|
|
int addr_offset=0;
|
|
for(int i=0;i<1024;i++){
|
|
k_pt[0][i]=addr_offset;
|
|
k_pt[0][i]|=7; // Permission
|
|
paging_set_usage(addr_offset,1); // Mark addr as used
|
|
addr_offset+=PAGING_PAGE_SIZE; // 4Ko pages
|
|
}
|
|
|
|
// Allow access to more ram
|
|
for(int i=1;i<PAGING_MAX_DIR_ENTRY;i++){
|
|
k_pd[i]=((int)&k_pt[i][0]);
|
|
k_pd[i]|=7; // Permissions
|
|
for(int j=0;j<1024;j++){
|
|
k_pt[i][j]=addr_offset;
|
|
k_pt[i][j]|=7; // Permission
|
|
addr_offset+=PAGING_PAGE_SIZE; // 4Ko pages
|
|
}
|
|
}
|
|
|
|
// Turns on paging
|
|
asm(
|
|
"movl %0, %%eax \n\t"
|
|
"movl %%eax, %%cr3 \n\t" // Configure page table location
|
|
"movl %%cr0, %%eax \n\t"
|
|
"orl %1, %%eax \n\t"
|
|
"movl %%eax, %%cr0 \n\t" // Turn on paging
|
|
:: "b" (k_pd), "i" (PAGING_CR0_BIT)
|
|
);
|
|
}
|
|
void paging_set_usage(int addr,char state){
|
|
char bytes=pages_status[addr/PAGING_PAGE_SIZE/8];
|
|
char bit=addr/PAGING_PAGE_SIZE%8;
|
|
if(state=0)
|
|
pages_status[addr/PAGING_PAGE_SIZE/8]=~(1<<bit)&bytes;
|
|
else
|
|
pages_status[addr/PAGING_PAGE_SIZE/8]=(1<<bit)|bytes;
|
|
}
|
|
|
|
void paging_dump(int min,int max){
|
|
for(int i=0;i<(PAGING_MAX_PAGES/8);i++){
|
|
for(int j=0;j<8;j++){
|
|
char status=(pages_status[i]>>j)&0x1;
|
|
if((i*8+j)>=min){
|
|
if((i*8+j)<max || max<0)
|
|
printi(status);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
char* paging_allocate_next_page(){
|
|
for(int i=0;i<(PAGING_MAX_PAGES/8);i++){
|
|
char bytes=pages_status[i];
|
|
for(int j=0;j<8;j++){
|
|
char state=(bytes>>j)&1;
|
|
if(state!=1){
|
|
int page_id=i*8+j;
|
|
int page_addr=PAGING_PAGE_SIZE*page_id;
|
|
paging_set_usage(page_addr,1);
|
|
return((char*)page_addr);
|
|
}
|
|
}
|
|
}
|
|
print("Could not allocate anymore pages! Stopping...");
|
|
asm("hlt");
|
|
}
|
|
|
|
// TODO: Take p into account
|
|
int *paging_allocate(int p){
|
|
// ----- Allow kernel access during interruption
|
|
int *page_dir=(int*)paging_allocate_next_page();
|
|
int *k_page_table=(int*)paging_allocate_next_page();
|
|
// Init page directory
|
|
page_dir[0]=(int)k_page_table|3;
|
|
// Init page table 0
|
|
int addr_offset=0;
|
|
for(int i=0;i<1024;i++){
|
|
k_page_table[i]=addr_offset;
|
|
k_page_table[i]|=3; // Permission
|
|
addr_offset+=PAGING_PAGE_SIZE; // 4Ko pages
|
|
}
|
|
|
|
// ----- Task table
|
|
int *u_page_table=(int*)paging_allocate_next_page();
|
|
page_dir[1]=(int)u_page_table|7; // 1024*1024*4096/4
|
|
u_page_table[0]=(int)page_dir|7;
|
|
u_page_table[1]=(int)k_page_table|7;
|
|
u_page_table[2]=(int)u_page_table|7;
|
|
u_page_table[3]=(int)paging_allocate_next_page()|7;
|
|
|
|
return page_dir;
|
|
}
|
|
|
|
void paging_page_fault(){
|
|
print("Page fault!");
|
|
asm("hlt");
|
|
} |