All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Bill Paul <wpaul@windriver.com>, qemu-devel@nongnu.org
Cc: Eduardo Habkost <ehabkost@redhat.com>,
	Richard Henderson <rth@twiddle.net>
Subject: Re: [Qemu-devel] Question about hw/timer/hpet.c, hw/intc/ioapic.c and polarity
Date: Tue, 5 Apr 2016 15:20:05 +0200	[thread overview]
Message-ID: <5703BB85.2070200@redhat.com> (raw)
In-Reply-To: <201604041442.46614.wpaul@windriver.com>



On 04/04/2016 23:42, Bill Paul wrote:
> I'm testing some of the HPET handling code in VxWorks using QEMU 2.4.1 and 
> I've encountered something which looks a little odd that I'm hoping someone 
> can clarify for me. First, some background:
> 
> The HPET timer supports three kinds of interrupt delivery:
> 
> Legacy: HPET can use the same IRQs as the old 8254 timer (IRQ2, IRQ8)
> I/O APIC: HPET can use any of the first 32 I/O APIC IRQs in the system
> FSB: HPET uses "front-side bus" mode, i.e interrupts are routed right to the 
> local APIC (I/O APIC is bypassed)
> 
> By default, VxWorks uses front-side bus mode, and that seems to work fine. 
> However I wanted to try I/O APIC mode too, and that seems to behave in a funny 
> way. In particular, the following code in hw/timer/hpet.c puzzles me:
> 
>     if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
>         s->isr &= ~mask;
>         if (!timer_fsb_route(timer)) {
>             /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
>             if (route >= ISA_NUM_IRQS) {
>                 qemu_irq_raise(s->irqs[route]);
>             } else {
>                 qemu_irq_lower(s->irqs[route]);
>             }
>         }
>     } else if (timer_fsb_route(timer)) {
>         address_space_stl_le(&address_space_memory, timer->fsb >> 32,
>                              timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
>                              NULL);
>     } else if (timer->config & HPET_TN_TYPE_LEVEL) {
>         s->isr |= mask;
>         /* fold the ICH PIRQ# pin's internal inversion logic into hpet */
>         if (route >= ISA_NUM_IRQS) {
>             qemu_irq_lower(s->irqs[route]);
>         } else {
>             qemu_irq_raise(s->irqs[route]);
>         }
>     } else {
>         s->isr &= ~mask;
>         qemu_irq_pulse(s->irqs[route]);
>     }
> 
> Note the part that inverts the interrupt handling logic for ICH PIRQ pins. I 
> don't understand how this is supposed to work.

I think t should be removed.

 If I use level triggered IRQ2
> or IRQ8 in VxWorks, then things work as expected. But if I use IRQ21, the HPET 
> timer interrupt service routine is immediately called, even though the timer 
> hasn't expired yet. The ISR reads 0 from the HPET status register, indicating 
> that no timers have events pending, so it just returns. The first 
> qemu_irq_raise() call is triggered because hpet_enabled() returns true, but 
> timer_enabled() returns false.
> 
> Researching the code history, I see that the inversion logic was added in 2013 
> in order to fix a problem with HPET usage in Linux. However something about 
> the way this was done looks wrong to me. In the case where we actually want to 
> signal an interrupt because the timer has expired, and the IRQ is larger than 
> 15, the code calls qemu_irq_lower() instead of qemu_irq_raise(). Eventually 
> this results in ioapic_set_irq() being called with level = 0. The problem is, 
> ioapic_set_irq() will only call ioapic_service() to notify the quest of an 
> interrupt if level == 1.
> 
> Given this, I can't understand how this is supposed to work. The hpet.c code 
> seems to treat qemu_irq_raise() and qemu_irq_lower() as though they can 
> trigger active high or active low interrupts, but the ioapic.c code doesn't 
> support any polarity settings. The only way to actually trigger an interrupt 
> to the guest is to "raise" (assert) the interrupt by calling qemu_irq_raise().

I think that commit 0d63b2d ("hpet: inverse polarity when pin above
ISA_NUM_IRQS", 2013-12-11) can be reverted.  The code was probably
tested on KVM only, but KVM now is *also* ignoring the IOAPIC polarity
(commit 100943c54e09, "kvm: x86: ignore ioapic polarity", 2014-03-13).

Does that work for you?  If so, can you post the patch for the revert?
Remember to add Signed-off-by, "git revert" doesn't do that for you.

Thanks,

Paolo

  reply	other threads:[~2016-04-05 13:20 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-04 21:42 [Qemu-devel] Question about hw/timer/hpet.c, hw/intc/ioapic.c and polarity Bill Paul
2016-04-05 13:20 ` Paolo Bonzini [this message]
2016-04-05 18:30   ` Bill Paul
2016-04-05 23:04     ` Paolo Bonzini

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=5703BB85.2070200@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=wpaul@windriver.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.