Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/arm64/pmap.c
Show First 20 Lines • Show All 5,304 Lines • ▼ Show 20 Lines | if (tmpl1 != 0) { | ||||
pmap_kremove(tmpl1); | pmap_kremove(tmpl1); | ||||
kva_free(tmpl1, PAGE_SIZE); | kva_free(tmpl1, PAGE_SIZE); | ||||
} | } | ||||
return (l2); | return (l2); | ||||
} | } | ||||
static void | static void | ||||
pmap_fill_l3(pt_entry_t *firstl3, pt_entry_t newl3) | |||||
{ | |||||
pt_entry_t *l3; | |||||
for (l3 = firstl3; l3 - firstl3 < Ln_ENTRIES; l3++) { | |||||
*l3 = newl3; | |||||
newl3 += L3_SIZE; | |||||
} | |||||
} | |||||
static void | |||||
pmap_demote_l2_abort(pmap_t pmap, vm_offset_t va, pt_entry_t *l2, | pmap_demote_l2_abort(pmap_t pmap, vm_offset_t va, pt_entry_t *l2, | ||||
struct rwlock **lockp) | struct rwlock **lockp) | ||||
{ | { | ||||
struct spglist free; | struct spglist free; | ||||
SLIST_INIT(&free); | SLIST_INIT(&free); | ||||
(void)pmap_remove_l2(pmap, l2, va, pmap_load(pmap_l1(pmap, va)), &free, | (void)pmap_remove_l2(pmap, l2, va, pmap_load(pmap_l1(pmap, va)), &free, | ||||
lockp); | lockp); | ||||
vm_page_free_pages_toq(&free, true); | vm_page_free_pages_toq(&free, true); | ||||
} | } | ||||
/* | /* | ||||
* Create an L3 table to map all addresses within an L2 mapping. | * Create an L3 table to map all addresses within an L2 mapping. | ||||
*/ | */ | ||||
static pt_entry_t * | static pt_entry_t * | ||||
pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, | pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2, vm_offset_t va, | ||||
struct rwlock **lockp) | struct rwlock **lockp) | ||||
{ | { | ||||
pt_entry_t *l3, newl3, oldl2; | pt_entry_t *l3, newl3, oldl2; | ||||
vm_offset_t tmpl2; | vm_offset_t tmpl2; | ||||
vm_paddr_t l3phys, phys; | vm_paddr_t l3phys; | ||||
vm_page_t ml3; | vm_page_t ml3; | ||||
int i; | |||||
PMAP_LOCK_ASSERT(pmap, MA_OWNED); | PMAP_LOCK_ASSERT(pmap, MA_OWNED); | ||||
l3 = NULL; | l3 = NULL; | ||||
oldl2 = pmap_load(l2); | oldl2 = pmap_load(l2); | ||||
KASSERT((oldl2 & ATTR_DESCR_MASK) == L2_BLOCK, | KASSERT((oldl2 & ATTR_DESCR_MASK) == L2_BLOCK, | ||||
("pmap_demote_l2: Demoting a non-block entry")); | ("pmap_demote_l2: Demoting a non-block entry")); | ||||
va &= ~L2_OFFSET; | va &= ~L2_OFFSET; | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if ((ml3 = pmap_remove_pt_page(pmap, va)) == NULL) { | ||||
if (va < VM_MAXUSER_ADDRESS) { | if (va < VM_MAXUSER_ADDRESS) { | ||||
ml3->wire_count = NL3PG; | ml3->wire_count = NL3PG; | ||||
pmap_resident_count_inc(pmap, 1); | pmap_resident_count_inc(pmap, 1); | ||||
} | } | ||||
} | } | ||||
l3phys = VM_PAGE_TO_PHYS(ml3); | l3phys = VM_PAGE_TO_PHYS(ml3); | ||||
l3 = (pt_entry_t *)PHYS_TO_DMAP(l3phys); | l3 = (pt_entry_t *)PHYS_TO_DMAP(l3phys); | ||||
/* Address the range points at */ | newl3 = (oldl2 & ~ATTR_DESCR_MASK) | L3_PAGE; | ||||
phys = oldl2 & ~ATTR_MASK; | |||||
/* The attributed from the old l2 table to be copied */ | |||||
newl3 = (oldl2 & (ATTR_MASK & ~ATTR_DESCR_MASK)) | L3_PAGE; | |||||
KASSERT((oldl2 & (ATTR_AP_RW_BIT | ATTR_SW_DBM)) != | KASSERT((oldl2 & (ATTR_AP_RW_BIT | ATTR_SW_DBM)) != | ||||
(ATTR_AP(ATTR_AP_RO) | ATTR_SW_DBM), | (ATTR_AP(ATTR_AP_RO) | ATTR_SW_DBM), | ||||
("pmap_demote_l2: L2 entry is writeable but not dirty")); | ("pmap_demote_l2: L2 entry is writeable but not dirty")); | ||||
/* | /* | ||||
* If the page table page is not leftover from an earlier promotion, | * If the page table page is not leftover from an earlier promotion, | ||||
* initialize it. | * or the mapping attributes have changed, (re)initialize the L3 table. | ||||
*/ | */ | ||||
if (ml3->valid == 0) { | if (ml3->valid == 0 || (l3[0] & ATTR_MASK) != (newl3 & ATTR_MASK)) | ||||
for (i = 0; i < Ln_ENTRIES; i++) { | pmap_fill_l3(l3, newl3); | ||||
l3[i] = newl3 | phys; | |||||
phys += L3_SIZE; | |||||
} | |||||
} | |||||
KASSERT(l3[0] == ((oldl2 & ~ATTR_DESCR_MASK) | L3_PAGE), | |||||
("Invalid l3 page (%lx != %lx)", l3[0], | |||||
(oldl2 & ~ATTR_DESCR_MASK) | L3_PAGE)); | |||||
/* | /* | ||||
* Map the temporary page so we don't lose access to the l2 table. | * Map the temporary page so we don't lose access to the l2 table. | ||||
*/ | */ | ||||
if (tmpl2 != 0) { | if (tmpl2 != 0) { | ||||
pmap_kenter(tmpl2, PAGE_SIZE, | pmap_kenter(tmpl2, PAGE_SIZE, | ||||
DMAP_TO_PHYS((vm_offset_t)l2) & ~L3_OFFSET, CACHED_MEMORY); | DMAP_TO_PHYS((vm_offset_t)l2) & ~L3_OFFSET, CACHED_MEMORY); | ||||
l2 = (pt_entry_t *)(tmpl2 + ((vm_offset_t)l2 & PAGE_MASK)); | l2 = (pt_entry_t *)(tmpl2 + ((vm_offset_t)l2 & PAGE_MASK)); | ||||
▲ Show 20 Lines • Show All 388 Lines • Show Last 20 Lines |