All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: Eva Chen <debby83729@gmail.com>
Cc: QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] Questions about the flow of interrupt simulation
Date: Fri, 1 Jun 2018 10:25:12 +0100	[thread overview]
Message-ID: <CAFEAcA9nfL6UwiZO6USfLuNH_yg3CMk=ngnrwVXC=DgVnjv9wg@mail.gmail.com> (raw)
In-Reply-To: <CAG0V3WRO4EnzKGk88LbVTSo2APdkch-3wm0hLBXkDYXOBuWa0w@mail.gmail.com>

On 1 June 2018 at 07:17, Eva Chen <debby83729@gmail.com> wrote:
> 1. There are two kinds of interrupt:  edge triggered and level triggered.
> I have seen two code segment related to the level: gic_set_irq() and
> arm_cpu_set_irq().
> In gic_set_irq(), if level == GIC_TEST_LEVEL(irq, cm), which means the
> level is not changed, will return.
> In arm_cpu_set_irq() said that if level ==1, call cpu_interrupt(). if
> level==0, call cpu_reset_interrupt(), which will clean up that irq bits..
> Does that mean all interrupt in arm are level triggered(high level)?
> How to know the triggered type of interrupt?

This is mixing up interrupts in two different places. For the Arm
architecture, IRQ and FIQ are always level-sensitive: the thing
which sets them (the GIC, typically) has to set them and keep them
set until the CPU acknowledges them.

For the GIC, its input interrupts may be either level sensitive or
edge sensitive. This is configurable for each interrupt on GICv2 by
writing to the GICD_ICFGRn registers. The gic_set_irq() code implements
the behaviour that the GIC specification requires, depending on whether
the ICFGRn register says that interrupt should be edge or level
triggered.

Other interrupt controllers that QEMU models may behave differently.
(For instance the ARMv7M NVIC is different again.)

> 2. interrupt signal will be passed through GIC from device to CPU. There
> are four types of interrupt in CPU: CPU_INTERRUPT_HARD/FIQ/VIRQ/VFIQ.
> Where exactly define the CPU_INTERRUPT_{type} that device's interrupt
> corresponded?

Again, this is configurable by the guest by writing to GIC registers.
In the GICv2, the GICD_IGROUPRn registers set the whether the interrupt
should be in "group 0" or "group 1". Group 1 interrupts always
cause an IRQ; group 0 interrupts cause either IRQ or FIQ depending
on the setting of the GICC_CTLR FIQEn bit. (The expected use is that
interrupts configured for use with the TrustZone Secure World will
use FIQ and those configured for use with the NonSecure World will
use IRQ.)

VIRQ and VFIQ are for when the GIC and CPU support the Virtualization
Extension.

The behaviour of all of this is defined by the GIC specification;
QEMU just has to implement what the hardware does.

> 3. I have seen others device's code under qemu/hw directory. Almost all
> device will call qemu_set_irq() at the end of device's read/write. Is that
> for the purpose of a device to tell CPU that it has done some works?
> but the second parameter of qemu_set_irq(), level, will be set to a
> different value(not always 1 or 0), which sometimes will cause the
> interrupt return at gic_set_irq() instead of passing to CPU.
> What does the interrupt at the end of device_read/write(device_update())
> mean?

The best way to think of this is not to try to think about whether
the interrupt line is connected to the CPU or anything else. Just
think about a device model as being an emulation of a particular
bit of hardware. For instance, take the pl011 UART. The specification
for that UART says that when certain conditions inside the device are
true, the UART will assert its outgoing interrupt line. So our model
also must check those conditions and call qemu_set_irq() to raise
and lower the interrupt at the right time. The common way to code
this is to have a function which is called whenever any of the
relevant state has changed, which rechecks the conditions and calls
qemu_set_irq(). The "purpose" of this code is just to behave the
way the hardware behaves.

Commonly, the output IRQ line from a device is connected to an
interrupt controller and thus to a CPU, but it doesn't have to be.
On some boards, the IRQ line might not be connected to anything.
Or it might be connected up to some other device which provides its
value to the guest via a status register. Or perhaps it's ORed together
with lines from other devices and the output of the OR gate goes
to the interrupt controller. If you're designing a board in real
hardware, you are taking various components (UART, interrupt
controller, etc) and connecting them up to implement a useful design.
In QEMU, we also take various components and connect them up, to
produce the same design the hardware has.

qemu_set_irq() is usually just modelling what in the hardware is a
simple wire. The source end calls this function to say "the wire
is at logical 0/1", and on the destination end a function is called
to handle that. It is also possible to pass in a value other than
0 or 1. This happens in two cases:
 (1) a bug, where the source end really ought to be using 0 or 1;
often this doesn't have any visible bad effects because the
destination end is testing 0 vs not-0, rather than 0 vs 1
 (2) we really do want to transfer an integer rather than just
a 0-vs-1 level. This is less common and only happens when both
ends of the "wire" know that that's the convention they want to use.

I think the overall theme of my reply is that fundamentally
QEMU is modelling hardware. If you want to understand why
parts of QEMU are connected the way they are, or why they
behave in a particular way, then looking at what the
specification of the hardware is and how the hardware is
connected, will often help a lot.

thanks
-- PMM

      reply	other threads:[~2018-06-01  9:25 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-23 10:45 [Qemu-devel] Questions about the flow of interrupt simulation Eva Chen
2018-05-24 13:40 ` Peter Maydell
2018-06-01  6:17   ` Eva Chen
2018-06-01  9:25     ` Peter Maydell [this message]

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='CAFEAcA9nfL6UwiZO6USfLuNH_yg3CMk=ngnrwVXC=DgVnjv9wg@mail.gmail.com' \
    --to=peter.maydell@linaro.org \
    --cc=debby83729@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /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.