started a bit of paging for x64
This commit is contained in:
parent
3f83577f8f
commit
c061f9e30c
10 changed files with 456 additions and 131 deletions
|
@ -2,6 +2,7 @@
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
extern int kernel_start;
|
extern int kernel_start;
|
||||||
extern int kernel_end;
|
extern int kernel_end;
|
||||||
|
pagedir global_kernel[256];
|
||||||
paging_context_x86::paging_context_x86(): paging_context() {
|
paging_context_x86::paging_context_x86(): paging_context() {
|
||||||
*pmm >> pagedir_addr;
|
*pmm >> pagedir_addr;
|
||||||
if(context_enabled) {
|
if(context_enabled) {
|
||||||
|
@ -175,12 +176,24 @@ paging_context_x86::~paging_context_x86() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void paging_context_x86::switch_context() {
|
void paging_context_x86::switch_context() {
|
||||||
|
pagedir* p = (pagedir*)pagedir_addr;
|
||||||
|
if(context_enabled)
|
||||||
|
p=(pagedir*)0x400000;
|
||||||
|
for(int i = 0; i < 256; i++) {
|
||||||
|
global_kernel[i]=p[i];
|
||||||
|
}
|
||||||
asm volatile("mov %0, %%cr3" :: "r"(pagedir_addr) : "memory");
|
asm volatile("mov %0, %%cr3" :: "r"(pagedir_addr) : "memory");
|
||||||
if(!context_enabled) {
|
if(!context_enabled) {
|
||||||
uint32_t cr0;
|
uint32_t cr0;
|
||||||
asm volatile("mov %%cr0, %0" : "=r"(cr0));
|
asm volatile("mov %%cr0, %0" : "=r"(cr0));
|
||||||
cr0 |= (1<<31);
|
cr0 |= (1<<31);
|
||||||
asm volatile("mov %0, %%cr0" :: "r"(cr0) : "memory");
|
asm volatile("mov %0, %%cr0" :: "r"(cr0) : "memory");
|
||||||
|
} else {
|
||||||
|
for(int i=0;i<256;i++)
|
||||||
|
if((i>=1)&&(i<=3))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
p[i]=global_kernel[i];
|
||||||
}
|
}
|
||||||
paging_context::switch_context();
|
paging_context::switch_context();
|
||||||
}
|
}
|
||||||
|
|
91
kernel/arch/x86_64/include/paging.h
Normal file
91
kernel/arch/x86_64/include/paging.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <pmm.hpp>
|
||||||
|
#include <regs.h>
|
||||||
|
#include <paging.hpp>
|
||||||
|
typedef phys_t virt_t;
|
||||||
|
struct pagemap_tbl {
|
||||||
|
bool active:1;
|
||||||
|
bool writable:1;
|
||||||
|
bool unprivileged:1;
|
||||||
|
bool no_write_cache:1;
|
||||||
|
bool no_read_cache:1;
|
||||||
|
bool accessed:1;
|
||||||
|
uint8_t sbz:3;
|
||||||
|
uint8_t ignored:3;
|
||||||
|
phys_t pagemap:40;
|
||||||
|
uint16_t ignored2:11;
|
||||||
|
bool executable:1;
|
||||||
|
|
||||||
|
}__attribute__((packed));
|
||||||
|
static_assert(sizeof(pagemap_tbl)==8);
|
||||||
|
|
||||||
|
struct pagemap {
|
||||||
|
bool active:1;
|
||||||
|
bool writable:1;
|
||||||
|
bool unprivileged:1;
|
||||||
|
bool no_write_cache:1;
|
||||||
|
bool no_read_cache:1;
|
||||||
|
bool accessed:1;
|
||||||
|
bool sbz:1;
|
||||||
|
bool _1G_page:1;
|
||||||
|
bool global:1;
|
||||||
|
uint8_t ignored:3;
|
||||||
|
phys_t pagedir:40;
|
||||||
|
uint16_t ignored2:11;
|
||||||
|
bool executable:1;
|
||||||
|
}__attribute__((packed));
|
||||||
|
static_assert(sizeof(pagemap)==8);
|
||||||
|
|
||||||
|
struct pagedir {
|
||||||
|
bool active:1;
|
||||||
|
bool writeable:1;
|
||||||
|
bool privileged:1;
|
||||||
|
bool no_write_cache:1;
|
||||||
|
bool no_read_cache:1;
|
||||||
|
bool accessed:1;
|
||||||
|
bool sbz:1;
|
||||||
|
bool _2M_page:1;
|
||||||
|
bool global:1;
|
||||||
|
uint8_t ignored:3;
|
||||||
|
phys_t pagetbl:40;
|
||||||
|
uint16_t ignored2:11;
|
||||||
|
bool executable:1;
|
||||||
|
}__attribute__((packed));
|
||||||
|
static_assert(sizeof(pagedir)==8);
|
||||||
|
|
||||||
|
struct pagetbl {
|
||||||
|
bool active:1;
|
||||||
|
bool writeable:1;
|
||||||
|
bool privileged:1;
|
||||||
|
bool no_write_cache:1;
|
||||||
|
bool no_read_cache:1;
|
||||||
|
bool accessed:1;
|
||||||
|
bool sbz:1;
|
||||||
|
bool pat:1;
|
||||||
|
bool global:1;
|
||||||
|
uint8_t ignored:2;
|
||||||
|
bool lazy:1;
|
||||||
|
phys_t page:40;
|
||||||
|
uint16_t ignored2:11;
|
||||||
|
bool executable:1;
|
||||||
|
}
|
||||||
|
}__attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
|
struct paging_context_x86: public paging_context {
|
||||||
|
phys_t pagemaptbl_addr;
|
||||||
|
paging_context_x86();
|
||||||
|
virtual ~paging_context_x86();
|
||||||
|
virtual void switch_context();
|
||||||
|
virtual void map_pagetable(struct paging_context *);
|
||||||
|
virtual void *mmap(phys_t addr, void *dest, protection prot=protection::RW, bool lazy=true);
|
||||||
|
virtual void munmap(void *addr);
|
||||||
|
virtual bool is_mapped(void *addr);
|
||||||
|
virtual void mprotect(void *addr, protection prot);
|
||||||
|
virtual bool has_no_exec();
|
||||||
|
virtual void *get_exception_address(cpu_state *cpu);
|
||||||
|
virtual bool lazymap(void *addr, cpu_state *cpu);
|
||||||
|
pagedir * operator*();
|
||||||
|
pagetbl * operator[](phys_t);
|
||||||
|
};
|
30
kernel/arch/x86_64/paging.cpp
Normal file
30
kernel/arch/x86_64/paging.cpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include <paging.h>
|
||||||
|
#include <base.hpp>
|
||||||
|
extern int kernel_start;
|
||||||
|
extern int kernel_end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
paging_context_x86::paging_context_x86(): paging_context() {
|
||||||
|
*pmm >> pagedir_addr;
|
||||||
|
if(context_enabled) {
|
||||||
|
current_context->mmap(pagedir_addr, (void*)0x800000, protection::RW, false);
|
||||||
|
pagemap *src=(pagemap *)0x400000;
|
||||||
|
pagemap *dest=(pagedir*)0x600000;
|
||||||
|
for(int i=0;i<256;i++)
|
||||||
|
dest[i]=src[i];
|
||||||
|
for(int i=256;i<512;i++)
|
||||||
|
dest[i].active=false;
|
||||||
|
dest[0].active=false;
|
||||||
|
phys_t first_pagedir;
|
||||||
|
*pmm >> first_pagedir;
|
||||||
|
dest[0].pagetable = first_pagedir >> 12;
|
||||||
|
dest[0].writeable=true;
|
||||||
|
dest[0].unprivileged=false;
|
||||||
|
dest[0].no_write_cache=true;
|
||||||
|
dest[0].no_read_cache=false;
|
||||||
|
dest[0].sbz=0;
|
||||||
|
dest[0].active=true;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,9 +17,12 @@ CGATerm term;
|
||||||
VESAfb term(mb_info);
|
VESAfb term(mb_info);
|
||||||
#endif
|
#endif
|
||||||
PMM_MB lpmm(mb_info);
|
PMM_MB lpmm(mb_info);
|
||||||
|
|
||||||
|
#include<paging.hpp>
|
||||||
void main();
|
void main();
|
||||||
extern "C" void start(int eax, multiboot_info_t *ebx) {
|
extern "C" void start(int eax, multiboot_info_t *ebx) {
|
||||||
mb_info = ebx;
|
mb_info = ebx;
|
||||||
|
context_enabled=false;
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
void drivers_init() {
|
void drivers_init() {
|
||||||
|
|
|
@ -58,7 +58,7 @@ union MMAPTag {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
}__attribute__((packed)) BITS;
|
}__attribute__((packed)) BITSi;
|
||||||
struct {
|
struct {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
|
@ -108,7 +108,7 @@ PMM_MMAP::PMM_MMAP(): PMM(0x1000) {
|
||||||
;
|
;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
bits = tag.BITS.value;
|
bits = tag.BITSi.value;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if(tag.REGION.permission != PERM::RWX)
|
if(tag.REGION.permission != PERM::RWX)
|
||||||
|
|
|
@ -21,3 +21,9 @@ extern "C" void panic(const char* s);
|
||||||
#define __BIG_ENDIAN__
|
#define __BIG_ENDIAN__
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
#define BITS 64
|
||||||
|
#else
|
||||||
|
#define BITS 32
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
class PMM;
|
||||||
|
#include <base.hpp>
|
||||||
typedef uintptr_t phys_t; ///< Type used for physical addresses
|
typedef uintptr_t phys_t; ///< Type used for physical addresses
|
||||||
/**
|
/**
|
||||||
* A single entry in the PMM list
|
* A single entry in the PMM list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if BITS == 32
|
||||||
/**
|
/**
|
||||||
* Physical memory manager. It stores the free memory in a linked list
|
* Physical memory manager. It stores the free memory in a linked list
|
||||||
*/
|
*/
|
||||||
|
@ -26,6 +30,34 @@ class PMM {
|
||||||
virtual auto operator&&(phys_t page) -> bool; //Returns true if this page is free. O(1).
|
virtual auto operator&&(phys_t page) -> bool; //Returns true if this page is free. O(1).
|
||||||
virtual auto setUsed(phys_t page) -> void; //Marks a page as used. O(1).
|
virtual auto setUsed(phys_t page) -> void; //Marks a page as used. O(1).
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
struct pmm_entry {
|
||||||
|
phys_t next;
|
||||||
|
phys_t last;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PMM {
|
||||||
|
protected:
|
||||||
|
phys_t head;
|
||||||
|
virtual auto isFree(phys_t address) -> bool;
|
||||||
|
auto fill() -> void;
|
||||||
|
phys_t page_size, lowest_page, highest_page;
|
||||||
|
void push(phys_t);
|
||||||
|
phys_t pop();
|
||||||
|
public:
|
||||||
|
PMM(phys_t page_size);
|
||||||
|
virtual ~PMM();
|
||||||
|
virtual auto operator<<(phys_t page) -> PMM &;
|
||||||
|
virtual auto operator>>(phys_t &page) -> PMM &;
|
||||||
|
virtual auto operator,(size_t no_pages) -> phys_t;
|
||||||
|
virtual auto operator()(phys_t pages, size_t no_pages) -> void;
|
||||||
|
virtual auto operator&&(phys_t page) -> bool;
|
||||||
|
virtual auto setUsed(phys_t page) -> void;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* This definition is for having a python-like syntax - like `page in pmm`
|
* This definition is for having a python-like syntax - like `page in pmm`
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,131 +1,7 @@
|
||||||
#include <base.hpp>
|
#include <base.hpp>
|
||||||
#include <pmm.hpp>
|
|
||||||
extern "C" int kernel_start;
|
|
||||||
extern "C" int kernel_end;
|
|
||||||
|
|
||||||
|
#ifdef BITS == 64
|
||||||
uint32_t pmm_bitmap[32768];
|
#include "pmm64.hpp"
|
||||||
|
#else
|
||||||
|
#include "pmm32.hpp"
|
||||||
auto PMM::isFree(phys_t addr) -> bool {
|
#endif
|
||||||
if(addr == 0)
|
|
||||||
return false;
|
|
||||||
phys_t start = (phys_t)(&kernel_start);
|
|
||||||
phys_t end = (phys_t)(&kernel_end);
|
|
||||||
if((addr >= start) && (addr < end))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
PMM::PMM(phys_t page_size): page_size(page_size), first_free(0), lowest_page(~0), highest_page(0) {
|
|
||||||
for(int i=0;i<32768;i++) {
|
|
||||||
pmm_bitmap[i]=0;
|
|
||||||
}
|
|
||||||
pmm = this;
|
|
||||||
}
|
|
||||||
void PMM::fill() {
|
|
||||||
for(phys_t i=highest_page; i>=lowest_page && i; i-=page_size) {
|
|
||||||
if(isFree(i))
|
|
||||||
*this << i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PMM::~PMM() {}
|
|
||||||
|
|
||||||
auto PMM::operator<<(phys_t page) -> PMM & {
|
|
||||||
(*this)(page,1);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
auto PMM::operator>>(phys_t &page) -> PMM & {
|
|
||||||
page = (*this, 1);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto PMM::operator,(size_t no_pages) -> phys_t {
|
|
||||||
if(first_free > highest_page)
|
|
||||||
panic("No free physical memory is available.");
|
|
||||||
if(no_pages == 1) {
|
|
||||||
while(!(first_free in *this)) {
|
|
||||||
first_free += page_size;
|
|
||||||
if(first_free > highest_page)
|
|
||||||
panic("No free physical memory is available.");
|
|
||||||
}
|
|
||||||
phys_t pageno = first_free / page_size;
|
|
||||||
phys_t index = pageno >> 5;
|
|
||||||
phys_t bit = pageno & 31;
|
|
||||||
pmm_bitmap[index] &= ~(1<<bit);
|
|
||||||
auto x = first_free;
|
|
||||||
first_free += page_size;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
//Now we need to find a free page with n-1 free pages after it
|
|
||||||
phys_t linear_start = first_free;
|
|
||||||
phys_t length = (no_pages-1) * page_size;
|
|
||||||
while(true) {
|
|
||||||
bool found=true;
|
|
||||||
while(!(linear_start in *this)) {
|
|
||||||
linear_start += page_size;
|
|
||||||
if((linear_start > highest_page)||(linear_start+length > highest_page))
|
|
||||||
panic("No free physical memory is available.");
|
|
||||||
}
|
|
||||||
if(!((linear_start + length) in *this)) {
|
|
||||||
linear_start += no_pages * page_size;
|
|
||||||
}
|
|
||||||
//We're on to something
|
|
||||||
phys_t i;
|
|
||||||
for(i=linear_start; i < linear_start + length; i+=page_size) {
|
|
||||||
if(!(i in *this)) {
|
|
||||||
found=false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!found) {
|
|
||||||
linear_start=i+page_size;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//Set the first_free variable correctly when the first page was a hit
|
|
||||||
if(linear_start == first_free)
|
|
||||||
first_free += length + page_size;
|
|
||||||
|
|
||||||
phys_t pageno = linear_start / page_size;
|
|
||||||
|
|
||||||
for(i=linear_start; i <= linear_start + length; i+= page_size) {
|
|
||||||
phys_t index = pageno >> 5;
|
|
||||||
phys_t bit = pageno & 31;
|
|
||||||
pmm_bitmap[index] &= ~(1<<bit);
|
|
||||||
pageno++;
|
|
||||||
}
|
|
||||||
return linear_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
auto PMM::operator()(phys_t pages, size_t no_pages) -> void {
|
|
||||||
phys_t pageno = pages / page_size;
|
|
||||||
if(pages < first_free)
|
|
||||||
first_free = pages;
|
|
||||||
for(size_t i=0; i<no_pages; i++, pages+=page_size) {
|
|
||||||
if(!isFree(pages))
|
|
||||||
continue;
|
|
||||||
phys_t index = pageno >> 5;
|
|
||||||
phys_t bit = pageno & 31;
|
|
||||||
pmm_bitmap[index] |= 1<<bit;
|
|
||||||
pageno++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto PMM::operator&&(phys_t page) -> bool {
|
|
||||||
phys_t pageno = page / page_size;
|
|
||||||
phys_t index = pageno >> 5;
|
|
||||||
if(!pmm_bitmap[index])
|
|
||||||
return false;
|
|
||||||
phys_t bit = pageno & 31;
|
|
||||||
if(!(pmm_bitmap[index] & (1<<bit)))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
auto PMM::setUsed(phys_t page) -> void {
|
|
||||||
phys_t pageno = page / page_size;
|
|
||||||
phys_t index = pageno >> 5;
|
|
||||||
phys_t bit = pageno & 31;
|
|
||||||
pmm_bitmap[index] &= ~(1<<bit);
|
|
||||||
}
|
|
||||||
auto operator&&(phys_t a, PMM mm) -> bool {
|
|
||||||
return mm && a;
|
|
||||||
}
|
|
||||||
|
|
131
kernel/src/pmm32.hpp
Normal file
131
kernel/src/pmm32.hpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include <base.hpp>
|
||||||
|
#include <pmm.hpp>
|
||||||
|
extern "C" int kernel_start;
|
||||||
|
extern "C" int kernel_end;
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t pmm_bitmap[32768];
|
||||||
|
|
||||||
|
|
||||||
|
auto PMM::isFree(phys_t addr) -> bool {
|
||||||
|
if(addr == 0)
|
||||||
|
return false;
|
||||||
|
phys_t start = (phys_t)(&kernel_start);
|
||||||
|
phys_t end = (phys_t)(&kernel_end);
|
||||||
|
if((addr >= start) && (addr < end))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
PMM::PMM(phys_t page_size): page_size(page_size), first_free(0), lowest_page(~0), highest_page(0) {
|
||||||
|
for(int i=0;i<32768;i++) {
|
||||||
|
pmm_bitmap[i]=0;
|
||||||
|
}
|
||||||
|
pmm = this;
|
||||||
|
}
|
||||||
|
void PMM::fill() {
|
||||||
|
for(phys_t i=highest_page; i>=lowest_page && i; i-=page_size) {
|
||||||
|
if(isFree(i))
|
||||||
|
*this << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PMM::~PMM() {}
|
||||||
|
|
||||||
|
auto PMM::operator<<(phys_t page) -> PMM & {
|
||||||
|
(*this)(page,1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
auto PMM::operator>>(phys_t &page) -> PMM & {
|
||||||
|
page = (*this, 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PMM::operator,(size_t no_pages) -> phys_t {
|
||||||
|
if(first_free > highest_page)
|
||||||
|
panic("No free physical memory is available.");
|
||||||
|
if(no_pages == 1) {
|
||||||
|
while(!(first_free in *this)) {
|
||||||
|
first_free += page_size;
|
||||||
|
if(first_free > highest_page)
|
||||||
|
panic("No free physical memory is available.");
|
||||||
|
}
|
||||||
|
phys_t pageno = first_free / page_size;
|
||||||
|
phys_t index = pageno >> 5;
|
||||||
|
phys_t bit = pageno & 31;
|
||||||
|
pmm_bitmap[index] &= ~(1<<bit);
|
||||||
|
auto x = first_free;
|
||||||
|
first_free += page_size;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
//Now we need to find a free page with n-1 free pages after it
|
||||||
|
phys_t linear_start = first_free;
|
||||||
|
phys_t length = (no_pages-1) * page_size;
|
||||||
|
while(true) {
|
||||||
|
bool found=true;
|
||||||
|
while(!(linear_start in *this)) {
|
||||||
|
linear_start += page_size;
|
||||||
|
if((linear_start > highest_page)||(linear_start+length > highest_page))
|
||||||
|
panic("No free physical memory is available.");
|
||||||
|
}
|
||||||
|
if(!((linear_start + length) in *this)) {
|
||||||
|
linear_start += no_pages * page_size;
|
||||||
|
}
|
||||||
|
//We're on to something
|
||||||
|
phys_t i;
|
||||||
|
for(i=linear_start; i < linear_start + length; i+=page_size) {
|
||||||
|
if(!(i in *this)) {
|
||||||
|
found=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) {
|
||||||
|
linear_start=i+page_size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//Set the first_free variable correctly when the first page was a hit
|
||||||
|
if(linear_start == first_free)
|
||||||
|
first_free += length + page_size;
|
||||||
|
|
||||||
|
phys_t pageno = linear_start / page_size;
|
||||||
|
|
||||||
|
for(i=linear_start; i <= linear_start + length; i+= page_size) {
|
||||||
|
phys_t index = pageno >> 5;
|
||||||
|
phys_t bit = pageno & 31;
|
||||||
|
pmm_bitmap[index] &= ~(1<<bit);
|
||||||
|
pageno++;
|
||||||
|
}
|
||||||
|
return linear_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
auto PMM::operator()(phys_t pages, size_t no_pages) -> void {
|
||||||
|
phys_t pageno = pages / page_size;
|
||||||
|
if(pages < first_free)
|
||||||
|
first_free = pages;
|
||||||
|
for(size_t i=0; i<no_pages; i++, pages+=page_size) {
|
||||||
|
if(!isFree(pages))
|
||||||
|
continue;
|
||||||
|
phys_t index = pageno >> 5;
|
||||||
|
phys_t bit = pageno & 31;
|
||||||
|
pmm_bitmap[index] |= 1<<bit;
|
||||||
|
pageno++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto PMM::operator&&(phys_t page) -> bool {
|
||||||
|
phys_t pageno = page / page_size;
|
||||||
|
phys_t index = pageno >> 5;
|
||||||
|
if(!pmm_bitmap[index])
|
||||||
|
return false;
|
||||||
|
phys_t bit = pageno & 31;
|
||||||
|
if(!(pmm_bitmap[index] & (1<<bit)))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto PMM::setUsed(phys_t page) -> void {
|
||||||
|
phys_t pageno = page / page_size;
|
||||||
|
phys_t index = pageno >> 5;
|
||||||
|
phys_t bit = pageno & 31;
|
||||||
|
pmm_bitmap[index] &= ~(1<<bit);
|
||||||
|
}
|
||||||
|
auto operator&&(phys_t a, PMM mm) -> bool {
|
||||||
|
return mm && a;
|
||||||
|
}
|
143
kernel/src/pmm64.hpp
Normal file
143
kernel/src/pmm64.hpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#include <pmm.hpp>
|
||||||
|
#include <paging.hpp>
|
||||||
|
extern "C" int kernel_start;
|
||||||
|
extern "C" int kernel_end;
|
||||||
|
|
||||||
|
static inline void * map(phys_t addr) {
|
||||||
|
if(__builtin_expect(context_enabled, true))
|
||||||
|
return current_context->mmap(addr, (void*)1, protection::RW, false);
|
||||||
|
return (void*)addr;
|
||||||
|
}
|
||||||
|
static inline void unmap(void* addr) {
|
||||||
|
/* if(__builtin_expect(context_enabled, true))
|
||||||
|
current_context->munmap(addr);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PMM::isFree(phys_t addr) -> bool {
|
||||||
|
if(!addr)
|
||||||
|
return false;
|
||||||
|
auto start = (phys_t)(&kernel_start);
|
||||||
|
auto end = (phys_t)(&kernel_end);
|
||||||
|
if((addr >= start) && (addr < end))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PMM::push(phys_t p) {
|
||||||
|
phys_t h=head;
|
||||||
|
auto ent=(pmm_entry*)map(p);
|
||||||
|
ent->next=head;
|
||||||
|
ent->last=0;
|
||||||
|
head=p;
|
||||||
|
unmap(ent);
|
||||||
|
ent=(pmm_entry*)map(h);
|
||||||
|
ent->last=p;
|
||||||
|
unmap(ent);
|
||||||
|
}
|
||||||
|
phys_t PMM::pop() {
|
||||||
|
phys_t p = head;
|
||||||
|
if(!p)
|
||||||
|
panic("oom");
|
||||||
|
auto ent=(pmm_entry*)map(p);
|
||||||
|
head=ent->next;
|
||||||
|
unmap(ent);
|
||||||
|
ent=(pmm_entry*)map(head);
|
||||||
|
ent->last=0;
|
||||||
|
unmap(ent);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMM::PMM(phys_t page_size): page_size(page_size), head(0), lowest_page(~0), highest_page(0) {
|
||||||
|
pmm=this;
|
||||||
|
}
|
||||||
|
void PMM::fill() {
|
||||||
|
for(phys_t i=highest_page; i>=lowest_page && i; i-=page_size) {
|
||||||
|
if(isFree(i))
|
||||||
|
*this << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PMM::~PMM() {}
|
||||||
|
|
||||||
|
auto PMM::operator<<(phys_t page) -> PMM & {
|
||||||
|
push(page);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
auto PMM::operator>>(phys_t &page) -> PMM& {
|
||||||
|
page=pop();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#define self (*this)
|
||||||
|
auto PMM::operator,(size_t no_pages) -> phys_t {
|
||||||
|
if(no_pages == 1)
|
||||||
|
return pop();
|
||||||
|
for(phys_t i = lowest_page; i < highest_page; i+=page_size) {
|
||||||
|
if(not (i in self))
|
||||||
|
continue;
|
||||||
|
if(not ((i+no_pages*page_size) in self)) {
|
||||||
|
i+=(no_pages-1)*page_size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//we found something
|
||||||
|
for(phys_t j = i+page_size; j<i+no_pages*page_size; j+=page_size) {
|
||||||
|
if(not (j in self)) {
|
||||||
|
i+=(no_pages-1)*page_size;
|
||||||
|
goto outlbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//if we are here, we found it
|
||||||
|
for(phys_t j = i; j<=i+no_pages*page_size; j+=page_size) {
|
||||||
|
setUsed(j);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
outlbl:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PMM::operator()(phys_t pages, size_t no_pages) -> void {
|
||||||
|
for(phys_t i=pages; i<=pages+no_pages*page_size; i+=page_size) {
|
||||||
|
if(!isFree(i))
|
||||||
|
continue;
|
||||||
|
push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PMM::operator&&(phys_t page) -> bool {
|
||||||
|
phys_t curr = head;
|
||||||
|
while(curr) {
|
||||||
|
if(curr == page)
|
||||||
|
return true;
|
||||||
|
auto ent = (pmm_entry *)map(curr);
|
||||||
|
curr = ent->next;
|
||||||
|
unmap(ent);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto PMM::setUsed(phys_t page) -> void {
|
||||||
|
if(head == page) {
|
||||||
|
pop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(not (page in self))
|
||||||
|
return;
|
||||||
|
phys_t next, last;
|
||||||
|
auto ent = (pmm_entry*)map(page);
|
||||||
|
next=ent->next;
|
||||||
|
last=ent->last;
|
||||||
|
unmap(ent);
|
||||||
|
if(next) {
|
||||||
|
ent=(pmm_entry*)map(next);
|
||||||
|
ent->last=last;
|
||||||
|
unmap(ent);
|
||||||
|
}
|
||||||
|
if(last) {
|
||||||
|
ent=(pmm_entry*)map(last);
|
||||||
|
ent->next=next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator&&(phys_t a, PMM mm) -> bool{
|
||||||
|
return mm in a;
|
||||||
|
}
|
Loading…
Reference in a new issue