Skip to content
  • Jeremy Fitzhardinge's avatar
    x86: don't apply __supported_pte_mask to non-present ptes · b534816b
    Jeremy Fitzhardinge authored
    
    
    On an x86 system which doesn't support global mappings,
    __supported_pte_mask has _PAGE_GLOBAL clear, to make sure it never
    appears in the PTE.  pfn_pte() and so on will enforce it with:
    
    static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
    {
    	return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) |
    		      pgprot_val(pgprot)) & __supported_pte_mask);
    }
    
    However, we overload _PAGE_GLOBAL with _PAGE_PROTNONE on non-present
    ptes to distinguish them from swap entries.  However, applying
    __supported_pte_mask indiscriminately will clear the bit and corrupt the
    pte.
    
    I guess the best fix is to only apply __supported_pte_mask to present
    ptes.  This seems like the right solution to me, as it means we can
    completely ignore the issue of overlaps between the present pte bits and
    the non-present pte-as-swap entry use of the bits.
    
    __supported_pte_mask contains the set of flags we support on the
    current hardware.  We also use bits in the pte for things like
    logically present ptes with no permissions, and swap entries for
    swapped out pages.  We should only apply __supported_pte_mask to
    present ptes, because otherwise we may destroy other information being
    stored in the ptes.
    
    Signed-off-by: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
    Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
    b534816b