From 3afd93860aec19e3e22c3e82b397b7348f5ea36f Mon Sep 17 00:00:00 2001 From: vanperdung Date: Wed, 5 Mar 2025 22:50:51 +0700 Subject: [PATCH] Temp commit --- doc/8_Paging.md | 0 dos/kernel/Makefile | 7 ++ dos/kernel/idt/idt.asm | 11 ++- dos/kernel/idt/idt.h | 2 + dos/kernel/memory/paging/paging.asm | 27 +++++++ dos/kernel/memory/paging/paging.c | 71 ++++++++++++++++++ dos/kernel/memory/paging/paging.h | 110 ++++++++++++++++++++++++++++ 7 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 doc/8_Paging.md create mode 100644 dos/kernel/memory/paging/paging.asm create mode 100644 dos/kernel/memory/paging/paging.c create mode 100644 dos/kernel/memory/paging/paging.h diff --git a/doc/8_Paging.md b/doc/8_Paging.md new file mode 100644 index 0000000..e69de29 diff --git a/dos/kernel/Makefile b/dos/kernel/Makefile index fa13b35..992fbff 100644 --- a/dos/kernel/Makefile +++ b/dos/kernel/Makefile @@ -1,4 +1,5 @@ FILE = ../build/kernel.asm.o ../build/kernel.o ../build/text.o ../build/idt.asm.o ../build/idt.o ../build/vendor_excpts.o ../build/user_intrs.o ../build/mem_utils.o ../build/io.asm.o ../build/heap.o +FILE += ../build/paging.asm.o ../build/paging.o INCLUDE = -I. C_FLAGS = -g -ffreestanding -falign-jumps -falign-functions -falign-labels -falign-loops -fstrength-reduce -fomit-frame-pointer -finline-functions -Wno-unused-function -fno-builtin -Werror -Wno-unused-label -Wno-cpp -Wno-unused-parammeter -nostdlib -nostartfiles -nodefaultlibs -Wall -O0 -Iinc -std=gnu99 @@ -42,3 +43,9 @@ all: ../build/kernel.bin ../build/heap.o: memory/heap/heap.c i686-elf-gcc ${INCLUDE} ${C_FLAGS} -std=gnu99 -c memory/heap/heap.c -o ../build/heap.o + +../build/paging.asm.o: memory/paging/paging.asm + nasm -f elf32 -g memory/paging/paging.asm -o ../build/paging.asm.o + +../build/paging.o: memory/paging/paging.c + i686-elf-gcc ${INCLUDE} ${C_FLAGS} -std=gnu99 -c memory/paging/paging.c -o ../build/paging.o \ No newline at end of file diff --git a/dos/kernel/idt/idt.asm b/dos/kernel/idt/idt.asm index d3f842d..705bed1 100644 --- a/dos/kernel/idt/idt.asm +++ b/dos/kernel/idt/idt.asm @@ -6,6 +6,16 @@ extern no_isr_handler global idt_load global int21h global no_isr +global enable_interrupts +global disable_interrupts + +enable_interrupts: + sti + ret + +disable_interrupts: + cli + ret idt_load: push ebp @@ -23,7 +33,6 @@ int21h: sti iret - no_isr: cli pushad diff --git a/dos/kernel/idt/idt.h b/dos/kernel/idt/idt.h index 78cfc3a..ba4f931 100644 --- a/dos/kernel/idt/idt.h +++ b/dos/kernel/idt/idt.h @@ -24,5 +24,7 @@ struct idtr_desc void idt_init(void); void idt_set(int index, uint32_t offset, uint16_t selector, uint8_t type_attr); +void enable_interrupts(void); +void disable_interrupts(void); #endif \ No newline at end of file diff --git a/dos/kernel/memory/paging/paging.asm b/dos/kernel/memory/paging/paging.asm new file mode 100644 index 0000000..b64c4bd --- /dev/null +++ b/dos/kernel/memory/paging/paging.asm @@ -0,0 +1,27 @@ +[BITS 32] + +section .asm + +global load_page_directory_table +global enable_paging + +load_page_directory_table: + push ebp + mov ebp, esp + + mov eax, [ebp+8] + mov cr3, eax + + pop ebp + ret + +enable_paging: + push ebp + mov ebp, esp + + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + + pop ebp + ret \ No newline at end of file diff --git a/dos/kernel/memory/paging/paging.c b/dos/kernel/memory/paging/paging.c new file mode 100644 index 0000000..029f0bc --- /dev/null +++ b/dos/kernel/memory/paging/paging.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include "paging.h" +#include "heap/heap.h" +#include "utils/mem_utils.h" + +static struct page_directory page_directory; +static struct page_table page_table; + +/* +* Tell the processor where to find out page directory by putting +* it's address into CR3 register +*/ +void load_page_directory_table(uint32_t *ptr); + +void enable_paging(void); + +static int page_directory_init(void) +{ + // Create a blank Page Directory + page_directory.entries = kmalloc(NUMS_OF_PDE * sizeof(struct page_directory_entry)); + if (!page_directory.entries) + return -1; + + memset(page_directory.entries, 0, NUMS_OF_PDE * sizeof(struct page_directory_entry)); + + /* + * Set each entry to not present so that if the MMU looks for that page table, + * it will see that it is not there yet. + */ + for (int i = 0; i < NUMS_OF_PDE; i++) + { + // A page is "not present" when it's not used + page_directory.entries[i].present = PDE_NOT_PRESENT; + page_directory.entries[i].rw = PDE_RW; + page_directory.entries[i].us = PDE_SUPERVISOR_ONLY; + } + + return 0; +} + +static int page_table_init(void) +{ + page_table.entries = kmalloc(NUMS_OF_PTE * sizeof(struct page_table_entry)); + if (!page_table.entries) + return -1; + + memset(page_table.entries, 0, NUMS_OF_PTE * sizeof(struct page_directory_entry)); + + for (int i = 0; i < NUMS_OF_PTE; i++) + { + // A page is "not present" when it's not used + page_directory.entries[i].present = PDE_NOT_PRESENT; + page_directory.entries[i].rw = PDE_RW; + page_directory.entries[i].us = PDE_SUPERVISOR_ONLY; + } + +} + +int paging_init(void) +{ + int ret; + + ret = page_directory_init(); + if (ret) + return ret; + + +} \ No newline at end of file diff --git a/dos/kernel/memory/paging/paging.h b/dos/kernel/memory/paging/paging.h new file mode 100644 index 0000000..a9a9bcf --- /dev/null +++ b/dos/kernel/memory/paging/paging.h @@ -0,0 +1,110 @@ +#ifndef __PAGING_H__ +#define __PAGING_H__ + +#include + +#define NUMS_OF_PDE 1024 +#define NUMS_OF_PTE 1024 + +#define PDE_PRESENT 1 +#define PDE_NOT_PRESENT 0 + +#define PDE_RW 1 +#define PDE_RO 0 + +#define PDE_ALL 1 +#define PDE_SUPERVISOR_ONLY 0 + + +// Currently, DOS only supports 4-KiB aligned +struct page_directory_entry +{ + // If present is set, page is actually in physical memory + uint32_t present : 1; + + // Read/Write, if rw is set, page is read/write + // Otherwise, page is read only + uint32_t rw : 1; + + // User/Supervisor, constrols access to page based on priviledge level + // If us is set, page may be accessed by all + // Otherwise, only supervisor has access to page + uint32_t us : 1; + + // Write-Through, controls "Write-Through" abilities of the page + // If pwt is set, write-through caching is enabled + // If not, then write-back is enabled instead + uint32_t pwt : 1; + + // Cache Disable, if pcd is set, page will not be cached + // Otherwise, it will be + uint32_t pcd : 1; + + // Accessed is used to discover whether PDE or PTE was reading during address translation + uint32_t accessed : 1; + uint32_t reserved2 : 1; + + // Page size determines the size of page frame + // If page_size is set, PDE maps to a page frame, that is 4MB in size + // Otherwise, PDE maps to a 4KiB page table + uint32_t page_size : 1; + uint32_t reserved1 : 4; + + // A 4-KiB aligned PTE address + uint32_t page_table_addr : 20; +}; + +struct page_directory +{ + struct page_directory_entry *entries; +}; + +struct page_table_entry +{ + // If present is set, page is actually in physical memory + uint32_t present : 1; + + // Read/Write, if rw is set, page is read/write + // Otherwise, page is read only + uint32_t rw : 1; + + // User/Supervisor, constrols access to page based on priviledge level + // If us is set, page may be access by all + // Otherwise, only supervisor has access to page + uint32_t us : 1; + + // Write-Through, controls "Write-Through" abilities of the page + // If pwt is set, write-through caching is enabled + // If not, then write-back is enabled instead + uint32_t pwt : 1; + + // Cache Disable, if pcd is set, page will not be cached + // Otherwise, it will be + uint32_t pcd : 1; + + // Accessed is used to discover whether PDE or PTE was reading during address translation + uint32_t accessed2 : 1; + + // Dirty is used to determine a page has been written to + uint32_t dirty : 1; + + // If PAT is supported, then PAT along with PCD and PWT shall indicate the memory caching type + // Otherwise, it is reserved and must be set to 0. + uint32_t pat : 1; + + // Global tells the processor not to invalidate the TLB entry corresponding to the page upon a MOV to CR3 instruction + // Bit 7 (PGE) in CR4 must be set to enable global pages. + uint32_t global : 1; + uint32_t reserved1 : 3; + + // A 4-KiB aligned physical address + uint32_t physical_addr : 20; +}; + +struct page_table +{ + struct page_table_entry *entries; +}; + + +#endif \ No newline at end of file