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
This commit is contained in:
parent
ba6faad63c
commit
5289eda203
@ -3850,21 +3850,19 @@ pmap_zero_page_generic(vm_paddr_t phys, int off, int size)
|
|||||||
|
|
||||||
mtx_lock(&cmtx);
|
mtx_lock(&cmtx);
|
||||||
/*
|
/*
|
||||||
* Hook in the page, zero it, and purge the cache for that
|
* Hook in the page, zero it, invalidate the TLB as needed.
|
||||||
* zeroed page. 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 |
|
*cdst_pte = L2_S_PROTO | phys | L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE);
|
||||||
L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
|
|
||||||
PTE_SYNC(cdst_pte);
|
|
||||||
cpu_tlb_flushD_SE(cdstp);
|
cpu_tlb_flushD_SE(cdstp);
|
||||||
cpu_cpwait();
|
cpu_cpwait();
|
||||||
if (off || size != PAGE_SIZE) {
|
if (off || size != PAGE_SIZE)
|
||||||
bzero((void *)(cdstp + off), size);
|
bzero((void *)(cdstp + off), size);
|
||||||
cpu_dcache_wbinv_range(cdstp + off, size);
|
else
|
||||||
} else {
|
|
||||||
bzero_page(cdstp);
|
bzero_page(cdstp);
|
||||||
cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
mtx_unlock(&cmtx);
|
mtx_unlock(&cmtx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user