blob: cf5b9516bb46dd1359bced1157bdcf75b779bab1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "paging.h"
#include "libc/stdio.h"
#include "libc/math.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");
}
int *paging_allocate(int p){
// ----- Populate kernel adresses (to be able to execute interrupts codes)
int *page_dir=(int*)paging_allocate_next_page();
int *k_page_table=(int*)paging_allocate_next_page();
// Kernel is located in the first 4Mb (page dir entry 0)
page_dir[0]=(int)k_page_table|3;
int addr_offset=0;
for(int i=0;i<1024;i++){
k_page_table[i]=addr_offset;
k_page_table[i]|=3; // Permissions
addr_offset+=PAGING_PAGE_SIZE; // 4Ko pages
}
// ----- Populate task adresses
int *u_page_table=(int)paging_allocate_next_page();
page_dir[1]=(int)u_page_table|7;
int dir_entry=1; // Entry point is at 1024*4096=4194304 (page dir entry 1 and page table entry 0)
int pt_entry=0;
int p_current=max(1,p); // Allocate at least 1 page
while(p_current!=0){
u_page_table[pt_entry]=(int)paging_allocate_next_page()|7;
p_current--;
pt_entry++;
if(pt_entry%1024==0){
dir_entry++;
pt_entry=0;
u_page_table=(int*)paging_allocate_next_page();
page_dir[dir_entry]=(int)u_page_table|7;
}
}
return page_dir;
}
void paging_page_fault(){
print("Page fault!");
asm("hlt");
}
|