int set_page_data(struct DataTable *tbl, void *va, data_t id) { int i; pge_t *pge = &(tbl->table)[PGX(va)]; if(! *pge) { pthread_mutex_lock(&tbl->lock); *pge = malloc(sizeof(pue_t) * TBLENTRIES); memset(*pge, 0, sizeof(pue_t) * TBLENTRIES); pthread_mutex_unlock(&tbl->lock); } pue_t *pue = &(*pge)[PUX(va)]; if(! *pue) { pthread_mutex_lock(&tbl->lock); *pue = malloc(sizeof(pme_t) * TBLENTRIES); memset(*pue, 0, sizeof(pme_t) * TBLENTRIES); pthread_mutex_unlock(&tbl->lock); } pme_t *pme = &(*pue)[PMX(va)]; if(! *pme) { pthread_mutex_lock(&tbl->lock); *pme = malloc(sizeof(data_t) * TBLENTRIES); memset(*pme, 0, sizeof(data_t) * TBLENTRIES); pthread_mutex_unlock(&tbl->lock); } DEBUG_LOG("set_page_data of %p from %lu to %lu", va, (*pme)[PTX(va)], id); (*pme)[PTX(va)] = id; return 0; }
pud_t * get_pud(pgd_t *pgdir, uintptr_t la, bool create) { #if PUXSHIFT == PGXSHIFT return get_pgd(pgdir, la, create); #else /* PUXSHIFT == PGXSHIFT */ pgd_t *pgdp; if ((pgdp = get_pgd(pgdir, la, create)) == NULL) { return NULL; } if (! ptep_present(pgdp)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(KADDR(pa), 0, PGSIZE); ptep_map(pgdp, pa); ptep_set_u_write(pgdp); ptep_set_accessed(pgdp); ptep_set_dirty(pgdp); } return &((pud_t *)KADDR(PGD_ADDR(*pgdp)))[PUX(la)]; #endif /* PUXSHIFT == PGXSHIFT */ }
void kmm_pgfault(struct trapframe *tf) { // uint64_t err = tf->tf_err; uintptr_t addr = rcr2(); if (addr >= PBASE && addr < PBASE + PSIZE) { pgd_t *pgd = KADDR_DIRECT(PTE_ADDR(rcr3())); pud_t *pud; pmd_t *pmd; pte_t *ptd; /* PHYSICAL ADDRRESS ACCESSING */ if (last_pgd != NULL) { pud = KADDR_DIRECT(PGD_ADDR(last_pgd[PGX(last_addr)])); pmd = KADDR_DIRECT(PUD_ADDR(pud[PUX(last_addr)])); ptd = KADDR_DIRECT(PMD_ADDR(pmd[PMX(last_addr)])); ptd[PTX(last_addr)] = 0; if (ptd == temp_ptd) { pmd[PUX(last_addr)] = 0; if (pmd == temp_pmd) { pud[PUX(last_addr)] = 0; if (pud == temp_pud) last_pgd[PGX(last_addr)] = 0; } if (last_pgd == pgd) { invlpg((void *)last_addr); } } } if (pgd[PGX(last_addr)] == 0) pgd[PGX(last_addr)] = PADDR_DIRECT(temp_pud) | PTE_W | PTE_P; pud = KADDR_DIRECT(PGD_ADDR(pgd[PGX(last_addr)])); if (pud[PUX(last_addr)] == 0) pud[PUX(last_addr)] = PADDR_DIRECT(temp_pmd) | PTE_W | PTE_P; pmd = KADDR_DIRECT(PUD_ADDR(pud[PUX(last_addr)])); if (pmd[PMX(last_addr)] == 0) pmd[PMX(last_addr)] = PADDR_DIRECT(temp_ptd) | PTE_W | PTE_P; ptd = KADDR_DIRECT(PMD_ADDR(pmd[PMX(last_addr)])); ptd[PTX(last_addr)] = PADDR_DIRECT(addr) | PTE_W | PTE_P; last_pgd = pgd; last_addr = addr; /* XXX? */ // invlpg((void *)addr); } }
static void exit_range_pud(pud_t *pud) { #if PUXSHIFT == PGXSHIFT exit_range_pmd(pud); #else uintptr_t la = 0; do { pud_t *pudp = &pud[PUX(la)]; if (ptep_present(pudp)) { exit_range_pmd(KADDR(PUD_ADDR(*pudp))); free_page(pud2page(*pudp)), *pudp = 0; } la += PMSIZE; } while (la != PUSIZE); #endif }
int get_page_data(struct DataTable *tbl, void *va, data_t *id_out) { pge_t *pge = &(tbl->table)[PGX(va)]; if(! *pge) goto get_fault; pue_t *pue = &(*pge)[PUX(va)]; if(! *pue) goto get_fault; pme_t *pme = &(*pue)[PMX(va)]; if(! *pme) goto get_fault; *id_out = (*pme)[PTX(va)]; return 0; get_fault: if (tbl->do_get_faults) return -E_NO_ENTRY; *id_out = 0; return 0; }
static void unmap_range_pud(pgd_t *pgdir, pud_t *pud, uintptr_t base, uintptr_t start, uintptr_t end) { #if PUXSHIFT == PGXSHIFT unmap_range_pmd (pgdir, pud, base, start, end); #else assert(start >= 0 && start < end && end <= PUSIZE); size_t off, size; uintptr_t la = ROUNDDOWN(start, PMSIZE); do { off = start - la, size = PMSIZE - off; if (size > end - start) { size = end - start; } pud_t *pudp = &pud[PUX(la)]; if (ptep_present(pudp)) { unmap_range_pmd(pgdir, KADDR(PUD_ADDR(*pudp)), base + la, off, off + size); } start += size, la += PMSIZE; } while (start != 0 && start < end); #endif }
pud_t * get_pud(pgd_t *pgdir, uintptr_t la, bool create) { #if PUXSHIFT == PGXSHIFT return get_pgd(pgdir, la, create); #else /* PUXSHIFT == PGXSHIFT */ pgd_t *pgdp; if ((pgdp = get_pgd(pgdir, la, create)) == NULL) { return NULL; } if (!(*pgdp & PTE_P)) { struct Page *page; if (!create || (page = alloc_page()) == NULL) { return NULL; } set_page_ref(page, 1); uintptr_t pa = page2pa(page); memset(VADDR_DIRECT(pa), 0, PGSIZE); *pgdp = pa | PTE_U | PTE_W | PTE_P; } return &((pud_t *)VADDR_DIRECT(PGD_ADDR(*pgdp)))[PUX(la)]; #endif /* PUXSHIFT == PGXSHIFT */ }