Author: raj
Date: Mon Oct 13 18:42:25 2008
New Revision: 183836
URL: http://svn.freebsd.org/changeset/base/183836

Log:
  Do not use cached page for temporary mapping in pmap_zero_page_generic()
  
  The physical page which we clear is accessed via additional temp kernel
  mapping for the period of zeroing operation. However in systems with virtual
  d-cache (most ARMs) when write-allocate feature is enabled, we can have
  modified but unflushed content pertaining to this physical page still in the
  d-cache due to its primary (pre-existing) mapping. In such scenario that
  cached content upon flush is likely to overwrite [portions of] the physical
  page we want to zero here..
  
  This is a general problem with multiple virtual mappings covering the same
  physical page with write-allocate and virtual d-cache: there is inherent
  potential for corruptions of this kind, which are not easily resolved; it is
  best policy that such multiple mappings be not allowed.
  
  Obtained from:        Marvell, Semihalf

Modified:
  head/sys/arm/arm/pmap.c

Modified: head/sys/arm/arm/pmap.c
==============================================================================
--- head/sys/arm/arm/pmap.c     Mon Oct 13 18:16:54 2008        (r183835)
+++ head/sys/arm/arm/pmap.c     Mon Oct 13 18:42:25 2008        (r183836)
@@ -3850,21 +3850,19 @@ pmap_zero_page_generic(vm_paddr_t phys, 
 
        mtx_lock(&cmtx);
        /*
-        * Hook in the page, zero it, and purge the cache for that
-        * zeroed page. Invalidate the TLB as needed.
+        * Hook in the page, zero it, invalidate the TLB as needed.
+        *
+        * Note the temporary zero-page mapping must be a non-cached page in
+        * ordert to work without corruption when write-allocate is enabled.
         */
-       *cdst_pte = L2_S_PROTO | phys |
-           L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
-       PTE_SYNC(cdst_pte);
+       *cdst_pte = L2_S_PROTO | phys | L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE);
        cpu_tlb_flushD_SE(cdstp);
        cpu_cpwait();
-       if (off || size != PAGE_SIZE) {
+       if (off || size != PAGE_SIZE)
                bzero((void *)(cdstp + off), size);
-               cpu_dcache_wbinv_range(cdstp + off, size);
-       } else {
+       else
                bzero_page(cdstp);
-               cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
-       }
+
        mtx_unlock(&cmtx);
 #endif
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to