Skip to content

Commit e053bf2

Browse files
committed
Refactor paging to allow proper mapping
1 parent 4cb2efb commit e053bf2

File tree

5 files changed

+92
-114
lines changed

5 files changed

+92
-114
lines changed

rost/exec/elf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ fn write(msg: &str, value: u32) {
158158

159159
unsafe fn load_program_header(buffer: *u8, header: &ProgramHeader) {
160160
console::write_str("load_program_header()\n");
161-
paging::map(header.p_vaddr, header.p_memsz);
161+
paging::map(header.p_vaddr, header.p_memsz, paging::FLAG_WRITE);
162162
let vaddr = header.p_vaddr as *mut u8;
163163
console::write_str("Loading data at ");
164164
console::write_hex(vaddr as u32);

rost/memory/allocator.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
static FRAME_SIZE: u32 = 0x1000;
2+
3+
static mut next_frame: u32 = 1024; // First 1MB is in use, TODO: Make this nicer
4+
5+
6+
pub fn init() {
7+
unsafe {
8+
// Mark frames up to kernel_end as used
9+
extern { static kernel_end: u32; }
10+
next_frame = kernel_end % FRAME_SIZE + 1;
11+
}
12+
}
13+
14+
pub fn allocate_frame() -> u32 {
15+
unsafe {
16+
let frame = next_frame;
17+
next_frame += 1;
18+
frame * FRAME_SIZE
19+
}
20+
}

rost/memory/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
pub mod paging;
1+
pub mod allocator;
2+
pub mod paging;

rost/memory/paging.rs

Lines changed: 68 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,78 @@ use core::mem::size_of;
22

33
use kernel::console;
44
use arch::idt;
5+
use memory::allocator;
56

67
static PAGE_SIZE: u32 = 0x1000;
78

9+
static NUM_ENTRIES: u32 = 1024;
10+
811
#[packed]
912
struct Page(u32);
1013

1114
#[packed]
1215
struct PageTable {
13-
pages: [Page, ..1024]
16+
entries: [Page, ..NUM_ENTRIES]
1417
}
1518

16-
#[packed]
17-
struct PageDirectory {
18-
tables: [u32, ..1024]
19-
}
19+
static mut kernel_directory: *mut PageTable = 0xFFFFF000 as *mut PageTable;
20+
static PAGES : u32 = 0xFFC00000;
2021

21-
static mut kernel_directory: *mut PageDirectory = 0 as *mut PageDirectory;
22+
pub static FLAG_PRESENT: u32 = 1 << 0;
23+
pub static FLAG_WRITE: u32 = 1 << 1;
24+
pub static FLAG_USER: u32 = 1 << 2;
2225

23-
static NO_FLAGS: u32 = 0;
24-
static FLAG_PRESENT: u32 = 1 << 0;
25-
static FLAG_WRITE: u32 = 1 << 1;
26-
static FLAG_USER: u32 = 1 << 2;
27-
28-
static mut next_frame: u32 = 0;
29-
fn get_next_frame() -> u32 {
26+
pub fn init() {
3027
unsafe {
31-
let frame = next_frame;
32-
next_frame += 1;
33-
frame
28+
let directory = allocator::allocate_frame() as *mut PageTable;
29+
*directory = PageTable::empty();
30+
31+
let table = allocator::allocate_frame() as *mut PageTable;
32+
*table = PageTable::empty();
33+
34+
// Identity map table the whole table, 4MB
35+
let mut i = 0;
36+
while i < PAGE_SIZE * NUM_ENTRIES {
37+
let page = (*table).get_page(i);
38+
page.set(i, FLAG_PRESENT | FLAG_WRITE);
39+
i += PAGE_SIZE;
40+
}
41+
42+
(*directory).set_entry(0, table, FLAG_PRESENT | FLAG_WRITE);
43+
44+
// Map the directory itself as the last entry
45+
(*directory).set_entry(dir_index(kernel_directory as u32), directory, FLAG_PRESENT | FLAG_WRITE);
46+
47+
idt::register_isr_handler(14, page_fault);
48+
49+
switch_page_directory(unsafe { directory });
3450
}
3551
}
3652

37-
pub fn init() {
53+
pub fn map(addr: u32, size: u32, flags: u32) {
3854
unsafe {
39-
kernel_directory = box_alloc(PageDirectory::new());
40-
}
55+
// FIXME: We assume the table doesn't exist and it can hold the whole size
56+
let directory_index = dir_index(addr);
4157

42-
// Identity map all currently used memory
43-
let mut i = 0;
44-
// We don't currently have a real malloc so just use some extra space
45-
while i < unsafe { placement_address + PAGE_SIZE * 10 } {
46-
let page = unsafe { (*kernel_directory).get_page(i) };
47-
page.set(get_next_frame() * PAGE_SIZE, FLAG_PRESENT | FLAG_WRITE);
48-
i += PAGE_SIZE;
49-
}
58+
let table_physical = allocator::allocate_frame() as *mut PageTable;
59+
(*kernel_directory).set_entry(directory_index, table_physical, FLAG_PRESENT | flags);
5060

51-
idt::register_isr_handler(14, page_fault);
61+
let table = page_table(directory_index);
62+
// Flush table so we can write to its virtual address
63+
flush_tlb(table);
5264

53-
switch_page_directory(unsafe { kernel_directory });
54-
}
65+
*table = PageTable::empty();
5566

56-
pub fn map(addr: u32, size: u32) {
57-
let mut current_addr = addr;
58-
while current_addr < addr + size {
59-
let page = unsafe { (*kernel_directory).get_page(current_addr) };
60-
page.set(get_next_frame() * PAGE_SIZE, FLAG_PRESENT | FLAG_WRITE);
61-
flush_tlb(current_addr);
67+
let mut current_addr = addr;
68+
while current_addr < addr + size {
69+
let page = (*table).get_page(current_addr);
6270

63-
current_addr += PAGE_SIZE;
64-
}
71+
page.set(allocator::allocate_frame(), FLAG_PRESENT | FLAG_WRITE);
72+
flush_tlb(current_addr);
6573

66-
console::write_str("Mapping: ");
67-
console::write_hex(addr);
68-
console::write_newline();
69-
//reload_page_directory();
74+
current_addr += PAGE_SIZE;
75+
}
76+
}
7077
}
7178

7279
fn page_fault(regs: &idt::Registers) {
@@ -110,66 +117,40 @@ impl Page {
110117

111118
impl PageTable {
112119
fn empty() -> PageTable {
113-
PageTable { pages: [Page::empty(), ..1024] }
120+
PageTable { entries: [Page::empty(), ..NUM_ENTRIES] }
114121
}
115-
}
116122

117-
impl PageDirectory {
118-
fn new() -> PageDirectory {
119-
PageDirectory {
120-
tables: [0, ..1024]
121-
}
123+
unsafe fn set_entry<T>(&mut self, index: u32, entry: *mut T, flags: u32) {
124+
self.entries[index] = Page(entry as u32 | flags);
122125
}
123126

124-
unsafe fn get_table(&mut self, address: u32) -> *mut PageTable {
125-
let table_index = address / (4096 * 1024);
126-
127-
/*console::write_str("Table index: ");
128-
console::write_num(table_index);
129-
console::write_newline();*/
130-
131-
if to_addr(self.tables[table_index]) == 0 {
132-
//console::write_str("does not exists\n");
133-
let table = box_alloc(PageTable::empty());
134-
135-
136-
137-
self.tables[table_index] = table as u32 | FLAG_PRESENT | FLAG_WRITE | FLAG_USER;
138-
table
139-
} else {
140-
//console::write_str("exists\n");
141-
to_addr(self.tables[table_index]) as *mut PageTable
142-
}
127+
unsafe fn get_page<'a>(&'a mut self, addr: u32) -> &'a mut Page {
128+
&'a mut self.entries[table_index(addr)]
143129
}
130+
}
144131

145-
unsafe fn get_page(&mut self, address: u32) -> &mut Page {
146-
let table = self.get_table(address);
147-
148-
let page_index = address / 4096;
149-
150-
/*console::write_str("Page index: ");
151-
console::write_num(page_index % 1024);
152-
console::write_newline();*/
132+
fn page_table(index: u32) -> *mut PageTable {
133+
let size = size_of::<PageTable>() as u32;
134+
(PAGES + index * size) as *mut PageTable
135+
}
153136

154-
&mut (*table).pages[page_index % 1024]
155-
}
137+
fn dir_index(addr: u32) -> u32 {
138+
addr / (PAGE_SIZE * NUM_ENTRIES)
139+
}
156140

157-
unsafe fn get_physical(&mut self, address: u32) -> u32 {
158-
let page = self.get_page(address);
159-
page.addr() + (address % 1024)
160-
}
141+
fn table_index(addr: u32) -> u32 {
142+
(addr / PAGE_SIZE) % NUM_ENTRIES
161143
}
162144

163-
fn flush_tlb(addr: u32) {
145+
fn flush_tlb<T>(addr: T) {
164146
unsafe {
165-
asm!("invlpg ($0)" :: "r"(addr) : "volatile memory");
147+
asm!("invlpg ($0)" :: "r"(addr) : "volatile", "memory");
166148
}
167149
}
168150

169-
fn switch_page_directory(directory: *mut PageDirectory) {
151+
fn switch_page_directory(directory: *mut PageTable) {
170152
unsafe {
171-
let address = (*directory).get_physical(directory as u32);
172-
write_cr3(address);
153+
write_cr3(directory as u32);
173154
// Set the paging bit in CR0 to 1
174155
write_cr0(read_cr0() | 0x80000000);
175156
}
@@ -202,28 +183,3 @@ unsafe fn read_cr0() -> u32 {
202183
unsafe fn write_cr0(value: u32) {
203184
asm!("mov $0, %cr0" :: "r"(value) :: "volatile");
204185
}
205-
206-
#[inline]
207-
unsafe fn box_alloc<T>(value: T) -> *mut T {
208-
let size = size_of::<T>();
209-
let ptr = alloc::<T>(size as u32);
210-
*ptr = value;
211-
ptr
212-
}
213-
214-
static mut placement_address: u32 = 0;
215-
unsafe fn alloc<T>(size: u32) -> *mut T {
216-
if placement_address == 0 {
217-
extern { static kernel_end: u32; }
218-
placement_address = (&kernel_end as *u32) as u32;
219-
}
220-
221-
if placement_address & !0xfff != 0 {
222-
placement_address &= !0xfff;
223-
placement_address += 0x1000;
224-
}
225-
226-
let address = placement_address;
227-
placement_address += size;
228-
address as *mut T
229-
}

rost/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub extern fn kernel_main() {
2424
arch::idt::init();
2525
drivers::init();
2626

27+
memory::allocator::init();
2728
memory::paging::init();
2829

2930
exec::syscalls::init();

0 commit comments

Comments
 (0)