New paging manager and multiboot2 tools

This commit is contained in:
Loic Guegan 2021-04-24 10:09:43 +02:00
parent 99019721a9
commit 657372f1be
10 changed files with 331 additions and 6 deletions

View file

@ -5,14 +5,15 @@ LD_SCRIPT := linker.ld
# Note that BOOT_OBJ do not match boot.S
# Indeed boot.o generated by boot.S should appear
# first in the kernel binary (thus it must be linked first, cf the $(EXEC) rule)
BOOT_OBJ := $(addsuffix .cc,$(basename $(shell find ./boot -name '*.cc' -name '*.S' ! -name "boot.S")))
BOOT_OBJ := $(addsuffix .o,$(basename $(shell find ./boot -name '*.cc' -o -name '*.S' ! -name "boot.S")))
DRIVERS_OBJ := $(addsuffix .o,$(basename $(shell find ./drivers -name '*.cc' -o -name '*.S')))
LIBS_OBJ := $(addsuffix .cc,$(basename $(shell find ./libs -name '*.cc' -o -name '*.S')))
LIBS_OBJ := $(addsuffix .o,$(basename $(shell find ./libs -name '*.cc' -o -name '*.S')))
CORE_OBJ := $(addsuffix .o,$(basename $(shell find ./core -name '*.cc' -o -name '*.S')))
all: $(EXEC)
$(EXEC): boot/boot.o $(BOOT_OBJ) $(DRIVERS_OBJ) $(LIBS_OBJ) $(CORE_OBJ) boucane.o
echo $(BOOT_OBJ)
$(CC) -n -T $(LD_SCRIPT) -nostdlib -o $@ $^
%.o: %.S

View file

@ -43,11 +43,11 @@ mb_header_end:
.section .text
.code32 # Require since grub do not enable long mode
MB_INFO:
.int 0xABCDEF # Will contains the Multiboot2 information data structure address
MB_INFO: # Will contains the Multiboot2 information data structure address
.long 0x0
_start:
mov %ebx,(MB_INFO)
mov %ebx, (MB_INFO)
# Zeroing the .bss section
mov $_bss_start, %eax
mov $_bss_end, %ebx

55
src/boot/multiboot2.cc Normal file
View file

@ -0,0 +1,55 @@
#include "multiboot2.hpp"
#include "libs/string.hpp"
#include "libs/stdio.hpp"
u32* mb2_find_tag(u32 *mb2_info_addr, char type){
u32 size=(u32)mb2_info_addr[0];
char *location=((char*)mb2_info_addr)+8; // Goto first tag
char *start=(char*)mb2_info_addr;
while((location-start) < size){
// Goto next 64bit align address
while(((u64)location&0x7) != 0)
location++;
// Parse type
u32 cur_type=((u32*)location)[0];
u32 cur_size=((u32*)location)[1];
if(cur_type==type){
return (u32*)location;
}
location+=cur_size;
}
return 0;
}
char mb2_find_bootloader_name(u32* mb2_info_addr, char *return_name){
u32* addr=mb2_find_tag(mb2_info_addr,2);
if(addr){
u32 size=addr[1];
memcpy(addr+2, return_name, size);
return 1;
}
return 0;
}
char mb2_find_new_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size){
u32* addr=mb2_find_tag(mb2_info_addr,15);
if(addr){
*return_size=addr[1];
*return_addr=(u64)addr+2;
return 1;
}
return 0;
}
char mb2_find_old_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size){
u32* addr=mb2_find_tag(mb2_info_addr,14);
if(addr){
*return_size=addr[1];
*return_addr=(u64)addr+2;
return 1;
}
return 0;
}

8
src/boot/multiboot2.hpp Normal file
View file

@ -0,0 +1,8 @@
#pragma once
#include "core/types.hpp"
u32* mb2_find_tag(u32 *mb2_info_addr, char type);
char mb2_find_bootloader_name(u32* mb2_info_addr, char *return_name);
char mb2_find_new_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size);
char mb2_find_old_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size);

View file

@ -1,10 +1,21 @@
#include "boucane.hpp"
#include "core/idt.hpp"
#include "boot/multiboot2.hpp"
#include "core/paging.hpp"
extern u32 MB_INFO;
extern "C" void boucane(){
clear();
printk("Booting Boucane v%d.%d.%d",VERSION_MAJOR,VERSION_MINOR, VERSION_PATH);
printk("Booting Boucane v%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR, VERSION_PATH);
idt_enable_interrupt();
paging_enable();
u64 p;
u32 size;
if(mb2_find_old_rsdp((u32*)MB_INFO,&p,&size)){
printk("RSDP Table found!");
}
while(1);
}

173
src/core/paging.cc Normal file
View file

@ -0,0 +1,173 @@
#include "paging.hpp"
#include "core/types.hpp"
#include "libs/stdio.hpp"
#include "libs/string.hpp"
char paging_status[PAGING_MAX_PAGE / 8];
void paging_enable() {
// Init status
for (int i = 0; i < PAGING_MAX_PAGE / 8; i++) {
paging_status[i] = 0;
}
// Allocate paging for the kernel (to not override the source
// code during the next paging_allocate_table() calls)
paging_allocate_contiguous(PAGING_KERNEL_USED_PAGE);
// Setting up new kernel address space
u64* pml4=paging_allocate_table();
for(int i=0;i<PAGING_KERNEL_SPACE_MAX_PAGE;i++){
int addr=i*4096;
paging_allocate_addr(pml4,addr,addr, PAGING_OPT_P|PAGING_OPT_RW); // Identity map
}
// Load new pml4
asm volatile(
"movq %0, %%rax \n\t"
"movq %%rax, %%cr3 \n\t"
:: "r" (pml4));
}
u64 paging_as_phy(u64* pml4_table, u64 virt){
u16 pml4=virt>>39&0x1FF;
u16 pdp=virt>>30&0x1FF;
u16 pd=virt>>21&0x1FF;
u16 pt=(virt>>12)&0x1FF;
u64* pdp_table=(u64*)PAGE(pml4_table[pml4]);
u64* pd_table=(u64*)PAGE(pdp_table[pdp]);
u64* pt_table=(u64*)PAGE(pd_table[pd]);
return((PAGE(pt_table[pt]))|(virt&0xFFF));
}
u64* paging_allocate_contiguous(int npages){
int n_contiguous=0;
for (int i = 0; i < PAGING_MAX_PAGE / 8; i++) {
for (int j = 0; j < 8; j++) {
char bit=(paging_status[i]&(0x1<<j))>>j;
if(bit!=1){
n_contiguous++;
}
else {
n_contiguous=0;
}
if(n_contiguous==npages){
n_contiguous--; // Since we use it now as index, not a counter
int start_page=(i*8+j)-n_contiguous;
while(n_contiguous>=0){
int cur_page=(i*8+j)-n_contiguous;
paging_status[cur_page/8]|=(0x1<<(cur_page%8)); // Allocate
n_contiguous--;
}
u64 phy_addr=(4096*start_page);
return (u64*) phy_addr;
}
}
}
printk("Could not allocate %d contigous pages. Kernel panic!",npages);
while(1);
return 0;
}
void paging_deallocate(u64 addr){
u64 page_number=PAGE(addr)/4096;
char byte=paging_status[page_number/8];
paging_status[page_number/8]=byte&(~(1<<(page_number%8)));
}
void paging_deallocate_pml4(u64* pml4){
for(int i=0;i<512;i++){
u64* pdp=(u64*)PAGE(pml4[i]);
if(pml4[i]==0)
continue;
for(int j=0;j<512;j++){
u64* pd=(u64*)PAGE(pdp[j]);
if(pdp[j]==0)
continue;
for(int k=0;k<512;k++){
u64* pt=(u64*)PAGE(pd[k]);
if(pd[k]==0)
continue;
for(int l=0;l<512;l++){
if(pt[l]==0)
continue;
paging_deallocate_table((u64*)PAGE(pt[l]));
}
paging_deallocate_table((u64*)PAGE(pd[k]));
}
paging_deallocate_table((u64*)PAGE(pdp[j]));
}
paging_deallocate_table((u64*)PAGE(pml4[i]));
}
paging_deallocate_table((u64*)PAGE((u64)pml4));
}
void paging_dump(int min, int max) {
for (int i = 0; i < PAGING_MAX_PAGE / 8; i++) {
if(i>=min && i<=max){
printk("Byte %d ", i);
for (int j = 0; j < 8; j++) {
char bit = (paging_status[i] & (0x1 << j)) >> j;
printk("%d", bit);
}
print("\n");
}
}
}
u64* paging_allocate_table(){
u64* table=paging_allocate_contiguous(8);
memset(table, 0, 32768); // nb_entries * entry size = 512 * 64
return table;
}
void paging_deallocate_table(u64* table){
char *c_table=(char*)PAGE((u64)table);
for(u8 i=0;i<8;i++){
paging_deallocate((u64)c_table);
c_table+=4096;
}
}
void paging_allocate_addr(u64* pml4_table, u64 virt, u64 phy, u16 options){
u16 pml4=virt>>39&0x1FF;
u16 pdp=virt>>30&0x1FF;
u16 pd=virt>>21&0x1FF;
u16 pt=virt>>12&0x1FF;
options&=0xFFF; // Ensure options are on 12bits
// Solve pdp
if(pml4_table[pml4] == 0){
pml4_table[pml4]=(u64)paging_allocate_table();
pml4_table[pml4]|=options;
paging_allocate_addr(pml4_table,virt,phy,options);
return;
}
// Solve pd
u64* pdp_table=(u64*)PAGE(pml4_table[pml4]);
if(pdp_table[pdp] == 0){
pdp_table[pdp]=(u64)paging_allocate_table();
pdp_table[pdp]|=options;
paging_allocate_addr(pml4_table,virt,phy,options);
return;
}
// Solve pt
u64* pd_table=(u64*)PAGE(pdp_table[pdp]);
if(pd_table[pd] == 0){
pd_table[pd]=(u64)paging_allocate_table();
pd_table[pd]|=options;
paging_allocate_addr(pml4_table,virt,phy,options);
return;
}
// Solve address
u64* pt_table=(u64*)PAGE(pd_table[pd]);
if(pt_table[pt] == 0){
pt_table[pt]=PAGE(phy);
pt_table[pt]|=options;
return;
}
printk("Virtual address %x already in use. Kernel panic!",virt);
while(1);
}

66
src/core/paging.hpp Normal file
View file

@ -0,0 +1,66 @@
#pragma once
#include "core/types.hpp"
#define PAGING_MAX_PAGE (20*512)
/**
* Current number of page (from the beginning of the ram) used by the kernel that
* should not be used by the paging allocation mechanism and should not be granted
* for allocation
*/
#define PAGING_KERNEL_USED_PAGE (2*512)
/// @brief New number of page reachable at the end of the paging_enable() call
#define PAGING_KERNEL_SPACE_MAX_PAGE (20*512)
#define PAGING_ALLOCATE() paging_allocate_contiguous(1)
#define PAGING_OPT_P 1
#define PAGING_OPT_RW (1<<1)
/// @brief Get page address that contain addr
#define PAGE(addr) (addr&(~(0xFFF)))
/**
* Setup and enable PAE paging
*/
void paging_enable();
/**
* Allocate the next available page
* and return its physical address
*/
u64* paging_allocate_contiguous(int npages);
/**
* Deallocate a page located at addr
*/
void paging_deallocate(u64 addr);
/**
* Dump a specific range of bytes in the paging_status
*/
void paging_dump(int min, int max);
/**
* Deallocate all the pages linked to a pml4
*/
void paging_deallocate_pml4(u64* pml4);
/**
* Deallocate all the pages related to a pml4 structure
*/
void paging_deallocate_table(u64* table);
/**
* Allocate table structure (pml4, pdp etc..)
*/
u64* paging_allocate_table();
/**
* Map virtual page associated to virt
* to the physical page associated with phy
*/
void paging_allocate_addr(u64* pml4_table,u64 virt, u64 phy, u16 options);
/**
* Get associated physical address
*/
u64 paging_as_phy(u64* pml4_table, u64 virt);

View file

@ -8,6 +8,13 @@ void memcpy(void* src, void* dst, u32 size){
*(c_dst+i)=*(c_src+i);
}
void memset(void *dst, char value, u64 size){
char* ptr=(char*)dst;
for(u64 i=0;i<size;i++){
ptr[i]=value;
}
}
void itoa(u64 i, char *a){
// Check if lower than 0
u8 neg=0;

View file

@ -7,6 +7,8 @@
*/
void memcpy(void *src, void *dst, u32 size);
void memset(void *dst, char value, u64 size);
/**
* Convert int to char array
*/

View file

@ -1,2 +1,4 @@
romimage: file=$BXSHARE/BIOS-bochs-latest, options=fastboot
vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
cpu: count=1, ips=10000000, reset_on_triple_fault=0