- if (pmap_aliasmask && !pmap_pte_ci(pte) &&
- !(pmap == kernel_pmap && firstpage))
- flushcache = TRUE;
-#ifdef DEBUG
- opte = *pte;
- remove_stats.removes++;
-#endif
- /*
- * Update statistics
- */
- if (pmap_pte_w(pte))
- pmap->pm_stats.wired_count--;
- pmap->pm_stats.resident_count--;
-
- /*
- * Invalidate the PTEs.
- * XXX: should cluster them up and invalidate as many
- * as possible at once.
- */
-#ifdef DEBUG
- if (pmapdebug & PDB_REMOVE)
- printf("remove: invalidating %x ptes at %x\n",
- hppagesperpage, pte);
-#endif
- /*
- * Flush VAC to ensure we get the correct state of any
- * hardware maintained bits.
- */
- if (firstpage && pmap_aliasmask) {
- firstpage = FALSE;
- if (pmap == kernel_pmap)
- flushcache = FALSE;
- DCIS();
-#ifdef DEBUG
- remove_stats.sflushes++;
-#endif
- }
- bits = ix = 0;
- do {
- bits |= *(int *)pte & (PG_U|PG_M);
- *(int *)pte++ = PG_NV;
- TBIS(va + ix * HP_PAGE_SIZE);
- } while (++ix != hppagesperpage);
-
- /*
- * For user mappings decrement the wiring count on
- * the PT page. We do this after the PTE has been
- * invalidated because vm_map_pageable winds up in
- * pmap_pageable which clears the modify bit for the
- * PT page.
- */
- if (pmap != kernel_pmap) {
- pte = pmap_pte(pmap, va);
- vm_map_pageable(pt_map, trunc_page(pte),
- round_page(pte+1), TRUE);
-#ifdef DEBUG
- if (pmapdebug & PDB_WIRING)
- pmap_check_wiring("remove", trunc_page(pte));
-#endif
- }
- /*
- * Remove from the PV table (raise IPL since we
- * may be called at interrupt time).
- */
- if (pa < vm_first_phys || pa >= vm_last_phys)
- continue;
- pv = pa_to_pvh(pa);
- ste = (int *)0;
- s = splimp();
- /*
- * If it is the first entry on the list, it is actually
- * in the header and we must copy the following entry up
- * to the header. Otherwise we must search the list for
- * the entry. In either case we free the now unused entry.
- */
- if (pmap == pv->pv_pmap && va == pv->pv_va) {
- ste = (int *)pv->pv_ptste;
- ptpmap = pv->pv_ptpmap;
- npv = pv->pv_next;
- if (npv) {
- *pv = *npv;
- free((caddr_t)npv, M_VMPVENT);
- } else
- pv->pv_pmap = NULL;
-#ifdef DEBUG
- remove_stats.pvfirst++;
-#endif
- } else {
- for (npv = pv->pv_next; npv; npv = npv->pv_next) {
-#ifdef DEBUG
- remove_stats.pvsearch++;
-#endif
- if (pmap == npv->pv_pmap && va == npv->pv_va)
- break;
- pv = npv;
- }
-#ifdef DEBUG
- if (npv == NULL)
- panic("pmap_remove: PA not in pv_tab");
-#endif
- ste = (int *)npv->pv_ptste;
- ptpmap = npv->pv_ptpmap;
- pv->pv_next = npv->pv_next;
- free((caddr_t)npv, M_VMPVENT);
- pv = pa_to_pvh(pa);
- }
- /*
- * If only one mapping left we no longer need to cache inhibit
- */
- if (pv->pv_pmap &&
- pv->pv_next == NULL && (pv->pv_flags & PV_CI)) {
-#ifdef DEBUG
- if (pmapdebug & PDB_CACHE)
- printf("remove: clearing CI for pa %x\n", pa);
-#endif
- pv->pv_flags &= ~PV_CI;
- pmap_changebit(pa, PG_CI, FALSE);
-#ifdef DEBUG
- if ((pmapdebug & (PDB_CACHE|PDB_PVDUMP)) ==
- (PDB_CACHE|PDB_PVDUMP))
- pmap_pvdump(pa);
-#endif
- }
-
- /*
- * If this was a PT page we must also remove the
- * mapping from the associated segment table.
- */
- if (ste) {
-#ifdef DEBUG
- remove_stats.ptinvalid++;
- if (pmapdebug & (PDB_REMOVE|PDB_PTPAGE)) {
- printf("remove: ste was %x@%x pte was %x@%x\n",
- *ste, ste,
- *(int *)&opte, pmap_pte(pmap, va));
- }
-#endif
- *ste = SG_NV;
- /*
- * If it was a user PT page, we decrement the
- * reference count on the segment table as well,
- * freeing it if it is now empty.
- */
- if (ptpmap != kernel_pmap) {
-#ifdef DEBUG
- if (pmapdebug & (PDB_REMOVE|PDB_SEGTAB))
- printf("remove: stab %x, refcnt %d\n",
- ptpmap->pm_stab,
- ptpmap->pm_sref - 1);
- if ((pmapdebug & PDB_PARANOIA) &&
- ptpmap->pm_stab != (st_entry_t *)trunc_page(ste))
- panic("remove: bogus ste");
-#endif
- if (--(ptpmap->pm_sref) == 0) {
-#ifdef DEBUG
- if (pmapdebug&(PDB_REMOVE|PDB_SEGTAB))
- printf("remove: free stab %x\n",
- ptpmap->pm_stab);