lkml.org 
[lkml]   [2022]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.18 231/231] x86/pat: Fix x86_has_pat_wp()
    Date
    From: Juergen Gross <jgross@suse.com>

    commit 230ec83d4299b30c51a1c133b4f2a669972cc08a upstream.

    x86_has_pat_wp() is using a wrong test, as it relies on the normal
    PAT configuration used by the kernel. In case the PAT MSR has been
    setup by another entity (e.g. Xen hypervisor) it might return false
    even if the PAT configuration is allowing WP mappings. This due to the
    fact that when running as Xen PV guest the PAT MSR is setup by the
    hypervisor and cannot be changed by the guest. This results in the WP
    related entry to be at a different position when running as Xen PV
    guest compared to the bare metal or fully virtualized case.

    The correct way to test for WP support is:

    1. Get the PTE protection bits needed to select WP mode by reading
    __cachemode2pte_tbl[_PAGE_CACHE_MODE_WP] (depending on the PAT MSR
    setting this might return protection bits for a stronger mode, e.g.
    UC-)
    2. Translate those bits back into the real cache mode selected by those
    PTE bits by reading __pte2cachemode_tbl[__pte2cm_idx(prot)]
    3. Test for the cache mode to be _PAGE_CACHE_MODE_WP

    Fixes: f88a68facd9a ("x86/mm: Extend early_memremap() support with additional attrs")
    Signed-off-by: Juergen Gross <jgross@suse.com>
    Signed-off-by: Borislav Petkov <bp@suse.de>
    Cc: <stable@vger.kernel.org> # 4.14
    Link: https://lore.kernel.org/r/20220503132207.17234-1-jgross@suse.com
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    arch/x86/mm/init.c | 14 ++++++++++++--
    1 file changed, 12 insertions(+), 2 deletions(-)

    --- a/arch/x86/mm/init.c
    +++ b/arch/x86/mm/init.c
    @@ -77,10 +77,20 @@ static uint8_t __pte2cachemode_tbl[8] =
    [__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC,
    };

    -/* Check that the write-protect PAT entry is set for write-protect */
    +/*
    + * Check that the write-protect PAT entry is set for write-protect.
    + * To do this without making assumptions how PAT has been set up (Xen has
    + * another layout than the kernel), translate the _PAGE_CACHE_MODE_WP cache
    + * mode via the __cachemode2pte_tbl[] into protection bits (those protection
    + * bits will select a cache mode of WP or better), and then translate the
    + * protection bits back into the cache mode using __pte2cm_idx() and the
    + * __pte2cachemode_tbl[] array. This will return the really used cache mode.
    + */
    bool x86_has_pat_wp(void)
    {
    - return __pte2cachemode_tbl[_PAGE_CACHE_MODE_WP] == _PAGE_CACHE_MODE_WP;
    + uint16_t prot = __cachemode2pte_tbl[_PAGE_CACHE_MODE_WP];
    +
    + return __pte2cachemode_tbl[__pte2cm_idx(prot)] == _PAGE_CACHE_MODE_WP;
    }

    enum page_cache_mode pgprot2cachemode(pgprot_t pgprot)

    \
     
     \ /
      Last update: 2022-07-19 15:13    [W:2.554 / U:0.260 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site