Re: [PATCH 10/10] ARM: KVM: timer: lower timer interrupt after injection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Nov 24, 2012 at 2:33 PM, Christoffer Dall
<c.dall@xxxxxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, Nov 22, 2012 at 5:57 AM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote:
>> On 21/11/12 21:46, Christoffer Dall wrote:
>>> On Wed, Nov 21, 2012 at 1:15 PM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote:
>>>> While the vgic code doesn't really care about an edge interrupt
>>>> having its line "lowered", doing so makes more sense from a timer
>>>> perspective, and clearly indicates that this is an edge-triggered
>>>> interrupt.
>>>>
>>>
>>> I am extremely confused.
>>>
>>> The architected timers on an A15 is always level interrupt, correct?
>>> We present an A15 to the guest so the guest kernel expects that this
>>> is the case and that's what the emulated cfg register will contain. So
>>> I don't understand your reference to the edge thingy above?
>>
>> The cfg register exposes an edge interrupt to the guest. And for all
>> purpose, the fact that it is treated as an edge interrupt is irrelevant
>> to the guest, as it makes no observable difference.
>
> The A15 TRM clearly specifies the timer interrupts as being
> level-triggered active-LOW, but OK, I see that you ignore writes to
> the CFG register for PPIs, and force them to be always edge-triggered,
> so I guess we're not exposing the same GIC to the guest that would be
> there on an A15...?
>
> This may also deserve a comment in the code.
>
>>
>> On the host, it makes a hell of a difference (vgic maintenance interrupts).
>>
>>> If I understand the patch correctly, this relates to the fact that the
>>> timer interrupts are active-LOW, and then I get all scared, because I
>>> think I always assumed that when we set level==1 in the kvm_irq_level
>>> struct we mean "raise an interrupt", regardless of wether the line is
>>> active-LOW or active-HIGH. Otherwise we will never inject an interrupt
>>> that is active-LOW when it's active, but always inject that interrupt
>>> when it's inactive.
>>
>> It doesn't matter! We don't really inject a level, we inject an
>> interrupt. An event. The fact that we use the same internal API is pure
>> convenience.
>
> Why do you say it doesn't matter? For en edge-triggered interrupt,
> vgic_update_irq_state short-circuits on (is_edge && !level). ????
>
> And by the way, that API relies on the fact that deep in the VGIC code
> PPIs are programmed to be edge-triggered and it's assumed that the
> arch. timers are always PPIs, which may be a consequence of the
> architecture, but it is not obvious for anyone else ever reading this
> code.
>
>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
>>>> ---
>>>>  arch/arm/kvm/timer.c | 3 +++
>>>>  1 file changed, 3 insertions(+)
>>>>
>>>> diff --git a/arch/arm/kvm/timer.c b/arch/arm/kvm/timer.c
>>>> index a241298..b9e573f 100644
>>>> --- a/arch/arm/kvm/timer.c
>>>> +++ b/arch/arm/kvm/timer.c
>>>> @@ -42,6 +42,9 @@ static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
>>>>         kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
>>>>                             vcpu->arch.timer_cpu.irq->irq,
>>>>                             vcpu->arch.timer_cpu.irq->level);
>>>> +       kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
>>>> +                           vcpu->arch.timer_cpu.irq->irq,
>>>> +                           !vcpu->arch.timer_cpu.irq->level);
>>>
>>> regardless of the above, this looks super screwy and must be explained
>>> with a comment.
>>>
>>> If we start supporting a core where the timer interrupt is edge-based,
>>> than we never raise a timer interrupt, which is just plain weird.
>>
>> You assume we care about the hardware timer. We don't. It is just a
>> convenient and standardized interface to let the guest request an event.
>> The interrupt is handled on the host, where the interrupt polarity
>> matters. What we inject into the guest is a different story, and I don't
>> think it matters.
>>
> I don't understand what you say I assume here, at all. (I'm not saying
> that you're wrong, it may very well be that I'm getting the whole
> thing wrong, but then walk me through the code and explain me why this
> makes sense. And please put a comment explaining other people who are
> as stupid as me why we do this, because it certainly looks
> unintuitive.)
>
> Having that negation is weird, why not just change the level field in
> reset.c to 0. But I think it should be 1, and not negated.
>
> If the idea is simply that that you always want to use the
> kvm_vgic_inject_irq interface on the host, and always make it fire,
> then you want to make sure that vgic_update_irq_state always reads
> this specific interrupt as edge triggered (which you do, although it's
> not obvious) and indeed inject level=1.
>
If I read the code correctly, this comment should probably be added:

diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index f697c14..960bbc9 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -35,10 +35,11 @@
  * - At any time, the dist->irq_pending_on_cpu is the oracle that knows if
  *   something is pending
  * - VGIC pending interrupts are stored on the vgic.irq_state vgic
- *   bitmap (this bitmap is updated by both user land ioctls and guest
- *   mmio ops) and indicate the 'wire' state.
- * - Every time the bitmap changes, the irq_pending_on_cpu oracle is
- *   recalculated
+ *   bitmap (this bitmap is updated by both user land ioctls, guest
+ *   mmio ops, and other in-kernel peripherals such as the arch. timers) and
+ *   indicate the 'wire' state.
+ * - Every time the irq_state bitmap changes, the irq_pending_on_cpu oracle
+ *   is recalculated
  * - To calculate the oracle, we need info for each cpu from
  *   compute_pending_for_cpu, which considers:
  *   - PPI: dist->irq_state & dist->irq_enable
@@ -988,6 +989,20 @@ out:
 	return ret;
 }

+/**
+ * kvm_vgic_inject_irq - Inject an IRQ from a device to the vgic
+ * @kvm:     The VM structure pointer
+ * @cpuid:   The CPU for PPIs
+ * @irq_num: The IRQ number that is assigned to the device
+ * @level:   Edge-triggered:  true:  to trigger the interrupt
+ * 			      false: to ignore the call
+ *	     Level-sensitive  true:  activates an interrupt
+ *			      false: deactivates an interrupt
+ *
+ * The GIC is not concerned with devices being active-LOW or active-HIGH for
+ * level-sensitive interrupts.  You can think of the level parameter as 1
+ * being HIGH and 0 bing LOW and all devices being active-HIGH.
+ */
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level)
 {
_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux