x86/page: add page flagging functions
This commit is contained in:
parent
ec889c08b9
commit
637ac5ce92
2 changed files with 70 additions and 0 deletions
|
@ -165,6 +165,50 @@ uintptr_t unmap_page(void *virt)
|
|||
return phys;
|
||||
}
|
||||
|
||||
enum pflags get_pflags(void *page)
|
||||
{
|
||||
usize pd_index = ((uintptr_t)page >> PAGE_SHIFT) / 1024;
|
||||
usize pt_index = ((uintptr_t)page >> PAGE_SHIFT) % 1024;
|
||||
|
||||
struct x86_page_directory_entry *pde = &X86_CURRENT_PD->entries[pd_index];
|
||||
if (pde->huge) {
|
||||
return *(unsigned long *)pde & ~PAGE_MASK;
|
||||
} else if (pde->present) {
|
||||
struct x86_page_table_entry *pte = &X86_CURRENT_PT(pd_index)->entries[pt_index];
|
||||
return *(unsigned long *)pte & ~PAGE_MASK;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int set_pflags(void *page, enum pflags pflags)
|
||||
{
|
||||
usize pd_index = ((uintptr_t)page >> PAGE_SHIFT) / 1024;
|
||||
usize pt_index = ((uintptr_t)page >> PAGE_SHIFT) % 1024;
|
||||
|
||||
struct x86_page_directory_entry *pde = &X86_CURRENT_PD->entries[pd_index];
|
||||
if (pflags & P_HUGE) {
|
||||
/* if the PDE referred to a Page Table, free it first */
|
||||
if (pde->present && !pde->huge)
|
||||
free_pages((void *)((uintptr_t)pde->shifted_address << PAGE_SHIFT));
|
||||
|
||||
unsigned long pde_raw = *(unsigned long *)pde;
|
||||
pde_raw &= PAGE_MASK;
|
||||
pde_raw |= (pflags & ~PAGE_MASK);
|
||||
*(unsigned long *)pde = pde_raw;
|
||||
} else if (pde->present) {
|
||||
struct x86_page_table_entry *pte = X86_CURRENT_PTE(pd_index, pt_index);
|
||||
unsigned long pte_raw = *(unsigned long *)pte;
|
||||
pte_raw &= PAGE_MASK;
|
||||
pte_raw |= (pflags & ~PAGE_MASK);
|
||||
*(unsigned long *)pte = pte_raw;
|
||||
} else {
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void x86_isr_page_fault(trap_frame_t *frame, u32 error_code)
|
||||
{
|
||||
void *address;
|
||||
|
|
|
@ -116,6 +116,32 @@ int map_page(uintptr_t phys, void *virt, enum pflags flags);
|
|||
*/
|
||||
uintptr_t unmap_page(void *virt);
|
||||
|
||||
/**
|
||||
* @brief Get a page's flags in the page tables.
|
||||
*
|
||||
* @param page Page to get the flags of (if the page is in a hugepage area,
|
||||
* the flags for that hugepage will be returned with `P_HUGE = 1`)
|
||||
* @return The flags, as currently stored in the page table structures
|
||||
* (but not necessarily applied if they have been modified and `vm_flush()`
|
||||
* has not been called yet!)
|
||||
*/
|
||||
enum pflags get_pflags(void *page);
|
||||
|
||||
/**
|
||||
* @brief Update a page's flags in the page tables.
|
||||
* You should always use this in conjunction with `get_pflags()`, as in getting
|
||||
* the flags first, then toggling the flags you need to, and then setting them
|
||||
* in the tables again. This is because this method will clear *any* previous
|
||||
* flags.
|
||||
*
|
||||
* @param page Page to set flags for (if flags has `P_HUGE` set, must be
|
||||
* `HUGEPAGE_SIZE` aligned, otherwise `PAGE_SIZE` aligned)
|
||||
* @param flags Flags to set
|
||||
* @return 0 on success, or a negative value if either a page table allocation
|
||||
* failed or
|
||||
*/
|
||||
int set_pflags(void *page, enum pflags flags);
|
||||
|
||||
/** @brief Flush the TLB. */
|
||||
void vm_flush(void);
|
||||
|
||||
|
|
Loading…
Reference in a new issue