vmx_check_intercept is not yet fully implemented. To avoid emulating instructions disallowed by the L1 hypervisor, refuse to emulate instructions by default.
Cc: stable@vger.kernel.org [Made commit, added commit msg - Oliver] Signed-off-by: Oliver Upton oupton@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com --- arch/x86/kvm/vmx/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index dcca514ffd42..5801a86f9c24 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7164,7 +7164,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, }
/* TODO: check more intercepts... */ - return X86EMUL_CONTINUE; + return X86EMUL_UNHANDLEABLE; }
#ifdef CONFIG_X86_64
On 24.02.20 19:56, Paolo Bonzini wrote:
vmx_check_intercept is not yet fully implemented. To avoid emulating instructions disallowed by the L1 hypervisor, refuse to emulate instructions by default.
Cc: stable@vger.kernel.org [Made commit, added commit msg - Oliver] Signed-off-by: Oliver Upton oupton@google.com Signed-off-by: Paolo Bonzini pbonzini@redhat.com
arch/x86/kvm/vmx/vmx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index dcca514ffd42..5801a86f9c24 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7164,7 +7164,7 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, }
/* TODO: check more intercepts... */
- return X86EMUL_CONTINUE;
return X86EMUL_UNHANDLEABLE; }
#ifdef CONFIG_X86_64
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
Jan
Hi Jan,
On Sat, Feb 29, 2020 at 10:00 AM Jan Kiszka jan.kiszka@web.de wrote:
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
I'm guessing that Jailhouse doesn't use 'descriptor table exiting', so when KVM gets the corresponding exit from L2 the emulation burden is on L0. We now refuse the emulation, which kicks a #UD back to L2. I can get a patch out quickly to address this case (like the PIO exiting one that came in this series) but the eventual solution is to map emulator intercept checks into VM-exits + call into the nested_vmx_exit_reflected() plumbing.
-- Thanks, Oliver
On Sat, Feb 29, 2020 at 10:33 AM Oliver Upton oupton@google.com wrote:
Hi Jan,
On Sat, Feb 29, 2020 at 10:00 AM Jan Kiszka jan.kiszka@web.de wrote:
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
I'm guessing that Jailhouse doesn't use 'descriptor table exiting', so when KVM gets the corresponding exit from L2 the emulation burden is on L0. We now refuse the emulation, which kicks a #UD back to L2. I can get a patch out quickly to address this case (like the PIO exiting one that came in this series) but the eventual solution is to map emulator intercept checks into VM-exits + call into the nested_vmx_exit_reflected() plumbing.
If Jailhouse doesn't use descriptor table exiting, why is L0 intercepting descriptor table instructions? Is this just so that L0 can partially emulate UMIP on hardware that doesn't support it?
On 29.02.20 20:00, Jim Mattson wrote:
On Sat, Feb 29, 2020 at 10:33 AM Oliver Upton oupton@google.com wrote:
Hi Jan,
On Sat, Feb 29, 2020 at 10:00 AM Jan Kiszka jan.kiszka@web.de wrote:
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
I'm guessing that Jailhouse doesn't use 'descriptor table exiting', so when KVM gets the corresponding exit from L2 the emulation burden is on L0. We now refuse the emulation, which kicks a #UD back to L2. I can get a patch out quickly to address this case (like the PIO exiting one that came in this series) but the eventual solution is to map emulator intercept checks into VM-exits + call into the nested_vmx_exit_reflected() plumbing.
If Jailhouse doesn't use descriptor table exiting, why is L0 intercepting descriptor table instructions? Is this just so that L0 can partially emulate UMIP on hardware that doesn't support it?
That seems to be the case: My host lacks umip, L1 has it. So, KVM is intercepting descriptor table load instructions to emulate umip. Jailhouse never activates that interception.
Jan
KVM emulates UMIP on hardware that doesn't support it by setting the 'descriptor table exiting' VM-execution control and performing instruction emulation. When running nested, this emulation is broken as KVM refuses to emulate L2 instructions by default.
Correct this regression by allowing the emulation of descriptor table instructions if L1 hasn't requested 'descriptor table exiting'.
Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode") Reported-by: Jan Kiszka jan.kiszka@web.de Cc: stable@vger.kernel.org Cc: Paolo Bonzini pbonzini@redhat.com Cc: Jim Mattson jmattson@google.com Signed-off-by: Oliver Upton oupton@google.com --- arch/x86/kvm/vmx/vmx.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 63aaf44edd1f..e718b4c9455f 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7204,6 +7204,17 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, case x86_intercept_outs: return vmx_check_intercept_io(vcpu, info);
+ case x86_intercept_lgdt: + case x86_intercept_lidt: + case x86_intercept_lldt: + case x86_intercept_ltr: + case x86_intercept_sgdt: + case x86_intercept_sidt: + case x86_intercept_sldt: + case x86_intercept_str: + if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC)) + return X86EMUL_CONTINUE; + /* TODO: check more intercepts... */ default: break;
On 29/02/20 20:30, Oliver Upton wrote:
KVM emulates UMIP on hardware that doesn't support it by setting the 'descriptor table exiting' VM-execution control and performing instruction emulation. When running nested, this emulation is broken as KVM refuses to emulate L2 instructions by default.
Correct this regression by allowing the emulation of descriptor table instructions if L1 hasn't requested 'descriptor table exiting'.
Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode") Reported-by: Jan Kiszka jan.kiszka@web.de Cc: stable@vger.kernel.org Cc: Paolo Bonzini pbonzini@redhat.com Cc: Jim Mattson jmattson@google.com Signed-off-by: Oliver Upton oupton@google.com
arch/x86/kvm/vmx/vmx.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 63aaf44edd1f..e718b4c9455f 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7204,6 +7204,17 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu, case x86_intercept_outs: return vmx_check_intercept_io(vcpu, info);
- case x86_intercept_lgdt:
- case x86_intercept_lidt:
- case x86_intercept_lldt:
- case x86_intercept_ltr:
- case x86_intercept_sgdt:
- case x86_intercept_sidt:
- case x86_intercept_sldt:
- case x86_intercept_str:
if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
return X86EMUL_CONTINUE;
- /* TODO: check more intercepts... */ default: break;
Queued, thanks.
Paolo
Since UMIP emulation is broken, I'm not sure why anyone would use it. (Sorry, Paolo.)
On Sat, Feb 29, 2020 at 11:21 AM Jan Kiszka jan.kiszka@web.de wrote:
On 29.02.20 20:00, Jim Mattson wrote:
On Sat, Feb 29, 2020 at 10:33 AM Oliver Upton oupton@google.com wrote:
Hi Jan,
On Sat, Feb 29, 2020 at 10:00 AM Jan Kiszka jan.kiszka@web.de wrote:
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
I'm guessing that Jailhouse doesn't use 'descriptor table exiting', so when KVM gets the corresponding exit from L2 the emulation burden is on L0. We now refuse the emulation, which kicks a #UD back to L2. I can get a patch out quickly to address this case (like the PIO exiting one that came in this series) but the eventual solution is to map emulator intercept checks into VM-exits + call into the nested_vmx_exit_reflected() plumbing.
If Jailhouse doesn't use descriptor table exiting, why is L0 intercepting descriptor table instructions? Is this just so that L0 can partially emulate UMIP on hardware that doesn't support it?
That seems to be the case: My host lacks umip, L1 has it. So, KVM is intercepting descriptor table load instructions to emulate umip. Jailhouse never activates that interception.
Jan
On 29.02.20 21:17, Jim Mattson wrote:
Since UMIP emulation is broken, I'm not sure why anyone would use it. (Sorry, Paolo.)
FWIW, adding "-umip" to the "-cpu host" in my qemu setup works around the bug.
Jan
On Sat, Feb 29, 2020 at 11:21 AM Jan Kiszka jan.kiszka@web.de wrote:
On 29.02.20 20:00, Jim Mattson wrote:
On Sat, Feb 29, 2020 at 10:33 AM Oliver Upton oupton@google.com wrote:
Hi Jan,
On Sat, Feb 29, 2020 at 10:00 AM Jan Kiszka jan.kiszka@web.de wrote:
Is this expected to cause regressions on less common workloads? Jailhouse as L1 now fails when Linux as L2 tries to boot a CPU: L2-Linux gets a triple fault on load_current_idt() in start_secondary(). Only bisected so far, didn't debug further.
I'm guessing that Jailhouse doesn't use 'descriptor table exiting', so when KVM gets the corresponding exit from L2 the emulation burden is on L0. We now refuse the emulation, which kicks a #UD back to L2. I can get a patch out quickly to address this case (like the PIO exiting one that came in this series) but the eventual solution is to map emulator intercept checks into VM-exits + call into the nested_vmx_exit_reflected() plumbing.
If Jailhouse doesn't use descriptor table exiting, why is L0 intercepting descriptor table instructions? Is this just so that L0 can partially emulate UMIP on hardware that doesn't support it?
That seems to be the case: My host lacks umip, L1 has it. So, KVM is intercepting descriptor table load instructions to emulate umip. Jailhouse never activates that interception.
Jan
linux-stable-mirror@lists.linaro.org