Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added doc/8_Paging.md
Empty file.
7 changes: 7 additions & 0 deletions dos/kernel/Makefile
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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
11 changes: 10 additions & 1 deletion dos/kernel/idt/idt.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,7 +33,6 @@ int21h:
sti
iret


no_isr:
cli
pushad
Expand Down
2 changes: 2 additions & 0 deletions dos/kernel/idt/idt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 27 additions & 0 deletions dos/kernel/memory/paging/paging.asm
Original file line number Diff line number Diff line change
@@ -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
71 changes: 71 additions & 0 deletions dos/kernel/memory/paging/paging.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#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;


}
110 changes: 110 additions & 0 deletions dos/kernel/memory/paging/paging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#ifndef __PAGING_H__
#define __PAGING_H__

#include <stdint.h>

#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
Loading