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

View File

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