Skip to content

Commit 7e0fee6

Browse files
committed
wip
1 parent 225a154 commit 7e0fee6

11 files changed

+226
-136
lines changed

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ drivers/serial_port.o \
3232
interrupts.o \
3333
kmain.o \
3434
multiboot_utils.o \
35-
page_allocator.o \
3635
stdio.o \
3736
string.o
3837

data_structures/page_table.c

Lines changed: 188 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,39 @@
11
#include "page_table.h"
22

33
#include "../loader.h"
4+
#include "../multiboot_utils.h"
45

6+
uint32_t free_pages;
7+
8+
#define PAGE_DIRECTORY_OFFSET_BITS 10
9+
#define PAGE_TABLE_OFFSET_BITS 10
10+
#define PAGE_OFFSET_BITS 12
11+
12+
#define PAGE_SIZE_BYTES 4096
13+
#define PAGE_SIZE_DWORDS 1024
14+
15+
// #define BITMAP_SIZE 32768
16+
// Enough room for 512 MB of RAM
17+
// TODO: Find a more efficient way to initialize page allocator
18+
#define BITMAP_SIZE 4096
19+
uint32_t free_page_bitmap[BITMAP_SIZE];
20+
21+
uint32_t page_number(uint32_t address);
522
enum page_size_t {FOUR_KB, FOUR_MB};
623
enum page_privilege_t {SUPERVISOR, USER};
724
enum page_permissions_t {READ_ONLY, READ_WRITE};
825

9-
struct page_directory_entry_t {
10-
uint32_t page_table_address;
11-
} __attribute__((packed));
12-
1326
uint32_t make_page_directory_entry(
14-
uint32_t page_table_address,
27+
void* page_table_physical_address,
1528
enum page_size_t page_size,
1629
bool cache_disabled,
1730
bool write_through,
1831
enum page_privilege_t privelage,
1932
enum page_permissions_t permissions,
2033
bool present
2134
) {
22-
uint32_t entry = page_table_address;
35+
log("make_page_directory_entry()\n");
36+
uint32_t entry = (uint32_t) page_table_physical_address;
2337
entry |= page_size << 7;
2438
entry |= cache_disabled << 4;
2539
entry |= write_through << 3;
@@ -31,15 +45,15 @@ uint32_t make_page_directory_entry(
3145
}
3246

3347
uint32_t make_page_table_entry(
34-
uint32_t page_frame_address,
48+
void* page_frame_address,
3549
bool global,
3650
bool cache_disabled,
3751
bool write_through,
3852
enum page_privilege_t privelage,
3953
enum page_permissions_t permissions,
4054
bool present
4155
) {
42-
uint32_t entry = page_frame_address;
56+
uint32_t entry = (uint32_t) page_frame_address;
4357
entry |= global << 8;
4458
entry |= cache_disabled << 6;
4559
entry |= write_through << 3;
@@ -50,12 +64,104 @@ uint32_t make_page_table_entry(
5064
return entry;
5165
}
5266

67+
void mark_free(uint32_t page_number);
68+
void mark_unavailable(uint32_t page_number);
69+
5370
// 1 page = 1024 * 4 bytes = 4 kB
5471
// 1 page table = 1024 pages = 4 mB
5572
// 1 page directory = 1024 page tables = 4 gB
5673

74+
void* allocate_physical_page() {
75+
// log("allocate_physical_page()\n");
76+
for (uint32_t index = 0; index < BITMAP_SIZE; index++) {
77+
// log("allocate_physical_page() index ");
78+
// print_uint32(LOG, index);
79+
// log("\n");
80+
if (free_page_bitmap[index] != 0) {
81+
for (uint8_t bit = 0; bit < 32; bit++) {
82+
// log("allocate_physical_page() bit ");
83+
// print_uint32(LOG, bit);
84+
// log("\n");
85+
if ((free_page_bitmap[index] & (1 << bit)) != 0) {
86+
uint32_t page_number = index * 32 + bit;
87+
mark_unavailable(page_number);
88+
uint32_t* page_start = (uint32_t*) (page_number << 12);
89+
// for (uint32_t i = 0; i < PAGE_SIZE_DWORDS; i++) {
90+
// page_start[i] = 0;
91+
// }
92+
return (void*) page_start;
93+
}
94+
}
95+
}
96+
}
97+
return 0;
98+
}
99+
100+
void * page_table_virtual_address(uint32_t page_number) {
101+
uint32_t virtual_address = page_number << PAGE_OFFSET_BITS;
102+
virtual_address |= 0xFFC00000;
103+
return (void*) virtual_address;
104+
}
105+
57106
page_directory_t initialize_page_directory() {
58107
page_directory_t pd = (page_directory_t) &BootPageDirectory;
108+
log("pd: ");
109+
print_uint32(LOG, (uint32_t) pd);
110+
log("\n");
111+
112+
// Make the last entry in the pd a pointer to itself
113+
log("Setting last entry in page directory.\n");
114+
uint32_t pde = make_page_directory_entry(
115+
(void*) &BootPageDirectoryPhysicalAddress,
116+
FOUR_KB,
117+
false,
118+
false,
119+
SUPERVISOR,
120+
READ_WRITE,
121+
true
122+
);
123+
log("pde: ");
124+
print_uint32(LOG, pde);
125+
log("\n");
126+
pd[1023] = pde;
127+
128+
// dedicate one page table for memory for the kernel
129+
void* page_table_physical_address = allocate_physical_page();
130+
log("allocated physical memory for page table: ");
131+
print_uint32(LOG, (uint32_t) page_table_physical_address);
132+
log("\n");
133+
pd[768] = make_page_directory_entry(
134+
page_table_physical_address,
135+
FOUR_KB,
136+
false,
137+
false,
138+
SUPERVISOR,
139+
READ_WRITE,
140+
true
141+
);
142+
143+
// From here on out, we can access present page tables by setting the
144+
// upper bits of the address to 0xFFFFF
145+
page_table_t pt = (page_table_t) page_table_virtual_address(768);
146+
log("page_table virtual address: ");
147+
print_uint32(LOG, (uint32_t) pt);
148+
log("\n");
149+
for (uint32_t i = 0; i < 1024; i++) {
150+
void* page_base = allocate_physical_page();
151+
// log("allocated physical memory for a kernel page: ");
152+
// print_uint32(LOG, (uint32_t) page_base);
153+
// log("\n");
154+
pt[i] = make_page_table_entry(
155+
page_base,
156+
false,
157+
false,
158+
false,
159+
SUPERVISOR,
160+
READ_WRITE,
161+
true
162+
);
163+
}
164+
59165
return pd;
60166
}
61167

@@ -71,3 +177,77 @@ void print_page_directory(FILE stream, page_directory_t pd) {
71177
}
72178
}
73179
}
180+
181+
uint32_t round_up_to_nearest_page_start(uint32_t address) {
182+
if ((address & 0xFFF) != 0) {
183+
address &= 0xFFFFF000;
184+
address += 0x00001000;
185+
}
186+
return address;
187+
}
188+
189+
uint32_t round_down_to_nearest_page_start(uint32_t address) {
190+
if ((address & 0xFFF) != 0) {
191+
address &= 0xFFFFF000;
192+
address -= 0x00001000;
193+
}
194+
return address;
195+
}
196+
197+
uint32_t page_number(uint32_t address) {
198+
return address >> 12;
199+
}
200+
201+
void mark_free(uint32_t page_number) {
202+
uint32_t index = page_number >> 5;
203+
uint32_t bit = page_number & 0b11111;
204+
uint32_t value = free_page_bitmap[index];
205+
value |= (1 << bit);
206+
free_page_bitmap[index] = value;
207+
free_pages++;
208+
}
209+
210+
void mark_unavailable(uint32_t page_number) {
211+
uint32_t index = page_number >> 5;
212+
uint32_t bit = page_number & 0b11111;
213+
uint32_t value = free_page_bitmap[index];
214+
value &= ~(1 << bit);
215+
free_page_bitmap[index] = value;
216+
free_pages--;
217+
}
218+
219+
uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo) {
220+
memory_map_t * memory_map = (memory_map_t *) p_to_v(mbinfo->mmap_addr);
221+
uint32_t num_entries = mbinfo->mmap_length / sizeof(memory_map_t);
222+
223+
for (uint32_t i = 0; i < num_entries; i++) {
224+
if (memory_map[i].type == 1) {
225+
// Available
226+
uint32_t first_addr = memory_map[i].base_addr_low;
227+
uint32_t one_past_last_addr = first_addr + memory_map[i].length_low;
228+
uint32_t first_full_page = page_number(round_up_to_nearest_page_start(first_addr));
229+
uint32_t one_past_last_full_page = page_number(round_down_to_nearest_page_start(one_past_last_addr));
230+
231+
for(uint32_t i = first_full_page; i < one_past_last_full_page; i++) {
232+
mark_free(i);
233+
}
234+
} else {
235+
// Unavailable
236+
}
237+
}
238+
239+
uint32_t first_partial_page = page_number(round_down_to_nearest_page_start(kernel_memory.kernel_physical_start));
240+
uint32_t one_past_last_partial_page = page_number(round_up_to_nearest_page_start(kernel_memory.kernel_physical_end));
241+
242+
for(uint32_t i = first_partial_page; i < one_past_last_partial_page; i++) {
243+
mark_unavailable(i);
244+
}
245+
246+
// for(uint16_t i = 0; i < BITMAP_SIZE; i++) {
247+
// print_uint16(LOG, i);
248+
// print_uint32(LOG, free_page_bitmap[i]);
249+
// log("\n");
250+
// }
251+
252+
return free_pages;
253+
}

data_structures/page_table.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
#ifndef INCLUDE_PAGE_TABLE_H
22
#define INCLUDE_PAGE_TABLE_H
33

4-
#include "../types.h"
4+
#include "../multiboot.h"
55
#include "../stdio.h"
6+
#include "../types.h"
7+
8+
9+
struct kernel_memory_descriptor_t {
10+
uint32_t kernel_virtual_start;
11+
uint32_t kernel_virtual_end;
12+
uint32_t kernel_physical_start;
13+
uint32_t kernel_physical_end;
14+
};
15+
16+
void* allocate_page();
17+
uint32_t initialize_page_allocator(struct kernel_memory_descriptor_t kernel_memory, multiboot_info_t* mbinfo);
618

719
typedef uint32_t * page_directory_t;
820
typedef uint32_t * page_table_t;

data_structures/symbol_table.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "symbol_table.h"
2-
#include "../multiboot_utils.h"
32

3+
#include "../loader.h"
4+
#include "../multiboot_utils.h"
45
#include "../stdio.h"
56

67
struct symbol_table_descriptor_t {
@@ -19,8 +20,8 @@ bool load_symbol_table(struct elf_section_header_t * symbol_table_section, struc
1920
} else {
2021
symbol_table_descriptor.present = true;
2122
symbol_table_descriptor.num_symbols = symbol_table_section->sh_size / sizeof(Elf32_Sym);
22-
symbol_table_descriptor.symbols = (Elf32_Sym *) symbol_table_section->sh_addr;
23-
symbol_table_descriptor.string_table_addr = (char*) string_table_section->sh_addr;
23+
symbol_table_descriptor.symbols = (Elf32_Sym *) p_to_v(symbol_table_section->sh_addr);
24+
symbol_table_descriptor.string_table_addr = (char*) p_to_v(string_table_section->sh_addr);
2425
return true;
2526
}
2627
}

kmain.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "drivers/pic.h"
88
#include "drivers/serial_port.h"
99
#include "multiboot_utils.h"
10-
#include "page_allocator.h"
1110
#include "stdio.h"
1211
#include "types.h"
1312

@@ -82,6 +81,13 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) {
8281
pic_init();
8382
log("Initialized PIC\n");
8483

84+
uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo);
85+
log("Initialized page allocator.\n");
86+
print_uint32(LOG, free_pages);
87+
log(" free pages (");
88+
print_uint32(LOG, free_pages / 256);
89+
log(" MB)\n");
90+
8591
page_directory_t pd = initialize_page_directory();
8692
log("Initialized page directory.\n");
8793
log("Address of page directory: ");
@@ -90,18 +96,11 @@ void kmain(struct kernel_memory_descriptor_t kernel_memory, uint32_t ebx) {
9096

9197
print_page_directory(LOG, pd);
9298

93-
uint32_t free_pages = initialize_page_allocator(kernel_memory, mbinfo);
94-
log("Initialized page allocator.\n");
95-
print_uint32(LOG, free_pages);
96-
log(" free pages (");
97-
print_uint32(LOG, free_pages / 256);
98-
log(" MB)\n");
99-
100-
bad_function();
99+
// bad_function();
101100

102-
void_function_t start_program = first_module_as_a_function(mbinfo);
103-
start_program();
104-
log("Got past call to start_program()\n");
101+
// void_function_t start_program = first_module_as_a_function(mbinfo);
102+
// start_program();
103+
// log("Got past call to start_program()\n");
105104

106105
// Loop forever
107106
// User input is accepted asynchronously via interrupts

loader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
uint32_t KERNEL_VIRTUAL_BASE;
77

88
void * BootPageDirectory;
9+
void * BootPageDirectoryPhysicalAddress;
910
void * boot_pagetab1;
1011

1112
#endif /* INCLUDE_LOADER_H */

loader.s

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ loader equ (_loader - KERNEL_VIRTUAL_BASE)
7575
_loader:
7676
; NOTE: Until paging is set up, the code must be position-independent and use physical
7777
; addresses, not virtual ones!
78-
mov ecx, (BootPageDirectory - KERNEL_VIRTUAL_BASE) ; 0x104000
78+
global BootPageDirectoryPhysicalAddress
79+
BootPageDirectoryPhysicalAddress equ (BootPageDirectory - KERNEL_VIRTUAL_BASE) ; 0x104000
80+
mov ecx, BootPageDirectoryPhysicalAddress
7981
mov cr3, ecx ; Load Page Directory Base Register.
8082
8183
mov ecx, cr4
@@ -96,8 +98,8 @@ _loader:
9698
higher_half_loader:
9799
; Unmap the identity-mapped first 4MB of physical address space. It should not be needed
98100
; anymore.
99-
; mov dword [BootPageDirectory], 0
100-
; invlpg [0]
101+
mov dword [BootPageDirectory], 0
102+
invlpg [0]
101103

102104
mov esp, kernel_stack + KERNEL_STACK_SIZE ; point esp to the start of the
103105
; stack (end of memory area)

multiboot_utils.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct elf_section_header_t * get_elf_section(multiboot_info_t* info, char * sec
2626
uint32_t shndx = section_table.shndx;
2727

2828
struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr;
29-
uint32_t string_table_start = section_header_table[shndx].sh_addr;
29+
uint32_t string_table_start = p_to_v(section_header_table[shndx].sh_addr);
3030

3131
for (uint32_t i = 0; i < num_sections; i++) {
3232
uint32_t sh_name = section_header_table[i].sh_name;
@@ -51,7 +51,7 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl
5151
uint32_t shndx = table.shndx;
5252

5353
struct elf_section_header_t * section_header_table = (struct elf_section_header_t *) addr;
54-
uint32_t string_table_start = section_header_table[shndx].sh_addr;
54+
uint32_t string_table_start = p_to_v(section_header_table[shndx].sh_addr);
5555

5656
for (uint32_t i = 0; i < num; i++) {
5757
uint32_t sh_addr = section_header_table[i].sh_addr;
@@ -74,7 +74,7 @@ void print_elf_section_header_table(FILE stream, elf_section_header_table_t tabl
7474

7575
void print_memory_map(FILE stream, multiboot_info_t* info) {
7676
fprintf(stream, "\nmemory map:\n");
77-
memory_map_t * memory_map = (memory_map_t *) info->mmap_addr;
77+
memory_map_t * memory_map = (memory_map_t *) p_to_v(info->mmap_addr);
7878
uint32_t num_entries = info->mmap_length / sizeof(memory_map_t);
7979

8080
for (uint32_t i = 0; i < num_entries; i++) {

0 commit comments

Comments
 (0)