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 =
|
LDFLAGS =
|
||||||
|
|
||||||
DISK_IMG_FILES = kernel.bin
|
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
|
run: disk.img
|
||||||
qemu-system-x86_64 disk.img
|
qemu-system-x86_64 disk.img
|
||||||
@ -26,7 +26,7 @@ boot.sector: boot.asm
|
|||||||
boot.stage2: boot_stage2.ld boot.stage2.o
|
boot.stage2: boot_stage2.ld boot.stage2.o
|
||||||
ld $(LDFLAGS) -T $< 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 $<
|
gcc $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
%.bin: %.asm
|
%.bin: %.asm
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
OUTPUT_FORMAT(binary)
|
OUTPUT_FORMAT(binary)
|
||||||
OUTPUT_ARCH(i386:i386)
|
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)
|
OUTPUT(boot.stage2)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
@ -4,7 +4,7 @@ OUTPUT_ARCH(i386:i386)
|
|||||||
OUTPUT(kernel.bin)
|
OUTPUT(kernel.bin)
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0x80000;
|
. = 0xc0000000;
|
||||||
|
|
||||||
.text : {
|
.text : {
|
||||||
c_code_entry.o(.text)
|
c_code_entry.o(.text)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "../kernel/atapio.h"
|
#include "../kernel/atapio.h"
|
||||||
#include "../kernel/screenstuff.h"
|
#include "../kernel/screenstuff.h"
|
||||||
|
#include "../kernel/paging.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t base_low;
|
uint32_t base_low;
|
||||||
@ -10,6 +11,8 @@ typedef struct {
|
|||||||
uint32_t acpi3_extended;
|
uint32_t acpi3_extended;
|
||||||
}__attribute__((packed)) e820entry;
|
}__attribute__((packed)) e820entry;
|
||||||
|
|
||||||
|
uint8_t* bitmap = 0x100000;
|
||||||
|
|
||||||
void set_bit(uint32_t offset, uint8_t* buffer) {
|
void set_bit(uint32_t offset, uint8_t* buffer) {
|
||||||
uint32_t index = offset / 8;
|
uint32_t index = offset / 8;
|
||||||
uint32_t bit = offset % 8;
|
uint32_t bit = offset % 8;
|
||||||
@ -17,6 +20,33 @@ void set_bit(uint32_t offset, uint8_t* buffer) {
|
|||||||
buffer[index] |= (1<<(7 - bit));
|
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() {
|
void main() {
|
||||||
init_term();
|
init_term();
|
||||||
init_atapio();
|
init_atapio();
|
||||||
@ -24,11 +54,8 @@ void main() {
|
|||||||
// e820 memory map exists at 0x20000
|
// e820 memory map exists at 0x20000
|
||||||
e820entry* e820_entries = 0x20000;
|
e820entry* e820_entries = 0x20000;
|
||||||
|
|
||||||
uint8_t* bitmap = 0x100000;
|
|
||||||
|
|
||||||
// Zero out the bitmap.
|
// Zero out the bitmap.
|
||||||
for (int i=0; i<0x20000; i++)
|
memset(bitmap, 0x20000, 0);
|
||||||
bitmap[i] = 0;
|
|
||||||
// Ensure the bitmap data is clear
|
// Ensure the bitmap data is clear
|
||||||
|
|
||||||
for (int i=0; i<0x20000; i++)
|
for (int i=0; i<0x20000; i++)
|
||||||
@ -58,18 +85,54 @@ void main() {
|
|||||||
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
|
printf("Page Index: %d\nLength (Pages): %d\n", page_index, length / 4096);
|
||||||
|
|
||||||
for (int j=0; length > 4096; length -= 4096, j++) {
|
for (int j=0; length > 4096; length -= 4096, j++) {
|
||||||
uint32_t index = (page_index+j) / 8;
|
set_bit(page_index + j, bitmap);
|
||||||
uint32_t bit = (page_index+j) % 8;
|
|
||||||
|
|
||||||
bitmap[index] |= (1<<(7 - bit));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* kernel_location = 0x80000;
|
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);
|
load_file("KERNEL BIN", kernel_location);
|
||||||
|
|
||||||
printf("Stage2 success!\n");
|
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);
|
while (1);
|
||||||
((void(*)(void))kernel_location)();
|
((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