Skip to contentSkip to conversation

Patch 6

PATCH In review Andi Kleen 1 participant 1 message May 2, 2018

Subsystems (4)
lore
Share & tools
lore

Andi Kleen

author
#0 lore raw

PATCH 6/6 Patch 6

For the L1TF workaround we want to limit the swap file size to below MAX_PA/2, so that the higher bits of the swap offset inverted never point to valid memory.

Add a way for the architecture to override the swap file size check in swapfile.c and add a x86 specific max swapfile check function that enforces that limit.

The check is only enabled if the CPU is vulnerable to L1TF.

In VMs with 42bit MAX_PA the typical limit is 2TB now, on a native system with 46bit PA it is 32TB. The limit is only per individual swap file, so it's always possible to exceed these limits with multiple swap files or partitions.

---
 arch/x86/mm/init.c       | 17 +++++++++++++++++
 include/linux/swapfile.h |  2 ++
 mm/swapfile.c            | 44 ++++++++++++++++++++++++++++----------------
 3 files changed, 47 insertions(+), 16 deletions(-)
arch/x86/mm/init.c +17 -0
index fec82b577c18..9f571225f5db 100644
@@ -4,6 +4,8 @@
 #include <linux/swap.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>	/* for max_low_pfn */
+#include <linux/swapfile.h>
+#include <linux/swapops.h>
 
 #include <asm/set_memory.h>
 #include <asm/e820/api.h>
@@ -878,3 +880,18 @@ void update_cache_mode_entry(unsigned entry, enum page_cache_mode cache)
 	__cachemode2pte_tbl[cache] = __cm_idx2pte(entry);
 	__pte2cachemode_tbl[entry] = cache;
 }
+
+unsigned long max_swapfile_size(void)
+{
+	unsigned long pages;
+
+	pages = generic_max_swapfile_size();
+
+	if (boot_cpu_has(X86_BUG_L1TF)) {
+		/* Limit the swap file size to MAX_PA/2 for the L1TF workaround */
+		pages = min_t(unsigned long,
+			      1ULL << (boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT),
+			      pages);
+	}
+	return pages;
+}
include/linux/swapfile.h +2 -0
index 06bd7b096167..e06febf62978 100644
@@ -10,5 +10,7 @@ extern spinlock_t swap_lock;
 extern struct plist_head swap_active_head;
 extern struct swap_info_struct *swap_info[];
 extern int try_to_unuse(unsigned int, bool, unsigned long);
+extern unsigned long generic_max_swapfile_size(void);
+extern unsigned long max_swapfile_size(void);
 
 #endif /* _LINUX_SWAPFILE_H */
mm/swapfile.c +28 -16

56 lines not on this page · raw message

Signature · 1 line
2.15.0