x86/cpu: Use alternative to generate the TASK_SIZE_MAX constant
[linux-2.6-microblaze.git] / arch / x86 / include / asm / page_64.h
index 939b1cf..ca840fe 100644 (file)
@@ -56,6 +56,39 @@ static inline void clear_page(void *page)
 
 void copy_page(void *to, void *from);
 
+#ifdef CONFIG_X86_5LEVEL
+/*
+ * User space process size.  This is the first address outside the user range.
+ * There are a few constraints that determine this:
+ *
+ * On Intel CPUs, if a SYSCALL instruction is at the highest canonical
+ * address, then that syscall will enter the kernel with a
+ * non-canonical return address, and SYSRET will explode dangerously.
+ * We avoid this particular problem by preventing anything
+ * from being mapped at the maximum canonical address.
+ *
+ * On AMD CPUs in the Ryzen family, there's a nasty bug in which the
+ * CPUs malfunction if they execute code from the highest canonical page.
+ * They'll speculate right off the end of the canonical space, and
+ * bad things happen.  This is worked around in the same way as the
+ * Intel problem.
+ *
+ * With page table isolation enabled, we map the LDT in ... [stay tuned]
+ */
+static inline unsigned long task_size_max(void)
+{
+       unsigned long ret;
+
+       alternative_io("movq %[small],%0","movq %[large],%0",
+                       X86_FEATURE_LA57,
+                       "=r" (ret),
+                       [small] "i" ((1ul << 47)-PAGE_SIZE),
+                       [large] "i" ((1ul << 56)-PAGE_SIZE));
+
+       return ret;
+}
+#endif /* CONFIG_X86_5LEVEL */
+
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_X86_VSYSCALL_EMULATION