aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLoic Guegan <manzerbredes@mailbox.org>2021-04-24 10:09:43 +0200
committerLoic Guegan <manzerbredes@mailbox.org>2021-04-24 10:09:43 +0200
commit657372f1be95393b76a54f258ba3f937b4073abe (patch)
tree18aa2cb9b7f3e4d38a5208d9db2811f6af46fa61 /src/core
parent99019721a9e147c49becc466c5427609b937aca8 (diff)
New paging manager and multiboot2 tools
Diffstat (limited to 'src/core')
-rw-r--r--src/core/paging.cc173
-rw-r--r--src/core/paging.hpp66
2 files changed, 239 insertions, 0 deletions
diff --git a/src/core/paging.cc b/src/core/paging.cc
new file mode 100644
index 0000000..b9ab94e
--- /dev/null
+++ b/src/core/paging.cc
@@ -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);
+
+} \ No newline at end of file
diff --git a/src/core/paging.hpp b/src/core/paging.hpp
new file mode 100644
index 0000000..1457d10
--- /dev/null
+++ b/src/core/paging.hpp
@@ -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); \ No newline at end of file