All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Auger <eric.auger@linaro.org>
To: Christoffer Dall <christoffer.dall@linaro.org>
Cc: eric.auger@st.com, marc.zyngier@arm.com,
	linux-arm-kernel@lists.infradead.org,
	kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org,
	alex.williamson@redhat.com, joel.schopp@amd.com,
	kim.phillips@freescale.com, paulus@samba.org, gleb@kernel.org,
	pbonzini@redhat.com, linux-kernel@vger.kernel.org,
	patches@linaro.org, will.deacon@arm.com,
	a.motakis@virtualopensystems.com, a.rigo@virtualopensystems.com,
	john.liuli@huawei.com
Subject: Re: [RFC v2 1/9] KVM: ARM: VGIC: fix multiple injection of level sensitive forwarded IRQ
Date: Thu, 11 Sep 2014 20:17:49 +0200	[thread overview]
Message-ID: <5411E74D.4080309@linaro.org> (raw)
In-Reply-To: <20140911030945.GC2784@lvm>

On 09/11/2014 05:09 AM, Christoffer Dall wrote:
> On Mon, Sep 01, 2014 at 02:52:40PM +0200, Eric Auger wrote:
>> Fix multiple injection of level sensitive forwarded IRQs.
>> With current code, the second injection fails since the state bitmaps
>> are not reset (process_maintenance is not called anymore).
>> New implementation consists in fully bypassing the vgic state
>> management for forwarded IRQ (checks are ignored in
>> vgic_update_irq_pending). This obviously assumes the forwarded IRQ is
>> injected from kernel side.
>>
>> Signed-off-by: Eric Auger <eric.auger@linaro.org>
>>
>> ---
>>
>> It was attempted to reset the states in __kvm_vgic_sync_hwstate, checking
>> the emptied LR of forwarded IRQ. However surprisingly this solution does
>> not seem to work. Some times, a new forwarded IRQ injection is observed
>> while the LR of the previous instance was not observed as empty.
> 
> hmmm, concerning.  It would probably have been helpful overall if you
> could start by describing the problem with the current implementation in
> the commit message, and then explain the fix...
> 
>>
>> v1 -> v2:
>> - fix vgic state bypass in vgic_queue_hwirq
>> ---
>>  virt/kvm/arm/vgic.c | 13 ++++++++++---
>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
>> index 0007300..8ef495b 100644
>> --- a/virt/kvm/arm/vgic.c
>> +++ b/virt/kvm/arm/vgic.c
>> @@ -1259,7 +1259,9 @@ static bool vgic_queue_sgi(struct kvm_vcpu *vcpu, int irq)
>>  
>>  static bool vgic_queue_hwirq(struct kvm_vcpu *vcpu, int irq)
>>  {
>> -	if (vgic_irq_is_queued(vcpu, irq))
>> +	bool is_forwarded =  (vgic_get_phys_irq(vcpu, irq) > 0);
> 
> can you create a static function to factor this vgic_get_phys_irq check out, please?
yes sure
> 
>> +
>> +	if (vgic_irq_is_queued(vcpu, irq) && !is_forwarded)
>>  		return true; /* level interrupt, already queued */
> 
> so essentially if an IRQ is already on a LR so we shouldn't resample the
> line, then we still resample the line if the IRQ is forwarded?
> 
> I think you need to explain this, both to me here, and also in the code
> by moving the comment following the return statement above the check and
> comment this clearly.
Well, I admit it may look a bit pushy! When we discussed this issue with
Marc, the outcome was that the vgic states were not accurate with
forwarded IRQs and VGIC state may be fully bypassed. Since the first
injection still sets the state - and I did not want to modify this - the
2d one would fail due to that check, and the validate_injection. May be
cleaner to not update the states when injecting the fwd irq too.

> 
>>  
>>  	if (vgic_queue_irq(vcpu, 0, irq)) {
>> @@ -1517,14 +1519,18 @@ static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
>>  	int edge_triggered, level_triggered;
>>  	int enabled;
>>  	bool ret = true;
>> +	bool is_forwarded;
>>  
>>  	spin_lock(&dist->lock);
>>  
>>  	vcpu = kvm_get_vcpu(kvm, cpuid);
>> +	is_forwarded = (vgic_get_phys_irq(vcpu, irq_num) > 0);
> 
> use your new function here as well.
ok
> 
>> +
>>  	edge_triggered = vgic_irq_is_edge(vcpu, irq_num);
>>  	level_triggered = !edge_triggered;
>>  
>> -	if (!vgic_validate_injection(vcpu, irq_num, level)) {
>> +	if (!is_forwarded &&
>> +		!vgic_validate_injection(vcpu, irq_num, level)) {
> 
> I don't see the rationale here either.  If an IRQ is forwarded, why do
> you need to do anything if the condition of the line hasn't changed for
> a level-triggered IRQ or if you have a falling edge on an edge-triggered
> IRQ (assuming active-HIGH)?
To me this even cannot cannot happen. a second fwd irq can only hit if
the same virtual IRQ was completed and completed the corresponding phys
IRQ. Still the problem is that on the 1st injection we updated the VGIC
state. I aknowledge this is a hack to work around the 1st injection
update the state and nothing reset them. So on subsequent injections, -
and even on the 1st one-  I never check the state.
> 
>>  		ret = false;
>>  		goto out;
>>  	}
>> @@ -1557,7 +1563,8 @@ static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
>>  		goto out;
>>  	}
>>  
>> -	if (level_triggered && vgic_irq_is_queued(vcpu, irq_num)) {
>> +	if (!is_forwarded &&
>> +		level_triggered && vgic_irq_is_queued(vcpu, irq_num)) {
> 
> So here it's making sense for SPIs since you can have an EOIed interrupt
> on a CPU that didn't exit the VM yet, and this it's still queued, but
> you still need to resample the line to respect other CPUs.  Only, we
> ever only target a single CPU for SPIs IIRC (the first in the target
> list register) so we have to wait for that CPU to to exit the VM anyhow.
> 
> This leads me to believe that, given a fowarded irq, you can only have
> XXX situations at this point:
> 
> (1) is_queued && target_vcpu_in_vm:
> The vcpu should resample this line when it exits the VM, because we
> check the LRs for IRQs like this one, so we don't have to do anything
> and go to out here.
> 
> (2) is_queued && !target_vcpu_in_vm::
> You have a bug because you exited the VM which must have done an EOI on
> the interrupt, otherwise this function shouldn't have been called!  This
> means that we should have cleared the queued state of the interrupt.
> 
> (3) !is_queued && whatever:
> Set the irq pending bits, so do not goto out.
> 
> I'm aware that there's theoretically a race between (1) and (2), but you
> should consider target_cpu_in_vm as "it hasn't been through
> __kvm_vgic_sync_hwstate() yet" and this should hold.
I will prepare something accurate for next week.

Thanks

Best Regards

Eric
> 
> Tell me where this breaks?
> 
> -Christoffer
> 


WARNING: multiple messages have this Message-ID (diff)
From: eric.auger@linaro.org (Eric Auger)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC v2 1/9] KVM: ARM: VGIC: fix multiple injection of level sensitive forwarded IRQ
Date: Thu, 11 Sep 2014 20:17:49 +0200	[thread overview]
Message-ID: <5411E74D.4080309@linaro.org> (raw)
In-Reply-To: <20140911030945.GC2784@lvm>

On 09/11/2014 05:09 AM, Christoffer Dall wrote:
> On Mon, Sep 01, 2014 at 02:52:40PM +0200, Eric Auger wrote:
>> Fix multiple injection of level sensitive forwarded IRQs.
>> With current code, the second injection fails since the state bitmaps
>> are not reset (process_maintenance is not called anymore).
>> New implementation consists in fully bypassing the vgic state
>> management for forwarded IRQ (checks are ignored in
>> vgic_update_irq_pending). This obviously assumes the forwarded IRQ is
>> injected from kernel side.
>>
>> Signed-off-by: Eric Auger <eric.auger@linaro.org>
>>
>> ---
>>
>> It was attempted to reset the states in __kvm_vgic_sync_hwstate, checking
>> the emptied LR of forwarded IRQ. However surprisingly this solution does
>> not seem to work. Some times, a new forwarded IRQ injection is observed
>> while the LR of the previous instance was not observed as empty.
> 
> hmmm, concerning.  It would probably have been helpful overall if you
> could start by describing the problem with the current implementation in
> the commit message, and then explain the fix...
> 
>>
>> v1 -> v2:
>> - fix vgic state bypass in vgic_queue_hwirq
>> ---
>>  virt/kvm/arm/vgic.c | 13 ++++++++++---
>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
>> index 0007300..8ef495b 100644
>> --- a/virt/kvm/arm/vgic.c
>> +++ b/virt/kvm/arm/vgic.c
>> @@ -1259,7 +1259,9 @@ static bool vgic_queue_sgi(struct kvm_vcpu *vcpu, int irq)
>>  
>>  static bool vgic_queue_hwirq(struct kvm_vcpu *vcpu, int irq)
>>  {
>> -	if (vgic_irq_is_queued(vcpu, irq))
>> +	bool is_forwarded =  (vgic_get_phys_irq(vcpu, irq) > 0);
> 
> can you create a static function to factor this vgic_get_phys_irq check out, please?
yes sure
> 
>> +
>> +	if (vgic_irq_is_queued(vcpu, irq) && !is_forwarded)
>>  		return true; /* level interrupt, already queued */
> 
> so essentially if an IRQ is already on a LR so we shouldn't resample the
> line, then we still resample the line if the IRQ is forwarded?
> 
> I think you need to explain this, both to me here, and also in the code
> by moving the comment following the return statement above the check and
> comment this clearly.
Well, I admit it may look a bit pushy! When we discussed this issue with
Marc, the outcome was that the vgic states were not accurate with
forwarded IRQs and VGIC state may be fully bypassed. Since the first
injection still sets the state - and I did not want to modify this - the
2d one would fail due to that check, and the validate_injection. May be
cleaner to not update the states when injecting the fwd irq too.

> 
>>  
>>  	if (vgic_queue_irq(vcpu, 0, irq)) {
>> @@ -1517,14 +1519,18 @@ static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
>>  	int edge_triggered, level_triggered;
>>  	int enabled;
>>  	bool ret = true;
>> +	bool is_forwarded;
>>  
>>  	spin_lock(&dist->lock);
>>  
>>  	vcpu = kvm_get_vcpu(kvm, cpuid);
>> +	is_forwarded = (vgic_get_phys_irq(vcpu, irq_num) > 0);
> 
> use your new function here as well.
ok
> 
>> +
>>  	edge_triggered = vgic_irq_is_edge(vcpu, irq_num);
>>  	level_triggered = !edge_triggered;
>>  
>> -	if (!vgic_validate_injection(vcpu, irq_num, level)) {
>> +	if (!is_forwarded &&
>> +		!vgic_validate_injection(vcpu, irq_num, level)) {
> 
> I don't see the rationale here either.  If an IRQ is forwarded, why do
> you need to do anything if the condition of the line hasn't changed for
> a level-triggered IRQ or if you have a falling edge on an edge-triggered
> IRQ (assuming active-HIGH)?
To me this even cannot cannot happen. a second fwd irq can only hit if
the same virtual IRQ was completed and completed the corresponding phys
IRQ. Still the problem is that on the 1st injection we updated the VGIC
state. I aknowledge this is a hack to work around the 1st injection
update the state and nothing reset them. So on subsequent injections, -
and even on the 1st one-  I never check the state.
> 
>>  		ret = false;
>>  		goto out;
>>  	}
>> @@ -1557,7 +1563,8 @@ static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
>>  		goto out;
>>  	}
>>  
>> -	if (level_triggered && vgic_irq_is_queued(vcpu, irq_num)) {
>> +	if (!is_forwarded &&
>> +		level_triggered && vgic_irq_is_queued(vcpu, irq_num)) {
> 
> So here it's making sense for SPIs since you can have an EOIed interrupt
> on a CPU that didn't exit the VM yet, and this it's still queued, but
> you still need to resample the line to respect other CPUs.  Only, we
> ever only target a single CPU for SPIs IIRC (the first in the target
> list register) so we have to wait for that CPU to to exit the VM anyhow.
> 
> This leads me to believe that, given a fowarded irq, you can only have
> XXX situations at this point:
> 
> (1) is_queued && target_vcpu_in_vm:
> The vcpu should resample this line when it exits the VM, because we
> check the LRs for IRQs like this one, so we don't have to do anything
> and go to out here.
> 
> (2) is_queued && !target_vcpu_in_vm::
> You have a bug because you exited the VM which must have done an EOI on
> the interrupt, otherwise this function shouldn't have been called!  This
> means that we should have cleared the queued state of the interrupt.
> 
> (3) !is_queued && whatever:
> Set the irq pending bits, so do not goto out.
> 
> I'm aware that there's theoretically a race between (1) and (2), but you
> should consider target_cpu_in_vm as "it hasn't been through
> __kvm_vgic_sync_hwstate() yet" and this should hold.
I will prepare something accurate for next week.

Thanks

Best Regards

Eric
> 
> Tell me where this breaks?
> 
> -Christoffer
> 

  reply	other threads:[~2014-09-11 18:18 UTC|newest]

Thread overview: 101+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-01 12:52 [RFC v2 0/9] KVM-VFIO IRQ forward control Eric Auger
2014-09-01 12:52 ` Eric Auger
2014-09-01 12:52 ` [RFC v2 1/9] KVM: ARM: VGIC: fix multiple injection of level sensitive forwarded IRQ Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:09   ` Christoffer Dall
2014-09-11  3:09     ` Christoffer Dall
2014-09-11 18:17     ` Eric Auger [this message]
2014-09-11 18:17       ` Eric Auger
2014-09-11 22:14       ` Christoffer Dall
2014-09-11 22:14         ` Christoffer Dall
2014-09-01 12:52 ` [RFC v2 2/9] KVM: ARM: VGIC: add forwarded irq rbtree lock Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:09   ` Christoffer Dall
2014-09-11  3:09     ` Christoffer Dall
2014-09-11 17:31     ` Eric Auger
2014-09-11 17:31       ` Eric Auger
2014-09-01 12:52 ` [RFC v2 3/9] ARM: KVM: Enable the KVM-VFIO device Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-01 12:52 ` [RFC v2 4/9] VFIO: platform: handler tests whether the IRQ is forwarded Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  8:44     ` Eric Auger
2014-09-11  8:44       ` Eric Auger
2014-09-11 17:05       ` Christoffer Dall
2014-09-11 17:05         ` Christoffer Dall
2014-09-11 18:07         ` Alex Williamson
2014-09-11 18:07           ` Alex Williamson
2014-09-11 17:08       ` Antonios Motakis
2014-09-11 17:08         ` Antonios Motakis
2014-09-01 12:52 ` [RFC v2 5/9] KVM: KVM-VFIO: update user API to program forwarded IRQ Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  8:49     ` Eric Auger
2014-09-11  8:49       ` Eric Auger
2014-09-11 17:08       ` Christoffer Dall
2014-09-11 17:08         ` Christoffer Dall
2014-09-01 12:52 ` [RFC v2 6/9] VFIO: Extend external user API Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  8:50     ` Eric Auger
2014-09-11  8:50       ` Eric Auger
2014-09-01 12:52 ` [RFC v2 7/9] KVM: KVM-VFIO: add new VFIO external API hooks Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  8:51     ` Eric Auger
2014-09-11  8:51       ` Eric Auger
2014-09-01 12:52 ` [RFC v2 8/9] KVM: KVM-VFIO: generic KVM_DEV_VFIO_DEVICE command and IRQ forwarding control Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  5:05     ` Alex Williamson
2014-09-11  5:05       ` Alex Williamson
2014-09-11  5:05       ` Alex Williamson
2014-09-11 12:04       ` Eric Auger
2014-09-11 12:04         ` Eric Auger
2014-09-11 15:59         ` Alex Williamson
2014-09-11 15:59           ` Alex Williamson
2014-09-11 17:24           ` Christoffer Dall
2014-09-11 17:24             ` Christoffer Dall
2014-09-11 17:22         ` Christoffer Dall
2014-09-11 17:22           ` Christoffer Dall
2014-09-11 17:10       ` Christoffer Dall
2014-09-11 17:10         ` Christoffer Dall
2014-09-11 18:14         ` Alex Williamson
2014-09-11 18:14           ` Alex Williamson
2014-09-11 21:59           ` Christoffer Dall
2014-09-11 21:59             ` Christoffer Dall
2014-09-11  9:35     ` Eric Auger
2014-09-11  9:35       ` Eric Auger
2014-09-11 15:47       ` Alex Williamson
2014-09-11 15:47         ` Alex Williamson
2014-09-11 15:47         ` Alex Williamson
2014-09-11 17:32       ` Christoffer Dall
2014-09-11 17:32         ` Christoffer Dall
2014-09-01 12:52 ` [RFC v2 9/9] KVM: KVM-VFIO: ARM " Eric Auger
2014-09-01 12:52   ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-02 21:05 ` [RFC v2 0/9] KVM-VFIO IRQ forward control Alex Williamson
2014-09-02 21:05   ` Alex Williamson
2014-09-05 12:52   ` Eric Auger
2014-09-05 12:52     ` Eric Auger
2014-09-11  3:10   ` Christoffer Dall
2014-09-11  3:10     ` Christoffer Dall
2014-09-11  5:09     ` Alex Williamson
2014-09-11  5:09       ` Alex Williamson
2014-11-17 11:25       ` Wu, Feng
2014-11-17 11:25         ` Wu, Feng
2014-11-17 11:25         ` Wu, Feng
2014-11-17 13:41         ` Eric Auger
2014-11-17 13:41           ` Eric Auger
2014-11-17 13:41           ` Eric Auger
2014-11-17 13:45           ` Wu, Feng
2014-11-17 13:45             ` Wu, Feng
2014-11-17 13:45             ` Wu, Feng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5411E74D.4080309@linaro.org \
    --to=eric.auger@linaro.org \
    --cc=a.motakis@virtualopensystems.com \
    --cc=a.rigo@virtualopensystems.com \
    --cc=alex.williamson@redhat.com \
    --cc=christoffer.dall@linaro.org \
    --cc=eric.auger@st.com \
    --cc=gleb@kernel.org \
    --cc=joel.schopp@amd.com \
    --cc=john.liuli@huawei.com \
    --cc=kim.phillips@freescale.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=patches@linaro.org \
    --cc=paulus@samba.org \
    --cc=pbonzini@redhat.com \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.