From a152234cf9a52766984ecb9a96cc1e5740ae9d78 Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 1 Aug 2006 19:06:06 +0000 Subject: Complete the transition from pmap_page_protect() to pmap_remove_write(). Originally, I had adopted sparc64's name, pmap_clear_write(), for the function that is now pmap_remove_write(). However, this function is more like pmap_remove_all() than like pmap_clear_modify() or pmap_clear_reference(), hence, the name change. The higher-level rationale behind this change is described in src/sys/amd64/amd64/pmap.c revision 1.567. The short version is that I'm trying to clean up and fix our support for execute access. Reviewed by: marcel@ (ia64) --- sys/powerpc/aim/mmu_oea.c | 121 +++++++++++++----------------------- sys/powerpc/powerpc/mmu_if.m | 26 ++++---- sys/powerpc/powerpc/mmu_oea.c | 121 +++++++++++++----------------------- sys/powerpc/powerpc/pmap_dispatch.c | 12 ++-- 4 files changed, 106 insertions(+), 174 deletions(-) (limited to 'sys/powerpc') diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 9729fa3..df5431d 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -322,7 +322,6 @@ boolean_t moea_is_modified(mmu_t, vm_page_t); boolean_t moea_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t); -void moea_page_protect(mmu_t, vm_page_t, vm_prot_t); void moea_pinit(mmu_t, pmap_t); void moea_pinit0(mmu_t, pmap_t); void moea_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t); @@ -331,6 +330,7 @@ void moea_qremove(mmu_t, vm_offset_t, int); void moea_release(mmu_t, pmap_t); void moea_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t); void moea_remove_all(mmu_t, vm_page_t); +void moea_remove_write(mmu_t, vm_page_t); void moea_zero_page(mmu_t, vm_page_t); void moea_zero_page_area(mmu_t, vm_page_t, int, int); void moea_zero_page_idle(mmu_t, vm_page_t); @@ -358,7 +358,6 @@ static mmu_method_t moea_methods[] = { MMUMETHOD(mmu_ts_referenced, moea_ts_referenced), MMUMETHOD(mmu_map, moea_map), MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick), - MMUMETHOD(mmu_page_protect, moea_page_protect), MMUMETHOD(mmu_pinit, moea_pinit), MMUMETHOD(mmu_pinit0, moea_pinit0), MMUMETHOD(mmu_protect, moea_protect), @@ -367,6 +366,7 @@ static mmu_method_t moea_methods[] = { MMUMETHOD(mmu_release, moea_release), MMUMETHOD(mmu_remove, moea_remove), MMUMETHOD(mmu_remove_all, moea_remove_all), + MMUMETHOD(mmu_remove_write, moea_remove_write), MMUMETHOD(mmu_zero_page, moea_zero_page), MMUMETHOD(mmu_zero_page_area, moea_zero_page_area), MMUMETHOD(mmu_zero_page_idle, moea_zero_page_idle), @@ -1293,6 +1293,48 @@ moea_clear_modify(mmu_t mmu, vm_page_t m) } /* + * Clear the write and modified bits in each of the given page's mappings. + */ +void +moea_remove_write(mmu_t mmu, vm_page_t m) +{ + struct pvo_entry *pvo; + struct pte *pt; + pmap_t pmap; + u_int lo; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 || + (m->flags & PG_WRITEABLE) == 0) + return; + lo = moea_attr_fetch(m); + SYNC(); + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + pmap = pvo->pvo_pmap; + PMAP_LOCK(pmap); + if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) { + pt = moea_pvo_to_pte(pvo, -1); + pvo->pvo_pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte_lo |= PTE_BR; + if (pt != NULL) { + moea_pte_synch(pt, &pvo->pvo_pte); + lo |= pvo->pvo_pte.pte_lo; + pvo->pvo_pte.pte_lo &= ~PTE_CHG; + moea_pte_change(pt, &pvo->pvo_pte, + pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + } + } + PMAP_UNLOCK(pmap); + } + if ((lo & PTE_CHG) != 0) { + moea_attr_clear(m, PTE_CHG); + vm_page_dirty(m); + } + vm_page_flag_clear(m, PG_WRITEABLE); +} + +/* * moea_ts_referenced: * * Return a count of reference bits for a page, clearing those bits. @@ -1420,81 +1462,6 @@ moea_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start, } /* - * Lower the permission for all mappings to a given page. - */ -void -moea_page_protect(mmu_t mmu, vm_page_t m, vm_prot_t prot) -{ - struct pvo_head *pvo_head; - struct pvo_entry *pvo, *next_pvo; - struct pte *pt; - pmap_t pmap; - - /* - * Since the routine only downgrades protection, if the - * maximal protection is desired, there isn't any change - * to be made. - */ - if ((prot & (VM_PROT_READ|VM_PROT_WRITE)) == - (VM_PROT_READ|VM_PROT_WRITE)) - return; - - pvo_head = vm_page_to_pvoh(m); - for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) { - next_pvo = LIST_NEXT(pvo, pvo_vlink); - MOEA_PVO_CHECK(pvo); /* sanity check */ - pmap = pvo->pvo_pmap; - PMAP_LOCK(pmap); - - /* - * Downgrading to no mapping at all, we just remove the entry. - */ - if ((prot & VM_PROT_READ) == 0) { - moea_pvo_remove(pvo, -1); - PMAP_UNLOCK(pmap); - continue; - } - - /* - * If EXEC permission is being revoked, just clear the flag - * in the PVO. - */ - if ((prot & VM_PROT_EXECUTE) == 0) - pvo->pvo_vaddr &= ~PVO_EXECUTABLE; - - /* - * If this entry is already RO, don't diddle with the page - * table. - */ - if ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_BR) { - PMAP_UNLOCK(pmap); - MOEA_PVO_CHECK(pvo); - continue; - } - - /* - * Grab the PTE before we diddle the bits so pvo_to_pte can - * verify the pte contents are as expected. - */ - pt = moea_pvo_to_pte(pvo, -1); - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; - if (pt != NULL) { - moea_pte_change(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - } - PMAP_UNLOCK(pmap); - MOEA_PVO_CHECK(pvo); /* sanity check */ - } - - /* - * Downgrading from writeable: clear the VM page flag - */ - if ((prot & VM_PROT_WRITE) != VM_PROT_WRITE) - vm_page_flag_clear(m, PG_WRITEABLE); -} - -/* * Returns true if the pmap's pv is one of the first * 16 pvs linked to from this page. This count may * be changed upwards or downwards in the future; it diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m index 5fd0510..548660f 100644 --- a/sys/powerpc/powerpc/mmu_if.m +++ b/sys/powerpc/powerpc/mmu_if.m @@ -147,6 +147,18 @@ METHOD void clear_reference { /** + * @brief Clear the write and modified bits in each of the given + * physical page's mappings + * + * @param _pg physical page + */ +METHOD void remove_write { + mmu_t _mmu; + vm_page_t _pg; +}; + + +/** * @brief Copy the address range given by the source physical map, virtual * address and length to the destination physical map and virtual address. * This routine is optional (xxx default null implementation ?) @@ -419,20 +431,6 @@ METHOD void page_init { /** - * @brief Lower the protection to the given value for all mappings of the - * given physical page. - * - * @param _pg physical page - * @param _prot updated page protection - */ -METHOD void page_protect { - mmu_t _mmu; - vm_page_t _pg; - vm_prot_t _prot; -}; - - -/** * @brief Initialise a physical map data structure * * @param _pmap physical map diff --git a/sys/powerpc/powerpc/mmu_oea.c b/sys/powerpc/powerpc/mmu_oea.c index 9729fa3..df5431d 100644 --- a/sys/powerpc/powerpc/mmu_oea.c +++ b/sys/powerpc/powerpc/mmu_oea.c @@ -322,7 +322,6 @@ boolean_t moea_is_modified(mmu_t, vm_page_t); boolean_t moea_ts_referenced(mmu_t, vm_page_t); vm_offset_t moea_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int); boolean_t moea_page_exists_quick(mmu_t, pmap_t, vm_page_t); -void moea_page_protect(mmu_t, vm_page_t, vm_prot_t); void moea_pinit(mmu_t, pmap_t); void moea_pinit0(mmu_t, pmap_t); void moea_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t); @@ -331,6 +330,7 @@ void moea_qremove(mmu_t, vm_offset_t, int); void moea_release(mmu_t, pmap_t); void moea_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t); void moea_remove_all(mmu_t, vm_page_t); +void moea_remove_write(mmu_t, vm_page_t); void moea_zero_page(mmu_t, vm_page_t); void moea_zero_page_area(mmu_t, vm_page_t, int, int); void moea_zero_page_idle(mmu_t, vm_page_t); @@ -358,7 +358,6 @@ static mmu_method_t moea_methods[] = { MMUMETHOD(mmu_ts_referenced, moea_ts_referenced), MMUMETHOD(mmu_map, moea_map), MMUMETHOD(mmu_page_exists_quick,moea_page_exists_quick), - MMUMETHOD(mmu_page_protect, moea_page_protect), MMUMETHOD(mmu_pinit, moea_pinit), MMUMETHOD(mmu_pinit0, moea_pinit0), MMUMETHOD(mmu_protect, moea_protect), @@ -367,6 +366,7 @@ static mmu_method_t moea_methods[] = { MMUMETHOD(mmu_release, moea_release), MMUMETHOD(mmu_remove, moea_remove), MMUMETHOD(mmu_remove_all, moea_remove_all), + MMUMETHOD(mmu_remove_write, moea_remove_write), MMUMETHOD(mmu_zero_page, moea_zero_page), MMUMETHOD(mmu_zero_page_area, moea_zero_page_area), MMUMETHOD(mmu_zero_page_idle, moea_zero_page_idle), @@ -1293,6 +1293,48 @@ moea_clear_modify(mmu_t mmu, vm_page_t m) } /* + * Clear the write and modified bits in each of the given page's mappings. + */ +void +moea_remove_write(mmu_t mmu, vm_page_t m) +{ + struct pvo_entry *pvo; + struct pte *pt; + pmap_t pmap; + u_int lo; + + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 || + (m->flags & PG_WRITEABLE) == 0) + return; + lo = moea_attr_fetch(m); + SYNC(); + LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) { + pmap = pvo->pvo_pmap; + PMAP_LOCK(pmap); + if ((pvo->pvo_pte.pte_lo & PTE_PP) != PTE_BR) { + pt = moea_pvo_to_pte(pvo, -1); + pvo->pvo_pte.pte_lo &= ~PTE_PP; + pvo->pvo_pte.pte_lo |= PTE_BR; + if (pt != NULL) { + moea_pte_synch(pt, &pvo->pvo_pte); + lo |= pvo->pvo_pte.pte_lo; + pvo->pvo_pte.pte_lo &= ~PTE_CHG; + moea_pte_change(pt, &pvo->pvo_pte, + pvo->pvo_vaddr); + mtx_unlock(&moea_table_mutex); + } + } + PMAP_UNLOCK(pmap); + } + if ((lo & PTE_CHG) != 0) { + moea_attr_clear(m, PTE_CHG); + vm_page_dirty(m); + } + vm_page_flag_clear(m, PG_WRITEABLE); +} + +/* * moea_ts_referenced: * * Return a count of reference bits for a page, clearing those bits. @@ -1420,81 +1462,6 @@ moea_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start, } /* - * Lower the permission for all mappings to a given page. - */ -void -moea_page_protect(mmu_t mmu, vm_page_t m, vm_prot_t prot) -{ - struct pvo_head *pvo_head; - struct pvo_entry *pvo, *next_pvo; - struct pte *pt; - pmap_t pmap; - - /* - * Since the routine only downgrades protection, if the - * maximal protection is desired, there isn't any change - * to be made. - */ - if ((prot & (VM_PROT_READ|VM_PROT_WRITE)) == - (VM_PROT_READ|VM_PROT_WRITE)) - return; - - pvo_head = vm_page_to_pvoh(m); - for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) { - next_pvo = LIST_NEXT(pvo, pvo_vlink); - MOEA_PVO_CHECK(pvo); /* sanity check */ - pmap = pvo->pvo_pmap; - PMAP_LOCK(pmap); - - /* - * Downgrading to no mapping at all, we just remove the entry. - */ - if ((prot & VM_PROT_READ) == 0) { - moea_pvo_remove(pvo, -1); - PMAP_UNLOCK(pmap); - continue; - } - - /* - * If EXEC permission is being revoked, just clear the flag - * in the PVO. - */ - if ((prot & VM_PROT_EXECUTE) == 0) - pvo->pvo_vaddr &= ~PVO_EXECUTABLE; - - /* - * If this entry is already RO, don't diddle with the page - * table. - */ - if ((pvo->pvo_pte.pte_lo & PTE_PP) == PTE_BR) { - PMAP_UNLOCK(pmap); - MOEA_PVO_CHECK(pvo); - continue; - } - - /* - * Grab the PTE before we diddle the bits so pvo_to_pte can - * verify the pte contents are as expected. - */ - pt = moea_pvo_to_pte(pvo, -1); - pvo->pvo_pte.pte_lo &= ~PTE_PP; - pvo->pvo_pte.pte_lo |= PTE_BR; - if (pt != NULL) { - moea_pte_change(pt, &pvo->pvo_pte, pvo->pvo_vaddr); - mtx_unlock(&moea_table_mutex); - } - PMAP_UNLOCK(pmap); - MOEA_PVO_CHECK(pvo); /* sanity check */ - } - - /* - * Downgrading from writeable: clear the VM page flag - */ - if ((prot & VM_PROT_WRITE) != VM_PROT_WRITE) - vm_page_flag_clear(m, PG_WRITEABLE); -} - -/* * Returns true if the pmap's pv is one of the first * 16 pvs linked to from this page. This count may * be changed upwards or downwards in the future; it diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c index 77f8368..e970d48 100644 --- a/sys/powerpc/powerpc/pmap_dispatch.c +++ b/sys/powerpc/powerpc/pmap_dispatch.c @@ -196,12 +196,6 @@ pmap_page_init(vm_page_t m) } void -pmap_page_protect(vm_page_t m, vm_prot_t prot) -{ - MMU_PAGE_PROTECT(mmu_obj, m, prot); -} - -void pmap_pinit(pmap_t pmap) { MMU_PINIT(mmu_obj, pmap); @@ -256,6 +250,12 @@ pmap_remove_pages(pmap_t pmap) } void +pmap_remove_write(vm_page_t m) +{ + MMU_REMOVE_WRITE(mmu_obj, m); +} + +void pmap_zero_page(vm_page_t m) { MMU_ZERO_PAGE(mmu_obj, m); -- cgit v1.1