aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/set_memory.h1
-rw-r--r--arch/x86/mm/init.c26
-rw-r--r--arch/x86/mm/pageattr.c13
3 files changed, 38 insertions, 2 deletions
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index bd090367236c..34cffcef7375 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -46,6 +46,7 @@ int set_memory_np(unsigned long addr, int numpages);
46int set_memory_4k(unsigned long addr, int numpages); 46int set_memory_4k(unsigned long addr, int numpages);
47int set_memory_encrypted(unsigned long addr, int numpages); 47int set_memory_encrypted(unsigned long addr, int numpages);
48int set_memory_decrypted(unsigned long addr, int numpages); 48int set_memory_decrypted(unsigned long addr, int numpages);
49int set_memory_np_noalias(unsigned long addr, int numpages);
49 50
50int set_memory_array_uc(unsigned long *addr, int addrinarray); 51int set_memory_array_uc(unsigned long *addr, int addrinarray);
51int set_memory_array_wc(unsigned long *addr, int addrinarray); 52int set_memory_array_wc(unsigned long *addr, int addrinarray);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index bc11dedffc45..74b157ac078d 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -780,8 +780,30 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
780 */ 780 */
781void free_kernel_image_pages(void *begin, void *end) 781void free_kernel_image_pages(void *begin, void *end)
782{ 782{
783 free_init_pages("unused kernel image", 783 unsigned long begin_ul = (unsigned long)begin;
784 (unsigned long)begin, (unsigned long)end); 784 unsigned long end_ul = (unsigned long)end;
785 unsigned long len_pages = (end_ul - begin_ul) >> PAGE_SHIFT;
786
787
788 free_init_pages("unused kernel image", begin_ul, end_ul);
789
790 /*
791 * PTI maps some of the kernel into userspace. For performance,
792 * this includes some kernel areas that do not contain secrets.
793 * Those areas might be adjacent to the parts of the kernel image
794 * being freed, which may contain secrets. Remove the "high kernel
795 * image mapping" for these freed areas, ensuring they are not even
796 * potentially vulnerable to Meltdown regardless of the specific
797 * optimizations PTI is currently using.
798 *
799 * The "noalias" prevents unmapping the direct map alias which is
800 * needed to access the freed pages.
801 *
802 * This is only valid for 64bit kernels. 32bit has only one mapping
803 * which can't be treated in this way for obvious reasons.
804 */
805 if (IS_ENABLED(CONFIG_X86_64) && cpu_feature_enabled(X86_FEATURE_PTI))
806 set_memory_np_noalias(begin_ul, len_pages);
785} 807}
786 808
787void __ref free_initmem(void) 809void __ref free_initmem(void)
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index c04153796f61..0a74996a1149 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -53,6 +53,7 @@ static DEFINE_SPINLOCK(cpa_lock);
53#define CPA_FLUSHTLB 1 53#define CPA_FLUSHTLB 1
54#define CPA_ARRAY 2 54#define CPA_ARRAY 2
55#define CPA_PAGES_ARRAY 4 55#define CPA_PAGES_ARRAY 4
56#define CPA_NO_CHECK_ALIAS 8 /* Do not search for aliases */
56 57
57#ifdef CONFIG_PROC_FS 58#ifdef CONFIG_PROC_FS
58static unsigned long direct_pages_count[PG_LEVEL_NUM]; 59static unsigned long direct_pages_count[PG_LEVEL_NUM];
@@ -1486,6 +1487,9 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
1486 1487
1487 /* No alias checking for _NX bit modifications */ 1488 /* No alias checking for _NX bit modifications */
1488 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; 1489 checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;
1490 /* Has caller explicitly disabled alias checking? */
1491 if (in_flag & CPA_NO_CHECK_ALIAS)
1492 checkalias = 0;
1489 1493
1490 ret = __change_page_attr_set_clr(&cpa, checkalias); 1494 ret = __change_page_attr_set_clr(&cpa, checkalias);
1491 1495
@@ -1772,6 +1776,15 @@ int set_memory_np(unsigned long addr, int numpages)
1772 return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0); 1776 return change_page_attr_clear(&addr, numpages, __pgprot(_PAGE_PRESENT), 0);
1773} 1777}
1774 1778
1779int set_memory_np_noalias(unsigned long addr, int numpages)
1780{
1781 int cpa_flags = CPA_NO_CHECK_ALIAS;
1782
1783 return change_page_attr_set_clr(&addr, numpages, __pgprot(0),
1784 __pgprot(_PAGE_PRESENT), 0,
1785 cpa_flags, NULL);
1786}
1787
1775int set_memory_4k(unsigned long addr, int numpages) 1788int set_memory_4k(unsigned long addr, int numpages)
1776{ 1789{
1777 return change_page_attr_set_clr(&addr, numpages, __pgprot(0), 1790 return change_page_attr_set_clr(&addr, numpages, __pgprot(0),