* [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2
@ 2017-11-05 16:15 Liran Alon
2017-11-06 9:27 ` Paolo Bonzini
2017-11-06 12:36 ` Paolo Bonzini
0 siblings, 2 replies; 5+ messages in thread
From: Liran Alon @ 2017-11-05 16:15 UTC (permalink / raw)
To: pbonzini, rkrcmar, kvm
Cc: jmattson, idan.brown, Liran Alon, Konrad Rzeszutek Wilk
When running L2, #UD should be intercepted by L1 or just forwarded
directly to L2. It should not reach L0 x86 emulator.
Therefore, set intercept for #UD only based on L1 exception-bitmap.
Also add BUG_ON() on L0 #UD intercept handlers to make sure it is never
reached while running L2.
This improves commit ae1f57670703 ("KVM: nVMX: Do not emulate #UD while
in guest mode") by removing an unnecessary exit from L2 to L0 on #UD
when L1 doesn't intercept it.
In addition, SVM L0 #UD intercept handler doesn't handle correctly the
case it is raised from L2. In this case, it should forward the #UD to
guest instead of x86 emulator. As done in VMX #UD intercept handler.
This commit fixes this issue as-well.
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
arch/x86/kvm/svm.c | 4 +++-
arch/x86/kvm/vmx.c | 9 ++++-----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 0e68f0b3cbf7..1c7f76a417e7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1221,7 +1221,8 @@ static void init_vmcb(struct vcpu_svm *svm)
set_dr_intercepts(svm);
set_exception_intercept(svm, PF_VECTOR);
- set_exception_intercept(svm, UD_VECTOR);
+ if (!is_guest_mode(&svm->vcpu))
+ set_exception_intercept(svm, UD_VECTOR);
set_exception_intercept(svm, MC_VECTOR);
set_exception_intercept(svm, AC_VECTOR);
set_exception_intercept(svm, DB_VECTOR);
@@ -2188,6 +2189,7 @@ static int ud_interception(struct vcpu_svm *svm)
{
int er;
+ BUG_ON(is_guest_mode(&svm->vcpu));
er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);
if (er != EMULATE_DONE)
kvm_queue_exception(&svm->vcpu, UD_VECTOR);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 95a01609d7ee..5e2c47dd0c83 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1878,7 +1878,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
{
u32 eb;
- eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
+ eb = (1u << PF_VECTOR) | (1u << MC_VECTOR) |
(1u << DB_VECTOR) | (1u << AC_VECTOR);
if ((vcpu->guest_debug &
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
@@ -1896,6 +1896,8 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
*/
if (is_guest_mode(vcpu))
eb |= get_vmcs12(vcpu)->exception_bitmap;
+ else
+ eb |= 1u << UD_VECTOR;
vmcs_write32(EXCEPTION_BITMAP, eb);
}
@@ -5881,10 +5883,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
return 1; /* already handled by vmx_vcpu_run() */
if (is_invalid_opcode(intr_info)) {
- if (is_guest_mode(vcpu)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 1;
- }
+ BUG_ON(is_guest_mode(vcpu));
er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
if (er != EMULATE_DONE)
kvm_queue_exception(vcpu, UD_VECTOR);
--
1.9.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2
2017-11-05 16:15 [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2 Liran Alon
@ 2017-11-06 9:27 ` Paolo Bonzini
2017-11-06 11:02 ` Liran Alon
2017-11-06 12:36 ` Paolo Bonzini
1 sibling, 1 reply; 5+ messages in thread
From: Paolo Bonzini @ 2017-11-06 9:27 UTC (permalink / raw)
To: Liran Alon, rkrcmar, kvm; +Cc: jmattson, idan.brown, Konrad Rzeszutek Wilk
On 05/11/2017 17:15, Liran Alon wrote:
> When running L2, #UD should be intercepted by L1 or just forwarded
> directly to L2. It should not reach L0 x86 emulator.
> Therefore, set intercept for #UD only based on L1 exception-bitmap.
>
> Also add BUG_ON() on L0 #UD intercept handlers to make sure it is never
> reached while running L2.
>
> This improves commit ae1f57670703 ("KVM: nVMX: Do not emulate #UD while
> in guest mode") by removing an unnecessary exit from L2 to L0 on #UD
> when L1 doesn't intercept it.
>
> In addition, SVM L0 #UD intercept handler doesn't handle correctly the
> case it is raised from L2. In this case, it should forward the #UD to
> guest instead of x86 emulator. As done in VMX #UD intercept handler.
> This commit fixes this issue as-well.
>
> Signed-off-by: Liran Alon <liran.alon@oracle.com>
> Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> arch/x86/kvm/svm.c | 4 +++-
> arch/x86/kvm/vmx.c | 9 ++++-----
> 2 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 0e68f0b3cbf7..1c7f76a417e7 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -1221,7 +1221,8 @@ static void init_vmcb(struct vcpu_svm *svm)
> set_dr_intercepts(svm);
>
> set_exception_intercept(svm, PF_VECTOR);
> - set_exception_intercept(svm, UD_VECTOR);
> + if (!is_guest_mode(&svm->vcpu))
> + set_exception_intercept(svm, UD_VECTOR);
> set_exception_intercept(svm, MC_VECTOR);
> set_exception_intercept(svm, AC_VECTOR);
> set_exception_intercept(svm, DB_VECTOR);
This is not called on every vmexit. The right place to touch is
recalc_intercepts. Then on vmexit it will be automatically restored
when nested_svm_vmexit calls copy_vmcb_control_area.
> @@ -2188,6 +2189,7 @@ static int ud_interception(struct vcpu_svm *svm)
> {
> int er;
>
> + BUG_ON(is_guest_mode(&svm->vcpu));
> er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);
> if (er != EMULATE_DONE)
> kvm_queue_exception(&svm->vcpu, UD_VECTOR);
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 95a01609d7ee..5e2c47dd0c83 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -1878,7 +1878,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
> {
> u32 eb;
>
> - eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
> + eb = (1u << PF_VECTOR) | (1u << MC_VECTOR) |
> (1u << DB_VECTOR) | (1u << AC_VECTOR);
> if ((vcpu->guest_debug &
> (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
> @@ -1896,6 +1896,8 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
> */
> if (is_guest_mode(vcpu))
> eb |= get_vmcs12(vcpu)->exception_bitmap;
> + else
> + eb |= 1u << UD_VECTOR;
It's a nit, but since you have to send a v2, I'd prefer to keep
UD_VECTOR above and clear it here.
Thanks,
Paolo
> vmcs_write32(EXCEPTION_BITMAP, eb);
> }
> @@ -5881,10 +5883,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
> return 1; /* already handled by vmx_vcpu_run() */
>
> if (is_invalid_opcode(intr_info)) {
> - if (is_guest_mode(vcpu)) {
> - kvm_queue_exception(vcpu, UD_VECTOR);
> - return 1;
> - }
> + BUG_ON(is_guest_mode(vcpu));
> er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
> if (er != EMULATE_DONE)
> kvm_queue_exception(vcpu, UD_VECTOR);
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2
2017-11-06 9:27 ` Paolo Bonzini
@ 2017-11-06 11:02 ` Liran Alon
2017-11-06 11:24 ` Paolo Bonzini
0 siblings, 1 reply; 5+ messages in thread
From: Liran Alon @ 2017-11-06 11:02 UTC (permalink / raw)
To: Paolo Bonzini, rkrcmar, kvm; +Cc: jmattson, idan.brown, Konrad Rzeszutek Wilk
On 06/11/17 11:27, Paolo Bonzini wrote:
> On 05/11/2017 17:15, Liran Alon wrote:
>> When running L2, #UD should be intercepted by L1 or just forwarded
>> directly to L2. It should not reach L0 x86 emulator.
>> Therefore, set intercept for #UD only based on L1 exception-bitmap.
>>
>> Also add BUG_ON() on L0 #UD intercept handlers to make sure it is never
>> reached while running L2.
>>
>> This improves commit ae1f57670703 ("KVM: nVMX: Do not emulate #UD while
>> in guest mode") by removing an unnecessary exit from L2 to L0 on #UD
>> when L1 doesn't intercept it.
>>
>> In addition, SVM L0 #UD intercept handler doesn't handle correctly the
>> case it is raised from L2. In this case, it should forward the #UD to
>> guest instead of x86 emulator. As done in VMX #UD intercept handler.
>> This commit fixes this issue as-well.
>>
>> Signed-off-by: Liran Alon <liran.alon@oracle.com>
>> Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
>> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>> ---
>> arch/x86/kvm/svm.c | 4 +++-
>> arch/x86/kvm/vmx.c | 9 ++++-----
>> 2 files changed, 7 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
>> index 0e68f0b3cbf7..1c7f76a417e7 100644
>> --- a/arch/x86/kvm/svm.c
>> +++ b/arch/x86/kvm/svm.c
>> @@ -1221,7 +1221,8 @@ static void init_vmcb(struct vcpu_svm *svm)
>> set_dr_intercepts(svm);
>>
>> set_exception_intercept(svm, PF_VECTOR);
>> - set_exception_intercept(svm, UD_VECTOR);
>> + if (!is_guest_mode(&svm->vcpu))
>> + set_exception_intercept(svm, UD_VECTOR);
>> set_exception_intercept(svm, MC_VECTOR);
>> set_exception_intercept(svm, AC_VECTOR);
>> set_exception_intercept(svm, DB_VECTOR);
>
> This is not called on every vmexit. The right place to touch is
> recalc_intercepts. Then on vmexit it will be automatically restored
> when nested_svm_vmexit calls copy_vmcb_control_area.
Agreed. My bad. Will fix in v2 of this commit.
>
>> @@ -2188,6 +2189,7 @@ static int ud_interception(struct vcpu_svm *svm)
>> {
>> int er;
>>
>> + BUG_ON(is_guest_mode(&svm->vcpu));
>> er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD);
>> if (er != EMULATE_DONE)
>> kvm_queue_exception(&svm->vcpu, UD_VECTOR);
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index 95a01609d7ee..5e2c47dd0c83 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -1878,7 +1878,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
>> {
>> u32 eb;
>>
>> - eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
>> + eb = (1u << PF_VECTOR) | (1u << MC_VECTOR) |
>> (1u << DB_VECTOR) | (1u << AC_VECTOR);
>> if ((vcpu->guest_debug &
>> (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
>> @@ -1896,6 +1896,8 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
>> */
>> if (is_guest_mode(vcpu))
>> eb |= get_vmcs12(vcpu)->exception_bitmap;
>> + else
>> + eb |= 1u << UD_VECTOR;
>
> It's a nit, but since you have to send a v2, I'd prefer to keep
> UD_VECTOR above and clear it here.
I think your suggestion could be problematic.
In case (to_vmx(vcpu)->rmode.vm86_active == true) then we would like to
intercept all exceptions and therefore not clear UD_VECTOR.
This is why I preferred this approach.
>
> Thanks,
>
> Paolo
>
>> vmcs_write32(EXCEPTION_BITMAP, eb);
>> }
>> @@ -5881,10 +5883,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
>> return 1; /* already handled by vmx_vcpu_run() */
>>
>> if (is_invalid_opcode(intr_info)) {
>> - if (is_guest_mode(vcpu)) {
>> - kvm_queue_exception(vcpu, UD_VECTOR);
>> - return 1;
>> - }
>> + BUG_ON(is_guest_mode(vcpu));
>> er = emulate_instruction(vcpu, EMULTYPE_TRAP_UD);
>> if (er != EMULATE_DONE)
>> kvm_queue_exception(vcpu, UD_VECTOR);
>>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2
2017-11-06 11:02 ` Liran Alon
@ 2017-11-06 11:24 ` Paolo Bonzini
0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2017-11-06 11:24 UTC (permalink / raw)
To: Liran Alon, rkrcmar, kvm; +Cc: jmattson, idan.brown, Konrad Rzeszutek Wilk
On 06/11/2017 12:02, Liran Alon wrote:
>>
>> It's a nit, but since you have to send a v2, I'd prefer to keep
>> UD_VECTOR above and clear it here.
> I think your suggestion could be problematic.
> In case (to_vmx(vcpu)->rmode.vm86_active == true) then we would like to
> intercept all exceptions and therefore not clear UD_VECTOR.
> This is why I preferred this approach.
You're right. There is this
if (to_vmx(vcpu)->rmode.vm86_active)
eb = ~0;
but of course it would not take care of #UD due to where the line is
placed. You could either move the "if" at the end, or rewrite it as
if (to_vmx(vcpu)->rmode.vm86_active) {
vmcs_write32(EXCEPTION_BITMAP, ~0);
return;
}
and place it at the very beginning of update_exception_bitmap. But as I
said, it's just a nit and I'm okay with the code as is.
Thanks,
Paolo
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2
2017-11-05 16:15 [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2 Liran Alon
2017-11-06 9:27 ` Paolo Bonzini
@ 2017-11-06 12:36 ` Paolo Bonzini
1 sibling, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2017-11-06 12:36 UTC (permalink / raw)
To: Liran Alon, rkrcmar, kvm; +Cc: jmattson, idan.brown, Konrad Rzeszutek Wilk
On 05/11/2017 17:15, Liran Alon wrote:
> When running L2, #UD should be intercepted by L1 or just forwarded
> directly to L2. It should not reach L0 x86 emulator.
> Therefore, set intercept for #UD only based on L1 exception-bitmap.
>
> Also add BUG_ON() on L0 #UD intercept handlers to make sure it is never
> reached while running L2.
... and please make this WARN_ON_ONCE(1) instead. It's very wrong but
also harmless to hit the #UD handlers, so it's not necessary to hang the
whole host hard.
Paolo
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-11-06 12:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-11-05 16:15 [PATCH] KVM: nVMX/nSVM: Don't intercept #UD when running L2 Liran Alon
2017-11-06 9:27 ` Paolo Bonzini
2017-11-06 11:02 ` Liran Alon
2017-11-06 11:24 ` Paolo Bonzini
2017-11-06 12:36 ` Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox