VMM -- Various cleanup

This commit is contained in:
Thomas Lovén 2018-03-20 12:00:57 +01:00
parent e86857dca4
commit ae2de799f3

View File

@ -20,18 +20,17 @@ union PTE {
}; };
#define PT(ptr) ((union PTE *)P2V(MASK_FLAGS(ptr))) #define PT(ptr) ((union PTE *)P2V(MASK_FLAGS(ptr)))
#define P4e(pt, addr) (PT(pt)[P4_OFFSET(addr)]) // Get the entry correspoding to address addr in page dir P4
#define P3e(pt, addr) PT(P4e(pt, addr).value)[P3_OFFSET(addr)] // for P4 table (P4E), P3 table (P3E) and so on.
#define P2e(pt, addr) PT(P3e(pt, addr).value)[P2_OFFSET(addr)] // Note: Those macros requires variables to be named
#define P1e(pt, addr) PT(P2e(pt, addr).value)[P1_OFFSET(addr)] #define P4E (PT(P4)[P4_OFFSET(addr)])
#define P3E PT(P4E.value)[P3_OFFSET(addr)]
#define P2E PT(P3E.value)[P2_OFFSET(addr)]
#define P1E PT(P2E.value)[P1_OFFSET(addr)]
static int page_exists(uint64_t P4, uint64_t addr) static int page_exists(uint64_t P4, uint64_t addr)
{ {
if(P4 if(P4 && P4E.present && P3E.present && P2E.present)
&& P4e(P4, addr).present
&& P3e(P4, addr).present
&& P2e(P4, addr).present
)
return 1; return 1;
return 0; return 0;
} }
@ -39,43 +38,40 @@ static int page_exists(uint64_t P4, uint64_t addr)
uint64_t vmm_get_page(uint64_t P4, uint64_t addr) uint64_t vmm_get_page(uint64_t P4, uint64_t addr)
{ {
if(page_exists(P4, addr)) if(page_exists(P4, addr))
if(P2e(P4, addr).huge) {
return P2e(P4, addr).value; if(P2E.huge)
else return P2E.value;
return P1e(P4, addr).value; return P1E.value;
else }
return -1; return -1;
} }
int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags, int touch) int vmm_set_page(uint64_t P4, uint64_t addr, uint64_t page, uint16_t flags, int touch)
{ {
if(flags & PAGE_HUGE) if(flags & PAGE_HUGE)
{ {
if(!(P4 if(!(P4 && P4E.present && P3E.present))
&& P4e(P4, addr).present
&& P3e(P4, addr).present
))
{ {
if(touch) if(!touch)
touch_page(P4, addr, flags);
else
return -1; return -1;
touch_page(P4, addr, flags);
} }
if(P2e(P4, addr).present && !P2e(P4,addr).huge)
// Don't overwrite a non-huge page with a huge one
if(P2E.present && !P2E.huge)
return -1; return -1;
P2e(P4, addr).value = page | flags; P2E.value = page | flags;
return 0; return 0;
} }
if(!page_exists(P4, addr)) if(!page_exists(P4, addr))
{ {
if(touch) if(!touch)
touch_page(P4, addr, flags);
else
return -1; return -1;
touch_page(P4, addr, flags);
} }
P1e(P4, addr).value = page | flags; P1E.value = page | flags;
return 0; return 0;
} }
@ -86,22 +82,19 @@ int touch_page(uint64_t P4, uint64_t addr, uint16_t flags)
int huge=(flags & PAGE_HUGE)?1:0; int huge=(flags & PAGE_HUGE)?1:0;
flags ^= PAGE_HUGE*huge; flags ^= PAGE_HUGE*huge;
if((!P4e(P4, addr).present) if((!P4E.present) && (!(P4E.value = pmm_calloc())))
&& (!(P4e(P4, addr).value = pmm_calloc())))
return -1; return -1;
P4e(P4, addr).value |= flags | PAGE_PRESENT; P4E.value |= flags | PAGE_PRESENT;
if((!P3e(P4, addr).present) if((!P3E.present) && (!(P3E.value = pmm_calloc())))
&& (!(P3e(P4, addr).value = pmm_calloc())))
return -1; return -1;
P3e(P4, addr).value |= flags | PAGE_PRESENT; P3E.value |= flags | PAGE_PRESENT;
if(huge) return 0; if(huge) return 0;
if((!P2e(P4, addr).present) if((!P2E.present) && (!(P2E.value = pmm_calloc())))
&& (!(P2e(P4, addr).value = pmm_calloc())))
return -1; return -1;
P2e(P4, addr).value |= flags | PAGE_PRESENT; P2E.value |= flags | PAGE_PRESENT;
return 0; return 0;
} }
@ -113,35 +106,37 @@ void free_page(uint64_t P4, uint64_t addr, int free)
union PTE *pt; union PTE *pt;
if(P2e(P4, addr).huge) if(P2E.huge)
{ {
P2e(P4, addr).value = 0; P2E.value = 0;
if(!free) return; if(!free)
return;
} else { } else {
P1e(P4, addr).value = 0; P1E.value = 0;
if(!free) return; if(!free)
return;
pt = PT(P2e(P4, addr).value); pt = PT(P2E.value);
for(int i = 0; i < ENTRIES_PER_PT; i++) for(int i = 0; i < ENTRIES_PER_PT; i++)
if(pt[i].value) if(pt[i].value)
return; return;
pmm_free(MASK_FLAGS(P2e(P4, addr).value)); pmm_free(MASK_FLAGS(P2E.value));
P2e(P4, addr).value = 0; P2E.value = 0;
} }
pt = PT(P3e(P4, addr).value); pt = PT(P3E.value);
for(int i = 0; i < ENTRIES_PER_PT; i++) for(int i = 0; i < ENTRIES_PER_PT; i++)
if(pt[i].value) if(pt[i].value)
return; return;
pmm_free(MASK_FLAGS(P3e(P4, addr).value)); pmm_free(MASK_FLAGS(P3E.value));
P3e(P4, addr).value = 0; P3E.value = 0;
pt = PT(P4e(P4, addr).value); pt = PT(P4E.value);
for(int i = 0; i < ENTRIES_PER_PT; i++) for(int i = 0; i < ENTRIES_PER_PT; i++)
if(pt[i].value) if(pt[i].value)
return; return;
pmm_free(MASK_FLAGS(P4e(P4, addr).value)); pmm_free(MASK_FLAGS(P4E.value));
P4e(P4, addr).value = 0; P4E.value = 0;
} }