Added initial paging support.
This commit is contained in:
parent
e9f610d4aa
commit
65b8e7773e
4
Makefile
4
Makefile
@ -2,7 +2,7 @@ CFLAGS = -m32 -mgeneral-regs-only -nostdlib -fno-builtin -fno-exceptions -fno-le
|
||||
LDFLAGS =
|
||||
|
||||
DISK_IMG_FILES = kernel.bin
|
||||
KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o
|
||||
KERNEL32_OBJS = screenstuff.o io.o idt.o keyboard.o strings.o atapio.o c_code_entry.o kernel.o paging.o
|
||||
|
||||
run: disk.img
|
||||
qemu-system-x86_64 disk.img
|
||||
@ -26,7 +26,7 @@ boot.sector: boot.asm
|
||||
boot.stage2: boot_stage2.ld boot.stage2.o
|
||||
ld $(LDFLAGS) -T $< boot.stage2.o
|
||||
|
||||
boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o
|
||||
boot.stage2.o: src/boot_stage2/main.c io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o
|
||||
gcc $(CFLAGS) -o $@ -c $<
|
||||
|
||||
%.bin: %.asm
|
||||
|
@ -1,7 +1,7 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
OUTPUT_ARCH(i386:i386)
|
||||
|
||||
INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o)
|
||||
INPUT(io.o atapio.o strings.o c_code_entry.o screenstuff.o paging.o)
|
||||
OUTPUT(boot.stage2)
|
||||
|
||||
SECTIONS {
|
||||
|
@ -4,7 +4,7 @@ OUTPUT_ARCH(i386:i386)
|
||||
OUTPUT(kernel.bin)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x80000;
|
||||
. = 0xc0000000;
|
||||
|
||||
.text : {
|
||||
c_code_entry.o(.text)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../kernel/atapio.h"
|
||||
#include "../kernel/screenstuff.h"
|
||||
#include "../kernel/paging.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t base_low;
|
||||
@ -10,66 +11,128 @@ typedef struct {
|
||||
uint32_t acpi3_extended;
|
||||
}__attribute__((packed)) e820entry;
|
||||
|
||||
void set_bit(uint32_t offset, uint8_t* buffer) {
|
||||
uint32_t index = offset / 8;
|
||||
uint32_t bit = offset % 8;
|
||||
uint8_t* bitmap = 0x100000;
|
||||
|
||||
buffer[index] |= (1<<(7 - bit));
|
||||
void set_bit(uint32_t offset, uint8_t* buffer) {
|
||||
uint32_t index = offset / 8;
|
||||
uint32_t bit = offset % 8;
|
||||
|
||||
buffer[index] |= (1<<(7 - bit));
|
||||
}
|
||||
|
||||
void unset_bit(uint32_t offset, uint8_t* buffer) {
|
||||
uint32_t index = offset / 8;
|
||||
uint32_t bit = offset % 8;
|
||||
|
||||
buffer[index] &= (255 - (1<<(7 - bit)));
|
||||
}
|
||||
|
||||
void memset(uint8_t* base, uint32_t count, uint8_t to) {
|
||||
for (int i=0; i<count; i++) {
|
||||
base[i] = to;
|
||||
}
|
||||
}
|
||||
|
||||
void mark_unavailble(uint32_t address, uint32_t size) {
|
||||
// This function takes an address and length and marks the corresponding pages as unavailable.
|
||||
address -= address % 4096;
|
||||
if (size % 4096)
|
||||
size += 4096 - (size % 4096);
|
||||
|
||||
address /= 4096;
|
||||
size /= 4096;
|
||||
|
||||
for (int i=0; i<size; i++) {
|
||||
unset_bit(address + i, bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
init_term();
|
||||
init_atapio();
|
||||
init_term();
|
||||
init_atapio();
|
||||
|
||||
// e820 memory map exists at 0x20000
|
||||
e820entry* e820_entries = 0x20000;
|
||||
// e820 memory map exists at 0x20000
|
||||
e820entry* e820_entries = 0x20000;
|
||||
|
||||
uint8_t* bitmap = 0x100000;
|
||||
// Zero out the bitmap.
|
||||
memset(bitmap, 0x20000, 0);
|
||||
// Ensure the bitmap data is clear
|
||||
|
||||
// Zero out the bitmap.
|
||||
for (int i=0; i<0x20000; i++)
|
||||
bitmap[i] = 0;
|
||||
// Ensure the bitmap data is clear
|
||||
for (int i=0; i<0x20000; i++)
|
||||
if (bitmap[i])
|
||||
printf("Found data in bitmap at %x!\n", (bitmap+i));
|
||||
|
||||
for (int i=0; i<0x20000; i++)
|
||||
if (bitmap[i])
|
||||
printf("Found data in bitmap at %x!\n", (bitmap+i));
|
||||
for (int i=0; e820_entries[i].length_low != 0 || e820_entries[i].length_high != 0; i++) {
|
||||
e820entry entry = e820_entries[i];
|
||||
printf("BIOS-e820: Starting %x%x, length %x%x is %s\n", entry.base_high, entry.base_low, entry.length_high, entry.length_low, entry.type == 1 ? "Available" : "Reserved");
|
||||
|
||||
for (int i=0; e820_entries[i].length_low != 0 || e820_entries[i].length_high != 0; i++) {
|
||||
e820entry entry = e820_entries[i];
|
||||
printf("BIOS-e820: Starting %x%x, length %x%x is %s\n", entry.base_high, entry.base_low, entry.length_high, entry.length_low, entry.type == 1 ? "Available" : "Reserved");
|
||||
if (entry.type != 1)
|
||||
continue;
|
||||
|
||||
if (entry.type != 1)
|
||||
continue;
|
||||
uint32_t base = entry.base_low;
|
||||
uint32_t length = entry.length_low;
|
||||
|
||||
uint32_t base = entry.base_low;
|
||||
uint32_t length = entry.length_low;
|
||||
|
||||
if (base % 4096) {
|
||||
// Memory isn't page aligned, we need to fix that.
|
||||
uint32_t add_offset = 4096 - (base % 4096);
|
||||
if (length > add_offset) {
|
||||
base += add_offset;
|
||||
length -= add_offset;
|
||||
}
|
||||
}
|
||||
uint32_t page_index = base / 4096;
|
||||
|
||||
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
|
||||
|
||||
for (int j=0; length > 4096; length -= 4096, j++) {
|
||||
uint32_t index = (page_index+j) / 8;
|
||||
uint32_t bit = (page_index+j) % 8;
|
||||
|
||||
bitmap[index] |= (1<<(7 - bit));
|
||||
}
|
||||
if (base % 4096) {
|
||||
// Memory isn't page aligned, we need to fix that.
|
||||
uint32_t add_offset = 4096 - (base % 4096);
|
||||
if (length > add_offset) {
|
||||
base += add_offset;
|
||||
length -= add_offset;
|
||||
}
|
||||
}
|
||||
uint32_t page_index = base / 4096;
|
||||
|
||||
uint8_t* kernel_location = 0x80000;
|
||||
load_file("KERNEL BIN", kernel_location);
|
||||
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
|
||||
|
||||
printf("Stage2 success!\n");
|
||||
for (int j=0; length > 4096; length -= 4096, j++) {
|
||||
set_bit(page_index + j, bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
while (1);
|
||||
((void(*)(void))kernel_location)();
|
||||
mark_unavailble(bitmap, 0x20000);
|
||||
|
||||
// Page Directory
|
||||
PDE* kernel_page_directory = bitmap + 0x20000;
|
||||
// Clear the PD
|
||||
memset((uint8_t*)kernel_page_directory, 4096, 0);
|
||||
|
||||
// Clear 4MB of RAM from 0x121000 to 0x521000 for the 1024 page tables
|
||||
memset((uint8_t*)0x121000, 0x400000, 0);
|
||||
|
||||
// Construct a 1024 long PTE** at 0x521000
|
||||
for (int i=0; i<1024; i++) {
|
||||
((uint32_t*)0x521000)[i] = 0x121000 + 0x1000*i;
|
||||
}
|
||||
|
||||
PTE** kernel_page_tables = 0x521000;
|
||||
|
||||
// Mark unavailable bitmap to 0x522000
|
||||
mark_unavailble(bitmap, 0x522000 - (uint32_t)bitmap);
|
||||
|
||||
// Now we want to map some stuff.
|
||||
// But first, we should load the kernel somewhere
|
||||
|
||||
uint8_t* kernel_location = 0x522000; // Just load it at 0x522000 for now
|
||||
mark_unavailble(0x522000, 32768); // Just treat the kernel as not growing beyong 32k for now.
|
||||
|
||||
map_many_4k_phys_to_virt(0x522000, 0xc0000000, kernel_page_directory, kernel_page_tables, 8); // Map 8 pages from 0x522000 to 0xc0000000;
|
||||
map_4k_phys_to_virt((uint32_t)kernel_page_directory, 0xc0100000, kernel_page_directory, kernel_page_tables); // Map the page directory to 0xc0100000
|
||||
map_many_4k_phys_to_virt(0x121000, 0xc0101000, kernel_page_directory, kernel_page_tables, 1024); // Map 1024 pages from 0x121000 to 0xc0101000
|
||||
map_4k_phys_to_virt(0xb8000, 0xc0501000, kernel_page_directory, kernel_page_tables); // Map 0xb8000 (video) to 0xc0501000
|
||||
|
||||
map_4k_phys_to_virt(0x8000, 0x8000, kernel_page_directory, kernel_page_tables);
|
||||
|
||||
load_file("KERNEL BIN", kernel_location);
|
||||
|
||||
printf("Stage2 success!\n");
|
||||
|
||||
asm ("mov %0, %%eax;"
|
||||
"mov %%eax, %%cr3" : : "m" (kernel_page_directory));
|
||||
|
||||
asm ("mov %cr0, %eax;"
|
||||
"or $0x80000001, %eax;"
|
||||
"mov %eax, %cr0");
|
||||
|
||||
while (1);
|
||||
((void(*)(void))0xc0000000)();
|
||||
}
|
41
src/kernel/paging.c
Normal file
41
src/kernel/paging.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include "paging.h"
|
||||
|
||||
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables) {
|
||||
uint32_t pd_index = (virtual & (1023 << 20)) >> 20;
|
||||
uint32_t pt_index = (virtual & (1023 << 10)) >> 10;
|
||||
|
||||
page_directory[pd_index] = (PDE){
|
||||
.address = (uint32_t)(page_tables[pd_index]) >> 12,
|
||||
.available = 0,
|
||||
.page_4mb = 0,
|
||||
.accessed = 0,
|
||||
.disable_cache = 0,
|
||||
.write_through_cache = 0,
|
||||
.privilege = 0,
|
||||
.present = 1,
|
||||
.read_write = 1,
|
||||
|
||||
.ignored = 0,
|
||||
.ignored2 = 0
|
||||
};
|
||||
|
||||
page_tables[pd_index][pt_index] = (PTE){
|
||||
.address = physical >> 12,
|
||||
.available = 0,
|
||||
.global = 0,
|
||||
.accessed = 0,
|
||||
.disable_cache = 0,
|
||||
.dirty = 0,
|
||||
.write_through_cache = 0,
|
||||
.privilege = 0,
|
||||
.present = 1,
|
||||
.read_write = 1,
|
||||
|
||||
.ignored = 0
|
||||
};
|
||||
}
|
||||
|
||||
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count) {
|
||||
for (int i=0; i<count; i++)
|
||||
map_4k_phys_to_virt(physical + 4096*i, virtual + 4096*i, page_directory, page_tables);
|
||||
}
|
37
src/kernel/paging.h
Normal file
37
src/kernel/paging.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef PAGING_H
|
||||
#define PAGING_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "types.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t address : 20;
|
||||
uint32_t available : 3;
|
||||
uint32_t ignored : 1;
|
||||
uint32_t page_4mb : 1;
|
||||
uint32_t ignored2 : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t disable_cache : 1;
|
||||
uint32_t write_through_cache : 1;
|
||||
uint32_t privilege : 1;
|
||||
uint32_t read_write : 1;
|
||||
uint32_t present : 1;
|
||||
}__attribute__((packed)) PDE;
|
||||
|
||||
typedef struct {
|
||||
uint32_t address : 20;
|
||||
uint32_t available : 3;
|
||||
uint32_t global : 1;
|
||||
uint32_t ignored : 1;
|
||||
uint32_t dirty : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t disable_cache : 1;
|
||||
uint32_t write_through_cache : 1;
|
||||
uint32_t privilege : 1;
|
||||
uint32_t read_write : 1;
|
||||
uint32_t present : 1;
|
||||
}__attribute__((packed)) PTE;
|
||||
|
||||
void map_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables);
|
||||
void map_many_4k_phys_to_virt(uint32_t physical, uint32_t virtual, PDE* page_directory, PTE** page_tables, uint32_t count);
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user