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;
|
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 x86_isr_page_fault(trap_frame_t *frame, u32 error_code)
|
||||||
{
|
{
|
||||||
void *address;
|
void *address;
|
||||||
|
|
|
@ -116,6 +116,32 @@ int map_page(uintptr_t phys, void *virt, enum pflags flags);
|
||||||
*/
|
*/
|
||||||
uintptr_t unmap_page(void *virt);
|
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. */
|
/** @brief Flush the TLB. */
|
||||||
void vm_flush(void);
|
void vm_flush(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue