Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1423783 > unrolled thread
| Started by | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| First post | 2016-06-16 10:30 +0200 |
| Last post | 2016-06-17 07:30 +0200 |
| Articles | 8 — 3 participants |
Back to article view | Back to linux.kernel
[RFC PATCH 0/2] KVM: x86: guest exit microoptimization Paolo Bonzini <pbonzini@redhat.com> - 2016-06-16 10:30 +0200
[RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit Paolo Bonzini <pbonzini@redhat.com> - 2016-06-16 10:30 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit David Matlack <dmatlack@google.com> - 2016-06-16 18:50 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit Paolo Bonzini <pbonzini@redhat.com> - 2016-06-16 18:50 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit David Matlack <dmatlack@google.com> - 2016-06-16 19:10 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit Paolo Bonzini <pbonzini@redhat.com> - 2016-06-16 19:30 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit Bandan Das <bsd@redhat.com> - 2016-06-17 00:10 +0200
Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit Paolo Bonzini <pbonzini@redhat.com> - 2016-06-17 07:30 +0200
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-06-16 10:30 +0200 |
| Subject | [RFC PATCH 0/2] KVM: x86: guest exit microoptimization |
| Message-ID | <rKAQx-5Ue-7@gated-at.bofh.it> |
This saves about 20 clock cycles per vmexit by avoiding a local_irq_save/restore pair. The price is that nested VMX will break with KVM hosts < 3.16, because the "acknowledge interrupt on exit" feature becomes mandatory. What do you think? Paolo Paolo Bonzini (2): KVM: x86: always use "acknowledge interrupt on exit" KVM: x86: use __kvm_guest_exit arch/x86/kvm/svm.c | 6 ++++++ arch/x86/kvm/vmx.c | 11 ++++------- arch/x86/kvm/x86.c | 11 ++--------- 3 files changed, 12 insertions(+), 16 deletions(-) -- 1.8.3.1
[toc] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-06-16 10:30 +0200 |
| Subject | [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKAQy-5Ue-11@gated-at.bofh.it> |
| In reply to | #1423783 |
This gains ~20 clock cycles per vmexit. On Intel there is no need
anymore to enable the interrupts in vmx_handle_external_intr, since we
are using the "acknowledge interrupt on exit" feature. AMD needs to do
that temporarily, and must be careful to avoid the interrupt shadow.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/kvm/svm.c | 6 ++++++
arch/x86/kvm/vmx.c | 4 +---
arch/x86/kvm/x86.c | 11 ++---------
3 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 5ff292778110..5bfdbbf1ce79 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -4935,6 +4935,12 @@ out:
static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
{
local_irq_enable();
+ /*
+ * We must execute an instruction with interrupts enabled, so
+ * the "cli" doesn't fall right on the interrupt shadow.
+ */
+ asm("nop");
+ local_irq_disable();
}
static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 4e9657730bf6..a46bce9e3683 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8544,7 +8544,6 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
"push %[sp]\n\t"
#endif
"pushf\n\t"
- "orl $0x200, (%%" _ASM_SP ")\n\t"
__ASM_SIZE(push) " $%c[cs]\n\t"
"call *%[entry]\n\t"
:
@@ -8557,8 +8556,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
[ss]"i"(__KERNEL_DS),
[cs]"i"(__KERNEL_CS)
);
- } else
- local_irq_enable();
+ }
}
static bool vmx_has_high_real_mode_segbase(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7e3041ef050f..cc741b68139c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
kvm_put_guest_xcr0(vcpu);
- /* Interrupt is enabled by handle_external_intr() */
kvm_x86_ops->handle_external_intr(vcpu);
++vcpu->stat.exits;
- /*
- * We must have an instruction between local_irq_enable() and
- * kvm_guest_exit(), so the timer interrupt isn't delayed by
- * the interrupt shadow. The stat.exits increment will do nicely.
- * But we need to prevent reordering, hence this barrier():
- */
- barrier();
-
- kvm_guest_exit();
+ __kvm_guest_exit();
+ local_irq_enable();
preempt_enable();
vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
--
1.8.3.1
[toc] | [prev] | [next] | [standalone]
| From | David Matlack <dmatlack@google.com> |
|---|---|
| Date | 2016-06-16 18:50 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKIEq-2jH-35@gated-at.bofh.it> |
| In reply to | #1423786 |
On Thu, Jun 16, 2016 at 1:21 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> This gains ~20 clock cycles per vmexit. On Intel there is no need
> anymore to enable the interrupts in vmx_handle_external_intr, since we
> are using the "acknowledge interrupt on exit" feature. AMD needs to do
> that temporarily, and must be careful to avoid the interrupt shadow.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> arch/x86/kvm/svm.c | 6 ++++++
> arch/x86/kvm/vmx.c | 4 +---
> arch/x86/kvm/x86.c | 11 ++---------
> 3 files changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
> index 5ff292778110..5bfdbbf1ce79 100644
> --- a/arch/x86/kvm/svm.c
> +++ b/arch/x86/kvm/svm.c
> @@ -4935,6 +4935,12 @@ out:
> static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
> {
> local_irq_enable();
> + /*
> + * We must execute an instruction with interrupts enabled, so
> + * the "cli" doesn't fall right on the interrupt shadow.
> + */
> + asm("nop");
> + local_irq_disable();
> }
>
> static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 4e9657730bf6..a46bce9e3683 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -8544,7 +8544,6 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
> "push %[sp]\n\t"
> #endif
> "pushf\n\t"
> - "orl $0x200, (%%" _ASM_SP ")\n\t"
> __ASM_SIZE(push) " $%c[cs]\n\t"
> "call *%[entry]\n\t"
> :
> @@ -8557,8 +8556,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
> [ss]"i"(__KERNEL_DS),
> [cs]"i"(__KERNEL_CS)
> );
> - } else
> - local_irq_enable();
> + }
If you make the else case the same as svm_handle_external_intr, can we
avoid requiring ack-intr-on-exit?
> }
>
> static bool vmx_has_high_real_mode_segbase(void)
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7e3041ef050f..cc741b68139c 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>
> kvm_put_guest_xcr0(vcpu);
>
> - /* Interrupt is enabled by handle_external_intr() */
> kvm_x86_ops->handle_external_intr(vcpu);
>
> ++vcpu->stat.exits;
>
> - /*
> - * We must have an instruction between local_irq_enable() and
> - * kvm_guest_exit(), so the timer interrupt isn't delayed by
> - * the interrupt shadow. The stat.exits increment will do nicely.
> - * But we need to prevent reordering, hence this barrier():
> - */
> - barrier();
> -
> - kvm_guest_exit();
> + __kvm_guest_exit();
>
> + local_irq_enable();
> preempt_enable();
>
> vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
> --
> 1.8.3.1
>
[toc] | [prev] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-06-16 18:50 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKIEq-2jH-33@gated-at.bofh.it> |
| In reply to | #1424272 |
On 16/06/2016 18:43, David Matlack wrote:
> On Thu, Jun 16, 2016 at 1:21 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> This gains ~20 clock cycles per vmexit. On Intel there is no need
>> anymore to enable the interrupts in vmx_handle_external_intr, since we
>> are using the "acknowledge interrupt on exit" feature. AMD needs to do
>> that temporarily, and must be careful to avoid the interrupt shadow.
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>> arch/x86/kvm/svm.c | 6 ++++++
>> arch/x86/kvm/vmx.c | 4 +---
>> arch/x86/kvm/x86.c | 11 ++---------
>> 3 files changed, 9 insertions(+), 12 deletions(-)
>>
>> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
>> index 5ff292778110..5bfdbbf1ce79 100644
>> --- a/arch/x86/kvm/svm.c
>> +++ b/arch/x86/kvm/svm.c
>> @@ -4935,6 +4935,12 @@ out:
>> static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
>> {
>> local_irq_enable();
>> + /*
>> + * We must execute an instruction with interrupts enabled, so
>> + * the "cli" doesn't fall right on the interrupt shadow.
>> + */
>> + asm("nop");
>> + local_irq_disable();
>> }
>>
>> static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>> index 4e9657730bf6..a46bce9e3683 100644
>> --- a/arch/x86/kvm/vmx.c
>> +++ b/arch/x86/kvm/vmx.c
>> @@ -8544,7 +8544,6 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
>> "push %[sp]\n\t"
>> #endif
>> "pushf\n\t"
>> - "orl $0x200, (%%" _ASM_SP ")\n\t"
>> __ASM_SIZE(push) " $%c[cs]\n\t"
>> "call *%[entry]\n\t"
>> :
>> @@ -8557,8 +8556,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
>> [ss]"i"(__KERNEL_DS),
>> [cs]"i"(__KERNEL_CS)
>> );
>> - } else
>> - local_irq_enable();
>> + }
>
> If you make the else case the same as svm_handle_external_intr, can we
> avoid requiring ack-intr-on-exit?
Yes, but the sti/nop/cli would be useless if ack-intr-on-exit is
available. It's a bit ugly, so I RFCed the bold thing instead.
Are you thinking of some distros in particular that lack nested
ack-intr-on-exit? All processors have it as far as I know.
Paolo
>> }
>>
>> static bool vmx_has_high_real_mode_segbase(void)
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index 7e3041ef050f..cc741b68139c 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>>
>> kvm_put_guest_xcr0(vcpu);
>>
>> - /* Interrupt is enabled by handle_external_intr() */
>> kvm_x86_ops->handle_external_intr(vcpu);
>>
>> ++vcpu->stat.exits;
>>
>> - /*
>> - * We must have an instruction between local_irq_enable() and
>> - * kvm_guest_exit(), so the timer interrupt isn't delayed by
>> - * the interrupt shadow. The stat.exits increment will do nicely.
>> - * But we need to prevent reordering, hence this barrier():
>> - */
>> - barrier();
>> -
>> - kvm_guest_exit();
>> + __kvm_guest_exit();
>>
>> + local_irq_enable();
>> preempt_enable();
>>
>> vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
>> --
>> 1.8.3.1
>>
[toc] | [prev] | [next] | [standalone]
| From | David Matlack <dmatlack@google.com> |
|---|---|
| Date | 2016-06-16 19:10 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKIXM-2Gg-15@gated-at.bofh.it> |
| In reply to | #1424273 |
On Thu, Jun 16, 2016 at 9:47 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> On 16/06/2016 18:43, David Matlack wrote:
>> On Thu, Jun 16, 2016 at 1:21 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> This gains ~20 clock cycles per vmexit. On Intel there is no need
>>> anymore to enable the interrupts in vmx_handle_external_intr, since we
>>> are using the "acknowledge interrupt on exit" feature. AMD needs to do
>>> that temporarily, and must be careful to avoid the interrupt shadow.
>>>
>>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>>> ---
>>> arch/x86/kvm/svm.c | 6 ++++++
>>> arch/x86/kvm/vmx.c | 4 +---
>>> arch/x86/kvm/x86.c | 11 ++---------
>>> 3 files changed, 9 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
>>> index 5ff292778110..5bfdbbf1ce79 100644
>>> --- a/arch/x86/kvm/svm.c
>>> +++ b/arch/x86/kvm/svm.c
>>> @@ -4935,6 +4935,12 @@ out:
>>> static void svm_handle_external_intr(struct kvm_vcpu *vcpu)
>>> {
>>> local_irq_enable();
>>> + /*
>>> + * We must execute an instruction with interrupts enabled, so
>>> + * the "cli" doesn't fall right on the interrupt shadow.
>>> + */
>>> + asm("nop");
>>> + local_irq_disable();
>>> }
>>>
>>> static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
>>> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
>>> index 4e9657730bf6..a46bce9e3683 100644
>>> --- a/arch/x86/kvm/vmx.c
>>> +++ b/arch/x86/kvm/vmx.c
>>> @@ -8544,7 +8544,6 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
>>> "push %[sp]\n\t"
>>> #endif
>>> "pushf\n\t"
>>> - "orl $0x200, (%%" _ASM_SP ")\n\t"
>>> __ASM_SIZE(push) " $%c[cs]\n\t"
>>> "call *%[entry]\n\t"
>>> :
>>> @@ -8557,8 +8556,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
>>> [ss]"i"(__KERNEL_DS),
>>> [cs]"i"(__KERNEL_CS)
>>> );
>>> - } else
>>> - local_irq_enable();
>>> + }
>>
>> If you make the else case the same as svm_handle_external_intr, can we
>> avoid requiring ack-intr-on-exit?
>
> Yes, but the sti/nop/cli would be useless if ack-intr-on-exit is
> available. It's a bit ugly, so I RFCed the bold thing instead.
Ahh, and handle_external_intr is called on every VM-exit, not just
VM-exits caused by external interrupts. So we'd be doing the
sti/nop/cli quite often. I was thinking we never hit the else case
when the CPU supports ack-intr-on-exit.
>
> Are you thinking of some distros in particular that lack nested
> ack-intr-on-exit? All processors have it as far as I know.
Nope, I just thought it was possible to avoid the requirement.
>
> Paolo
>
>
>>> }
>>>
>>> static bool vmx_has_high_real_mode_segbase(void)
>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>> index 7e3041ef050f..cc741b68139c 100644
>>> --- a/arch/x86/kvm/x86.c
>>> +++ b/arch/x86/kvm/x86.c
>>> @@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>>>
>>> kvm_put_guest_xcr0(vcpu);
>>>
>>> - /* Interrupt is enabled by handle_external_intr() */
>>> kvm_x86_ops->handle_external_intr(vcpu);
>>>
>>> ++vcpu->stat.exits;
>>>
>>> - /*
>>> - * We must have an instruction between local_irq_enable() and
>>> - * kvm_guest_exit(), so the timer interrupt isn't delayed by
>>> - * the interrupt shadow. The stat.exits increment will do nicely.
>>> - * But we need to prevent reordering, hence this barrier():
>>> - */
>>> - barrier();
>>> -
>>> - kvm_guest_exit();
>>> + __kvm_guest_exit();
>>>
>>> + local_irq_enable();
>>> preempt_enable();
>>>
>>> vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
>>> --
>>> 1.8.3.1
>>>
[toc] | [prev] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-06-16 19:30 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKJh8-2MG-33@gated-at.bofh.it> |
| In reply to | #1424284 |
On 16/06/2016 19:03, David Matlack wrote: > > > If you make the else case the same as svm_handle_external_intr, can we > > > avoid requiring ack-intr-on-exit? > > > > Yes, but the sti/nop/cli would be useless if ack-intr-on-exit is > > available. It's a bit ugly, so I RFCed the bold thing instead. > > Ahh, and handle_external_intr is called on every VM-exit, not just > VM-exits caused by external interrupts. So we'd be doing the > sti/nop/cli quite often. I was thinking we never hit the else case > when the CPU supports ack-intr-on-exit. Actually it's really just aesthetics, because the sti and cli are pretty cheap. It's the pushf/popf that kills performance for kvm_guest_exit. I also thought of just doing a cli/sti around __kvm_guest_exit and calling it a day. Ubuntu 14.04 had kernel 3.13, but the latest hardware enablement kernels are as recent as 4.4. And the most recent released RHEL (7.2) has all the fixes too. Debian Jessie has 3.16.7-ckt25, and all three patches for APICv support have been backported to 3.16.7-ckt11. So they should be there (but I can only check tomorrow). Paolo >> > >> > Are you thinking of some distros in particular that lack nested >> > ack-intr-on-exit? All processors have it as far as I know. > Nope, I just thought it was possible to avoid the requirement. >
[toc] | [prev] | [next] | [standalone]
| From | Bandan Das <bsd@redhat.com> |
|---|---|
| Date | 2016-06-17 00:10 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKNE5-5vQ-1@gated-at.bofh.it> |
| In reply to | #1423786 |
... > static bool vmx_has_high_real_mode_segbase(void) > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 7e3041ef050f..cc741b68139c 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > > kvm_put_guest_xcr0(vcpu); > > - /* Interrupt is enabled by handle_external_intr() */ > kvm_x86_ops->handle_external_intr(vcpu); > > ++vcpu->stat.exits; > > - /* > - * We must have an instruction between local_irq_enable() and > - * kvm_guest_exit(), so the timer interrupt isn't delayed by > - * the interrupt shadow. The stat.exits increment will do nicely. > - * But we need to prevent reordering, hence this barrier(): > - */ > - barrier(); > - > - kvm_guest_exit(); > + __kvm_guest_exit(); kvm_guest_exit has no more callers and so can be removed. Bandan > + local_irq_enable(); > preempt_enable(); > > vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
[toc] | [prev] | [next] | [standalone]
| From | Paolo Bonzini <pbonzini@redhat.com> |
|---|---|
| Date | 2016-06-17 07:30 +0200 |
| Subject | Re: [RFC PATCH 2/2] KVM: x86: use __kvm_guest_exit |
| Message-ID | <rKUvU-2ml-33@gated-at.bofh.it> |
| In reply to | #1424498 |
> > static bool vmx_has_high_real_mode_segbase(void) > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > > index 7e3041ef050f..cc741b68139c 100644 > > --- a/arch/x86/kvm/x86.c > > +++ b/arch/x86/kvm/x86.c > > @@ -6706,21 +6706,13 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) > > > > kvm_put_guest_xcr0(vcpu); > > > > - /* Interrupt is enabled by handle_external_intr() */ > > kvm_x86_ops->handle_external_intr(vcpu); > > > > ++vcpu->stat.exits; > > > > - /* > > - * We must have an instruction between local_irq_enable() and > > - * kvm_guest_exit(), so the timer interrupt isn't delayed by > > - * the interrupt shadow. The stat.exits increment will do nicely. > > - * But we need to prevent reordering, hence this barrier(): > > - */ > > - barrier(); > > - > > - kvm_guest_exit(); > > + __kvm_guest_exit(); > > kvm_guest_exit has no more callers and so can be removed. ARM and PPC call it. Paolo
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web