Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/arm64/pmap.c
Show First 20 Lines • Show All 1,122 Lines • ▼ Show 20 Lines | retry: | ||||
PMAP_UNLOCK(pmap); | PMAP_UNLOCK(pmap); | ||||
return (m); | return (m); | ||||
} | } | ||||
vm_paddr_t | vm_paddr_t | ||||
pmap_kextract(vm_offset_t va) | pmap_kextract(vm_offset_t va) | ||||
{ | { | ||||
pt_entry_t *pte, tpte; | pt_entry_t *pte, tpte; | ||||
vm_paddr_t pa; | |||||
int lvl; | |||||
if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) { | if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) | ||||
pa = DMAP_TO_PHYS(va); | return (DMAP_TO_PHYS(va)); | ||||
} else { | pte = pmap_l1(kernel_pmap, va); | ||||
pa = 0; | if (pte == NULL) | ||||
pte = pmap_pte(kernel_pmap, va, &lvl); | return (0); | ||||
if (pte != NULL) { | |||||
/* | |||||
* A concurrent pmap_update_entry() will clear the entry's valid bit | |||||
* but leave the rest of the entry unchanged. Therefore, we treat a | |||||
* non-zero entry as being valid, and we ignore the valid bit when | |||||
* determining whether the entry maps a block, page, or table. | |||||
*/ | |||||
tpte = pmap_load(pte); | tpte = pmap_load(pte); | ||||
pa = tpte & ~ATTR_MASK; | if (tpte == 0) | ||||
switch(lvl) { | return (0); | ||||
case 1: | if ((tpte & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) | ||||
KASSERT((tpte & ATTR_DESCR_MASK) == L1_BLOCK, | return ((tpte & ~ATTR_MASK) | (va & L1_OFFSET)); | ||||
("pmap_kextract: Invalid L1 pte found: %lx", | pte = pmap_l1_to_l2(&tpte, va); | ||||
tpte & ATTR_DESCR_MASK)); | tpte = pmap_load(pte); | ||||
pa |= (va & L1_OFFSET); | if (tpte == 0) | ||||
break; | return (0); | ||||
case 2: | if ((tpte & ATTR_DESCR_TYPE_MASK) == ATTR_DESCR_TYPE_BLOCK) | ||||
KASSERT((tpte & ATTR_DESCR_MASK) == L2_BLOCK, | return ((tpte & ~ATTR_MASK) | (va & L2_OFFSET)); | ||||
("pmap_kextract: Invalid L2 pte found: %lx", | pte = pmap_l2_to_l3(&tpte, va); | ||||
tpte & ATTR_DESCR_MASK)); | tpte = pmap_load(pte); | ||||
pa |= (va & L2_OFFSET); | if (tpte == 0) | ||||
break; | return (0); | ||||
case 3: | return ((tpte & ~ATTR_MASK) | (va & L3_OFFSET)); | ||||
KASSERT((tpte & ATTR_DESCR_MASK) == L3_PAGE, | |||||
("pmap_kextract: Invalid L3 pte found: %lx", | |||||
tpte & ATTR_DESCR_MASK)); | |||||
pa |= (va & L3_OFFSET); | |||||
break; | |||||
} | } | ||||
} | |||||
} | |||||
return (pa); | |||||
} | |||||
/*************************************************** | /*************************************************** | ||||
* Low level mapping routines..... | * Low level mapping routines..... | ||||
***************************************************/ | ***************************************************/ | ||||
void | void | ||||
pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode) | pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 1,842 Lines • ▼ Show 20 Lines | pmap_update_entry(pmap_t pmap, pd_entry_t *pte, pd_entry_t newpte, | ||||
/* | /* | ||||
* Ensure we don't get switched out with the page table in an | * Ensure we don't get switched out with the page table in an | ||||
* inconsistent state. We also need to ensure no interrupts fire | * inconsistent state. We also need to ensure no interrupts fire | ||||
* as they may make use of an address we are about to invalidate. | * as they may make use of an address we are about to invalidate. | ||||
*/ | */ | ||||
intr = intr_disable(); | intr = intr_disable(); | ||||
critical_enter(); | critical_enter(); | ||||
/* Clear the old mapping */ | /* | ||||
pmap_clear(pte); | * Clear the old mapping's valid bit, but leave the rest of the entry | ||||
* unchanged, so that a lockless, concurrent pmap_kextract() can still | |||||
* lookup the physical address. | |||||
*/ | |||||
pmap_clear_bits(pte, ATTR_DESCR_VALID); | |||||
pmap_invalidate_range_nopin(pmap, va, va + size); | pmap_invalidate_range_nopin(pmap, va, va + size); | ||||
/* Create the new mapping */ | /* Create the new mapping */ | ||||
pmap_store(pte, newpte); | pmap_store(pte, newpte); | ||||
dsb(ishst); | dsb(ishst); | ||||
critical_exit(); | critical_exit(); | ||||
intr_restore(intr); | intr_restore(intr); | ||||
▲ Show 20 Lines • Show All 2,916 Lines • Show Last 20 Lines |