111 lines
2.4 KiB
C
111 lines
2.4 KiB
C
#include <memory.h>
|
|
|
|
#define FLAGS_MASK (PAGE_SIZE-1)
|
|
#define MASK_FLAGS(addr) ((uintptr_t)addr & ~FLAGS_MASK)
|
|
|
|
union PTE {
|
|
uint64_t value;
|
|
struct {
|
|
uintptr_t present:1;
|
|
uintptr_t write:1;
|
|
uintptr_t user:1;
|
|
uintptr_t write_through:1;
|
|
uintptr_t nocache:1;
|
|
uintptr_t accessed:1;
|
|
uintptr_t dirty:1;
|
|
uintptr_t huge:1;
|
|
uintptr_t global:1;
|
|
uintptr_t flags:3;
|
|
};
|
|
};
|
|
|
|
#define PT(ptr) ((union PTE *)MASK_FLAGS(ptr))
|
|
#define P4e(pt, addr) (PT(pt)[P4_OFFSET(addr)])
|
|
#define P3e(pt, addr) PT(P4e(pt, addr).value)[P3_OFFSET(addr)]
|
|
#define P2e(pt, addr) PT(P3e(pt, addr).value)[P2_OFFSET(addr)]
|
|
#define P1e(pt, addr) PT(P2e(pt, addr).value)[P1_OFFSET(addr)]
|
|
|
|
uintptr_t vmm_get_page(void *P4, uintptr_t addr)
|
|
{
|
|
if(P4
|
|
&& P4e(P4, addr).present
|
|
&& P3e(P4, addr).present
|
|
&& P2e(P4, addr).present
|
|
)
|
|
return P1e(P4, addr).value;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
int vmm_set_page(void *P4, uintptr_t addr, uintptr_t page, uint16_t flags)
|
|
{
|
|
if(!(P4
|
|
&& P4e(P4, addr).present
|
|
&& P3e(P4, addr).present
|
|
&& P2e(P4, addr).present
|
|
))
|
|
return -1;
|
|
|
|
P1e(P4, addr).value = page | flags;
|
|
return 0;
|
|
}
|
|
|
|
int touch_page(void *P4, uintptr_t addr, uint16_t flags)
|
|
{
|
|
if(!P4) return -1;
|
|
|
|
if((!P4e(P4, addr).present)
|
|
&& (!(P4e(P4, addr).value = pmm_alloc())))
|
|
return -1;
|
|
P4e(P4, addr).value |= flags | PAGE_PRESENT;
|
|
|
|
if((!P3e(P4, addr).present)
|
|
&& (!(P3e(P4, addr).value = pmm_alloc())))
|
|
return -1;
|
|
P3e(P4, addr).value |= flags | PAGE_PRESENT;
|
|
|
|
if((!P2e(P4, addr).present)
|
|
&& (!(P2e(P4, addr).value = pmm_alloc())))
|
|
return -1;
|
|
P2e(P4, addr).value |= flags | PAGE_PRESENT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void free_page(void *P4, uintptr_t addr, int free)
|
|
{
|
|
(void)free;
|
|
if(!(P4
|
|
&& P4e(P4, addr).present
|
|
&& P3e(P4, addr).present
|
|
&& P2e(P4, addr).present
|
|
))
|
|
return;
|
|
P1e(P4, addr).value = 0;
|
|
|
|
if(!free) return;
|
|
|
|
union PTE *pt;
|
|
|
|
pt = PT(P2e(P4, addr).value);
|
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
|
if(pt[i].value)
|
|
return;
|
|
pmm_free(MASK_FLAGS(P2e(P4, addr).value));
|
|
P2e(P4, addr).value = 0;
|
|
|
|
pt = PT(P3e(P4, addr).value);
|
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
|
if(pt[i].value)
|
|
return;
|
|
pmm_free(MASK_FLAGS(P3e(P4, addr).value));
|
|
P3e(P4, addr).value = 0;
|
|
|
|
pt = PT(P4e(P4, addr).value);
|
|
for(int i = 0; i < ENTRIES_PER_PT; i++)
|
|
if(pt[i].value)
|
|
return;
|
|
pmm_free(MASK_FLAGS(P4e(P4, addr).value));
|
|
P4e(P4, addr).value = 0;
|
|
}
|