x86: Prevent Split-Lock-Detection wreckage on VMX hypervisors
Subsystems (4)
cover x86: Prevent Split-Lock-Detection wreckage on VMX hypervisors
Kenneth reported that a VMWare guest crashes in the VMWare BIOS due to a Split-Lock induced #AC which is injected by the VMWare hypervisor into the guest.
While this is a good thing in principle, it's not really practical. That means that Split-Lock-Detection has to be disabled when any unprepared VMX hypervisor is loaded.
As hypervisor modules are not really identifiable, the only safe solution we came up with is to scan the module text at load time for a VMLAUNCH instruction. If VMLAUNCH is found then Split-Lock-Detection is disabled on the host to prevent the above. If the hypervisor has at least minimal handling code, the module can tell the kernel by adding MOD_INFO(sld_safe, "Y") which disables the text scan.
For KVM it's simple enough to handle it at least at the basic level by checking guest CR0.AM and EFLAGS.AC state and a trivial host side handler which depending on the SLD mode handles it gracefully or tells the VMX handler to deliver the #AC to user space which then can crash and burn itself.
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
Alternatively we can obviously revert SLD, but that does not make the problem vs. out of tree hypervisors go away magically. So we can just get over it now.
Thanks,
tglx
PATCH 1/2 x86,module: Detect VMX modules and disable Split-Lock-Detect
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
Hypervisors, which have been modified and are known to work correctly, can add:
MODULE_INFO(sld_safe, "Y");
to explicitly tell the module loader they're good.
NOTE: it is unfortunate that struct load_info is not available to the
arch module code, this means CONFIG_CPU_SUP_INTEL gunk is needed in generic code.
NOTE: while we can 'trivially' fix KVM, we're still stuck with stuff
like VMware and VirtualBox doing their own thing.
--- arch/x86/include/asm/cpu.h | 2 ++ arch/x86/kernel/cpu/intel.c | 38 +++++++++++++++++++++++++++++++++++++- arch/x86/kernel/module.c | 6 ++++++ include/linux/module.h | 4 ++++ kernel/module.c | 5 +++++ 5 files changed, 54 insertions(+), 1 deletion(-)
arch/x86/include/asm/cpu.h +2 -0
@@ -44,6 +44,7 @@ unsigned int x86_stepping(unsigned int sextern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn);extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {}
@@ -51,5 +52,6 @@ static inline bool handle_user_split_loc {return false; } +static inline void split_lock_validate_module_text (struct module *me,void *text,void *text_end) {}#endif #endif /* _ASM_X86_CPU_H */
arch/x86/kernel/cpu/intel.c +37 -1
@@ -9,6 +9,7 @@#include <linux/thread_info.h> #include <linux/init.h> #include <linux/uaccess.h> +#include <linux/module.h> #include <asm/cpufeature.h> #include <asm/pgtable.h>
@@ -21,6 +22,7 @@#include <asm/elf.h> #include <asm/cpu_device_id.h> #include <asm/cmdline.h> +#include <asm/insn.h> #ifdef CONFIG_X86_64 #include <linux/topology.h>
@@ -1055,12 +1057,46 @@ static void sld_update_msr(bool on) {u64 test_ctrl_val = msr_test_ctrl_cache; -if (on) +if (on && (sld_state != sld_off)) test_ctrl_val |=MSR_TEST_CTRL_SPLIT_LOCK_DETECT ;wrmsrl (MSR_TEST_CTRL , test_ctrl_val); } +static void sld_remote_kill (void *arg) +{ +sld_update_msr (false); +} + +void split_lock_validate_module_text (struct module *me,void *text,void *text_end) +{ +u8 vmlaunch[] = {0x0f ,0x01 ,0xc2 }; +struct insn insn; + +if (sld_state == sld_off) +return ; + +while (text < text_end) { +kernel_insn_init (&insn, text, text_end - text); +insn_get_length (&insn); + +if (WARN_ON_ONCE (!insn_complete (&insn))) +break ; + +if (insn.length ==sizeof (vmlaunch) && !memcmp (text, vmlaunch,sizeof (vmlaunch))) + goto bad_module; + + text += insn.length; + } + +return ; + +bad_module: +pr_warn ("disabled due to VMLAUNCH in module: %s\n" , me->name); + sld_state = sld_off; +on_each_cpu (sld_remote_kill,NULL ,1 ); +} +static void split_lock_init (void ) {split_lock_verify_msr (sld_state != sld_off);
arch/x86/kernel/module.c +6 -0
@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \
@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) { +void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + } +if (para) {void *pseg = (void *)para->sh_addr;apply_paravirt (pseg, pseg + para->sh_size);
include/linux/module.h +4 -0
@@ -407,6 +407,10 @@ struct module {bool sig_ok;#endif +#ifdef CONFIG_CPU_SUP_INTEL +bool sld_safe; +#endif +bool async_probe_requested;/* symbols that will be GPL-only in the near future. */
kernel/module.c +5 -0
@@ -3096,6 +3096,11 @@ static int check_modinfo(struct module * "is unknown, you have been warned.\n", mod->name); } +#ifdef CONFIG_CPU_SUP_INTEL +if (get_modinfo (info,"sld_safe" )) + mod->sld_safe = true; +#endif + err =check_modinfo_livepatch (mod, info);if (err)return err;
PATCH v2 1/2 x86,module: Detect VMX modules and disable Split-Lock-Detect
I picked VMXOFF (which also appears in vmmon.ko) instead of VMXON because that latter takes an argument is therefore more difficult to decode.
---
Subject: x86,module: Detect VMX modules and disable Split-Lock-Detect
From: Peter Zijlstra <[email protected]>
Date: Thu, 02 Apr 2020 14:32:59 +0200
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH/VMXOFF instructions. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
Hypervisors, which have been modified and are known to work correctly, can add:
MODULE_INFO(sld_safe, "Y");
to explicitly tell the module loader they're good.
NOTE: it is unfortunate that struct load_info is not available to the
arch module code, this means CONFIG_CPU_SUP_INTEL gunk is needed in generic code.
NOTE: while we can 'trivially' fix KVM, we're still stuck with stuff
like VMware and VirtualBox doing their own thing.
--- arch/x86/include/asm/cpu.h | 2 ++ arch/x86/kernel/cpu/intel.c | 41 ++++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/module.c | 6 ++++++ include/linux/module.h | 4 ++++ kernel/module.c | 5 +++++ 5 files changed, 57 insertions(+), 1 deletion(-)
arch/x86/include/asm/cpu.h +2 -0
@@ -44,6 +44,7 @@ unsigned int x86_stepping(unsigned int sextern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn);extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {}
@@ -51,5 +52,6 @@ static inline bool handle_user_split_loc {return false; } +static inline void split_lock_validate_module_text (struct module *me,void *text,void *text_end) {}#endif #endif /* _ASM_X86_CPU_H */
arch/x86/kernel/cpu/intel.c +40 -1
64 lines not on this page · raw message
arch/x86/kernel/module.c +6 -0
@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \
@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) { +void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + } +if (para) {void *pseg = (void *)para->sh_addr;apply_paravirt (pseg, pseg + para->sh_size);
include/linux/module.h +4 -0
@@ -407,6 +407,10 @@ struct module {bool sig_ok;#endif +#ifdef CONFIG_CPU_SUP_INTEL +bool sld_safe; +#endif +bool async_probe_requested;/* symbols that will be GPL-only in the near future. */
kernel/module.c +5 -0
@@ -3096,6 +3096,11 @@ static int check_modinfo(struct module * "is unknown, you have been warned.\n", mod->name); } +#ifdef CONFIG_CPU_SUP_INTEL +if (get_modinfo (info,"sld_safe" )) + mod->sld_safe = true; +#endif + err =check_modinfo_livepatch (mod, info);if (err)return err;
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 112 lines · Peter Zijlstra
I picked VMXOFF (which also appears in vmmon.ko) instead of VMXON because that latter takes an argument is therefore more difficult to decode.
---
Subject: x86,module: Detect VMX modules and disable Split-Lock-Detect
From: Peter Zijlstra <[email protected]>
Date: Thu, 02 Apr 2020 14:32:59 +0200It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH/VMXOFF instructions. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
Hypervisors, which have been modified and are known to work correctly, can add:
MODULE_INFO(sld_safe, "Y");to explicitly tell the module loader they're good.
NOTE: it is unfortunate that struct
load_infois not available to the
arch module code, this meansCONFIG_CPU_SUP_INTELgunk is needed in generic code.NOTE: while we can 'trivially' fix KVM, we're still stuck with stuff
like VMware and VirtualBox doing their own thing.Reported-by "Kenneth R. Crudup" <[email protected]>Signed-off-by Peter Zijlstra (Intel) <[email protected]>--- arch/x86/include/asm/cpu.h | 2 ++ arch/x86/kernel/cpu/intel.c | 41 ++++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/module.c | 6 ++++++ include/linux/module.h | 4 ++++ kernel/module.c | 5 +++++ 5 files changed, 57 insertions(+), 1 deletion(-)arch/x86/include/asm/cpu.h +2
-0@@ -44,6 +44,7 @@ unsigned int x86_stepping(unsigned int sextern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn);extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {}@@ -51,5 +52,6 @@ static inline bool handle_user_split_loc {return false; } +static inline void split_lock_validate_module_text (struct module *me,void *text,void *text_end) {}#endif #endif /* _ASM_X86_CPU_H */ arch/x86/kernel/cpu/intel.c +27
-1@@ -9,6 +9,7 @@#include <linux/thread_info.h> #include <linux/init.h> #include <linux/uaccess.h> +#include <linux/module.h> #include <asm/cpufeature.h> #include <asm/pgtable.h> @@ -21,6 +22,7 @@#include <asm/elf.h> #include <asm/cpu_device_id.h> #include <asm/cmdline.h> +#include <asm/insn.h> #ifdef CONFIG_X86_64 #include <linux/topology.h> @@ -1055,12 +1057,49 @@ static void sld_update_msr(bool on) {u64 test_ctrl_val = msr_test_ctrl_cache; -if (on) +if (on && (sld_state != sld_off)) test_ctrl_val |=MSR_TEST_CTRL_SPLIT_LOCK_DETECT ;wrmsrl (MSR_TEST_CTRL , test_ctrl_val); } +static void sld_remote_kill (void *arg) +{ +sld_update_msr (false); +} + +void split_lock_validate_module_text (struct module *me,void *text,void *text_end) +{ +u8 vmxoff[] = {0x0f ,0x01 ,0xc4 }; +u8 vmlaunch[] = {0x0f ,0x01 ,0xc2 }; +struct insn insn; + +if (sld_state == sld_off) +return ; + +while (text < text_end) { +kernel_insn_init (&insn, text, text_end - text); +insn_get_length (&insn); + +if (WARN_ON_ONCE (!insn_complete (&insn))) +break ; + +if (insn.length ==3 && + (!memcmp (text, vmlaunch,sizeof (vmlaunch)) || + !memcmp (text, vmxoff,sizeof (vmxoff))))
arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1099
Quoted 10 lines
arch/x86/kernel/cpu/intel.c +10
-0+ goto bad_module; + + text += insn.length; + } + +return ; + +bad_module: +pr_warn ("disabled due to VMX in module: %s\n" , me->name); + sld_state = sld_off;
shouldn't we remove the __ro_after_init of sld_state?
And, shouldn't we clear X86_FEATURE_SPLIT_LOCK_DETECT flag?
Quoted 56 lines
arch/x86/kernel/cpu/intel.c +3
-0+on_each_cpu (sld_remote_kill,NULL ,1 ); +} +static void split_lock_init (void ) {split_lock_verify_msr (sld_state != sld_off);arch/x86/kernel/module.c +6
-0@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) { +void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + } +if (para) {void *pseg = (void *)para->sh_addr;apply_paravirt (pseg, pseg + para->sh_size);include/linux/module.h +4
-0@@ -407,6 +407,10 @@ struct module {bool sig_ok;#endif +#ifdef CONFIG_CPU_SUP_INTEL +bool sld_safe; +#endif +bool async_probe_requested;/* symbols that will be GPL-only in the near future. */ kernel/module.c +5
-0@@ -3096,6 +3096,11 @@ static int check_modinfo(struct module * "is unknown, you have been warned.\n", mod->name); } +#ifdef CONFIG_CPU_SUP_INTEL +if (get_modinfo (info,"sld_safe" )) + mod->sld_safe = true; +#endif + err =check_modinfo_livepatch (mod, info);if (err)return err;
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Learn to trim your replies already!
Quoted 7 lines · Xiaoyao Li
arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1099
Quoted 3 lines · Peter Zijlstra
arch/x86/kernel/cpu/intel.c +3
-0+bad_module: +pr_warn ("disabled due to VMX in module: %s\n" , me->name); + sld_state = sld_off;shouldn't we remove the
__ro_after_initofsld_state?
Oh, that's probably a good idea. I can't actually test this due to no hardware.
Quoted 1 line
And, shouldn't we clear
X86_FEATURE_SPLIT_LOCK_DETECTflag?
Don't think you can do that this late. Also, the hardware has the MSR and it works, it's just that we should not.
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 8 lines · Peter Zijlstra
Learn to trim your replies already!
Quoted 1 line · Xiaoyao Li
On 4/2/2020 11:23 PM, Peter Zijlstra wrote:
Quoted 8 lines
Quoted 5 lines
arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1099
Quoted 3 lines
arch/x86/kernel/cpu/intel.c +3
-0+bad_module: +pr_warn ("disabled due to VMX in module: %s\n" , me->name); + sld_state = sld_off;shouldn't we remove the
__ro_after_initofsld_state?Oh, that's probably a good idea. I can't actually test this due to no hardware.
Just wondering, since I lack hardware as well: can the performance counter LOCK_CYCLES.SPLIT_LOCK_UC_LOCK_DURATION be used to detect split-locks similarly to SLD (although it would be after the split-lock event)?
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Peter ZijlstraQuoted 2 lines · Peter Zijlstra
Learn to trim your replies already!
Sorry.
Quoted 9 lines · Xiaoyao Li
Quoted 7 lines · Peter Zijlstra
arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1099
Quoted 4 lines
arch/x86/kernel/cpu/intel.c +3
-0+bad_module: +pr_warn ("disabled due to VMX in module: %s\n" , me->name); + sld_state = sld_off;shouldn't we remove the
__ro_after_initofsld_state?
Quoted 8 lines
Oh, that's probably a good idea. I can't actually test this due to no hardware.
Quoted 1 line
And, shouldn't we clear
X86_FEATURE_SPLIT_LOCK_DETECTflag?Don't think you can do that this late. Also, the hardware has the MSR and it works, it's just that we should not.
Actually, I agree to keep this flag.
But, during the previous patch review, tglx wants to make
sld_off = no X86_FEATURE_SPLIT_LOCK_DETECT
I'm not sure whether he still insists on it now.
I really want to decouple sld_off and X86_FEATURE_SPLIT_LOCK_DETECT.
So if X86_FEATURE_SPLIT_LOCK_DETECT is set, we can virtualize and expose it to guest even when host is sld_off.
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 8 lines · Xiaoyao Li
Quoted 6 lines · Peter Zijlstra
Quoted 1 line · Xiaoyao Li
And, shouldn't we clear
X86_FEATURE_SPLIT_LOCK_DETECTflag?Don't think you can do that this late. Also, the hardware has the MSR and it works, it's just that we should not.
Quoted 7 lines
Actually, I agree to keep this flag.
But, during the previous patch review, tglx wants to make
sld_off= noX86_FEATURE_SPLIT_LOCK_DETECTI'm not sure whether he still insists on it now.
Obviously I cant.
Quoted 3 lines
I really want to decouple
sld_offandX86_FEATURE_SPLIT_LOCK_DETECT. So ifX86_FEATURE_SPLIT_LOCK_DETECTis set, we can virtualize and expose it to guest even when host issld_off.
Can we first have a sane solution for the problem at hand?
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Thanks,
tglx
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 4 lines · Thomas Gleixner
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Eh, I still think the "off in host, on in guest" is a legit scenario for debug/development/testing, but I agree that the added complexity doesn't justify the minimal benefits versus sld_warn.
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 9 lines · Sean Christopherson
Quoted 4 lines · Thomas Gleixner
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Eh, I still think the "off in host, on in guest" is a legit scenario for debug/development/testing, but I agree that the added complexity doesn't justify the minimal benefits versus
sld_warn.
Off in host on in guest seems utterly insane to me. Why do you care about that?
That's like building a bridge with rotten timber.
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Sean Christopherson
Quoted 4 lines · Thomas Gleixner
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Quoted 6 lines
Quoted 3 lines
Eh, I still think the "off in host, on in guest" is a legit scenario for debug/development/testing, but I agree that the added complexity doesn't justify the minimal benefits versus
sld_warn.Off in host on in guest seems utterly insane to me. Why do you care about that?
For development/debug/testing. Ignoring the core-scope stupidity of split lock, the _functional_ behavior of the host kernel and guest kernel are completely separate. The host can generate split locks all it wants, but other than performance, its bad behavior has no impact on the guest.
For example, all of the debug that was done to eliminate split locks in the kernel could have been done in a KVM guest, even though the host kernel would not have yet been split-lock free.
It's somewhat of a moot point now that the kernel is split-lock free. But, if I encountered a split lock panic on my system, the first thing I would do (after rebooting) would be to fire up a VM to try and reproduce and debug the issue.
Oftentimes it's significantly easier to "enable" a feature in KVM, i.e. expose a feature to the guest, than it is to actually enable it in the kernel. Enabling KVM first doesn't work if there are hard dependencies on kernel enabling, e.g. most things that have an XSAVE component, but for a lot of features it's a viable strategy to enable KVM first, and then do all testing and debug inside a KVM guest.
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 29 lines · Sean Christopherson
Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Sean Christopherson
Quoted 4 lines · Thomas Gleixner
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Quoted 6 lines
Quoted 3 lines
Eh, I still think the "off in host, on in guest" is a legit scenario for debug/development/testing, but I agree that the added complexity doesn't justify the minimal benefits versus
sld_warn.Off in host on in guest seems utterly insane to me. Why do you care about that?
For development/debug/testing. Ignoring the core-scope stupidity of split lock, the _functional_ behavior of the host kernel and guest kernel are completely separate. The host can generate split locks all it wants, but other than performance, its bad behavior has no impact on the guest.
For example, all of the debug that was done to eliminate split locks in the kernel could have been done in a KVM guest, even though the host kernel would not have yet been split-lock free.
It's somewhat of a moot point now that the kernel is split-lock free. But, if I encountered a split lock panic on my system, the first thing I would do (after rebooting) would be to fire up a VM to try and reproduce and debug the issue.
Quoted 6 lines
Oftentimes it's significantly easier to "enable" a feature in KVM, i.e. expose a feature to the guest, than it is to actually enable it in the kernel. Enabling KVM first doesn't work if there are hard dependencies on kernel enabling, e.g. most things that have an XSAVE component, but for a lot of features it's a viable strategy to enable KVM first, and then do all testing and debug inside a KVM guest.
I can see that aspect, but there were pretty clear messages in one of the other threads:
"It's not about whether or not host is clean. It's for the cases that
users just don't want it enabled on host, to not break the applications or drivers that do have split lock issue."
"My thought is for CSPs that they might not turn on SLD on their
product environment. Any split lock in kernel or drivers may break their service for tenants."
which I back then called out as proliferating crap and ensuring that this stuff never gets fixed.
I still call it out as exactly that and you know as well as I do that this is the reality.
For people like you who actually want to debug stuff in a guest, the extra 10 lines of hack on top of the other 1000 lines of hacks you already have are not really something which justifies to give hardware and OS/application vendors the easy way out to avoid fixing their broken crap.
Thanks,
tglx
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 44 lines · Thomas Gleixner
Quoted 29 lines · Sean Christopherson
Quoted 7 lines · Peter Zijlstra
Quoted 6 lines · Sean Christopherson
Quoted 4 lines · Thomas Gleixner
Aside of that I'm still against the attempt of proliferating crap, i.e. disabling it because the host is triggering it and then exposing it to guests. The above does not change my mind in any way. This proposal is still wrong.
Quoted 6 lines
Quoted 3 lines
Eh, I still think the "off in host, on in guest" is a legit scenario for debug/development/testing, but I agree that the added complexity doesn't justify the minimal benefits versus
sld_warn.Off in host on in guest seems utterly insane to me. Why do you care about that?
For development/debug/testing. Ignoring the core-scope stupidity of split lock, the _functional_ behavior of the host kernel and guest kernel are completely separate. The host can generate split locks all it wants, but other than performance, its bad behavior has no impact on the guest.
For example, all of the debug that was done to eliminate split locks in the kernel could have been done in a KVM guest, even though the host kernel would not have yet been split-lock free.
It's somewhat of a moot point now that the kernel is split-lock free. But, if I encountered a split lock panic on my system, the first thing I would do (after rebooting) would be to fire up a VM to try and reproduce and debug the issue.
Quoted 6 lines
Oftentimes it's significantly easier to "enable" a feature in KVM, i.e. expose a feature to the guest, than it is to actually enable it in the kernel. Enabling KVM first doesn't work if there are hard dependencies on kernel enabling, e.g. most things that have an XSAVE component, but for a lot of features it's a viable strategy to enable KVM first, and then do all testing and debug inside a KVM guest.
I can see that aspect, but there were pretty clear messages in one of the other threads:
"It's not about whether or not host is clean. It's for the cases that
users just don't want it enabled on host, to not break the applications or drivers that do have split lock issue."
Quoted 6 lines
"My thought is for CSPs that they might not turn on SLD on their
product environment. Any split lock in kernel or drivers may break their service for tenants."which I back then called out as proliferating crap and ensuring that this stuff never gets fixed.
Or more likely, gets fixed, just not in upstream :-)
Quoted 8 lines
I still call it out as exactly that and you know as well as I do that this is the reality.
For people like you who actually want to debug stuff in a guest, the extra 10 lines of hack on top of the other 1000 lines of hacks you already have are not really something which justifies to give hardware and OS/application vendors the easy way out to avoid fixing their broken crap.
Ya, I see where you're coming from. As above, I agree that having a "KVM only" mode does more harm than good.
RE: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Peter ZijlstraFrom: Peter Zijlstra
Quoted 5 lines
Sent: 02 April 2020 16:24
I picked VMXOFF (which also appears in vmmon.ko) instead of VMXON because that latter takes an argument is therefore more difficult to decode.
...
Quoted 4 lines
arch/x86/kernel/cpu/intel.c +4
-0+while (text < text_end) { +kernel_insn_init (&insn, text, text_end - text); +insn_get_length (&insn); +
arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1093
Quoted 10 lines
arch/x86/kernel/cpu/intel.c +10
-0+if (WARN_ON_ONCE (!insn_complete (&insn))) +break ; + +if (insn.length ==3 && + (!memcmp (text, vmlaunch,sizeof (vmlaunch)) || + !memcmp (text, vmxoff,sizeof (vmxoff)))) + goto bad_module; + + text += insn.length; + }
How long is that going to take on a module with (say) 400k of text?
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Re: [patch v2 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 7 lines · David Laight
From: Peter Zijlstra
Quoted 5 lines
Sent: 02 April 2020 16:24
I picked VMXOFF (which also appears in vmmon.ko) instead of VMXON because that latter takes an argument is therefore more difficult to decode.
...
Quoted 16 lines
Quoted 4 lines
arch/x86/kernel/cpu/intel.c +4
-0+while (text < text_end) { +kernel_insn_init (&insn, text, text_end - text); +insn_get_length (&insn); +arch/x86/kernel/cpu/intel.c static void sld_update_msr(bool on) · line 1093
Quoted 10 lines
arch/x86/kernel/cpu/intel.c +10
-0+if (WARN_ON_ONCE (!insn_complete (&insn))) +break ; + +if (insn.length ==3 && + (!memcmp (text, vmlaunch,sizeof (vmlaunch)) || + !memcmp (text, vmxoff,sizeof (vmxoff)))) + goto bad_module; + + text += insn.length; + }How long is that going to take on a module with (say) 400k of text?
It's module load, why would you care? I suspect it's really fast, but even if it wasn't I couldn't be arsed.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Thomas GleixnerQuoted 9 lines · Thomas Gleixner
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
+++ Rasmus Villemoes [03/04/20 01:42 +0200]:
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Quoted 8 lines
Quoted 3 lines
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
I second Rasmus's question. It seems rather unfortunate that we have to do this text scan for every module load on x86, when it doesn't apply to the majority of them, and only to a handful of out-of-tree hypervisor modules (assuming kvm is taken care of already).
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
Jessica
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 17 lines · Jessica Yu
+++ Rasmus Villemoes [03/04/20 01:42 +0200]:
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Quoted 8 lines
Quoted 3 lines
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
Quoted 7 lines
I second Rasmus's question. It seems rather unfortunate that we have to do this text scan for every module load on x86, when it doesn't apply to the majority of them, and only to a handful of out-of-tree hypervisor modules (assuming kvm is taken care of already).
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 23 lines · Peter Zijlstra
Quoted 22 lines · Jessica Yu
+++ Rasmus Villemoes [03/04/20 01:42 +0200]:
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Quoted 8 lines
Quoted 3 lines
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
I second Rasmus's question. It seems rather unfortunate that we have to do this text scan for every module load on x86, when it doesn't apply to the majority of them, and only to a handful of out-of-tree hypervisor modules (assuming kvm is taken care of already).
Quoted 4 lines
Quoted 2 lines
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking native_write_cr4() to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?
Partially tested patch incoming...
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?
And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
RE: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
From: Peter Zijlstra
Quoted 14 lines
Sent: 03 April 2020 17:12
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?
Quoted 8 lines
And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Could you do the scanning in the last phase of the module build that has to be done against the target kernel headers and with the target kernel build infrastructure?
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 19 lines · David Laight
From: Peter Zijlstra
Quoted 18 lines
Sent: 03 April 2020 17:12
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
Quoted 8 lines
Quoted 4 lines
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Could you do the scanning in the last phase of the module build that has to be done against the target kernel headers and with the target kernel build infrastructure?
You think the binary module people care to respect our module build warnings?
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Peter ZijlstraQuoted 13 lines · Peter Zijlstra
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?
Quoted 8 lines
And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Ya, that's the big uknown. But wouldn't they'd already be broken in the sense that they'd corrupt the CR4 shadow? E.g. setting VMXE without updating cpu_tlbstate.cr4 would result in future in-kernel writes to CR4 attempting to clear CR4.VMXE post-VMXON, which would #GP.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 23 lines · Sean Christopherson
Quoted 13 lines · Peter Zijlstra
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?Quoted 8 lines
And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Quoted 4 lines
Ya, that's the big uknown. But wouldn't they'd already be broken in the sense that they'd corrupt the CR4 shadow? E.g. setting VMXE without updating cpu_tlbstate.cr4 would result in future in-kernel writes to CR4 attempting to clear CR4.VMXE post-VMXON, which would #GP.
Sadly the CR4 shadow is exported, so they can actually fix that up :/
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 26 lines · Peter Zijlstra
Quoted 23 lines · Sean Christopherson
Quoted 21 lines · Peter Zijlstra
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Quoted 6 lines
Quoted 4 lines
Ya, that's the big uknown. But wouldn't they'd already be broken in the sense that they'd corrupt the CR4 shadow? E.g. setting VMXE without updating cpu_tlbstate.cr4 would result in future in-kernel writes to CR4 attempting to clear CR4.VMXE post-VMXON, which would #GP.
Sadly the CR4 shadow is exported, so they can actually fix that up :/
I do not think that Sean’s idea would work for VMware.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 26 lines · Nadav Amit
Quoted 26 lines · Peter Zijlstra
Quoted 23 lines · Sean Christopherson
Quoted 21 lines · Peter Zijlstra
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Peter Zijlstra
Quoted 2 lines · Jessica Yu
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
Rather than scanning modules at all, what about hooking
native_write_cr4()to kill SLD if CR4.VMXE is toggled on and the caller didn't increment a "sld safe" counter?And then you're hoping that the module uses that and not:
asm volatile ("mov %0, cr4" :: "r" (val));
I think I feel safer with the scanning to be fair. Also with the intree hint on, we can extend the scanning for out-of-tree modules for more dodgy crap we really don't want modules to do, like for example the above.
Quoted 8 lines
Quoted 6 lines
Quoted 4 lines
Ya, that's the big uknown. But wouldn't they'd already be broken in the sense that they'd corrupt the CR4 shadow? E.g. setting VMXE without updating cpu_tlbstate.cr4 would result in future in-kernel writes to CR4 attempting to clear CR4.VMXE post-VMXON, which would #GP.
Sadly the CR4 shadow is exported, so they can actually fix that up :/
I do not think that Sean’s idea would work for VMware.
Well phooey.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Peter ZijlstraQuoted 23 lines · Peter Zijlstra
Quoted 22 lines · Jessica Yu
+++ Rasmus Villemoes [03/04/20 01:42 +0200]:
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Quoted 8 lines
Quoted 3 lines
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
I second Rasmus's question. It seems rather unfortunate that we have to do this text scan for every module load on x86, when it doesn't apply to the majority of them, and only to a handful of out-of-tree hypervisor modules (assuming kvm is taken care of already).
Quoted 4 lines
Quoted 2 lines
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
But that still would not make it complete.
I was staring at virtualbox today after Jann pointed out that this sucker does complete backwards things.
The kernel driver does not contain any VM* instructions at all.
The actual hypervisor code is built as a separate binary and somehow loaded into the kernel with their own magic fixup of relocations and function linking. This "design" probably comes from the original virtualbox implementation which circumvented GPL that way.
TBH, I don't care if we wreckage virtualbox simply because that thing is already a complete and utter trainwreck violating taste and common sense in any possible way. Just for illustration:
- It installs preempt notifiers and the first thing in the callback function is to issue 'stac()'!
- There is quite some other horrible code in there which fiddles in the guts of the kernel just because it can.
- Conditionals in release code which check stuff like VBOX_WITH_TEXT_MODMEM_HACK, VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV, VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS along with the most absurd hacks ever.
If you feel the need to look yourself, please use your eyecancer protection gear.
Can someone at Oracle please make sure, that this monstrosity gets shred in pieces?
Enough vented, but that still does not solve the SLD problem in any sensible way.
Thanks,
tglx
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 59 lines · Thomas Gleixner
Quoted 23 lines · Peter Zijlstra
Quoted 23 lines · Jessica Yu
+++ Rasmus Villemoes [03/04/20 01:42 +0200]:
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Quoted 8 lines
Quoted 3 lines
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
How long does that scan take/add to module load time? Would it make sense to exempt in-tree modules?
Rasmus
I second Rasmus's question. It seems rather unfortunate that we have to do this text scan for every module load on x86, when it doesn't apply to the majority of them, and only to a handful of out-of-tree hypervisor modules (assuming kvm is taken care of already).
Quoted 4 lines
Quoted 2 lines
I wonder if it would make sense then to limit the text scans to just out-of-tree modules (i.e., missing the intree modinfo flag)?
It would; didn't know there was one.
But that still would not make it complete.
I was staring at virtualbox today after Jann pointed out that this sucker does complete backwards things.
The kernel driver does not contain any VM* instructions at all.
The actual hypervisor code is built as a separate binary and somehow loaded into the kernel with their own magic fixup of relocations and function linking. This "design" probably comes from the original virtualbox implementation which circumvented GPL that way.
TBH, I don't care if we wreckage virtualbox simply because that thing is already a complete and utter trainwreck violating taste and common sense in any possible way. Just for illustration:
- It installs preempt notifiers and the first thing in the callback function is to issue '
stac()'!- There is quite some other horrible code in there which fiddles in the guts of the kernel just because it can.
- Conditionals in release code which check stuff like
VBOX_WITH_TEXT_MODMEM_HACK,VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV,VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKSalong with the most absurd hacks ever.
Quoted 8 lines
If you feel the need to look yourself, please use your eyecancer protection gear.
Can someone at Oracle please make sure, that this monstrosity gets shred in pieces?
Enough vented, but that still does not solve the SLD problem in any sensible way.
Could we unexport set_memory_x perhaps? And maybe try to make virtualbox break in as many ways as possible?
Quoted 4 lines
Thanks,
tglx
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 7 lines · Andy Lutomirski
Quoted 4 lines · Thomas Gleixner
Peter Zijlstra <[email protected]> writes:
Enough vented, but that still does not solve the SLD problem in any sensible way.Could we unexport
set_memory_xperhaps? And maybe try to make virtualbox break in as many ways as possible?
set_memory_x() is not exported anymore, but they found new ways of circumvention. set_memory_x() is only used on really old kernels.
Thanks,
tglx
kbuild test robot
build botRe: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Thomas GleixnerI love your patch! Yet something to improve:
Hi Thomas,
I love your patch! Yet something to improve:
[auto build test ERROR on tip/auto-latest]
[also build test ERROR on next-20200403]
[cannot apply to jeyu/modules-next tip/x86/core v5.6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Thomas-Gleixner/x86-Prevent-Split-Lock-Detection-wreckage-on-VMX-hypervisors/20200403-171430 base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git ee8bac724cc7767dcf9480afb656318994f22c3d config: um-x86_64_defconfig (attached as .config) compiler: gcc-7 (Ubuntu 7.5.0-6ubuntu2) 7.5.0 reproduce: # save the attached .config to linux build tree make ARCH=um SUBARCH=x86_64
If you fix the issue, kindly add following tag
All error/warnings (new ones prefixed by >>):
/usr/bin/ld: arch/x86/um/../kernel/module.o: in function `module_finalize':
>> module.c:(.text+0x315): undefined reference to `split_lock_validate_module_text'
>> collect2: error: ld returned 1 exit status
--
In file included from arch/x86/um/../kernel/module.c:27:0:
>> arch/x86/include/asm/cpu.h:38:31: warning: 'struct cpuinfo_x86' declared inside parameter list will not be visible outside of this definition or declaration
int mwait_usable(const struct cpuinfo_x86 *);
^~~~~~~~~~~
arch/x86/include/asm/cpu.h:44:49: warning: 'struct cpuinfo_x86' declared inside parameter list will not be visible outside of this definition or declaration
extern void __init cpu_set_core_cap_bits(struct cpuinfo_x86 *c);
^~~~~~~~~~~---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
kbuild test robot
build botRe: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Thomas GleixnerI love your patch! Yet something to improve:
Hi Thomas,
I love your patch! Yet something to improve:
[auto build test ERROR on tip/auto-latest]
[also build test ERROR on next-20200403]
[cannot apply to jeyu/modules-next tip/x86/core v5.6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Thomas-Gleixner/x86-Prevent-Split-Lock-Detection-wreckage-on-VMX-hypervisors/20200403-171430 base: https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git ee8bac724cc7767dcf9480afb656318994f22c3d config: x86_64-randconfig-s1-20200403 (attached as .config) compiler: gcc-7 (Ubuntu 7.5.0-6ubuntu2) 7.5.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64
If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
arch/x86/kernel/module.c: In function 'module_finalize':
>> arch/x86/kernel/module.c:257:17: error: 'struct module' has no member named 'sld_safe'
if (text && !me->sld_safe) {
^~vim +257 arch/x86/kernel/module.c
220
221 int module_finalize(const Elf_Ehdr *hdr,
222 const Elf_Shdr *sechdrs,
223 struct module *me)
224 {
225 const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
226 *para = NULL, *orc = NULL, *orc_ip = NULL;
227 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
228
229 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
230 if (!strcmp(".text", secstrings + s->sh_name))
231 text = s;
232 if (!strcmp(".altinstructions", secstrings + s->sh_name))
233 alt = s;
234 if (!strcmp(".smp_locks", secstrings + s->sh_name))
235 locks = s;
236 if (!strcmp(".parainstructions", secstrings + s->sh_name))
237 para = s;
238 if (!strcmp(".orc_unwind", secstrings + s->sh_name))
239 orc = s;
240 if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name))
241 orc_ip = s;
242 }
243
244 if (alt) {
245 /* patch .altinstructions */
246 void *aseg = (void *)alt->sh_addr;
247 apply_alternatives(aseg, aseg + alt->sh_size);
248 }
249 if (locks && text) {
250 void *lseg = (void *)locks->sh_addr;
251 void *tseg = (void *)text->sh_addr;
252 alternatives_smp_module_add(me, me->name,
253 lseg, lseg + locks->sh_size,
254 tseg, tseg + text->sh_size);
255 }
256
> 257 if (text && !me->sld_safe) { 258 void *tseg = (void *)text->sh_addr;
259 split_lock_validate_module_text(me, tseg, tseg + text->sh_size);
260 }
261
262 if (para) {
263 void *pseg = (void *)para->sh_addr;
264 apply_paravirt(pseg, pseg + para->sh_size);
265 }
266
267 /* make jump label nops */
268 jump_label_apply_nops(me);
269
270 if (orc && orc_ip)
271 unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size,
272 (void *)orc->sh_addr, orc->sh_size);
273
274 return 0;
275 }
276
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Thomas GleixnerQuoted 11 lines · Thomas Gleixner
arch/x86/kernel/module.c +1
-0@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \
arch/x86/kernel/module.c int module_finalize(const Elf_Ehdr *hdr, · line 257
Quoted 4 lines
arch/x86/kernel/module.c +1
-0@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) {
As also reported by the test bot, sld_safe only exist if CPU_SUP_INTEL=y.
This can also be conditioned on boot_cpu_has(X86_FEATURE_VMX), or the static variant. If CPU_SUP_INTEL=y, X86_FEATURE_VMX will be set if and only if VMX is fully enabled, i.e. supported by the CPU and enabled in MSR_IA32_FEATURE_CONTROl.
Quoted 35 lines
arch/x86/kernel/module.c +4
-0+void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + } +if (para) {void *pseg = (void *)para->sh_addr;apply_paravirt (pseg, pseg + para->sh_size);include/linux/module.h +4
-0@@ -407,6 +407,10 @@ struct module {bool sig_ok;#endif +#ifdef CONFIG_CPU_SUP_INTEL +bool sld_safe; +#endif +bool async_probe_requested;/* symbols that will be GPL-only in the near future. */ kernel/module.c +5
-0@@ -3096,6 +3096,11 @@ static int check_modinfo(struct module * "is unknown, you have been warned.\n", mod->name); } +#ifdef CONFIG_CPU_SUP_INTEL +if (get_modinfo (info,"sld_safe" )) + mod->sld_safe = true; +#endif + err =check_modinfo_livepatch (mod, info);if (err)return err;
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 19 lines · Sean Christopherson
Quoted 11 lines · Thomas Gleixner
arch/x86/kernel/module.c +1
-0@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \arch/x86/kernel/module.c int module_finalize(const Elf_Ehdr *hdr, · line 257
Quoted 4 lines
arch/x86/kernel/module.c +1
-0@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) {As also reported by the test bot,
sld_safeonly exist if CPU_SUP_INTEL=y.
Quoted 8 lines
This can also be conditioned on
boot_cpu_has(X86_FEATURE_VMX), or the static variant. If CPU_SUP_INTEL=y,X86_FEATURE_VMXwill be set if and only if VMX is fully enabled, i.e. supported by the CPU and enabled inMSR_IA32_FEATURE_CONTROl.arch/x86/kernel/module.c int module_finalize(const Elf_Ehdr *hdr, · line 260
Quoted 3 lines
arch/x86/kernel/module.c +3
-0+void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + }
Ideally we push it all into arch code, but load_info isn't exposed to arch module code :/.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
+++ Peter Zijlstra [03/04/20 18:41 +0200]:
Quoted 25 lines · Sean Christopherson
Quoted 24 lines · Thomas Gleixner
Quoted 11 lines
arch/x86/kernel/module.c +1
-0@@ -24,6 +24,7 @@#include <asm/pgtable.h> #include <asm/setup.h> #include <asm/unwind.h> +#include <asm/cpu.h> #if 0 #define DEBUGP (fmt, ...) \arch/x86/kernel/module.c int module_finalize(const Elf_Ehdr *hdr, · line 257
Quoted 4 lines
arch/x86/kernel/module.c +1
-0@@ -253,6 +254,11 @@ int module_finalize(const Elf_Ehdr *hdr, tseg, tseg + text->sh_size); } +if (text && !me->sld_safe) {As also reported by the test bot,
sld_safeonly exist if CPU_SUP_INTEL=y.This can also be conditioned on
boot_cpu_has(X86_FEATURE_VMX), or the static variant. If CPU_SUP_INTEL=y,X86_FEATURE_VMXwill be set if and only if VMX is fully enabled, i.e. supported by the CPU and enabled inMSR_IA32_FEATURE_CONTROl.
Quoted 6 lines
Quoted 3 lines
arch/x86/kernel/module.c int module_finalize(const Elf_Ehdr *hdr, · line 260
Quoted 3 lines
arch/x86/kernel/module.c +3
-0+void *tseg = (void *)text->sh_addr; +split_lock_validate_module_text (me, tseg, tseg + text->sh_size); + }Ideally we push it all into arch code, but
load_infoisn't exposed to arch module code :/.
Hm, I can look into exposing load_info to arch module code and will post a patch on Monday.
Jessica
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
In reply to Thomas GleixnerQuoted 15 lines · Thomas Gleixner
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
Hypervisors, which have been modified and are known to work correctly, can add:
MODULE_INFO(sld_safe, "Y");
Quoted 8 lines
to explicitly tell the module loader they're good.
NOTE: it is unfortunate that struct
load_infois not available to the
arch module code, this meansCONFIG_CPU_SUP_INTELgunk is needed in generic code.NOTE: while we can 'trivially' fix KVM, we're still stuck with stuff
like VMware and VirtualBox doing their own thing.
This is just crazy. We have never cared about any out tree module, why would we care here where it creates a real complexity. Just fix KVM and ignore anything else.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 22 lines · Christoph Hellwig
Quoted 21 lines · Thomas Gleixner
From: Peter Zijlstra <[email protected]>
It turns out that with Split-Lock-Detect enabled (default) any VMX hypervisor needs at least a little modification in order to not blindly inject the #AC into the guest without the guest being ready for it.
Since there is no telling which module implements a hypervisor, scan the module text and look for the VMLAUNCH instruction. If found, the module is assumed to be a hypervisor of some sort and SLD is disabled.
Hypervisors, which have been modified and are known to work correctly, can add:
MODULE_INFO(sld_safe, "Y");to explicitly tell the module loader they're good.
NOTE: it is unfortunate that struct
load_infois not available to the
arch module code, this meansCONFIG_CPU_SUP_INTELgunk is needed in generic code.
Quoted 6 lines
Quoted 2 lines
NOTE: while we can 'trivially' fix KVM, we're still stuck with stuff
like VMware and VirtualBox doing their own thing.This is just crazy. We have never cared about any out tree module, why would we care here where it creates a real complexity. Just fix KVM and ignore anything else.
It is absolutely bonkers, but at the same time we can extend this infrastructure to scan for dubious code patterns we don't want to support. Like for instance direct manipulation of CR4.
Look at is as another layer to enforce sanity on binary only modules.
Do we want to go that way, and do you know of other code patterns you'd want to fail module loading for?
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 3 lines · Peter Zijlstra
It is absolutely bonkers, but at the same time we can extend this infrastructure to scan for dubious code patterns we don't want to support. Like for instance direct manipulation of CR4.
But that is not what this code does - it disables split lock detection. If it failed to load the module the whole thing would make a little more sense.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 8 lines · Christoph Hellwig
Quoted 3 lines · Peter Zijlstra
It is absolutely bonkers, but at the same time we can extend this infrastructure to scan for dubious code patterns we don't want to support. Like for instance direct manipulation of CR4.
But that is not what this code does - it disables split lock detection. If it failed to load the module the whole thing would make a little more sense.
If this lives, it'll be to just to fail module loading. IIRC the same was suggested elsewhere in the thread.
Re: [patch 1/2] x86,module: Detect VMX modules and disable Split-Lock-Detect
Quoted 6 lines · On Mon, 6 Apr 2020 17:22:31 +0200 Peter Zijlstra <[email protected]> wrote:
Quoted 5 lines · Christoph Hellwig
Quoted 3 lines · Peter Zijlstra
It is absolutely bonkers, but at the same time we can extend this infrastructure to scan for dubious code patterns we don't want to support. Like for instance direct manipulation of CR4.
Quoted 6 lines
Quoted 3 lines
But that is not what this code does - it disables split lock detection. If it failed to load the module the whole thing would make a little more sense.
If this lives, it'll be to just to fail module loading. IIRC the same was suggested elsewhere in the thread.
I believe I may have been the one to suggest it. It's no different than breaking kabi if you ask me. If a module can't deal with a new feature, than it should not be able to load. And let whoever owns that module fix it for their users.
-- Steve
PATCH 2/2 x86/kvm/vmx: Prevent split lock detection induced #AC wreckage
In reply to Thomas GleixnerWithout at least minimal handling for split lock detection induced #AC, VMX will just run into the same problem as the VMWare hypervisor, which was reported by Kenneth.
It will inject the #AC blindly into the guest whether the guest is prepared or not.
Add the minimal required handling for it:
- Check guest state whether CR0.AM is enabled and EFLAGS.AC is set. If so, then the #AC originated from CPL3 and the guest has is prepared to handle it. In this case it does not matter whether the #AC is due to a split lock or a regular unaligned check.
- Invoke a minimal split lock detection handler. If the host SLD mode is sld_warn, then handle it in the same way as user space handling works:
Emit a warning, disable SLD and mark the current task with TIF_SLD. With that resume the guest without injecting #AC.
If the host mode is sld_fatal or sld_off, emit a warning and deliver the exception to user space which can crash and burn itself.
Mark the module with MOD_INFO(sld_safe, "Y") so the module loader does not force SLD off.
--- arch/x86/include/asm/cpu.h | 1 + arch/x86/kernel/cpu/intel.c | 28 +++++++++++++++++++++++----- arch/x86/kvm/vmx/vmx.c | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 8 deletions(-)
arch/x86/include/asm/cpu.h +1 -0
@@ -44,6 +44,7 @@ unsigned int x86_stepping(unsigned int sextern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn);extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern bool handle_guest_split_lock (unsigned long ip);extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}
arch/x86/kernel/cpu/intel.c +23 -5
@@ -1102,13 +1102,10 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); } -bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static void split_lock_warn (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) -return false; -pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);/* * Disable the split lock detection for this task so it can make
@@ -1117,6 +1114,27 @@ bool handle_user_split_lock(struct pt_re*/ sld_update_msr (false);set_tsk_thread_flag (current,TIF_SLD ); +} + +bool handle_guest_split_lock (unsigned long ip) +{ +if (sld_state == sld_warn) { +split_lock_warn (ip); +return true; + } + +pr_warn_once ("#AC: %s/%d %s split_lock trap at address: 0x%lx\n" , + current->comm, current->pid, + sld_state == sld_fatal ?"fatal" :"bogus" , ip); +return false; +} +EXPORT_SYMBOL_GPL (handle_guest_split_lock); + +bool handle_user_split_lock (struct pt_regs *regs,long error_code) +{ +if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) +return false; +split_lock_warn (regs->ip);return true; }
arch/x86/kvm/vmx/vmx.c +37 -3
@@ -65,6 +65,7 @@MODULE_AUTHOR ("Qumranet" );MODULE_LICENSE ("GPL" ); +MODULE_INFO (sld_safe,"Y" );#ifdef MODULE static const struct x86_cpu_id vmx_cpu_id[] = {
@@ -4623,6 +4624,22 @@ static int handle_machine_check(struct kreturn 1 ; } +static bool guest_handles_ac (struct kvm_vcpu *vcpu) +{ +/* +* If guest has alignment checking enabled in CR0 and activated in +* eflags, then the #AC originated from CPL3 and the guest is able +* to handle it. It does not matter whether this is a regular or +* a split lock operation induced #AC. +*/ +if (vcpu->arch.cr0 &X86_CR0_AM && +vmx_get_rflags (vcpu) &X86_EFLAGS_AC ) +return true; + +/* Add guest SLD handling checks here once it's supported */ +return false; +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);
@@ -4688,9 +4705,6 @@ static int handle_exception_nmi(struct kreturn handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &
@@ -4719,6 +4733,26 @@ static int handle_exception_nmi(struct k kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;break ; +case AC_VECTOR : +if (guest_handles_ac (vcpu)) { +kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); +return 1 ; + } +/* +* Handle #AC caused by split lock detection. If the host +* mode is sld_warn, then it warns, marks current with +* TIF_SLD and disables split lock detection. So the guest +* can just continue. +* +* If the host mode is fatal, the handling code warned. Let +* qemu kill itself. +* +* If the host mode is off, then this #AC is bonkers and +* something is badly wrong. Let it fail as well. +*/ +if (handle_guest_split_lock (kvm_rip_read (vcpu))) +return 1 ; +/* fall through */ default : kvm_run->exit_reason =KVM_EXIT_EXCEPTION ; kvm_run->ex.exception = ex_no;
Re: [patch 2/2] x86/kvm/vmx: Prevent split lock detection induced #AC wreckage
Quoted 19 lines · Thomas Gleixner
Without at least minimal handling for split lock detection induced #AC, VMX will just run into the same problem as the VMWare hypervisor, which was reported by Kenneth.
It will inject the #AC blindly into the guest whether the guest is prepared or not.
Add the minimal required handling for it:
- Check guest state whether CR0.AM is enabled and EFLAGS.AC is set. If so, then the #AC originated from CPL3 and the guest has is prepared to handle it. In this case it does not matter whether the #AC is due to a split lock or a regular unaligned check.
- Invoke a minimal split lock detection handler. If the host SLD mode is
sld_warn, then handle it in the same way as user space handling works:
Emit a warning, disable SLD and mark the current task withTIF_SLD. With that resume the guest without injecting #AC.
Quoted 5 lines
If the host mode is
sld_fatalorsld_off, emit a warning and deliver the exception to user space which can crash and burn itself.Mark the module with
MOD_INFO(sld_safe, "Y")so the module loader does not force SLD off.
Some comments below. But, any objection to taking Xiaoyao's patches that do effectively the same things, minus the MOD_INFO()? I'll repost them in reply to this thread.
Quoted 84 lines
Signed-off-by Thomas Gleixner <[email protected]>Cc "Kenneth R. Crudup" <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Fenghua Yu <[email protected]>Cc Xiaoyao Li <[email protected]>Cc Nadav Amit <[email protected]>Cc Thomas Hellstrom <[email protected]>Cc Sean Christopherson <[email protected]>Cc Tony Luck <[email protected]>--- arch/x86/include/asm/cpu.h | 1 + arch/x86/kernel/cpu/intel.c | 28 +++++++++++++++++++++++----- arch/x86/kvm/vmx/vmx.c | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 8 deletions(-)arch/x86/include/asm/cpu.h +1
-0@@ -44,6 +44,7 @@ unsigned int x86_stepping(unsigned int sextern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn);extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern bool handle_guest_split_lock (unsigned long ip);extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}arch/x86/kernel/cpu/intel.c +23
-5@@ -1102,13 +1102,10 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); } -bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static void split_lock_warn (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) -return false; -pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);/* * Disable the split lock detection for this task so it can make @@ -1117,6 +1114,27 @@ bool handle_user_split_lock(struct pt_re*/ sld_update_msr (false);set_tsk_thread_flag (current,TIF_SLD ); +} + +bool handle_guest_split_lock (unsigned long ip) +{ +if (sld_state == sld_warn) { +split_lock_warn (ip); +return true; + } + +pr_warn_once ("#AC: %s/%d %s split_lock trap at address: 0x%lx\n" , + current->comm, current->pid, + sld_state == sld_fatal ?"fatal" :"bogus" , ip); +return false; +} +EXPORT_SYMBOL_GPL (handle_guest_split_lock); + +bool handle_user_split_lock (struct pt_regs *regs,long error_code) +{ +if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) +return false; +split_lock_warn (regs->ip);return true; }arch/x86/kvm/vmx/vmx.c +1
-0@@ -65,6 +65,7 @@MODULE_AUTHOR ("Qumranet" );MODULE_LICENSE ("GPL" ); +MODULE_INFO (sld_safe,"Y" );#ifdef MODULE static const struct x86_cpu_id vmx_cpu_id[] = {@@ -4623,6 +4624,22 @@ static int handle_machine_check(struct kreturn 1 ; }
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct k · line 4635
Quoted 10 lines
arch/x86/kvm/vmx/vmx.c +9
-0+static bool guest_handles_ac (struct kvm_vcpu *vcpu) +{ +/* +* If guest has alignment checking enabled in CR0 and activated in +* eflags, then the #AC originated from CPL3 and the guest is able +* to handle it. It does not matter whether this is a regular or +* a split lock operation induced #AC. +*/ + if (vcpu->arch.cr0 & X86_CR0_AM &&
Technically not required since KVM doesn't let the gets toggle CR0.AM at will, but going through kvm_read_cr0{_bits}() is preferred.
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct k · line 4636
Quoted 1 line
arch/x86/kvm/vmx/vmx.c +1
-0+ vmx_get_rflags(vcpu) & X86_EFLAGS_AC)
I don't think this is correct. A guest could trigger a split-lock #AC at CPL0 with EFLAGS.AC=1 and CR0.AM=1, and then panic because it didn't expect #AC at CPL0.
Quoted 47 lines
arch/x86/kvm/vmx/vmx.c +26
-3+return true; + +/* Add guest SLD handling checks here once it's supported */ +return false; +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -4688,9 +4705,6 @@ static int handle_exception_nmi(struct kreturn handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &@@ -4719,6 +4733,26 @@ static int handle_exception_nmi(struct k kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;break ; +case AC_VECTOR : +if (guest_handles_ac (vcpu)) { +kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); +return 1 ; + } +/* +* Handle #AC caused by split lock detection. If the host +* mode is sld_warn, then it warns, marks current with +* TIF_SLD and disables split lock detection. So the guest +* can just continue. +* +* If the host mode is fatal, the handling code warned. Let +* qemu kill itself. +* +* If the host mode is off, then this #AC is bonkers and +* something is badly wrong. Let it fail as well. +*/ +if (handle_guest_split_lock (kvm_rip_read (vcpu))) +return 1 ; +/* fall through */ default : kvm_run->exit_reason =KVM_EXIT_EXCEPTION ; kvm_run->ex.exception = ex_no;
Re: [patch 2/2] x86/kvm/vmx: Prevent split lock detection induced #AC wreckage
Quoted 25 lines · Sean Christopherson
Quoted 22 lines · Thomas Gleixner
Without at least minimal handling for split lock detection induced #AC, VMX will just run into the same problem as the VMWare hypervisor, which was reported by Kenneth.
It will inject the #AC blindly into the guest whether the guest is prepared or not.
Add the minimal required handling for it:
- Check guest state whether CR0.AM is enabled and EFLAGS.AC is set. If so, then the #AC originated from CPL3 and the guest has is prepared to handle it. In this case it does not matter whether the #AC is due to a split lock or a regular unaligned check.
- Invoke a minimal split lock detection handler. If the host SLD mode is
sld_warn, then handle it in the same way as user space handling works:
Emit a warning, disable SLD and mark the current task withTIF_SLD. With that resume the guest without injecting #AC.If the host mode is
sld_fatalorsld_off, emit a warning and deliver the exception to user space which can crash and burn itself.
Quoted 6 lines
Quoted 2 lines
Mark the module with
MOD_INFO(sld_safe, "Y")so the module loader does not force SLD off.Some comments below. But, any objection to taking Xiaoyao's patches that do effectively the same things, minus the
MOD_INFO()? I'll repost them in reply to this thread.
IIUC they also deal with emulated split-lock accesses in the host, during instruction emulation [1]. This seems also to be required, although I am not sure the approach that he took once emulation encounters a split-lock is robust.
Re: [patch 2/2] x86/kvm/vmx: Prevent split lock detection induced #AC wreckage
Quoted 28 lines · Nadav Amit
Quoted 28 lines · Sean Christopherson
Quoted 24 lines · Thomas Gleixner
Without at least minimal handling for split lock detection induced #AC, VMX will just run into the same problem as the VMWare hypervisor, which was reported by Kenneth.
It will inject the #AC blindly into the guest whether the guest is prepared or not.
Add the minimal required handling for it:
- Check guest state whether CR0.AM is enabled and EFLAGS.AC is set. If so, then the #AC originated from CPL3 and the guest has is prepared to handle it. In this case it does not matter whether the #AC is due to a split lock or a regular unaligned check.
- Invoke a minimal split lock detection handler. If the host SLD mode is
sld_warn, then handle it in the same way as user space handling works:
Emit a warning, disable SLD and mark the current task withTIF_SLD. With that resume the guest without injecting #AC.If the host mode is
sld_fatalorsld_off, emit a warning and deliver the exception to user space which can crash and burn itself.Mark the module with
MOD_INFO(sld_safe, "Y")so the module loader does not force SLD off.
Quoted 8 lines
Quoted 3 lines
Some comments below. But, any objection to taking Xiaoyao's patches that do effectively the same things, minus the
MOD_INFO()? I'll repost them in reply to this thread.IIUC they also deal with emulated split-lock accesses in the host, during instruction emulation [1]. This seems also to be required, although I am not sure the approach that he took once emulation encounters a split-lock is robust.
Yep. It's "robust" in the sense that KVM won't panic the host. It's not robust from the perspective that it could possibly hose the guest. But, no sane, well-behaved guest should reach that particular emulator path on a split-lock enabled system.
Quoted 1 line
Re: [patch 2/2] x86/kvm/vmx: Prevent split lock detection induced #AC wreckage
In reply to Sean ChristophersonQuoted 7 lines · Sean Christopherson
Quoted 2 lines · Thomas Gleixner
Mark the module with
MOD_INFO(sld_safe, "Y")so the module loader does not force SLD off.Some comments below. But, any objection to taking Xiaoyao's patches that do effectively the same things, minus the
MOD_INFO()? I'll repost them in reply to this thread.
If they are sane, I don't have a problem. But TBH, I really couldn't be bothered to actually scan my mails whether there surfaced something sane by now. Writing that up was just faster :)
I'll have look.
Quoted 4 lines
Quoted 4 lines
arch/x86/kvm/vmx/vmx.c +4
-0+static bool guest_handles_ac (struct kvm_vcpu *vcpu) +{ +/* +* If guest has alignment checking enabled in CR0 and activated in
Quoted 8 lines
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct k · line 4635
Quoted 5 lines
arch/x86/kvm/vmx/vmx.c +5
-0+* eflags, then the #AC originated from CPL3 and the guest is able +* to handle it. It does not matter whether this is a regular or +* a split lock operation induced #AC. +*/ + if (vcpu->arch.cr0 & X86_CR0_AM &&Technically not required since KVM doesn't let the gets toggle CR0.AM at will, but going through kvm_read_cr0{_bits}() is preferred.
You're the expert here.
Quoted 5 lines
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct k · line 4636
Quoted 1 line
arch/x86/kvm/vmx/vmx.c +1
-0+ vmx_get_rflags(vcpu) & X86_EFLAGS_AC)I don't think this is correct. A guest could trigger a split-lock #AC at CPL0 with EFLAGS.AC=1 and CR0.AM=1, and then panic because it didn't expect #AC at CPL0.
Indeed.
Thanks,
tglx
cover x86: KVM: VMX: Add basic split-lock #AC handling
In reply to Thomas GleixnerFirst three patches from Xiaoyao's series to add split-lock #AC support in KVM.
Xiaoyao Li (3):
KVM: x86: Emulate split-lock access as a write in emulator x86/split_lock: Refactor and export handle_user_split_lock() for KVM
KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in
guest
arch/x86/include/asm/cpu.h | 4 ++-- arch/x86/kernel/cpu/intel.c | 7 ++++--- arch/x86/kernel/traps.c | 2 +- arch/x86/kvm/vmx/vmx.c | 30 +++++++++++++++++++++++++++--- arch/x86/kvm/x86.c | 12 +++++++++++- 5 files changed, 45 insertions(+), 10 deletions(-)
Signature · 1 line
2.24.1
PATCH 1/3 KVM: x86: Emulate split-lock access as a write in emulator
From: Xiaoyao Li <[email protected]>
Emulate split-lock accesses as writes if split lock detection is on to avoid #AC during emulation, which will result in a panic(). This should never occur for a well behaved guest, but a malicious guest can manipulate the TLB to trigger emulation of a locked instruction[1].
More discussion can be found [2][3].
[1] https://lkml.kernel.org/r/[email protected]
[2] https://lkml.kernel.org/r/[email protected]
[3] https://lkml.kernel.org/r/[email protected]
--- arch/x86/kvm/x86.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
arch/x86/kvm/x86.c +11 -1
@@ -5875,6 +5875,7 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, {struct kvm_host_map map;struct kvm_vcpu *vcpu =emul_to_vcpu (ctxt); +u64 page_line_mask;gpa_t gpa;char *kaddr;bool exchanged;
@@ -5889,7 +5890,16 @@ static int emulator_cmpxchg_emulated(struct x86_emulate_ctxt *ctxt, (gpa & PAGE_MASK) == APIC_DEFAULT_PHYS_BASE) goto emul_write; -if (((gpa + bytes -1 ) &PAGE_MASK ) != (gpa &PAGE_MASK )) +/* +* Emulate the atomic as a straight write to avoid #AC if SLD is +* enabled in the host and the access splits a cache line. +*/ +if (boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT )) + page_line_mask = ~(cache_line_size () -1 ); +else + page_line_mask =PAGE_MASK ; + +if (((gpa + bytes -1 ) & page_line_mask) != (gpa & page_line_mask)) goto emul_write;if (kvm_vcpu_map (vcpu,gpa_to_gfn (gpa), &map))
Signature · 1 line
2.24.1
PATCH 2/3 x86/split_lock: Refactor and export handle_user_split_lock() for KVM
In reply to Sean ChristophersonFrom: Xiaoyao Li <[email protected]>
In the future, KVM will use handle_user_split_lock() to handle #AC caused by split lock in guest. Due to the fact that KVM doesn't have a @regs context and will pre-check EFLAGS.AC, move the EFLAGS.AC check to do_alignment_check().
--- arch/x86/include/asm/cpu.h | 4 ++-- arch/x86/kernel/cpu/intel.c | 7 ++++--- arch/x86/kernel/traps.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-)
arch/x86/include/asm/cpu.h +2 -2
@@ -43,11 +43,11 @@ unsigned int x86_stepping(unsigned int sig);#ifdef CONFIG_CPU_SUP_INTEL extern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn); -extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern bool handle_user_split_lock (unsigned long ip);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {} -static inline bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static inline bool handle_user_split_lock (unsigned long ip) {return false; }
arch/x86/kernel/cpu/intel.c +4 -3
@@ -1066,13 +1066,13 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); } -bool handle_user_split_lock (struct pt_regs *regs,long error_code) +bool handle_user_split_lock (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) +if (sld_state == sld_fatal)return false;pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);/* * Disable the split lock detection for this task so it can make
@@ -1083,6 +1083,7 @@ bool handle_user_split_lock(struct pt_regs *regs, long error_code)set_tsk_thread_flag (current,TIF_SLD );return true; } +EXPORT_SYMBOL_GPL (handle_user_split_lock);/* * This function is called only when switching between tasks with
arch/x86/kernel/traps.c +1 -1
@@ -304,7 +304,7 @@ dotraplinkage void do_alignment_check(struct pt_regs *regs, long error_code)local_irq_enable (); -if (handle_user_split_lock (regs, error_code)) +if (!(regs->flags &X86_EFLAGS_AC ) &&handle_user_split_lock (regs->ip))return ; do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,
Signature · 1 line
2.24.1
Re: [PATCH 2/3] x86/split_lock: Refactor and export handle_user_split_lock() for KVM
Quoted 22 lines · Sean Christopherson
From: Xiaoyao Li <[email protected]>
In the future, KVM will use
handle_user_split_lock()to handle #AC caused by split lock in guest. Due to the fact that KVM doesn't have a @regs context and will pre-check EFLAGS.AC, move the EFLAGS.AC check todo_alignment_check().Suggested-by Sean Christopherson <[email protected]>Signed-off-by Xiaoyao Li <[email protected]>Reviewed-by Tony Luck <[email protected]>Signed-off-by Sean Christopherson <[email protected]>--- arch/x86/include/asm/cpu.h | 4 ++-- arch/x86/kernel/cpu/intel.c | 7 ++++--- arch/x86/kernel/traps.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-)arch/x86/include/asm/cpu.h +0
-0
arch/x86/include/asm/cpu.h unsigned int x86_stepping(unsigned int sig); · line 50
Quoted 10 lines
arch/x86/include/asm/cpu.h +2
-2@@ -43,11 +43,11 @@ unsigned int x86_stepping(unsigned int sig);#ifdef CONFIG_CPU_SUP_INTEL extern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn); -extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern bool handle_user_split_lock (unsigned long ip);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {} -static inline bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static inline bool handle_user_split_lock (unsigned long ip)
This is necessary because VMX can be compiled without CPU_SUP_INTEL?
Quoted 11 lines
arch/x86/include/asm/cpu.h +0
-0{return false; }arch/x86/kernel/cpu/intel.c +0
-0@@ -1066,13 +1066,13 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); }
arch/x86/kernel/cpu/intel.c static void split_lock_init(void) · line 1075
Quoted 10 lines
arch/x86/kernel/cpu/intel.c +3
-3-bool handle_user_split_lock (struct pt_regs *regs,long error_code) +bool handle_user_split_lock (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) +if (sld_state == sld_fatal)return false;pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);
So this returns true even in the case that sld_state == off.
Should never happen, but I rather have an extra check and be both verbose and correct. See the variant I did.
Thanks,
tglx
Re: [PATCH 2/3] x86/split_lock: Refactor and export handle_user_split_lock() for KVM
Quoted 27 lines · Thomas Gleixner
Quoted 26 lines · Sean Christopherson
From: Xiaoyao Li <[email protected]>
In the future, KVM will use
handle_user_split_lock()to handle #AC caused by split lock in guest. Due to the fact that KVM doesn't have a @regs context and will pre-check EFLAGS.AC, move the EFLAGS.AC check todo_alignment_check().Suggested-by Sean Christopherson <[email protected]>Signed-off-by Xiaoyao Li <[email protected]>Reviewed-by Tony Luck <[email protected]>Signed-off-by Sean Christopherson <[email protected]>--- arch/x86/include/asm/cpu.h | 4 ++-- arch/x86/kernel/cpu/intel.c | 7 ++++--- arch/x86/kernel/traps.c | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-)arch/x86/include/asm/cpu.h +0
-1@@ -43,11 +43,11 @@ unsigned int x86_stepping(unsigned int sig);#ifdef CONFIG_CPU_SUP_INTEL extern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn); -extern bool handle_user_split_lock (struct pt_regs *regs,long error_code);
Quoted 8 lines
arch/x86/include/asm/cpu.h unsigned int x86_stepping(unsigned int sig); · line 50
Quoted 6 lines
arch/x86/include/asm/cpu.h +2
-1+extern bool handle_user_split_lock (unsigned long ip);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {} -static inline bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static inline bool handle_user_split_lock (unsigned long ip)This is necessary because VMX can be compiled without
CPU_SUP_INTEL?
Ya, it came about when cleaning up the IA32_FEATURE_CONTROL MSR handling to consolidate duplicate code.
config KVM_INTEL
tristate "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL
config IA32_FEAT_CTL
def_bool y
depends on CPU_SUP_INTEL || CPU_SUP_CENTAUR || CPU_SUP_ZHAOXINRe: [PATCH 2/3] x86/split_lock: Refactor and export handle_user_split_lock() for KVM
Quoted 11 lines · Sean Christopherson
Quoted 6 lines · Thomas Gleixner
Review
Quoted 4 lines
static inline void
__initcpu_set_core_cap_bits(struct cpuinfo_x86 *c){} static inline voidswitch_to_sld(unsigned long tifn){}(quoted diff) +1
-1-static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code) +static inline bool handle_user_split_lock(unsigned long ip)This is necessary because VMX can be compiled without
CPU_SUP_INTEL?Ya, it came about when cleaning up the
IA32_FEATURE_CONTROLMSR handling to consolidate duplicate code.
Quoted 7 lines
config
KVM_INTEL
tristate "KVM for Intel (and compatible) processors support" depends on KVM &&IA32_FEAT_CTLconfig
IA32_FEAT_CTLdef_bool y depends on CPU_SUP_INTEL || CPU_SUP_CENTAUR || CPU_SUP_ZHAOXIN
Ah, indeed. So something like the below would make sense. Hmm?
Of course that can be mangled into Xiaoyao's patches, I'm not worried about my patch count :)
Aside of that I really wish Intel HW folks had indicated the source of the #AC via the error code. It can only be 0 or 1 for the regular #AC so there would have been 31 bits to chose from.
Thanks,
tglx
8<----------------
arch/x86/include/asm/cpu.h +3 -3
@@ -43,14 +43,14 @@ unsigned int x86_stepping(unsigned int s#ifdef CONFIG_CPU_SUP_INTEL extern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn); -extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern int handle_ac_split_lock (unsigned long ip);extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {} -static inline bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static int handle_ac_split_lock (unsigned long ip) { -return false; +return -ENOSYS ; }static inline void split_lock_validate_module_text (struct module *me,void *text,void *text_end) {}#endif
arch/x86/kernel/cpu/intel.c +13 -5
@@ -1102,13 +1102,20 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); } -bool handle_user_split_lock (struct pt_regs *regs,long error_code) +int handle_ac_split_lock (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) -return false; +switch (sld_state) { +case sld_warn: +break ; +case sld_off: +pr_warn_once ("#AC: Spurious trap at address: 0x%lx\n" , ip); +return -ENOSYS ; +case sld_fatal: +return -EFAULT ; + }pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);/* * Disable the split lock detection for this task so it can make
@@ -1117,8 +1124,9 @@ bool handle_user_split_lock(struct pt_re*/ sld_update_msr (false);set_tsk_thread_flag (current,TIF_SLD ); -return true; +return 0 ; } +EXPORT_SYMBOL_GPL (handle_ac_split_lock);/* * This function is called only when switching between tasks with
arch/x86/kernel/traps.c +1 -1
@@ -304,7 +304,7 @@ dotraplinkage void do_alignment_check(stlocal_irq_enable (); -if (handle_user_split_lock (regs, error_code)) +if (!(regs->flags &X86_EFLAGS_AC ) && !handle_ac_split_lock (regs->ip))return ; do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,
arch/x86/kvm/vmx/vmx.c +41 -3
74 lines not on this page · raw message
Re: [PATCH 2/3] x86/split_lock: Refactor and export handle_user_split_lock() for KVM
Quoted 16 lines · Thomas Gleixner
Quoted 15 lines · Sean Christopherson
Quoted 6 lines · Thomas Gleixner
Review
Quoted 4 lines
static inline void
__initcpu_set_core_cap_bits(struct cpuinfo_x86 *c){} static inline voidswitch_to_sld(unsigned long tifn){}(quoted diff) +1
-1-static inline bool handle_user_split_lock(struct pt_regs *regs, long error_code) +static inline bool handle_user_split_lock(unsigned long ip)This is necessary because VMX can be compiled without
CPU_SUP_INTEL?Ya, it came about when cleaning up the
IA32_FEATURE_CONTROLMSR handling to consolidate duplicate code.config
KVM_INTEL
tristate "KVM for Intel (and compatible) processors support" depends on KVM &&IA32_FEAT_CTL
Quoted 9 lines
Quoted 3 lines
config
IA32_FEAT_CTLdef_bool y depends on CPU_SUP_INTEL || CPU_SUP_CENTAUR || CPU_SUP_ZHAOXINAh, indeed. So something like the below would make sense. Hmm?
Of course that can be mangled into Xiaoyao's patches, I'm not worried about my patch count :)
I don't mind using yours in my next version.
Hi Paolo,
Are you OK with the kvm part below?
If no objection, I can spin the next version using tglx's.
Quoted 154 lines
8<----------------
arch/x86/include/asm/cpu.h +3
-3@@ -43,14 +43,14 @@ unsigned int x86_stepping(unsigned int s#ifdef CONFIG_CPU_SUP_INTEL extern void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c);extern void switch_to_sld (unsigned long tifn); -extern bool handle_user_split_lock (struct pt_regs *regs,long error_code); +extern int handle_ac_split_lock (unsigned long ip);extern void split_lock_validate_module_text (struct module *me,void *text,void *text_end);#else static inline void __init cpu_set_core_cap_bits (struct cpuinfo_x86 *c) {}static inline void switch_to_sld (unsigned long tifn) {} -static inline bool handle_user_split_lock (struct pt_regs *regs,long error_code) +static int handle_ac_split_lock (unsigned long ip) { -return false; +return -ENOSYS ; }static inline void split_lock_validate_module_text (struct module *me,void *text,void *text_end) {}#endif arch/x86/kernel/cpu/intel.c +13
-5@@ -1102,13 +1102,20 @@ static void split_lock_init(void)split_lock_verify_msr (sld_state != sld_off); } -bool handle_user_split_lock (struct pt_regs *regs,long error_code) +int handle_ac_split_lock (unsigned long ip) { -if ((regs->flags &X86_EFLAGS_AC ) || sld_state == sld_fatal) -return false; +switch (sld_state) { +case sld_warn: +break ; +case sld_off: +pr_warn_once ("#AC: Spurious trap at address: 0x%lx\n" , ip); +return -ENOSYS ; +case sld_fatal: +return -EFAULT ; + }pr_warn_ratelimited ("#AC: %s/%d took a split_lock trap at address: 0x%lx\n" , - current->comm, current->pid, regs->ip); + current->comm, current->pid, ip);/* * Disable the split lock detection for this task so it can make @@ -1117,8 +1124,9 @@ bool handle_user_split_lock(struct pt_re*/ sld_update_msr (false);set_tsk_thread_flag (current,TIF_SLD ); -return true; +return 0 ; } +EXPORT_SYMBOL_GPL (handle_ac_split_lock);/* * This function is called only when switching between tasks with arch/x86/kernel/traps.c +1
-1@@ -304,7 +304,7 @@ dotraplinkage void do_alignment_check(stlocal_irq_enable (); -if (handle_user_split_lock (regs, error_code)) +if (!(regs->flags &X86_EFLAGS_AC ) && !handle_ac_split_lock (regs->ip))return ; do_trap(X86_TRAP_AC, SIGBUS, "alignment check", regs,arch/x86/kvm/vmx/vmx.c +41
-3@@ -65,6 +65,7 @@MODULE_AUTHOR ("Qumranet" );MODULE_LICENSE ("GPL" ); +MODULE_INFO (sld_safe,"Y" );#ifdef MODULE static const struct x86_cpu_id vmx_cpu_id[] = {@@ -4623,6 +4624,22 @@ static int handle_machine_check(struct kreturn 1 ; } +static bool guest_handles_ac (struct kvm_vcpu *vcpu) +{ +/* +* If guest has alignment checking enabled in CR0 and activated in +* eflags, then the #AC originated from CPL3 and the guest is able +* to handle it. It does not matter whether this is a regular or +* a split lock operation induced #AC. +*/ +if (vmx_get_cpl (vcpu) ==3 &&kvm_read_cr0_bits (vcpu,X86_CR0_AM ) && +kvm_get_rflags (vcpu) &X86_EFLAGS_AC ) +return true; + +/* Add guest SLD handling checks here once it's supported */ +return false; +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -4630,6 +4647,7 @@ static int handle_exception_nmi(struct ku32 intr_info, ex_no, error_code;unsigned long cr2, rip, dr6;u32 vect_info; +int err; vect_info = vmx->idt_vectoring_info; intr_info = vmx->exit_intr_info;@@ -4688,9 +4706,6 @@ static int handle_exception_nmi(struct kreturn handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &@@ -4719,6 +4734,29 @@ static int handle_exception_nmi(struct k kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;break ; +case AC_VECTOR : +if (guest_handles_ac (vcpu)) { +kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); +return 1 ; + } +/* +* Handle #AC caused by split lock detection. If the host +* mode is sld_warn, then it warns, marks current with +* TIF_SLD and disables split lock detection. So the guest +* can just continue. +* +* If the host mode is fatal, the handling code warned. Let +* qemu kill itself. +* +* If the host mode is off, then this #AC is bonkers and +* something is badly wrong. Let it fail as well. +*/ + err =handle_ac_split_lock (kvm_rip_read (vcpu)); +if (!err) +return 1 ; +/* Propagate the error type to user space */ + error_code = err == -EFAULT ?0x100 :0x200 ; + fallthrough;default : kvm_run->exit_reason =KVM_EXIT_EXCEPTION ; kvm_run->ex.exception = ex_no;
Re: [PATCH 2/3] x86/split_lock: Refactor and export handle_user_split_lock() for KVM
Quoted 53 lines · Xiaoyao Li
+static bool
guest_handles_ac(struct kvm_vcpu *vcpu)arch/x86/kvm/vmx/vmx.c +15
-0+{ + /* + * If guest has alignment checking enabled in CR0 and activated in + * eflags, then the #AC originated from CPL3 and the guest is able + * to handle it. It does not matter whether this is a regular or + * a split lock operation induced #AC. + */ + if (vmx_get_cpl(vcpu) == 3 && kvm_read_cr0_bits(vcpu, X86_CR0_AM) && + kvm_get_rflags(vcpu) & X86_EFLAGS_AC) + return true; + + /* Add guest SLD handling checks here once it's supported */ + return false; +} +static int
handle_exception_nmi(struct kvm_vcpu *vcpu){
structvcpu_vmx*vmx =to_vmx(vcpu);arch/x86/kvm/vmx/vmx.c +1
-3@@ -4630,6 +4647,7 @@ static int handle_exception_nmi(struct k u32 intr_info, ex_no, error_code; unsigned long cr2, rip, dr6; u32 vect_info; + int err; vect_info = vmx->idt_vectoring_info; intr_info = vmx->exit_intr_info;@@ -4688,9 +4706,6 @@ static int handle_exception_nmi(struct k return handle_rmode_exception(vcpu, ex_no, error_code); switch (ex_no) { - case AC_VECTOR: - kvm_queue_exception_e(vcpu, AC_VECTOR, error_code); - return 1;case
DB_VECTOR:
dr6 =vmcs_readl(EXIT_QUALIFICATION);
if (!(vcpu->guest_debug &arch/x86/kvm/vmx/vmx.c +13
-0@@ -4719,6 +4734,29 @@ static int handle_exception_nmi(struct k kvm_run->debug.arch.pc = vmcs_readl(GUEST_CS_BASE) + rip; kvm_run->debug.arch.exception = ex_no; break; + case AC_VECTOR: + if (guest_handles_ac(vcpu)) { + kvm_queue_exception_e(vcpu, AC_VECTOR, error_code); + return 1; + } + /* +* Handle #AC caused by split lock detection. If the host +* mode is sld_warn, then it warns, marks current with +* TIF_SLD and disables split lock detection. So the guest +* can just continue. +* +* If the host mode is fatal, the handling code warned. Let +* qemu kill itself.
arch/x86/kvm/vmx/vmx.c static int handle_exception_nmi(struct k · line 4759
Quoted 10 lines
arch/x86/kvm/vmx/vmx.c +10
-0+* +* If the host mode is off, then this #AC is bonkers and +* something is badly wrong. Let it fail as well. +*/ + err = handle_ac_split_lock(kvm_rip_read(vcpu)); + if (!err) + return 1; + /* Propagate the error type to user space */ + error_code = err == -EFAULT ? 0x100 : 0x200; + fallthrough;
PATCH 3/3 KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
In reply to Sean ChristophersonFrom: Xiaoyao Li <[email protected]>
Two types #AC can be generated in Intel CPUs:
1. legacy alignment check #AC
2. split lock #AC
Reflect #AC back into the guest if the guest has legacy alignment checks enabled or if SLD is disabled. If SLD is enabled, treat the guest like a host userspace application by calling handle_user_split_lock(). If the #AC is handled (SLD disabled and TIF_SLD set), then simply resume the guest. If the #AC isn't handled, i.e. host is sld_fatal, then forward the #AC to the userspace VMM, similar to sending SIGBUS.
--- arch/x86/kvm/vmx/vmx.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
arch/x86/kvm/vmx/vmx.c +27 -3
@@ -4623,6 +4623,12 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)return 1 ; } +static inline bool guest_cpu_alignment_check_enabled (struct kvm_vcpu *vcpu) +{ +return vmx_get_cpl (vcpu) ==3 &&kvm_read_cr0_bits (vcpu,X86_CR0_AM ) && + (kvm_get_rflags (vcpu) &X86_EFLAGS_AC ); +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);
@@ -4688,9 +4694,6 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)return handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &
@@ -4719,6 +4722,27 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;break ; +case AC_VECTOR : +/* +* Reflect #AC to the guest if it's expecting the #AC, i.e. has +* legacy alignment check enabled. Pre-check host split lock +* turned on to avoid the VMREADs needed to check legacy #AC, +* i.e. reflect the #AC if the only possible source is legacy +* alignment checks. +*/ +if (!boot_cpu_has (X86_FEATURE_SPLIT_LOCK_DETECT ) || +guest_cpu_alignment_check_enabled (vcpu)) { +kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); +return 1 ; + } + +/* +* Forward the #AC to userspace if kernel policy does not allow +* temporarily disabling split lock detection. +*/ +if (handle_user_split_lock (kvm_rip_read (vcpu))) +return 1 ; + fallthrough;default : kvm_run->exit_reason =KVM_EXIT_EXCEPTION ; kvm_run->ex.exception = ex_no;
Signature · 1 line
2.24.1
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct kvm_vcpu *vcpu) · line 4626
Quoted 5 lines · Sean Christopherson
arch/x86/kvm/vmx/vmx.c +1
-0@@ -4623,6 +4623,12 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)return 1 ; } +static inline bool guest_cpu_alignment_check_enabled (struct kvm_vcpu *vcpu)
I used a different function name intentionally so the check for 'guest want's split lock #AC' can go there as well once it's sorted.
Quoted 21 lines
arch/x86/kvm/vmx/vmx.c +5
-3+{ +return vmx_get_cpl (vcpu) ==3 &&kvm_read_cr0_bits (vcpu,X86_CR0_AM ) && + (kvm_get_rflags (vcpu) &X86_EFLAGS_AC ); +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -4688,9 +4694,6 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)return handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &@@ -4719,6 +4722,27 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;
arch/x86/kvm/vmx/vmx.c static int handle_exception_nmi(struct kvm_vcpu *vcpu) · line 4733
Quoted 10 lines
arch/x86/kvm/vmx/vmx.c +9
-0break ; +case AC_VECTOR : +/* +* Reflect #AC to the guest if it's expecting the #AC, i.e. has +* legacy alignment check enabled. Pre-check host split lock +* turned on to avoid the VMREADs needed to check legacy #AC, +* i.e. reflect the #AC if the only possible source is legacy +* alignment checks. +*/ + if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ||
I think the right thing to do here is to make this really independent of that feature, i.e. inject the exception if
(CPL==3 && CR0.AM && EFLAGS.AC) || (FUTURE && (GUEST_TEST_CTRL & SLD))
iow. when its really clear that the guest asked for it. If there is an actual #AC with SLD disabled and !(CPL==3 && CR0.AM && EFLAGS.AC) then something is badly wrong and the thing should just die. That's why I separated handle_guest_split_lock() and tell about that case.
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 9 lines · Thomas Gleixner
arch/x86/kvm/vmx/vmx.c static int handle_machine_check(struct kvm_vcpu *vcpu) · line 4626
Quoted 5 lines · Sean Christopherson
arch/x86/kvm/vmx/vmx.c +1
-0@@ -4623,6 +4623,12 @@ static int handle_machine_check(struct kvm_vcpu *vcpu)return 1 ; } +static inline bool guest_cpu_alignment_check_enabled (struct kvm_vcpu *vcpu)I used a different function name intentionally so the check for 'guest want's split lock #AC' can go there as well once it's sorted.
Heh, IIRC, I advised Xiaoyao to do the opposite so that the injection logic in the #AC case statement was more or less complete without having to dive into the helper, e.g. the resulting code looks like this once split-lock is exposed to the guest:
if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ||
guest_cpu_alignment_check_enabled(vcpu) ||
guest_cpu_sld_on(vmx)) {
kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
return 1;
}Quoted 35 lines
Quoted 21 lines
arch/x86/kvm/vmx/vmx.c +5
-3+{ +return vmx_get_cpl (vcpu) ==3 &&kvm_read_cr0_bits (vcpu,X86_CR0_AM ) && + (kvm_get_rflags (vcpu) &X86_EFLAGS_AC ); +} +static int handle_exception_nmi (struct kvm_vcpu *vcpu) {struct vcpu_vmx *vmx =to_vmx (vcpu);@@ -4688,9 +4694,6 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)return handle_rmode_exception (vcpu, ex_no, error_code);switch (ex_no) { -case AC_VECTOR : -kvm_queue_exception_e (vcpu,AC_VECTOR , error_code); -return 1 ;case DB_VECTOR : dr6 =vmcs_readl (EXIT_QUALIFICATION ); if (!(vcpu->guest_debug &@@ -4719,6 +4722,27 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) kvm_run->debug.arch.pc =vmcs_readl (GUEST_CS_BASE ) + rip; kvm_run->debug.arch.exception = ex_no;arch/x86/kvm/vmx/vmx.c static int handle_exception_nmi(struct kvm_vcpu *vcpu) · line 4733
Quoted 10 lines
arch/x86/kvm/vmx/vmx.c +9
-0break ; +case AC_VECTOR : +/* +* Reflect #AC to the guest if it's expecting the #AC, i.e. has +* legacy alignment check enabled. Pre-check host split lock +* turned on to avoid the VMREADs needed to check legacy #AC, +* i.e. reflect the #AC if the only possible source is legacy +* alignment checks. +*/ + if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ||I think the right thing to do here is to make this really independent of that feature, i.e. inject the exception if
Quoted 6 lines
(CPL==3 && CR0.AM && EFLAGS.AC) || (FUTURE && (
GUEST_TEST_CTRL& SLD))iow. when its really clear that the guest asked for it. If there is an actual #AC with SLD disabled and !(CPL==3 && CR0.AM && EFLAGS.AC) then something is badly wrong and the thing should just die. That's why I separated
handle_guest_split_lock()and tell about that case.
That puts KVM in a weird spot if/when intercepting #AC is no longer necessary, e.g. "if" future CPUs happen to gain a feature that traps into the hypervisor (KVM) if a potential near-infinite ucode loop is detected.
The only reason KVM intercepts #AC (before split-lock) is to prevent a malicious guest from executing a DoS attack on the host by putting the #AC handler in ring 3. Current CPUs will get stuck in ucode vectoring #AC faults more or less indefinitely, e.g. long enough to trigger watchdogs in the host.
Injecting #AC if and only if KVM is 100% certain the guest wants the #AC would lead to divergent behavior if KVM chose to not intercept #AC, e.g. some theoretical unknown #AC source would conditionally result in exits to userspace depending on whether or not KVM wanted to intercept #AC for other reasons.
That's why we went with the approach of reflecting #AC unless KVM detected that the #AC was host-induced.
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Sean,
Quoted 26 lines · Sean Christopherson
Quoted 14 lines · Thomas Gleixner
arch/x86/kvm/vmx/vmx.c static int handle_exception_nmi(struct kvm_vcpu *vcpu) · line 4733
Quoted 9 lines · Sean Christopherson
arch/x86/kvm/vmx/vmx.c +9
-0+case AC_VECTOR : +/* +* Reflect #AC to the guest if it's expecting the #AC, i.e. has +* legacy alignment check enabled. Pre-check host split lock +* turned on to avoid the VMREADs needed to check legacy #AC, +* i.e. reflect the #AC if the only possible source is legacy +* alignment checks. +*/ + if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT) ||I think the right thing to do here is to make this really independent of that feature, i.e. inject the exception if
Quoted 6 lines
(CPL==3 && CR0.AM && EFLAGS.AC) || (FUTURE && (
GUEST_TEST_CTRL& SLD))iow. when its really clear that the guest asked for it. If there is an actual #AC with SLD disabled and !(CPL==3 && CR0.AM && EFLAGS.AC) then something is badly wrong and the thing should just die. That's why I separated
handle_guest_split_lock()and tell about that case.That puts KVM in a weird spot if/when intercepting #AC is no longer necessary, e.g. "if" future CPUs happen to gain a feature that traps into the hypervisor (KVM) if a potential near-infinite ucode loop is detected.
Quoted 5 lines
The only reason KVM intercepts #AC (before split-lock) is to prevent a malicious guest from executing a DoS attack on the host by putting the #AC handler in ring 3. Current CPUs will get stuck in ucode vectoring #AC faults more or less indefinitely, e.g. long enough to trigger watchdogs in the host.
Which is thankfully well documented in the VMX code and the corresponding chapter in the SDM.
Quoted 2 lines
Injecting #AC if and only if KVM is 100% certain the guest wants the #AC would lead to divergent behavior if KVM chose to not intercept #AC, e.g.
AFAICT, #AC is not really something which is performance relevant, but I might obviously be uninformed on that.
Assumed it is not, then there is neither a hard requirement nor a real incentive to give up on intercepting #AC even when future CPUs have a fix for the above wreckage.
Quoted 3 lines
some theoretical unknown #AC source would conditionally result in exits to userspace depending on whether or not KVM wanted to intercept #AC for other reasons.
I'd rather like to know when there is an unknown #AC source instead of letting the guest silently swallow it.
TBH, the more I learn about this, the more I tend to just give up on this whole split lock stuff in its current form and wait until HW folks provide something which is actually usable:
- Per thread
- Properly distinguishable from a regular #AC via error code
OTOH, that means I won't be able to use it before retirement. Oh well.
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines
TBH, the more I learn about this, the more I tend to just give up on this whole split lock stuff in its current form and wait until HW folks provide something which is actually usable:
- Per thread
- Properly distinguishable from a regular #AC via error code
Why the latter? I would argue that #AC from CPL3 with EFLAGS.AC set is almost by construction not a split lock. In particular, if you meet these conditions, how exactly can you do a split lock without simultaneously triggering an alignment check? (Maybe CMPXCHG16B?
Quoted 6 lines
OTOH, that means I won't be able to use it before retirement. Oh well.
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
In reply to Thomas GleixnerOn Thu, Apr 02, 2020 at 10:07:07PM +0200, Thomas Gleixner wrote:
If we're doing wish lists, I have one more ;-)
Quoted 6 lines
TBH, the more I learn about this, the more I tend to just give up on this whole split lock stuff in its current form and wait until HW folks provide something which is actually usable:
- Per thread
- Properly distinguishable from a regular #AC via error code
- is an actual alignment check.
That is, disallow all unaligned LOCK prefixed ops, not just those that happen to straddle a cacheline.
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
In reply to Thomas GleixnerQuoted 19 lines · Thomas Gleixner
Quoted 11 lines · Sean Christopherson
Quoted 1 line · Thomas Gleixner
Sean Christopherson <[email protected]> writes:
That puts KVM in a weird spot if/when intercepting #AC is no longer necessary, e.g. "if" future CPUs happen to gain a feature that traps into the hypervisor (KVM) if a potential near-infinite ucode loop is detected.
The only reason KVM intercepts #AC (before split-lock) is to prevent a malicious guest from executing a DoS attack on the host by putting the #AC handler in ring 3. Current CPUs will get stuck in ucode vectoring #AC faults more or less indefinitely, e.g. long enough to trigger watchdogs in the host.
Which is thankfully well documented in the VMX code and the corresponding chapter in the SDM.
Quoted 2 lines
Injecting #AC if and only if KVM is 100% certain the guest wants the #AC would lead to divergent behavior if KVM chose to not intercept #AC, e.g.
Quoted 6 lines
AFAICT, #AC is not really something which is performance relevant, but I might obviously be uninformed on that.
Assumed it is not, then there is neither a hard requirement nor a real incentive to give up on intercepting #AC even when future CPUs have a fix for the above wreckage.
Agreed that there's no hard requirement, but general speaking, the less KVM needs to poke into the guest the better.
Quoted 6 lines
Quoted 3 lines
some theoretical unknown #AC source would conditionally result in exits to userspace depending on whether or not KVM wanted to intercept #AC for other reasons.
I'd rather like to know when there is an unknown #AC source instead of letting the guest silently swallow it.
Trying to prevent the guest from squashing a spurious fault is a fools
errand. For example, with nested virtualization, the correct behavior
from an architectural perspective is to forward exceptions from L2 (the nested VM) to L1 (the direct VM) that L1 wants to intercept. E.g. if L1 wants to intercept #AC faults that happen in L2, then KVM reflects all #AC faults into L1 as VM-Exits without ever reaching this code.
Nested virt aside, detecting spurious #AC and a few other exceptions is mostly feasible, but for many exceptions it's flat out impossible.
Anyways, this particular case isn't a sticking point, i.e. I'd be ok with exiting to userspace on a spurious #AC, I just don't see the value in doing so. Returning KVM_EXIT_EXCEPTION doesn't necessarily equate to throwing up a red flag, e.g. from a kernel perspective you'd still be relying on the userspace VMM to report the error in a sane manner. I think at one point Xiaoyao had a WARN_ON for a spurious #AC, but it was removed because the odds of a false positive due to some funky corner case seemed higher than detecting a CPU bug.
Quoted 12 lines
TBH, the more I learn about this, the more I tend to just give up on this whole split lock stuff in its current form and wait until HW folks provide something which is actually usable:
- Per thread
- Properly distinguishable from a regular #AC via error codeOTOH, that means I won't be able to use it before retirement. Oh well.
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Sean,
Quoted 11 lines · Sean Christopherson
Quoted 7 lines · Thomas Gleixner
Sean Christopherson <[email protected]> writes:
AFAICT, #AC is not really something which is performance relevant, but I might obviously be uninformed on that.Assumed it is not, then there is neither a hard requirement nor a real incentive to give up on intercepting #AC even when future CPUs have a fix for the above wreckage.
Agreed that there's no hard requirement, but general speaking, the less KVM needs to poke into the guest the better.
Fair enough.
Quoted 7 lines
Quoted 6 lines
Quoted 3 lines
some theoretical unknown #AC source would conditionally result in exits to userspace depending on whether or not KVM wanted to intercept #AC for other reasons.
I'd rather like to know when there is an unknown #AC source instead of letting the guest silently swallow it.
Quoted 6 lines
Trying to prevent the guest from squashing a spurious fault is a fools
errand. For example, with nested virtualization, the correct behavior
from an architectural perspective is to forward exceptions from L2 (the nested VM) to L1 (the direct VM) that L1 wants to intercept. E.g. if L1 wants to intercept #AC faults that happen in L2, then KVM reflects all #AC faults into L1 as VM-Exits without ever reaching this code.
Which means L1 should have some handling for that case at least those L1 hypervisors which we can fix. If we want to go there.
Quoted 8 lines
Anyways, this particular case isn't a sticking point, i.e. I'd be ok with exiting to userspace on a spurious #AC, I just don't see the value in doing so. Returning
KVM_EXIT_EXCEPTIONdoesn't necessarily equate to throwing up a red flag, e.g. from a kernel perspective you'd still be relying on the userspace VMM to report the error in a sane manner. I think at one point Xiaoyao had aWARN_ONfor a spurious #AC, but it was removed because the odds of a false positive due to some funky corner case seemed higher than detecting a CPU bug.
Agreed. Relying on the user space side to crash and burn the guest is probably wishful thinking. So the right thing might be to just kill it right at the spot.
But coming back to the above discussion:
if (!cpu_has(SLD) || guest_wants_regular_ac()) {
kvm_queue_exception_e();
return 1;
}vs.
if (guest_wants_regular_ac()) {
kvm_queue_exception_e();
return 1;
}The only situation where this makes a difference is when the CPU does not support SLD. If it does the thing became ambiguous today.
With my previous attempt to bring sanity into this by not setting the feature flag when SLD is disabled at the command line, the check is consistent.
But the detection of unaware hypervisors with the module scan brings us into a situation where we have sld_state == sld_off and the feature flag being set because we can't undo it anymore.
So now you load VMWare which disables SLD, but the feature bit stays and then when you unload it and load VMX afterwards then you have exactly the same situation as with the feature check removed. Consistency gone.
So with that we might want to go back to the sld_state check instead of the cpu feature check, but that does not make it more consistent:
As I just verified, it's possible to load the vmware module parallel to the KVM/VMX one.
So either we deal with it in some way or just decide that SLD and HV modules which do not have the MOD_INFO(sld_safe) magic cannot be loaded when SLD is enabled on the host. I'm fine with the latter :)
What a mess.
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 10 lines · Thomas Gleixner
As I just verified, it's possible to load the vmware module parallel to the KVM/VMX one.
So either we deal with it in some way or just decide that SLD and HV modules which do not have the
MOD_INFO(sld_safe)magic cannot be loaded when SLD is enabled on the host. I'm fine with the latter :)What a mess.
[ +Doug ]
Just to communicate the information that was given to me: we do intend to fix the SLD issue in VMware and if needed to release a minor version that addresses it. Having said that, there are other hypervisors, such as virtualbox or jailhouse, which would have a similar issue.
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 4 lines · Nadav Amit
Just to communicate the information that was given to me: we do intend to fix the SLD issue in VMware and if needed to release a minor version that addresses it. Having said that, there are other hypervisors, such as virtualbox or jailhouse, which would have a similar issue.
I'm well aware of that and even if VMWare fixes this, this still will trip up users which fail to install updates for one reason or the other and leave them puzzled. Maybe we just should not care at all.
Despite that I might have mentioned it before: What a mess ...
Thanks,
tglx
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
In reply to Nadav AmitQuoted 9 lines · On Thu, 2 Apr 2020 22:40:03 +0000 Nadav Amit <[email protected]> wrote:
Quoted 9 lines · Thomas Gleixner
As I just verified, it's possible to load the vmware module parallel to the KVM/VMX one.
So either we deal with it in some way or just decide that SLD and HV modules which do not have the
MOD_INFO(sld_safe)magic cannot be loaded when SLD is enabled on the host. I'm fine with the latter :)
Quoted 8 lines
Quoted 1 line
What a mess.
[ +Doug ]
Just to communicate the information that was given to me: we do intend to fix the SLD issue in VMware and if needed to release a minor version that addresses it. Having said that, there are other hypervisors, such as virtualbox or jailhouse, which would have a similar issue.
If we go the approach of not letting VM modules load if it doesn't have the sld_safe flag set, how is this different than a VM module not loading due to kabi breakage?
If we prevent it from loading (and keeping from having to go into this inconsistent state that Thomas described), it would encourage people to get the latest modules, and the maintainers of said modules motivation to update them.
-- Steve
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 3 lines · Steven Rostedt
If we go the approach of not letting VM modules load if it doesn't have the
sld_safeflag set, how is this different than a VM module not loading due to kabi breakage?
Why not a compromise: if such a module is attempted to be loaded, print up a message saying something akin to "turn the parameter 'split_lock_detect' off" as we reject loading it- and if we see that we've booted with it off just splat a WARN_ON() if someone tries to load such modules?
-Kenny
Signature · 1 line
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Silicon Valley
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Quoted 4 lines · Kenneth R. Crudup
On Thu, 2 Apr 2020, Steven Rostedt wrote:
Quoted 8 lines
Quoted 3 lines
If we go the approach of not letting VM modules load if it doesn't have the
sld_safeflag set, how is this different than a VM module not loading due to kabi breakage?Why not a compromise: if such a module is attempted to be loaded, print up a message saying something akin to "turn the parameter '
split_lock_detect' off" as we reject loading it- and if we see that we've booted with it off just splat aWARN_ON()if someone tries to load such modules?
What modules are we talking about? I thought we were discussing L1 hypervisors, which are just binary blobs. The only modules at the L0 level are kvm and kvm_intel.
Re: [PATCH 3/3] KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in guest
Jim,
Quoted 7 lines · Jim Mattson
Quoted 6 lines · Kenneth R. Crudup
Quoted 3 lines · Steven Rostedt
If we go the approach of not letting VM modules load if it doesn't have the
sld_safeflag set, how is this different than a VM module not loading due to kabi breakage?
Quoted 8 lines
Quoted 4 lines
Why not a compromise: if such a module is attempted to be loaded, print up a message saying something akin to "turn the parameter '
split_lock_detect' off" as we reject loading it- and if we see that we've booted with it off just splat aWARN_ON()if someone tries to load such modules?What modules are we talking about? I thought we were discussing L1 hypervisors, which are just binary blobs. The only modules at the L0 level are kvm and
kvm_intel.
Maybe in your world, but VmWare (which got this started), VirtualBox, Jailhouse and who knows what else _are_ L0 hypervisors. Otherwise we wouldn't have that conversation at all.
Thanks,
tglx
Paolo Bonzini
maintainerRe: [PATCH 0/3] x86: KVM: VMX: Add basic split-lock #AC handling
In reply to Sean ChristophersonQuoted 8 lines · Sean Christopherson
First three patches from Xiaoyao's series to add split-lock #AC support in KVM.
Xiaoyao Li (3):
KVM: x86: Emulate split-lock access as a write in emulator x86/split_lock: Refactor and exporthandle_user_split_lock()for KVM
KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in
guest
Sorry I was out of the loop on this (I'm working part time and it's a mess). Sean, can you send the patches as a top-level message? I'll queue them and get them to Linus over the weekend.
Paolo
Re: [PATCH 0/3] x86: KVM: VMX: Add basic split-lock #AC handling
Quoted 10 lines · Paolo Bonzini
Quoted 8 lines · Sean Christopherson
First three patches from Xiaoyao's series to add split-lock #AC support in KVM.
Xiaoyao Li (3):
KVM: x86: Emulate split-lock access as a write in emulator x86/split_lock: Refactor and exporthandle_user_split_lock()for KVM
KVM: VMX: Extend VMX's #AC interceptor to handle split lock #AC in
guest
Quoted 3 lines
Sorry I was out of the loop on this (I'm working part time and it's a mess). Sean, can you send the patches as a top-level message? I'll queue them and get them to Linus over the weekend.
I have a reworked version. I'll post it after lunch.
Thanks,
tglx
Quoted 2 lines · Thomas Gleixner
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
I just applied both of these patches to my (Linus' tip) tree, and unfortunately VMWare still hangs if split_lock_detect= is set to anything but "off".
Was there anything else I'd needed to do?
-Kenny
Signature · 1 line
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Silicon Valley
Quoted 10 lines · Kenneth R. Crudup
Quoted 2 lines · Thomas Gleixner
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
I just applied both of these patches to my (Linus' tip) tree, and unfortunately VMWare still hangs if split_lock_detect= is set to anything but "off".
Was there anything else I'd needed to do?
Hmm, you're not seeing this:
+ pr_warn("disabled due to VMLAUNCH in module: %s\n", me->name);
fire when you load the vmware kernel module? Could you slip me a copy of that thing by private mail?
Quoted 3 lines · Peter Zijlstra
Hmm, you're not seeing this:
+pr_warn("disabled due to VMLAUNCH in module: %s\n", me->name);
fire when you load the vmware kernel module?
I just looked back at the syslog's copy of the kernel messages at the time I'd tried it, and no, I don't see that message.
Quoted 1 line
Could you slip me a copy of that thing by private mail?
OK, gimme a couple of days though, I've gotta get a little work done. (Also, what "thing" exactly did you want?)
-Kenny
Signature · 1 line
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Silicon Valley
Quoted 9 lines · Kenneth R. Crudup
Quoted 3 lines · Peter Zijlstra
Hmm, you're not seeing this:
+pr_warn("disabled due to VMLAUNCH in module: %s\n", me->name);
fire when you load the vmware kernel module?I just looked back at the syslog's copy of the kernel messages at the time I'd tried it, and no, I don't see that message.
Dang!
Quoted 4 lines
Quoted 1 line
Could you slip me a copy of that thing by private mail?
OK, gimme a couple of days though, I've gotta get a little work done. (Also, what "thing" exactly did you want?)
All the .ko files that come with vmware. I want to dig through them to see why the VMLAUNCH detection thing isn't working.
Quoted 2 lines
Quoted 2 lines
(Also, what "thing" exactly did you want?)
Quoted 1 line · Peter Zijlstra
All the .ko files that come with vmware.
Ah, gotcha. One thing you/VMWare may want to look at is it turns out that "vmw_vmci", part of the kernel tree (CONFIG_VMWARE_VMCI) has to be compiled into the kernel as a module so udev can properly create the Misc device node (I'd tried making it a built-in and messing with udev rules and the other, compiled-in-later VMWare module loading system didn't seem to like that).
Maybe some sort of mitigation for this can be done there, putting it back in-tree?
But anyway, I'll send you a .tar.bz2 in a little bit.
-Kenny
Signature · 1 line
Kenneth R. Crudup Sr. SW Engineer, Scott County Consulting, Silicon Valley
Quoted 9 lines · Kenneth R. Crudup
Quoted 2 lines · Thomas Gleixner
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
I just applied both of these patches to my (Linus' tip) tree, and unfortunately VMWare still hangs if split_lock_detect= is set to anything but "off".
Was there anything else I'd needed to do?
Hmm. Not really. Does dmesg show the warning when the VMWare module loads? Something like:
x86/split lock detection: disabled due to VMLAUNCH in module: ....
Thanks,
tglx
Quoted 12 lines · Thomas Gleixner
Quoted 8 lines · Kenneth R. Crudup
Quoted 2 lines · Thomas Gleixner
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
I just applied both of these patches to my (Linus' tip) tree, and unfortunately VMWare still hangs if split_lock_detect= is set to anything but "off".
Quoted 6 lines
Quoted 1 line
Was there anything else I'd needed to do?
Hmm. Not really. Does dmesg show the warning when the VMWare module loads? Something like:
x86/split lock detection: disabled due to VMLAUNCH in module: ….
I ran an objdump on VMware workstation and indeed I do not see a VMLAUNCH/VMRESUME. I do see however VMXON which should also be good for detecting hypervisors. I will try to understand why VMLAUNCH is not there.
Quoted 14 lines · Nadav Amit
Quoted 14 lines · Thomas Gleixner
Quoted 9 lines · Kenneth R. Crudup
Quoted 2 lines · Thomas Gleixner
As Peter and myself don't have access to a SLD enabled machine, the KVM/VMX part is untested. The module scan part works.
I just applied both of these patches to my (Linus' tip) tree, and unfortunately VMWare still hangs if split_lock_detect= is set to anything but "off".
Was there anything else I'd needed to do?
Quoted 8 lines
Quoted 4 lines
Hmm. Not really. Does dmesg show the warning when the VMWare module loads? Something like:
x86/split lock detection: disabled due to VMLAUNCH in module: ….
I ran an objdump on VMware workstation and indeed I do not see a VMLAUNCH/VMRESUME. I do see however VMXON which should also be good for detecting hypervisors. I will try to understand why VMLAUNCH is not there.
Let me send a version with VMXON detection added in as well.