Skip to contentSkip to conversation

x86/kaiser: Paravirt support and various fixlets

PATCH In review Thomas Gleixner 4 participants 9 messages Nov 27, 2017 – Nov 28, 2017

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover x86/kaiser: Paravirt support and various fixlets

The series contains the following changes against

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.x86/asm

- Remove the flush_tlb_single paravirt patching. It's not longer INVPCID anymore. Especially not with KAISER enabled.

- Remove the !PARAVIRT dependency of KAISER and just disable it at boot time when the kernel runs as XEN_PV guest.

- Address a few review comments.

Thanks,

tglx

---
 arch/x86/include/asm/hypervisor.h   |   25 +++++++++++++++----------
 arch/x86/kernel/paravirt_patch_64.c |    2 --
 arch/x86/mm/debug_pagetables.c      |    6 +++---
 arch/x86/mm/dump_pagetables.c       |    6 ++++--
 arch/x86/mm/kaiser.c                |    3 +++
 security/Kconfig                    |    2 +-
 6 files changed, 26 insertions(+), 18 deletions(-)
#1 lore raw

PATCH 1/4 x86/paravirt: Dont patch flush_tlb_single

native_flush_tlb_single() is not just INLVPG anymore. With X86_FEATURE_INVPCID_SINGLE and KAISER enabled it flushes also the shadow mapping. But even with KAISER disabled flushing the particular ASID is the right thing to do.

Remove the paravirt patching for it.

Fixes 1fde25dc8ef4 ("x86/mm/kaiser: Use PCID feature to make user and kernel switches faster")
---
 arch/x86/kernel/paravirt_patch_64.c |    2 --
 1 file changed, 2 deletions(-)
arch/x86/kernel/paravirt_patch_64.c +0 -2
@@ -10,7 +10,6 @@ DEF_NATIVE(pv_irq_ops, save_fl, "pushfq;
 DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax");
 DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
-DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
 DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
 
 DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
@@ -60,7 +59,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
-		PATCH_SITE(pv_mmu_ops, flush_tlb_single);
 		PATCH_SITE(pv_cpu_ops, wbinvd);
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 		case PARAVIRT_PATCH(pv_lock_ops.queued_spin_unlock):
maintainer
#2 lore raw

Re: [patch 1/4] x86/paravirt: Dont patch flush_tlb_single

Quoted 9 lines · Thomas Gleixner

native_flush_tlb_single() is not just INLVPG anymore. With X86_FEATURE_INVPCID_SINGLE and KAISER enabled it flushes also the shadow mapping. But even with KAISER disabled flushing the particular ASID is the right thing to do.

Remove the paravirt patching for it.

Fixes 1fde25dc8ef4 ("x86/mm/kaiser: Use PCID feature to make user and kernel switches faster")

Argh!! Yes quite.

ACK

Quoted 17 lines
---
 arch/x86/kernel/paravirt_patch_64.c |    2 --
 1 file changed, 2 deletions(-)
arch/x86/kernel/paravirt_patch_64.c +0 -1
@@ -10,7 +10,6 @@ DEF_NATIVE(pv_irq_ops, save_fl, "pushfq;
 DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax");
 DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
-DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
 DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
 
 DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");

arch/x86/kernel/paravirt_patch_64.c unsigned native_patch(u8 type, u16 clobb · line 64

Quoted 7 lines
arch/x86/kernel/paravirt_patch_64.c +0 -1
@@ -60,7 +59,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
-		PATCH_SITE(pv_mmu_ops, flush_tlb_single);
 		PATCH_SITE(pv_cpu_ops, wbinvd);
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 		case PARAVIRT_PATCH(pv_lock_ops.queued_spin_unlock):

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#3 lore raw

Re: [patch 1/4] x86/paravirt: Dont patch flush_tlb_single

In reply to Thomas Gleixner
Quoted 24 lines · Thomas Gleixner

native_flush_tlb_single() is not just INLVPG anymore. With X86_FEATURE_INVPCID_SINGLE and KAISER enabled it flushes also the shadow mapping. But even with KAISER disabled flushing the particular ASID is the right thing to do.

Remove the paravirt patching for it.

Fixes 1fde25dc8ef4 ("x86/mm/kaiser: Use PCID feature to make user and kernel switches faster")
---
 arch/x86/kernel/paravirt_patch_64.c |    2 --
 1 file changed, 2 deletions(-)
arch/x86/kernel/paravirt_patch_64.c +0 -1
@@ -10,7 +10,6 @@ DEF_NATIVE(pv_irq_ops, save_fl, "pushfq;
 DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %cr2, %rax");
 DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
-DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
 DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
 
 DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");

arch/x86/kernel/paravirt_patch_64.c unsigned native_patch(u8 type, u16 clobb · line 64

Quoted 7 lines
arch/x86/kernel/paravirt_patch_64.c +0 -1
@@ -60,7 +59,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
-		PATCH_SITE(pv_mmu_ops, flush_tlb_single);
 		PATCH_SITE(pv_cpu_ops, wbinvd);
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 		case PARAVIRT_PATCH(pv_lock_ops.queued_spin_unlock):

Nice find!

Signature · 7 lines
Josh

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#4 lore raw

PATCH 2/4 x86/kaiser: Enable PARAVIRT again

In reply to Thomas Gleixner

XEN_PV paravirtualizes read/write_c3. This does not work with KAISER as the CR3 switch from and to user space PGD would require to map the whole XEN_PV machinery into both. It's also not clear whether the register space is sufficient to do so. All other PV guests use the native implementations and are compatible with KAISER.

Add detection for XEN_PV and disable KAISER in the early boot process when the kernel is running as a XEN_PV guest.

---
 arch/x86/include/asm/hypervisor.h |   25 +++++++++++++++----------
 arch/x86/mm/kaiser.c              |    3 +++
 security/Kconfig                  |    2 +-
 3 files changed, 19 insertions(+), 11 deletions(-)
arch/x86/include/asm/hypervisor.h +15 -10
@@ -20,16 +20,7 @@
 #ifndef _ASM_X86_HYPERVISOR_H
 #define _ASM_X86_HYPERVISOR_H
 
-#ifdef CONFIG_HYPERVISOR_GUEST
-
-#include <asm/kvm_para.h>
-#include <asm/x86_init.h>
-#include <asm/xen/hypervisor.h>
-
-/*
- * x86 hypervisor information
- */
-
+/* x86 hypervisor types  */
 enum x86_hypervisor_type {
 	X86_HYPER_NATIVE = 0,
 	X86_HYPER_VMWARE,
@@ -39,6 +30,12 @@ enum x86_hypervisor_type {
 	X86_HYPER_KVM,
 };
 
+#ifdef CONFIG_HYPERVISOR_GUEST
+
+#include <asm/kvm_para.h>
+#include <asm/x86_init.h>
+#include <asm/xen/hypervisor.h>
+
 struct hypervisor_x86 {
 	/* Hypervisor name */
 	const char	*name;
@@ -58,7 +55,15 @@ struct hypervisor_x86 {
 
 extern enum x86_hypervisor_type x86_hyper_type;
 extern void init_hypervisor_platform(void);
+static inline bool hypervisor_is_type(enum x86_hypervisor_type type)
+{
+	return x86_hyper_type == type;
+}
 #else
 static inline void init_hypervisor_platform(void) { }
+static inline bool hypervisor_is_type(enum x86_hypervisor_type type)
+{
+	return type == X86_HYPER_NATIVE;
+}
 #endif /* CONFIG_HYPERVISOR_GUEST */
 #endif /* _ASM_X86_HYPERVISOR_H */
arch/x86/mm/kaiser.c +3 -0
@@ -34,6 +34,7 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 
+#include <asm/hypervisor.h>
 #include <asm/cmdline.h>
 #include <asm/kaiser.h>
 #include <asm/pgtable.h>
@@ -53,6 +54,8 @@ void __init kaiser_check_cmdline(void)
 {
 	if (cmdline_find_option_bool(boot_command_line, "nokaiser"))
 		kaiser_enabled = false;
+	if (hypervisor_is_type(X86_HYPER_XEN_PV))
+		kaiser_enabled = false;
 }
 
 /*
security/Kconfig +1 -1
@@ -56,7 +56,7 @@ config SECURITY_NETWORK
 
 config KAISER
 	bool "Remove the kernel mapping in user mode"
-	depends on X86_64 && SMP && !PARAVIRT && JUMP_LABEL
+	depends on X86_64 && SMP && JUMP_LABEL
 	help
 	  This feature reduces the number of hardware side channels by
 	  ensuring that the majority of kernel addresses are not mapped

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer Reviewed-by on v1 2/4
#5 lore raw

Re: [patch 2/4] x86/kaiser: Enable PARAVIRT again

Quoted 10 lines · Thomas Gleixner

XEN_PV paravirtualizes read/write_c3. This does not work with KAISER as the CR3 switch from and to user space PGD would require to map the whole XEN_PV machinery into both. It's also not clear whether the register space is sufficient to do so. All other PV guests use the native implementations and are compatible with KAISER.

Add detection for XEN_PV and disable KAISER in the early boot process when the kernel is running as a XEN_PV guest.

Juergen

#6 lore raw

PATCH 3/4 x86/mm/debug_pagetables: Use octal file permissions

In reply to Thomas Gleixner

As equested by several reviewers.

Fixes ca646ac417b8 ("x86/mm/debug_pagetables: Allow dumping current pagetables")
---
 arch/x86/mm/debug_pagetables.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/mm/debug_pagetables.c +3 -3
@@ -81,18 +81,18 @@ static void pt_dump_debug_remove_files(v
 
 static int __init pt_dump_debug_init(void)
 {
-	pe_knl = debugfs_create_file("kernel_page_tables", S_IRUSR, NULL, NULL,
+	pe_knl = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
 				     &ptdump_fops);
 	if (!pe_knl)
 		return -ENOMEM;
 
-	pe_curknl = debugfs_create_file("current_page_tables_knl", S_IRUSR,
+	pe_curknl = debugfs_create_file("current_page_tables_knl", 0400,
 					NULL, NULL, &ptdump_curknl_fops);
 	if (!pe_curknl)
 		goto err;
 
 #ifdef CONFIG_KAISER
-	pe_curusr = debugfs_create_file("current_page_tables_usr", S_IRUSR,
+	pe_curusr = debugfs_create_file("current_page_tables_usr", 0400,
 					NULL, NULL, &ptdump_curusr_fops);
 	if (!pe_curusr)
 		goto err;
maintainer
#7 lore raw

Re: [patch 3/4] x86/mm/debug_pagetables: Use octal file permissions

Quoted 4 lines · Thomas Gleixner

As equested by several reviewers.

Fixes ca646ac417b8 ("x86/mm/debug_pagetables: Allow dumping current pagetables")

Thanks! ACK

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

PATCH 4/4 x86/mm/dump_pagetables: Use helper to get the shadow PGD

In reply to Thomas Gleixner

Use kernel_to_shadow_pgdp() instead of open coding it.

Fixes ca646ac417b8 ("x86/mm/debug_pagetables: Allow dumping current pagetables")
Fixes 04bafab4b2ee ("x86/mm/dump_pagetables: Check Kaiser shadow page table for WX pages")
---
 arch/x86/mm/dump_pagetables.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/mm/dump_pagetables.c +4 -2
@@ -504,8 +504,10 @@ void ptdump_walk_pgd_level(struct seq_fi
 
 void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool shadow)
 {
+#ifdef CONFIG_KAISER
 	if (shadow && kaiser_enabled)
-		pgd += PTRS_PER_PGD;
+		pgd = kernel_to_shadow_pgdp(pgd);
+#endif
 	ptdump_walk_pgd_level_core(m, pgd, false, false);
 }
 EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs);
@@ -518,7 +520,7 @@ void ptdump_walk_shadow_pgd_level_checkw
 	if (!kaiser_enabled)
 		return;
 	pr_info("x86/mm: Checking shadow page tables\n");
-	pgd += PTRS_PER_PGD;
+	pgd = kernel_to_shadow_pgdp(pgd);
 	ptdump_walk_pgd_level_core(NULL, pgd, true, false);
 #endif
 }