Kernel: PageTable now supports reserved pages

You can now map pages as reserved, so that they will not be given
from get_free_page() or get_free_contiguous_pages().
This commit is contained in:
Bananymous 2023-08-01 16:32:51 +03:00
parent 9fe878bbec
commit 926df2b276
2 changed files with 25 additions and 12 deletions

View File

@ -48,7 +48,7 @@ namespace Kernel
static inline PageTable::flags_t parse_flags(uint64_t entry)
{
return (s_has_nxe && !(entry & (1ull << 63)) ? PageTable::Flags::Execute : 0) | (entry & 0b111);
return (s_has_nxe && !(entry & (1ull << 63)) ? PageTable::Flags::Execute : 0) | (entry & 0b100000111);
}
void PageTable::initialize()
@ -251,7 +251,7 @@ namespace Kernel
ASSERT(paddr % PAGE_SIZE == 0);
ASSERT(vaddr % PAGE_SIZE == 0);
ASSERT(flags & Flags::Present);
ASSERT(flags & Flags::Used);
uint64_t pml4e = (vaddr >> 39) & 0x1FF;
uint64_t pdpte = (vaddr >> 30) & 0x1FF;
@ -263,6 +263,8 @@ namespace Kernel
extra_flags |= 1ull << 63;
if (s_has_pge && pml4e == 511)
extra_flags |= 1ull << 8;
if (flags & Flags::Reserved)
extra_flags |= Flags::Reserved;
flags_t uwr_flags = flags & 0b111;
uint64_t* pml4 = (uint64_t*)P2V(m_highest_paging_struct);
@ -355,7 +357,7 @@ namespace Kernel
return (page_data & PAGE_ADDR_MASK) & ~(1ull << 63);
}
vaddr_t PageTable::get_free_page(vaddr_t first_address) const
vaddr_t PageTable::get_free_page(vaddr_t first_address)
{
LockGuard _(m_lock);
@ -390,13 +392,14 @@ namespace Kernel
uint64_t* pt = (uint64_t*)P2V(pd[pde] & PAGE_ADDR_MASK);
for (; pte < 512; pte++)
{
if (!(pt[pte] & Flags::Present))
if (!(pt[pte] & Flags::Used))
{
vaddr_t vaddr = 0;
vaddr |= pml4e << 39;
vaddr |= pdpte << 30;
vaddr |= pde << 21;
vaddr |= pte << 12;
pt[pte] |= Flags::Reserved;
return canonicalize(vaddr);
}
}
@ -404,12 +407,15 @@ namespace Kernel
}
}
// Find any free page page (except for page 0)
// Find any free page page
vaddr = first_address;
while (is_canonical(vaddr))
{
if (is_page_free(vaddr))
{
map_page_at(0, vaddr, Flags::Reserved);
return vaddr;
}
if (vaddr > vaddr + PAGE_SIZE)
break;
vaddr += PAGE_SIZE;
@ -418,7 +424,7 @@ namespace Kernel
ASSERT_NOT_REACHED();
}
vaddr_t PageTable::get_free_contiguous_pages(size_t page_count, vaddr_t first_address) const
vaddr_t PageTable::get_free_contiguous_pages(size_t page_count, vaddr_t first_address)
{
if (first_address % PAGE_SIZE)
first_address = (first_address + PAGE_SIZE - 1) & PAGE_ADDR_MASK;
@ -430,7 +436,7 @@ namespace Kernel
bool valid { true };
for (size_t page = 0; page < page_count; page++)
{
if (get_page_flags(vaddr + page * PAGE_SIZE) & Flags::Present)
if (get_page_flags(vaddr + page * PAGE_SIZE) & Flags::Used)
{
vaddr += page * PAGE_SIZE;
valid = false;
@ -438,7 +444,11 @@ namespace Kernel
}
}
if (valid)
{
for (size_t page = 0; page < page_count; page++)
map_page_at(0, vaddr + page * PAGE_SIZE, Flags::Reserved);
return vaddr;
}
}
ASSERT_NOT_REACHED();
@ -447,7 +457,7 @@ namespace Kernel
bool PageTable::is_page_free(vaddr_t page) const
{
ASSERT(page % PAGE_SIZE == 0);
return !(get_page_flags(page) & Flags::Present);
return !(get_page_flags(page) & Flags::Used);
}
bool PageTable::is_range_free(vaddr_t start, size_t size) const
@ -519,7 +529,7 @@ namespace Kernel
start = 0;
}
if (!(pt[pte] & Flags::Present))
if (!(pt[pte] & Flags::Used))
continue;
if (start == 0)

View File

@ -10,13 +10,16 @@ namespace Kernel
class PageTable
{
public:
using flags_t = uint8_t;
using flags_t = uint16_t;
enum Flags : flags_t
{
Present = 1,
ReadWrite = 2,
UserSupervisor = 4,
Execute = 8,
Reserved = 256,
Used = Present | Reserved,
};
public:
@ -40,8 +43,8 @@ namespace Kernel
bool is_page_free(vaddr_t) const;
bool is_range_free(vaddr_t, size_t bytes) const;
vaddr_t get_free_page(vaddr_t first_address = PAGE_SIZE) const;
vaddr_t get_free_contiguous_pages(size_t page_count, vaddr_t first_address = PAGE_SIZE) const;
vaddr_t get_free_page(vaddr_t first_address = PAGE_SIZE);
vaddr_t get_free_contiguous_pages(size_t page_count, vaddr_t first_address = PAGE_SIZE);
void load();