réplica de
https://github.com/Arnau478/quark.git
synced 2024-11-23 21:08:07 +01:00
Scoped VMM and PMM to arch/i686
This commit is contained in:
pare
f2b4802db2
commit
707a87828b
S'han modificat 19 arxius amb 486 adicions i 486 eliminacions
33
src/kernel/arch/i686/mm/pde.c
Normal file
33
src/kernel/arch/i686/mm/pde.c
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include "pde.h"
|
||||||
|
|
||||||
|
void i686_pd_entry_add_attr(i686_pd_entry_t *entry, uint32_t attr){
|
||||||
|
*entry |= attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pd_entry_del_attr(i686_pd_entry_t *entry, uint32_t attr){
|
||||||
|
*entry &= ~attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pd_entry_set_frame(i686_pd_entry_t *entry, i686_phys_addr frame){
|
||||||
|
*entry = (*entry & ~i686_PDE_FRAME) | frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
i686_phys_addr i686_pd_entry_get_frame(i686_pd_entry_t entry){
|
||||||
|
return entry & i686_PDE_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pd_entry_is_present(i686_pd_entry_t entry){
|
||||||
|
return entry & i686_PDE_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pd_entry_is_user(i686_pd_entry_t entry){
|
||||||
|
return entry & i686_PDE_USER;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pd_entry_is_4mb(i686_pd_entry_t entry){
|
||||||
|
return entry & i686_PDE_4MB;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pd_entry_is_writable(i686_pd_entry_t entry){
|
||||||
|
return entry & i686_PDE_WRITABLE;
|
||||||
|
}
|
30
src/kernel/arch/i686/mm/pde.h
Normal file
30
src/kernel/arch/i686/mm/pde.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
|
||||||
|
enum i686_PDE_PAGE_FLAGS{
|
||||||
|
i686_PDE_PRESENT = 0x0001,
|
||||||
|
i686_PDE_WRITABLE = 0x0002,
|
||||||
|
i686_PDE_USER = 0x0004,
|
||||||
|
i686_PDE_WRITETHROUGH = 0x0008,
|
||||||
|
i686_PDE_CACHE_DISABLED = 0x0010,
|
||||||
|
i686_PDE_ACCESSED = 0x0020,
|
||||||
|
i686_PDE_DIRTY = 0x0040,
|
||||||
|
i686_PDE_4MB = 0x0080,
|
||||||
|
i686_PDE_CPU_GLOBAL = 0x0100,
|
||||||
|
i686_PDE_LV4_GLOBAL = 0x0200,
|
||||||
|
i686_PDE_FRAME = 0x7FFFF000,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t i686_pd_entry_t;
|
||||||
|
|
||||||
|
void i686_pd_entry_add_attr(i686_pd_entry_t *entry, uint32_t attr);
|
||||||
|
void i686_pd_entry_del_attr(i686_pd_entry_t *entry, uint32_t attr);
|
||||||
|
void i686_pd_entry_set_frame(i686_pd_entry_t *entry, i686_phys_addr frame);
|
||||||
|
i686_phys_addr i686_pd_entry_get_frame(i686_pd_entry_t entry);
|
||||||
|
bool i686_pd_entry_is_present(i686_pd_entry_t entry);
|
||||||
|
bool i686_pd_entry_is_user(i686_pd_entry_t entry);
|
||||||
|
bool i686_pd_entry_is_4mb(i686_pd_entry_t entry);
|
||||||
|
bool i686_pd_entry_is_writable(i686_pd_entry_t entry);
|
|
@ -1,5 +1,5 @@
|
||||||
global pmm_paging_enable
|
global i686_pmm_paging_enable
|
||||||
pmm_paging_enable:
|
i686_pmm_paging_enable:
|
||||||
[bits 32]
|
[bits 32]
|
||||||
; New call frame
|
; New call frame
|
||||||
push ebp
|
push ebp
|
||||||
|
@ -22,22 +22,22 @@ pmm_paging_enable:
|
||||||
pop ebp
|
pop ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global pmm_is_paging
|
global i686_pmm_is_paging
|
||||||
pmm_is_paging:
|
i686_pmm_is_paging:
|
||||||
[bits 32]
|
[bits 32]
|
||||||
mov eax, cr0
|
mov eax, cr0
|
||||||
and eax, 0x80000000
|
and eax, 0x80000000
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global pmm_load_pdbr
|
global i686_pmm_load_pdbr
|
||||||
pmm_load_pdbr:
|
i686_pmm_load_pdbr:
|
||||||
[bits 32]
|
[bits 32]
|
||||||
mov eax, [esp + 4]
|
mov eax, [esp + 4]
|
||||||
mov cr3, eax
|
mov cr3, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
global pmm_get_pdbr
|
global i686_pmm_get_pdbr
|
||||||
pmm_get_pdbr:
|
i686_pmm_get_pdbr:
|
||||||
[bits 32]
|
[bits 32]
|
||||||
mov eax, cr3
|
mov eax, cr3
|
||||||
ret
|
ret
|
152
src/kernel/arch/i686/mm/pmm.c
Normal file
152
src/kernel/arch/i686/mm/pmm.c
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "../../../lib/memory.h"
|
||||||
|
|
||||||
|
static uint32_t g_pmm_memory_size = 0;
|
||||||
|
static uint32_t g_pmm_used_blocks = 0;
|
||||||
|
static uint32_t g_pmm_max_blocks = 0;
|
||||||
|
static uint32_t *g_pmm_memory_map = 0;
|
||||||
|
|
||||||
|
static inline void i686_pmm_map_set(int bit){
|
||||||
|
g_pmm_memory_map[bit / 32] |= (1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void i686_pmm_map_unset(int bit){
|
||||||
|
g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool i686_pmm_map_get(int bit){
|
||||||
|
return g_pmm_memory_map[bit / 32] & (1 << (bit % 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
int i686_pmm_map_first_free(){
|
||||||
|
for(uint32_t i = 0; i < i686_pmm_get_block_count() / 32; i++){
|
||||||
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
||||||
|
for(int j = 0; j < 32; j++){
|
||||||
|
if(!(g_pmm_memory_map[i] & (1 << j))){
|
||||||
|
return i*4*8+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i686_pmm_map_first_free_s(size_t size){
|
||||||
|
if(size == 0) return -1;
|
||||||
|
if(size == 1) return i686_pmm_map_first_free();
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < i686_pmm_get_block_count() / 32; i++){
|
||||||
|
if(g_pmm_memory_map[i] != 0xffffffff){
|
||||||
|
for(int j = 0; j < 32; j++){
|
||||||
|
int bit = 1 << j;
|
||||||
|
if(!(g_pmm_memory_map[i] & bit)){
|
||||||
|
int start_bit = i*32;
|
||||||
|
start_bit+=bit;
|
||||||
|
|
||||||
|
uint32_t free = 0;
|
||||||
|
for(uint32_t count = 0; count <= size; count++){
|
||||||
|
if(!i686_pmm_map_get(start_bit+count)) free++;
|
||||||
|
if(free == size) return i*4*8+j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pmm_initialize(size_t mem_size, i686_phys_addr bitmap){
|
||||||
|
g_pmm_memory_size = mem_size;
|
||||||
|
g_pmm_memory_map = (uint32_t *)bitmap;
|
||||||
|
g_pmm_max_blocks = (i686_pmm_get_memory_size()*1024) / i686_PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks = g_pmm_max_blocks;
|
||||||
|
|
||||||
|
memset(g_pmm_memory_map, 0xFF, i686_pmm_get_block_count() / i686_PMM_BLOCKS_PER_BYTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pmm_init_region(i686_phys_addr base, size_t size){
|
||||||
|
int align = base / i686_PMM_BLOCK_SIZE;
|
||||||
|
int blocks = size / i686_PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(; blocks >= 0; blocks--){
|
||||||
|
i686_pmm_map_unset(align++);
|
||||||
|
g_pmm_used_blocks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
i686_pmm_map_set(0); // First block always set
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pmm_deinit_region(i686_phys_addr base, size_t size){
|
||||||
|
int align = base / i686_PMM_BLOCK_SIZE;
|
||||||
|
int blocks = size / i686_PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(; blocks >= 0; blocks--){
|
||||||
|
i686_pmm_map_set(align++);
|
||||||
|
g_pmm_used_blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i686_pmm_map_set(0); // First block always set
|
||||||
|
}
|
||||||
|
|
||||||
|
void *i686_pmm_alloc_block(){
|
||||||
|
if(i686_pmm_get_free_block_count() <= 0) return 0; // Out of memory
|
||||||
|
|
||||||
|
int frame = i686_pmm_map_first_free();
|
||||||
|
if(frame == -1) return 0; // Out of memory
|
||||||
|
|
||||||
|
i686_pmm_map_set(frame);
|
||||||
|
|
||||||
|
i686_phys_addr addr = frame * i686_PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks++;
|
||||||
|
|
||||||
|
return (void *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pmm_free_block(void *p){
|
||||||
|
i686_phys_addr addr = (i686_phys_addr)p;
|
||||||
|
int frame = addr / i686_PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
i686_pmm_map_unset(frame);
|
||||||
|
|
||||||
|
g_pmm_used_blocks--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *i686_pmm_alloc_blocks(size_t size){
|
||||||
|
if(i686_pmm_get_free_block_count() <= size) return 0; // Out of memory
|
||||||
|
|
||||||
|
int frame = i686_pmm_map_first_free_s(size);
|
||||||
|
if(frame == -1) return 0; // Out of memory
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size; i++) i686_pmm_map_set(frame+i);
|
||||||
|
|
||||||
|
i686_phys_addr addr = frame * i686_PMM_BLOCK_SIZE;
|
||||||
|
g_pmm_used_blocks += size;
|
||||||
|
|
||||||
|
return (void *)addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pmm_free_blocks(void *p, size_t size){
|
||||||
|
i686_phys_addr addr = (i686_phys_addr)p;
|
||||||
|
int frame = addr / i686_PMM_BLOCK_SIZE;
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size; i++) i686_pmm_map_unset(frame+i);
|
||||||
|
|
||||||
|
g_pmm_used_blocks -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t i686_pmm_get_memory_size(){
|
||||||
|
return g_pmm_memory_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i686_pmm_get_block_count(){
|
||||||
|
return g_pmm_max_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i686_pmm_get_used_block_count(){
|
||||||
|
return g_pmm_used_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t i686_pmm_get_free_block_count(){
|
||||||
|
return g_pmm_max_blocks - g_pmm_used_blocks;
|
||||||
|
}
|
28
src/kernel/arch/i686/mm/pmm.h
Normal file
28
src/kernel/arch/i686/mm/pmm.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define i686_PMM_BLOCKS_PER_BYTE 8
|
||||||
|
#define i686_PMM_BLOCK_SIZE 4096
|
||||||
|
#define i686_PMM_BLOCK_ALIGN PMM_BLOCK_SIZE
|
||||||
|
|
||||||
|
typedef uint32_t i686_phys_addr;
|
||||||
|
|
||||||
|
int i686_pmm_map_first_free();
|
||||||
|
int i686_pmm_map_first_free_s(size_t size);
|
||||||
|
void i686_pmm_initialize(size_t mem_size, i686_phys_addr bitmap);
|
||||||
|
void i686_pmm_init_region(i686_phys_addr base, size_t size);
|
||||||
|
void i686_pmm_deinit_region(i686_phys_addr base, size_t size);
|
||||||
|
void *i686_pmm_alloc_block();
|
||||||
|
void i686_pmm_free_block(void *p);
|
||||||
|
void *i686_pmm_alloc_blocks(size_t size);
|
||||||
|
void i686_pmm_free_blocks(void *p, size_t size);
|
||||||
|
size_t i686_pmm_get_memory_size();
|
||||||
|
uint32_t i686_pmm_get_block_count();
|
||||||
|
uint32_t i686_pmm_get_used_block_count();
|
||||||
|
uint32_t i686_pmm_get_free_block_count();
|
||||||
|
void __attribute__((cdecl)) i686_pmm_paging_enable(bool enabled);
|
||||||
|
bool __attribute__((cdecl)) i686_pmm_is_paging();
|
||||||
|
void __attribute__((cdecl)) i686_pmm_load_pdbr(i686_phys_addr addr);
|
||||||
|
i686_phys_addr __attribute__((cdecl)) i686_pmm_get_pdbr();
|
25
src/kernel/arch/i686/mm/pte.c
Normal file
25
src/kernel/arch/i686/mm/pte.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "pte.h"
|
||||||
|
|
||||||
|
void i686_pt_entry_add_attr(i686_pt_entry_t *entry, uint32_t attr){
|
||||||
|
*entry |= attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pt_entry_del_attr(i686_pt_entry_t *entry, uint32_t attr){
|
||||||
|
*entry &= ~attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_pt_entry_set_frame(i686_pt_entry_t *entry, i686_phys_addr frame){
|
||||||
|
*entry = (*entry & ~i686_PTE_FRAME) | frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
i686_phys_addr i686_pt_entry_get_frame(i686_pt_entry_t entry){
|
||||||
|
return entry & i686_PTE_FRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pt_entry_is_present(i686_pt_entry_t entry){
|
||||||
|
return entry & i686_PTE_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_pt_entry_is_writable(i686_pt_entry_t entry){
|
||||||
|
return entry & i686_PTE_WRITABLE;
|
||||||
|
}
|
27
src/kernel/arch/i686/mm/pte.h
Normal file
27
src/kernel/arch/i686/mm/pte.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
|
||||||
|
enum i686_PTE_PAGE_FLAGS{
|
||||||
|
i686_PTE_PRESENT = 0x0001,
|
||||||
|
i686_PTE_WRITABLE = 0x0002,
|
||||||
|
i686_PTE_USER = 0x0004,
|
||||||
|
i686_PTE_WRITETHROUGH = 0x0008,
|
||||||
|
i686_PTE_NOT_CACHEABLE = 0x0010,
|
||||||
|
i686_PTE_ACCESSED = 0x0020,
|
||||||
|
i686_PTE_DIRTY = 0x0040,
|
||||||
|
i686_PTE_PAT = 0x0080,
|
||||||
|
i686_PTE_CPU_GLOBAL = 0x0100,
|
||||||
|
i686_PTE_LV4_GLOBAL = 0x0200,
|
||||||
|
i686_PTE_FRAME = 0x7FFFF000
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef uint32_t i686_pt_entry_t;
|
||||||
|
|
||||||
|
void i686_pt_entry_add_attr(i686_pt_entry_t *entry, uint32_t attr);
|
||||||
|
void i686_pt_entry_del_attr(i686_pt_entry_t *entry, uint32_t attr);
|
||||||
|
void i686_pt_entry_set_frame(i686_pt_entry_t *entry, i686_phys_addr frame);
|
||||||
|
i686_phys_addr i686_pt_entry_get_frame(i686_pt_entry_t entry);
|
||||||
|
bool i686_pt_entry_is_present(i686_pt_entry_t entry);
|
||||||
|
bool i686_pt_entry_is_writable(i686_pt_entry_t entry);
|
|
@ -1,5 +1,5 @@
|
||||||
global vmm_flush_tlb_entry
|
global i686_vmm_flush_tlb_entry
|
||||||
vmm_flush_tlb_entry:
|
i686_vmm_flush_tlb_entry:
|
||||||
[bits 32]
|
[bits 32]
|
||||||
cli
|
cli
|
||||||
invlpg [esp + 4]
|
invlpg [esp + 4]
|
142
src/kernel/arch/i686/mm/vmm.c
Normal file
142
src/kernel/arch/i686/mm/vmm.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
#include "vmm.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
#include "../../../lib/memory.h"
|
||||||
|
|
||||||
|
i686_vmm_page_directory_t *g_vmm_current_dir = 0;
|
||||||
|
i686_phys_addr g_vmm_current_pdbr = 0;
|
||||||
|
|
||||||
|
void __attribute__((cdecl)) i686_vmm_flush_tlb_entry(i686_virt_addr addr);
|
||||||
|
|
||||||
|
static inline i686_pt_entry_t *i686_vmm_ptable_lookup_entry(i686_vmm_page_table_t *p, i686_virt_addr addr){
|
||||||
|
if(p) return &p->entries[i686_PAGE_TABLE_INDEX(addr)];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline i686_pd_entry_t *i686_vmm_pdirectory_lookup_entry(i686_vmm_page_directory_t *p, i686_virt_addr addr){
|
||||||
|
if(p) return &p->entries[i686_PAGE_DIRECTORY_INDEX(addr)];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool i686_vmm_switch_pdirectory(i686_vmm_page_directory_t *dir){
|
||||||
|
if(!dir) return false;
|
||||||
|
|
||||||
|
g_vmm_current_dir = dir;
|
||||||
|
i686_pmm_load_pdbr(g_vmm_current_pdbr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline i686_vmm_page_directory_t *i686_vmm_get_pdirectory(){
|
||||||
|
return g_vmm_current_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i686_vmm_alloc_page(i686_pt_entry_t *entry){
|
||||||
|
void *p = i686_pmm_alloc_block();
|
||||||
|
if(!p) return false;
|
||||||
|
|
||||||
|
i686_pt_entry_set_frame(entry, (i686_phys_addr)p);
|
||||||
|
i686_pt_entry_add_attr(entry, i686_PTE_PRESENT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_vmm_free_page(i686_pt_entry_t *entry){
|
||||||
|
void *p = (void *)i686_pt_entry_get_frame(*entry);
|
||||||
|
if(p) i686_pmm_free_block(p);
|
||||||
|
|
||||||
|
i686_pt_entry_del_attr(entry, i686_PTE_PRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_vmm_map_page(void *phys, void *virt){
|
||||||
|
// Get page directory
|
||||||
|
i686_vmm_page_directory_t *page_dir = i686_vmm_get_pdirectory();
|
||||||
|
|
||||||
|
// Get page table
|
||||||
|
i686_pd_entry_t *e = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
||||||
|
if((*e & i686_PTE_PRESENT) != i686_PTE_PRESENT){
|
||||||
|
// Must allocate
|
||||||
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
||||||
|
if(!table) return;
|
||||||
|
|
||||||
|
// Clear page table
|
||||||
|
memset(table, 0, sizeof(i686_vmm_page_table_t));
|
||||||
|
|
||||||
|
// Create a new entry
|
||||||
|
i686_pd_entry_t *entry = &page_dir->entries[i686_PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
||||||
|
|
||||||
|
// Map in the table
|
||||||
|
i686_pd_entry_add_attr(entry, i686_PDE_PRESENT);
|
||||||
|
i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE);
|
||||||
|
i686_pd_entry_set_frame(entry, (i686_phys_addr)table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get table
|
||||||
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_PAGE_GET_PHYS_ADDR(e);
|
||||||
|
|
||||||
|
// Get page
|
||||||
|
i686_pt_entry_t *page = &table->entries[i686_PAGE_TABLE_INDEX((uint32_t)virt)];
|
||||||
|
|
||||||
|
// Map it
|
||||||
|
i686_pt_entry_set_frame(page, (i686_phys_addr)phys);
|
||||||
|
i686_pt_entry_add_attr(page, i686_PTE_PRESENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i686_vmm_initialize(){
|
||||||
|
// Allocate default page table
|
||||||
|
i686_vmm_page_table_t *table = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
||||||
|
if(!table) return;
|
||||||
|
|
||||||
|
// Allocate 3GB page table
|
||||||
|
i686_vmm_page_table_t *table2 = (i686_vmm_page_table_t *)i686_pmm_alloc_block();
|
||||||
|
if(!table2) return;
|
||||||
|
|
||||||
|
// Clear default table
|
||||||
|
memset(table, 0, sizeof(i686_vmm_page_table_t));
|
||||||
|
|
||||||
|
// First 4MB are identity mapped
|
||||||
|
for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){
|
||||||
|
// Create a new page
|
||||||
|
i686_pt_entry_t page = 0;
|
||||||
|
i686_pt_entry_add_attr(&page, i686_PTE_PRESENT);
|
||||||
|
i686_pt_entry_set_frame(&page, frame);
|
||||||
|
|
||||||
|
// Add the page to the page table
|
||||||
|
table2->entries[i686_PAGE_TABLE_INDEX(virt)] = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map 1MB to 3GB
|
||||||
|
for(int i = 0, frame = 0x100000, virt = 0xc0000000; i<1024; i++, frame += 4096, virt += 4096){
|
||||||
|
// Create a new page
|
||||||
|
i686_pt_entry_t page = 0;
|
||||||
|
i686_pt_entry_add_attr(&page, i686_PTE_PRESENT);
|
||||||
|
i686_pt_entry_set_frame(&page, frame);
|
||||||
|
|
||||||
|
// Add the page to the page table
|
||||||
|
table->entries[i686_PAGE_TABLE_INDEX(virt)] = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create default directory table
|
||||||
|
i686_vmm_page_directory_t *dir = (i686_vmm_page_directory_t *)i686_pmm_alloc_blocks(3);
|
||||||
|
if(!dir) return;
|
||||||
|
|
||||||
|
// Clear directory table and set it as current
|
||||||
|
memset(dir, 0, sizeof(i686_vmm_page_directory_t));
|
||||||
|
|
||||||
|
i686_pd_entry_t *entry = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0xc0000000)];
|
||||||
|
i686_pd_entry_add_attr(entry, i686_PDE_PRESENT);
|
||||||
|
i686_pd_entry_add_attr(entry, i686_PDE_WRITABLE);
|
||||||
|
i686_pd_entry_set_frame(entry, (i686_phys_addr)table);
|
||||||
|
|
||||||
|
i686_pd_entry_t *entry2 = &dir->entries[i686_PAGE_DIRECTORY_INDEX(0x00000000)];
|
||||||
|
i686_pd_entry_add_attr(entry2, i686_PDE_PRESENT);
|
||||||
|
i686_pd_entry_add_attr(entry2, i686_PDE_WRITABLE);
|
||||||
|
i686_pd_entry_set_frame(entry2, (i686_phys_addr)table2);
|
||||||
|
|
||||||
|
// Store current PDBR
|
||||||
|
g_vmm_current_pdbr = (i686_phys_addr)&dir->entries;
|
||||||
|
|
||||||
|
// Switch to our page directory
|
||||||
|
i686_vmm_switch_pdirectory(dir);
|
||||||
|
|
||||||
|
// Enable paging
|
||||||
|
i686_pmm_paging_enable(true);
|
||||||
|
}
|
33
src/kernel/arch/i686/mm/vmm.h
Normal file
33
src/kernel/arch/i686/mm/vmm.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "pte.h"
|
||||||
|
#include "pde.h"
|
||||||
|
|
||||||
|
typedef uint32_t i686_virt_addr;
|
||||||
|
|
||||||
|
#define i686_PAGES_PER_TABLE 1024
|
||||||
|
#define i686_PAGES_PER_DIR 1024
|
||||||
|
|
||||||
|
#define i686_PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)
|
||||||
|
#define i686_PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)
|
||||||
|
#define i686_PAGE_GET_PHYS_ADDR(x) (*(x) & ~0xFFF)
|
||||||
|
|
||||||
|
#define i686_PTABLE_ADDR_SPACE_SIZE 0x400000
|
||||||
|
#define i686_DTABLE_ADDR_SPACE_SIZE 0x100000000
|
||||||
|
|
||||||
|
#define i686_PAGE_SIZE 4096
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
i686_pt_entry_t entries[i686_PAGES_PER_TABLE];
|
||||||
|
} i686_vmm_page_table_t;
|
||||||
|
|
||||||
|
typedef struct{
|
||||||
|
i686_pd_entry_t entries[i686_PAGES_PER_DIR];
|
||||||
|
} i686_vmm_page_directory_t;
|
||||||
|
|
||||||
|
bool i686_vmm_alloc_page(i686_pt_entry_t *entry);
|
||||||
|
void i686_vmm_free_page(i686_pt_entry_t *entry);
|
||||||
|
void i686_vmm_map_page(void *phys, void *virt);
|
||||||
|
void i686_vmm_initialize();
|
|
@ -5,8 +5,8 @@
|
||||||
#include "drivers/keyboard.h"
|
#include "drivers/keyboard.h"
|
||||||
#include "drivers/serial.h"
|
#include "drivers/serial.h"
|
||||||
#include "fs/vfs.h"
|
#include "fs/vfs.h"
|
||||||
#include "mm/pmm.h"
|
#include "arch/i686/mm/pmm.h"
|
||||||
#include "mm/vmm.h"
|
#include "arch/i686/mm/vmm.h"
|
||||||
#include "multiboot.h"
|
#include "multiboot.h"
|
||||||
|
|
||||||
extern uint8_t end; // Kernel end
|
extern uint8_t end; // Kernel end
|
||||||
|
@ -21,21 +21,21 @@ void __attribute__((cdecl)) kmain(multiboot_info_t *multiboot_info){
|
||||||
// Initialize physical memory manager
|
// Initialize physical memory manager
|
||||||
uint32_t mem_size = 1024 + multiboot_info->mem_lower + multiboot_info->mem_upper*64;
|
uint32_t mem_size = 1024 + multiboot_info->mem_lower + multiboot_info->mem_upper*64;
|
||||||
|
|
||||||
pmm_initialize(mem_size, (int)(&end));
|
i686_pmm_initialize(mem_size, (int)(&end));
|
||||||
|
|
||||||
for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){
|
for(int i = 0; i < multiboot_info->mmap_length; i += sizeof(multiboot_memory_map_t)){
|
||||||
multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i);
|
multiboot_memory_map_t *memory_map = (multiboot_memory_map_t *)(multiboot_info->mmap_addr + i);
|
||||||
printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
printf("Start Addr: 0x%x%x | Length: 0x%x%x | Size: 0x%x | Type: %i\n", memory_map->addr_h, memory_map->addr_l, memory_map->len_h, memory_map->len_l, memory_map->size, memory_map->type);
|
||||||
|
|
||||||
if(memory_map->type == 1){
|
if(memory_map->type == 1){
|
||||||
pmm_init_region(memory_map->addr_l, memory_map->len_l);
|
i686_pmm_init_region(memory_map->addr_l, memory_map->len_l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pmm_deinit_region(0x100000, (int)(&end) - 0x100000); // Deinit the section the kernel is in
|
i686_pmm_deinit_region(0x100000, (int)(&end) - 0x100000); // Deinit the section the kernel is in
|
||||||
|
|
||||||
// Initialize virtual memory
|
// Initialize virtual memory
|
||||||
vmm_initialize();
|
i686_vmm_initialize();
|
||||||
|
|
||||||
// Initialize drivers
|
// Initialize drivers
|
||||||
timer_initialize();
|
timer_initialize();
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#include "pde.h"
|
|
||||||
|
|
||||||
void pd_entry_add_attr(pd_entry_t *entry, uint32_t attr){
|
|
||||||
*entry |= attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pd_entry_del_attr(pd_entry_t *entry, uint32_t attr){
|
|
||||||
*entry &= ~attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pd_entry_set_frame(pd_entry_t *entry, phys_addr frame){
|
|
||||||
*entry = (*entry & ~PDE_FRAME) | frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
phys_addr pd_entry_get_frame(pd_entry_t entry){
|
|
||||||
return entry & PDE_FRAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pd_entry_is_present(pd_entry_t entry){
|
|
||||||
return entry & PDE_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pd_entry_is_user(pd_entry_t entry){
|
|
||||||
return entry & PDE_USER;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pd_entry_is_4mb(pd_entry_t entry){
|
|
||||||
return entry & PDE_4MB;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pd_entry_is_writable(pd_entry_t entry){
|
|
||||||
return entry & PDE_WRITABLE;
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "pmm.h"
|
|
||||||
|
|
||||||
enum PDE_PAGE_FLAGS{
|
|
||||||
PDE_PRESENT = 0x0001,
|
|
||||||
PDE_WRITABLE = 0x0002,
|
|
||||||
PDE_USER = 0x0004,
|
|
||||||
PDE_WRITETHROUGH = 0x0008,
|
|
||||||
PDE_CACHE_DISABLED = 0x0010,
|
|
||||||
PDE_ACCESSED = 0x0020,
|
|
||||||
PDE_DIRTY = 0x0040,
|
|
||||||
PDE_4MB = 0x0080,
|
|
||||||
PDE_CPU_GLOBAL = 0x0100,
|
|
||||||
PDE_LV4_GLOBAL = 0x0200,
|
|
||||||
PDE_FRAME = 0x7FFFF000,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t pd_entry_t;
|
|
||||||
|
|
||||||
void pd_entry_add_attr(pd_entry_t *entry, uint32_t attr);
|
|
||||||
void pd_entry_del_attr(pd_entry_t *entry, uint32_t attr);
|
|
||||||
void pd_entry_set_frame(pd_entry_t *entry, phys_addr frame);
|
|
||||||
phys_addr pd_entry_get_frame(pd_entry_t entry);
|
|
||||||
bool pd_entry_is_present(pd_entry_t entry);
|
|
||||||
bool pd_entry_is_user(pd_entry_t entry);
|
|
||||||
bool pd_entry_is_4mb(pd_entry_t entry);
|
|
||||||
bool pd_entry_is_writable(pd_entry_t entry);
|
|
|
@ -1,152 +0,0 @@
|
||||||
#include <stdint.h>
|
|
||||||
#include "pmm.h"
|
|
||||||
#include "../lib/memory.h"
|
|
||||||
|
|
||||||
static uint32_t g_pmm_memory_size = 0;
|
|
||||||
static uint32_t g_pmm_used_blocks = 0;
|
|
||||||
static uint32_t g_pmm_max_blocks = 0;
|
|
||||||
static uint32_t *g_pmm_memory_map = 0;
|
|
||||||
|
|
||||||
static inline void pmm_map_set(int bit){
|
|
||||||
g_pmm_memory_map[bit / 32] |= (1 << (bit % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void pmm_map_unset(int bit){
|
|
||||||
g_pmm_memory_map[bit / 32] &= ~(1 << (bit % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool pmm_map_get(int bit){
|
|
||||||
return g_pmm_memory_map[bit / 32] & (1 << (bit % 32));
|
|
||||||
}
|
|
||||||
|
|
||||||
int pmm_map_first_free(){
|
|
||||||
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
|
||||||
if(g_pmm_memory_map[i] != 0xffffffff){
|
|
||||||
for(int j = 0; j < 32; j++){
|
|
||||||
if(!(g_pmm_memory_map[i] & (1 << j))){
|
|
||||||
return i*4*8+j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pmm_map_first_free_s(size_t size){
|
|
||||||
if(size == 0) return -1;
|
|
||||||
if(size == 1) return pmm_map_first_free();
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < pmm_get_block_count() / 32; i++){
|
|
||||||
if(g_pmm_memory_map[i] != 0xffffffff){
|
|
||||||
for(int j = 0; j < 32; j++){
|
|
||||||
int bit = 1 << j;
|
|
||||||
if(!(g_pmm_memory_map[i] & bit)){
|
|
||||||
int start_bit = i*32;
|
|
||||||
start_bit+=bit;
|
|
||||||
|
|
||||||
uint32_t free = 0;
|
|
||||||
for(uint32_t count = 0; count <= size; count++){
|
|
||||||
if(!pmm_map_get(start_bit+count)) free++;
|
|
||||||
if(free == size) return i*4*8+j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmm_initialize(size_t mem_size, phys_addr bitmap){
|
|
||||||
g_pmm_memory_size = mem_size;
|
|
||||||
g_pmm_memory_map = (uint32_t *)bitmap;
|
|
||||||
g_pmm_max_blocks = (pmm_get_memory_size()*1024) / PMM_BLOCK_SIZE;
|
|
||||||
g_pmm_used_blocks = g_pmm_max_blocks;
|
|
||||||
|
|
||||||
memset(g_pmm_memory_map, 0xFF, pmm_get_block_count() / PMM_BLOCKS_PER_BYTE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmm_init_region(phys_addr base, size_t size){
|
|
||||||
int align = base / PMM_BLOCK_SIZE;
|
|
||||||
int blocks = size / PMM_BLOCK_SIZE;
|
|
||||||
|
|
||||||
for(; blocks >= 0; blocks--){
|
|
||||||
pmm_map_unset(align++);
|
|
||||||
g_pmm_used_blocks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmm_map_set(0); // First block always set
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmm_deinit_region(phys_addr base, size_t size){
|
|
||||||
int align = base / PMM_BLOCK_SIZE;
|
|
||||||
int blocks = size / PMM_BLOCK_SIZE;
|
|
||||||
|
|
||||||
for(; blocks >= 0; blocks--){
|
|
||||||
pmm_map_set(align++);
|
|
||||||
g_pmm_used_blocks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmm_map_set(0); // First block always set
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pmm_alloc_block(){
|
|
||||||
if(pmm_get_free_block_count() <= 0) return 0; // Out of memory
|
|
||||||
|
|
||||||
int frame = pmm_map_first_free();
|
|
||||||
if(frame == -1) return 0; // Out of memory
|
|
||||||
|
|
||||||
pmm_map_set(frame);
|
|
||||||
|
|
||||||
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
|
||||||
g_pmm_used_blocks++;
|
|
||||||
|
|
||||||
return (void *)addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmm_free_block(void *p){
|
|
||||||
phys_addr addr = (phys_addr)p;
|
|
||||||
int frame = addr / PMM_BLOCK_SIZE;
|
|
||||||
|
|
||||||
pmm_map_unset(frame);
|
|
||||||
|
|
||||||
g_pmm_used_blocks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pmm_alloc_blocks(size_t size){
|
|
||||||
if(pmm_get_free_block_count() <= size) return 0; // Out of memory
|
|
||||||
|
|
||||||
int frame = pmm_map_first_free_s(size);
|
|
||||||
if(frame == -1) return 0; // Out of memory
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < size; i++) pmm_map_set(frame+i);
|
|
||||||
|
|
||||||
phys_addr addr = frame * PMM_BLOCK_SIZE;
|
|
||||||
g_pmm_used_blocks += size;
|
|
||||||
|
|
||||||
return (void *)addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pmm_free_blocks(void *p, size_t size){
|
|
||||||
phys_addr addr = (phys_addr)p;
|
|
||||||
int frame = addr / PMM_BLOCK_SIZE;
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < size; i++) pmm_map_unset(frame+i);
|
|
||||||
|
|
||||||
g_pmm_used_blocks -= size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t pmm_get_memory_size(){
|
|
||||||
return g_pmm_memory_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pmm_get_block_count(){
|
|
||||||
return g_pmm_max_blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pmm_get_used_block_count(){
|
|
||||||
return g_pmm_used_blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t pmm_get_free_block_count(){
|
|
||||||
return g_pmm_max_blocks - g_pmm_used_blocks;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define PMM_BLOCKS_PER_BYTE 8
|
|
||||||
#define PMM_BLOCK_SIZE 4096
|
|
||||||
#define PMM_BLOCK_ALIGN PMM_BLOCK_SIZE
|
|
||||||
|
|
||||||
typedef uint32_t phys_addr;
|
|
||||||
|
|
||||||
int pmm_map_first_free();
|
|
||||||
int pmm_map_first_free_s(size_t size);
|
|
||||||
void pmm_initialize(size_t mem_size, phys_addr bitmap);
|
|
||||||
void pmm_init_region(phys_addr base, size_t size);
|
|
||||||
void pmm_deinit_region(phys_addr base, size_t size);
|
|
||||||
void *pmm_alloc_block();
|
|
||||||
void pmm_free_block(void *p);
|
|
||||||
void *pmm_alloc_blocks(size_t size);
|
|
||||||
void pmm_free_blocks(void *p, size_t size);
|
|
||||||
size_t pmm_get_memory_size();
|
|
||||||
uint32_t pmm_get_block_count();
|
|
||||||
uint32_t pmm_get_used_block_count();
|
|
||||||
uint32_t pmm_get_free_block_count();
|
|
||||||
void __attribute__((cdecl)) pmm_paging_enable(bool enabled);
|
|
||||||
bool __attribute__((cdecl)) pmm_is_paging();
|
|
||||||
void __attribute__((cdecl)) pmm_load_pdbr(phys_addr addr);
|
|
||||||
phys_addr __attribute__((cdecl)) pmm_get_pdbr();
|
|
|
@ -1,25 +0,0 @@
|
||||||
#include "pte.h"
|
|
||||||
|
|
||||||
void pt_entry_add_attr(pt_entry_t *entry, uint32_t attr){
|
|
||||||
*entry |= attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pt_entry_del_attr(pt_entry_t *entry, uint32_t attr){
|
|
||||||
*entry &= ~attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pt_entry_set_frame(pt_entry_t *entry, phys_addr frame){
|
|
||||||
*entry = (*entry & ~PTE_FRAME) | frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
phys_addr pt_entry_get_frame(pt_entry_t entry){
|
|
||||||
return entry & PTE_FRAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pt_entry_is_present(pt_entry_t entry){
|
|
||||||
return entry & PTE_PRESENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pt_entry_is_writable(pt_entry_t entry){
|
|
||||||
return entry & PTE_WRITABLE;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "pmm.h"
|
|
||||||
|
|
||||||
enum PTE_PAGE_FLAGS{
|
|
||||||
PTE_PRESENT = 0x0001,
|
|
||||||
PTE_WRITABLE = 0x0002,
|
|
||||||
PTE_USER = 0x0004,
|
|
||||||
PTE_WRITETHROUGH = 0x0008,
|
|
||||||
PTE_NOT_CACHEABLE = 0x0010,
|
|
||||||
PTE_ACCESSED = 0x0020,
|
|
||||||
PTE_DIRTY = 0x0040,
|
|
||||||
PTE_PAT = 0x0080,
|
|
||||||
PTE_CPU_GLOBAL = 0x0100,
|
|
||||||
PTE_LV4_GLOBAL = 0x0200,
|
|
||||||
PTE_FRAME = 0x7FFFF000
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint32_t pt_entry_t;
|
|
||||||
|
|
||||||
void pt_entry_add_attr(pt_entry_t *entry, uint32_t attr);
|
|
||||||
void pt_entry_del_attr(pt_entry_t *entry, uint32_t attr);
|
|
||||||
void pt_entry_set_frame(pt_entry_t *entry, phys_addr frame);
|
|
||||||
phys_addr pt_entry_get_frame(pt_entry_t entry);
|
|
||||||
bool pt_entry_is_present(pt_entry_t entry);
|
|
||||||
bool pt_entry_is_writable(pt_entry_t entry);
|
|
|
@ -1,142 +0,0 @@
|
||||||
#include "vmm.h"
|
|
||||||
#include "pmm.h"
|
|
||||||
#include "../lib/memory.h"
|
|
||||||
|
|
||||||
vmm_page_directory_t *g_vmm_current_dir = 0;
|
|
||||||
phys_addr g_vmm_current_pdbr = 0;
|
|
||||||
|
|
||||||
void __attribute__((cdecl)) vmm_flush_tlb_entry(virt_addr addr);
|
|
||||||
|
|
||||||
static inline pt_entry_t *vmm_ptable_lookup_entry(vmm_page_table_t *p, virt_addr addr){
|
|
||||||
if(p) return &p->entries[PAGE_TABLE_INDEX(addr)];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline pd_entry_t *vmm_pdirectory_lookup_entry(vmm_page_directory_t *p, virt_addr addr){
|
|
||||||
if(p) return &p->entries[PAGE_DIRECTORY_INDEX(addr)];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool vmm_switch_pdirectory(vmm_page_directory_t *dir){
|
|
||||||
if(!dir) return false;
|
|
||||||
|
|
||||||
g_vmm_current_dir = dir;
|
|
||||||
pmm_load_pdbr(g_vmm_current_pdbr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline vmm_page_directory_t *vmm_get_pdirectory(){
|
|
||||||
return g_vmm_current_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool vmm_alloc_page(pt_entry_t *entry){
|
|
||||||
void *p = pmm_alloc_block();
|
|
||||||
if(!p) return false;
|
|
||||||
|
|
||||||
pt_entry_set_frame(entry, (phys_addr)p);
|
|
||||||
pt_entry_add_attr(entry, PTE_PRESENT);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_free_page(pt_entry_t *entry){
|
|
||||||
void *p = (void *)pt_entry_get_frame(*entry);
|
|
||||||
if(p) pmm_free_block(p);
|
|
||||||
|
|
||||||
pt_entry_del_attr(entry, PTE_PRESENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_map_page(void *phys, void *virt){
|
|
||||||
// Get page directory
|
|
||||||
vmm_page_directory_t *page_dir = vmm_get_pdirectory();
|
|
||||||
|
|
||||||
// Get page table
|
|
||||||
pd_entry_t *e = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
||||||
if((*e & PTE_PRESENT) != PTE_PRESENT){
|
|
||||||
// Must allocate
|
|
||||||
vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block();
|
|
||||||
if(!table) return;
|
|
||||||
|
|
||||||
// Clear page table
|
|
||||||
memset(table, 0, sizeof(vmm_page_table_t));
|
|
||||||
|
|
||||||
// Create a new entry
|
|
||||||
pd_entry_t *entry = &page_dir->entries[PAGE_DIRECTORY_INDEX((uint32_t)virt)];
|
|
||||||
|
|
||||||
// Map in the table
|
|
||||||
pd_entry_add_attr(entry, PDE_PRESENT);
|
|
||||||
pd_entry_add_attr(entry, PDE_WRITABLE);
|
|
||||||
pd_entry_set_frame(entry, (phys_addr)table);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get table
|
|
||||||
vmm_page_table_t *table = (vmm_page_table_t *)PAGE_GET_PHYS_ADDR(e);
|
|
||||||
|
|
||||||
// Get page
|
|
||||||
pt_entry_t *page = &table->entries[PAGE_TABLE_INDEX((uint32_t)virt)];
|
|
||||||
|
|
||||||
// Map it
|
|
||||||
pt_entry_set_frame(page, (phys_addr)phys);
|
|
||||||
pt_entry_add_attr(page, PTE_PRESENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void vmm_initialize(){
|
|
||||||
// Allocate default page table
|
|
||||||
vmm_page_table_t *table = (vmm_page_table_t *)pmm_alloc_block();
|
|
||||||
if(!table) return;
|
|
||||||
|
|
||||||
// Allocate 3GB page table
|
|
||||||
vmm_page_table_t *table2 = (vmm_page_table_t *)pmm_alloc_block();
|
|
||||||
if(!table2) return;
|
|
||||||
|
|
||||||
// Clear default table
|
|
||||||
memset(table, 0, sizeof(vmm_page_table_t));
|
|
||||||
|
|
||||||
// First 4MB are identity mapped
|
|
||||||
for(int i = 0, frame = 0x0, virt = 0x00000000; i<1024; i++, frame += 4096, virt += 4096){
|
|
||||||
// Create a new page
|
|
||||||
pt_entry_t page = 0;
|
|
||||||
pt_entry_add_attr(&page, PTE_PRESENT);
|
|
||||||
pt_entry_set_frame(&page, frame);
|
|
||||||
|
|
||||||
// Add the page to the page table
|
|
||||||
table2->entries[PAGE_TABLE_INDEX(virt)] = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map 1MB to 3GB
|
|
||||||
for(int i = 0, frame = 0x100000, virt = 0xc0000000; i<1024; i++, frame += 4096, virt += 4096){
|
|
||||||
// Create a new page
|
|
||||||
pt_entry_t page = 0;
|
|
||||||
pt_entry_add_attr(&page, PTE_PRESENT);
|
|
||||||
pt_entry_set_frame(&page, frame);
|
|
||||||
|
|
||||||
// Add the page to the page table
|
|
||||||
table->entries[PAGE_TABLE_INDEX(virt)] = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create default directory table
|
|
||||||
vmm_page_directory_t *dir = (vmm_page_directory_t *)pmm_alloc_blocks(3);
|
|
||||||
if(!dir) return;
|
|
||||||
|
|
||||||
// Clear directory table and set it as current
|
|
||||||
memset(dir, 0, sizeof(vmm_page_directory_t));
|
|
||||||
|
|
||||||
pd_entry_t *entry = &dir->entries[PAGE_DIRECTORY_INDEX(0xc0000000)];
|
|
||||||
pd_entry_add_attr(entry, PDE_PRESENT);
|
|
||||||
pd_entry_add_attr(entry, PDE_WRITABLE);
|
|
||||||
pd_entry_set_frame(entry, (phys_addr)table);
|
|
||||||
|
|
||||||
pd_entry_t *entry2 = &dir->entries[PAGE_DIRECTORY_INDEX(0x00000000)];
|
|
||||||
pd_entry_add_attr(entry2, PDE_PRESENT);
|
|
||||||
pd_entry_add_attr(entry2, PDE_WRITABLE);
|
|
||||||
pd_entry_set_frame(entry2, (phys_addr)table2);
|
|
||||||
|
|
||||||
// Store current PDBR
|
|
||||||
g_vmm_current_pdbr = (phys_addr)&dir->entries;
|
|
||||||
|
|
||||||
// Switch to our page directory
|
|
||||||
vmm_switch_pdirectory(dir);
|
|
||||||
|
|
||||||
// Enable paging
|
|
||||||
pmm_paging_enable(true);
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "pte.h"
|
|
||||||
#include "pde.h"
|
|
||||||
|
|
||||||
typedef uint32_t virt_addr;
|
|
||||||
|
|
||||||
#define PAGES_PER_TABLE 1024
|
|
||||||
#define PAGES_PER_DIR 1024
|
|
||||||
|
|
||||||
#define PAGE_DIRECTORY_INDEX(x) (((x) >> 22) & 0x3FF)
|
|
||||||
#define PAGE_TABLE_INDEX(x) (((x) >> 12) & 0x3FF)
|
|
||||||
#define PAGE_GET_PHYS_ADDR(x) (*(x) & ~0xFFF)
|
|
||||||
|
|
||||||
#define PTABLE_ADDR_SPACE_SIZE 0x400000
|
|
||||||
#define DTABLE_ADDR_SPACE_SIZE 0x100000000
|
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
pt_entry_t entries[PAGES_PER_TABLE];
|
|
||||||
} vmm_page_table_t;
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
pd_entry_t entries[PAGES_PER_DIR];
|
|
||||||
} vmm_page_directory_t;
|
|
||||||
|
|
||||||
bool vmm_alloc_page(pt_entry_t *entry);
|
|
||||||
void vmm_free_page(pt_entry_t *entry);
|
|
||||||
void vmm_map_page(void *phys, void *virt);
|
|
||||||
void vmm_initialize();
|
|
Loading…
Referencia en una nova incidència