Skip to content

Commit 230ec83

Browse files
jgross1suryasaimadhu
authored andcommitted
x86/pat: Fix x86_has_pat_wp()
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: f88a68f ("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
1 parent 3131ef3 commit 230ec83

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

arch/x86/mm/init.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,20 @@ static uint8_t __pte2cachemode_tbl[8] = {
7777
[__pte2cm_idx(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)] = _PAGE_CACHE_MODE_UC,
7878
};
7979

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

8696
enum page_cache_mode pgprot2cachemode(pgprot_t pgprot)

0 commit comments

Comments
 (0)