|
@@ -434,6 +434,13 @@ static inline bool pti_kernel_image_global_ok(void)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * 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.
|
|
@@ -446,7 +453,8 @@ 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_hpage_align;
|
|
|
+ unsigned long end_clone = (unsigned long)__end_rodata_hpage_align;
|
|
|
+ unsigned long end_global = PFN_ALIGN((unsigned long)__stop___ex_table);
|
|
|
|
|
|
if (!pti_kernel_image_global_ok())
|
|
|
return;
|
|
@@ -458,14 +466,18 @@ void pti_clone_kernel_text(void)
|
|
|
* pti_set_kernel_image_nonglobal() did to clear the
|
|
|
* global bit.
|
|
|
*/
|
|
|
- pti_clone_pmds(start, end, _PAGE_RW);
|
|
|
+ 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);
|
|
|
void pti_set_kernel_image_nonglobal(void)
|
|
|
{
|
|
|
/*
|
|
@@ -477,9 +489,11 @@ 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);
|
|
|
}
|
|
|
|