diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2018-08-06 21:56:34 +0300 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-08-06 21:56:34 +0300 |
commit | 315706049c343794ad0d3e5b6f6b60b900457b11 (patch) | |
tree | 0a1596a4b5843a6262d17b4c656715854784977d /arch/x86/mm/pti.c | |
parent | 706d51681d636a0c4a5ef53395ec3b803e45ed4d (diff) | |
parent | c40a56a7818cfe735fc93a69e1875f8bba834483 (diff) | |
download | linux-315706049c343794ad0d3e5b6f6b60b900457b11.tar.xz |
Merge branch 'x86/pti-urgent' into x86/pti
Integrate the PTI Global bit fixes which conflict with the 32bit PTI
support.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm/pti.c')
-rw-r--r-- | arch/x86/mm/pti.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c index bcf35dac1920..ef8db6ffc836 100644 --- a/arch/x86/mm/pti.c +++ b/arch/x86/mm/pti.c @@ -470,6 +470,13 @@ static inline bool pti_kernel_image_global_ok(void) } /* + * This is the only user for these and it is not arch-generic + * like the other set_memory.h functions. Just extern them. + */ +extern int set_memory_nonglobal(unsigned long addr, int numpages); +extern int set_memory_global(unsigned long addr, int numpages); + +/* * For some configurations, map all of kernel text into the user page * tables. This reduces TLB misses, especially on non-PCID systems. */ @@ -481,7 +488,8 @@ static void pti_clone_kernel_text(void) * clone the areas past rodata, they might contain secrets. */ unsigned long start = PFN_ALIGN(_text); - unsigned long end = (unsigned long)__end_rodata_aligned; + unsigned long end_clone = (unsigned long)__end_rodata_aligned; + unsigned long end_global = PFN_ALIGN((unsigned long)__stop___ex_table); if (!pti_kernel_image_global_ok()) return; @@ -493,15 +501,19 @@ static void pti_clone_kernel_text(void) * pti_set_kernel_image_nonglobal() did to clear the * global bit. */ - pti_clone_pmds(start, end, 0); + pti_clone_pmds(start, end_clone, _PAGE_RW); + + /* + * pti_clone_pmds() will set the global bit in any PMDs + * that it clones, but we also need to get any PTEs in + * the last level for areas that are not huge-page-aligned. + */ + + /* Set the global bit for normal non-__init kernel text: */ + set_memory_global(start, (end_global - start) >> PAGE_SHIFT); } -/* - * This is the only user for it and it is not arch-generic like - * the other set_memory.h functions. Just extern it. - */ -extern int set_memory_nonglobal(unsigned long addr, int numpages); -static void pti_set_kernel_image_nonglobal(void) +void pti_set_kernel_image_nonglobal(void) { /* * The identity map is created with PMDs, regardless of the @@ -512,9 +524,11 @@ static void pti_set_kernel_image_nonglobal(void) unsigned long start = PFN_ALIGN(_text); unsigned long end = ALIGN((unsigned long)_end, PMD_PAGE_SIZE); - if (pti_kernel_image_global_ok()) - return; - + /* + * This clears _PAGE_GLOBAL from the entire kernel image. + * pti_clone_kernel_text() map put _PAGE_GLOBAL back for + * areas that are mapped to userspace. + */ set_memory_nonglobal(start, (end - start) >> PAGE_SHIFT); } |