Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/aim/mmu_oea64.c
Show First 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | |||||
uint64_t moea64_large_page_mask = 0; | uint64_t moea64_large_page_mask = 0; | ||||
uint64_t moea64_large_page_size = 0; | uint64_t moea64_large_page_size = 0; | ||||
int moea64_large_page_shift = 0; | int moea64_large_page_shift = 0; | ||||
/* | /* | ||||
* PVO calls. | * PVO calls. | ||||
*/ | */ | ||||
static int moea64_pvo_enter(mmu_t mmu, struct pvo_entry *pvo, | static int moea64_pvo_enter(mmu_t mmu, struct pvo_entry *pvo, | ||||
struct pvo_head *pvo_head); | struct pvo_head *pvo_head, struct pvo_entry **oldpvo); | ||||
static void moea64_pvo_remove_from_pmap(mmu_t mmu, struct pvo_entry *pvo); | static void moea64_pvo_remove_from_pmap(mmu_t mmu, struct pvo_entry *pvo); | ||||
static void moea64_pvo_remove_from_page(mmu_t mmu, struct pvo_entry *pvo); | static void moea64_pvo_remove_from_page(mmu_t mmu, struct pvo_entry *pvo); | ||||
static void moea64_pvo_remove_from_page_locked(mmu_t mmu, | static void moea64_pvo_remove_from_page_locked(mmu_t mmu, | ||||
struct pvo_entry *pvo, vm_page_t m); | struct pvo_entry *pvo, vm_page_t m); | ||||
static struct pvo_entry *moea64_pvo_find_va(pmap_t, vm_offset_t); | static struct pvo_entry *moea64_pvo_find_va(pmap_t, vm_offset_t); | ||||
/* | /* | ||||
* Utility routines. | * Utility routines. | ||||
▲ Show 20 Lines • Show All 427 Lines • ▼ Show 20 Lines | for (i = 0; i < pregions_sz; i++) { | ||||
} | } | ||||
if (pa + moea64_large_page_size > | if (pa + moea64_large_page_size > | ||||
pregions[i].mr_start + pregions[i].mr_size) | pregions[i].mr_start + pregions[i].mr_size) | ||||
pte_lo |= LPTE_G; | pte_lo |= LPTE_G; | ||||
pvo->pvo_pte.prot = VM_PROT_READ | VM_PROT_WRITE | | pvo->pvo_pte.prot = VM_PROT_READ | VM_PROT_WRITE | | ||||
VM_PROT_EXECUTE; | VM_PROT_EXECUTE; | ||||
pvo->pvo_pte.pa = pa | pte_lo; | pvo->pvo_pte.pa = pa | pte_lo; | ||||
moea64_pvo_enter(mmup, pvo, NULL); | moea64_pvo_enter(mmup, pvo, NULL, NULL); | ||||
} | } | ||||
} | } | ||||
PMAP_UNLOCK(kernel_pmap); | PMAP_UNLOCK(kernel_pmap); | ||||
} | } | ||||
/* | /* | ||||
* Make sure the kernel and BPVO pool stay mapped on systems either | * Make sure the kernel and BPVO pool stay mapped on systems either | ||||
* without a direct map or on which the kernel is not already executing | * without a direct map or on which the kernel is not already executing | ||||
▲ Show 20 Lines • Show All 732 Lines • ▼ Show 20 Lines | for (;;) { | ||||
PMAP_LOCK(pmap); | PMAP_LOCK(pmap); | ||||
if (pvo->pvo_pmap == NULL) | if (pvo->pvo_pmap == NULL) | ||||
init_pvo_entry(pvo, pmap, va); | init_pvo_entry(pvo, pmap, va); | ||||
if (prot & VM_PROT_WRITE) | if (prot & VM_PROT_WRITE) | ||||
if (pmap_bootstrapped && | if (pmap_bootstrapped && | ||||
(m->oflags & VPO_UNMANAGED) == 0) | (m->oflags & VPO_UNMANAGED) == 0) | ||||
vm_page_aflag_set(m, PGA_WRITEABLE); | vm_page_aflag_set(m, PGA_WRITEABLE); | ||||
oldpvo = moea64_pvo_find_va(pmap, va); | error = moea64_pvo_enter(mmu, pvo, pvo_head, &oldpvo); | ||||
if (oldpvo != NULL) { | if (error == EEXIST) { | ||||
if (oldpvo->pvo_vaddr == pvo->pvo_vaddr && | if (oldpvo->pvo_vaddr == pvo->pvo_vaddr && | ||||
oldpvo->pvo_pte.pa == pvo->pvo_pte.pa && | oldpvo->pvo_pte.pa == pvo->pvo_pte.pa && | ||||
oldpvo->pvo_pte.prot == prot) { | oldpvo->pvo_pte.prot == prot) { | ||||
/* Identical mapping already exists */ | /* Identical mapping already exists */ | ||||
error = 0; | error = 0; | ||||
/* If not in page table, reinsert it */ | /* If not in page table, reinsert it */ | ||||
if (MOEA64_PTE_SYNCH(mmu, oldpvo) < 0) { | if (MOEA64_PTE_SYNCH(mmu, oldpvo) < 0) { | ||||
moea64_pte_overflow--; | moea64_pte_overflow--; | ||||
MOEA64_PTE_INSERT(mmu, oldpvo); | MOEA64_PTE_INSERT(mmu, oldpvo); | ||||
} | } | ||||
/* Then just clean up and go home */ | /* Then just clean up and go home */ | ||||
PV_PAGE_UNLOCK(m); | PV_PAGE_UNLOCK(m); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
free_pvo_entry(pvo); | free_pvo_entry(pvo); | ||||
break; | break; | ||||
} | } | ||||
/* Otherwise, need to kill it first */ | /* Otherwise, need to kill it first */ | ||||
KASSERT(oldpvo->pvo_pmap == pmap, ("pmap of old " | KASSERT(oldpvo->pvo_pmap == pmap, ("pmap of old " | ||||
"mapping does not match new mapping")); | "mapping does not match new mapping")); | ||||
moea64_pvo_remove_from_pmap(mmu, oldpvo); | moea64_pvo_remove_from_pmap(mmu, oldpvo); | ||||
error = moea64_pvo_enter(mmu, pvo, pvo_head, NULL); | |||||
} | } | ||||
error = moea64_pvo_enter(mmu, pvo, pvo_head); | |||||
PV_PAGE_UNLOCK(m); | PV_PAGE_UNLOCK(m); | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
/* Free any dead pages */ | /* Free any dead pages */ | ||||
if (oldpvo != NULL) { | if (oldpvo != NULL) { | ||||
moea64_pvo_remove_from_page(mmu, oldpvo); | moea64_pvo_remove_from_page(mmu, oldpvo); | ||||
free_pvo_entry(oldpvo); | free_pvo_entry(oldpvo); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | moea64_uma_page_alloc(uma_zone_t zone, vm_size_t bytes, int domain, | ||||
pvo->pvo_pte.pa = VM_PAGE_TO_PHYS(m) | LPTE_M; | pvo->pvo_pte.pa = VM_PAGE_TO_PHYS(m) | LPTE_M; | ||||
if (needed_lock) | if (needed_lock) | ||||
PMAP_LOCK(kernel_pmap); | PMAP_LOCK(kernel_pmap); | ||||
init_pvo_entry(pvo, kernel_pmap, va); | init_pvo_entry(pvo, kernel_pmap, va); | ||||
pvo->pvo_vaddr |= PVO_WIRED; | pvo->pvo_vaddr |= PVO_WIRED; | ||||
moea64_pvo_enter(installed_mmu, pvo, NULL); | moea64_pvo_enter(installed_mmu, pvo, NULL, NULL); | ||||
if (needed_lock) | if (needed_lock) | ||||
PMAP_UNLOCK(kernel_pmap); | PMAP_UNLOCK(kernel_pmap); | ||||
if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) | if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0) | ||||
bzero((void *)va, PAGE_SIZE); | bzero((void *)va, PAGE_SIZE); | ||||
return (void *)va; | return (void *)va; | ||||
▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | moea64_kenter_attr(mmu_t mmu, vm_offset_t va, vm_paddr_t pa, vm_memattr_t ma) | ||||
pvo->pvo_pte.pa = (pa & ~ADDR_POFF) | moea64_calc_wimg(pa, ma); | pvo->pvo_pte.pa = (pa & ~ADDR_POFF) | moea64_calc_wimg(pa, ma); | ||||
pvo->pvo_vaddr |= PVO_WIRED; | pvo->pvo_vaddr |= PVO_WIRED; | ||||
PMAP_LOCK(kernel_pmap); | PMAP_LOCK(kernel_pmap); | ||||
oldpvo = moea64_pvo_find_va(kernel_pmap, va); | oldpvo = moea64_pvo_find_va(kernel_pmap, va); | ||||
if (oldpvo != NULL) | if (oldpvo != NULL) | ||||
moea64_pvo_remove_from_pmap(mmu, oldpvo); | moea64_pvo_remove_from_pmap(mmu, oldpvo); | ||||
init_pvo_entry(pvo, kernel_pmap, va); | init_pvo_entry(pvo, kernel_pmap, va); | ||||
error = moea64_pvo_enter(mmu, pvo, NULL); | error = moea64_pvo_enter(mmu, pvo, NULL, NULL); | ||||
PMAP_UNLOCK(kernel_pmap); | PMAP_UNLOCK(kernel_pmap); | ||||
/* Free any dead pages */ | /* Free any dead pages */ | ||||
if (oldpvo != NULL) { | if (oldpvo != NULL) { | ||||
moea64_pvo_remove_from_page(mmu, oldpvo); | moea64_pvo_remove_from_page(mmu, oldpvo); | ||||
free_pvo_entry(oldpvo); | free_pvo_entry(oldpvo); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 625 Lines • ▼ Show 20 Lines | for (i = 0; phys_avail[i + 1] != 0; i += 2) { | ||||
} | } | ||||
return (s); | return (s); | ||||
} | } | ||||
panic("moea64_bootstrap_alloc: could not allocate memory"); | panic("moea64_bootstrap_alloc: could not allocate memory"); | ||||
} | } | ||||
static int | static int | ||||
moea64_pvo_enter(mmu_t mmu, struct pvo_entry *pvo, struct pvo_head *pvo_head) | moea64_pvo_enter(mmu_t mmu, struct pvo_entry *pvo, struct pvo_head *pvo_head, | ||||
struct pvo_entry **oldpvop) | |||||
{ | { | ||||
int first, err; | int first, err; | ||||
struct pvo_entry *old_pvo; | |||||
PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED); | PMAP_LOCK_ASSERT(pvo->pvo_pmap, MA_OWNED); | ||||
KASSERT(moea64_pvo_find_va(pvo->pvo_pmap, PVO_VADDR(pvo)) == NULL, | KASSERT(moea64_pvo_find_va(pvo->pvo_pmap, PVO_VADDR(pvo)) == NULL, | ||||
("Existing mapping for VA %#jx", (uintmax_t)PVO_VADDR(pvo))); | ("Existing mapping for VA %#jx", (uintmax_t)PVO_VADDR(pvo))); | ||||
moea64_pvo_enter_calls++; | moea64_pvo_enter_calls++; | ||||
/* | /* | ||||
* Add to pmap list | * Add to pmap list | ||||
*/ | */ | ||||
RB_INSERT(pvo_tree, &pvo->pvo_pmap->pmap_pvo, pvo); | old_pvo = RB_INSERT(pvo_tree, &pvo->pvo_pmap->pmap_pvo, pvo); | ||||
if (old_pvo != NULL) { | |||||
if (oldpvop != NULL) | |||||
*oldpvop = old_pvo; | |||||
return (EEXIST); | |||||
} | |||||
/* | /* | ||||
* Remember if the list was empty and therefore will be the first | * Remember if the list was empty and therefore will be the first | ||||
* item. | * item. | ||||
*/ | */ | ||||
if (pvo_head != NULL) { | if (pvo_head != NULL) { | ||||
if (LIST_FIRST(pvo_head) == NULL) | if (LIST_FIRST(pvo_head) == NULL) | ||||
first = 1; | first = 1; | ||||
▲ Show 20 Lines • Show All 395 Lines • Show Last 20 Lines |