We propose the following method in order to support
interdomain interrupt sharing, where one of the domains is an HVM assigned with
a pass-through device.
This method is limited in a way that we can support
sharing between just two domains: dom0 and an HVM. This method is based on
changing polarity.
Terminology
========
Change polarity algorithm (CPA) - Algorithm when
polarity inversion is used for the EOI recognition. For details see http://lists.xensource.com/archives/html/xen-devel/2007-05/msg01148.html
PLINE - Physical Line. This is the reflection of the
physical line. By changing polarity we know what is the physical line's
status.
VLINE - Virtual Line. This is the HVM virtual
line.
PT Device - A pass-through PCI device assigned to the
HVM.
Dom0 Device - A PCI device assigned to dom0 (by
default).
Interrupt Sharing - Determined by two or more PCI
devices, which their's intx lines are connected to the same IOAPIC's pin (OR
wired), and assigned to different domains.
Re-occurring interrupts - The pline is held asserted
while the IOAPIC fire interrupts continuously.
Spurious interrupts - Whitin a domain context, an
interrupt that passed the ISR chain without handling.
NOTE: A single PCI device can not be assigned to more
than one domain simultaneously.
When a single device is assigned to an HVM, using
CPA, we update the HVM's VLINE according to the PLINE state (both hold the same
value) thus providing complete reflection. It is trivial to see how more than
one device that shares the same line could be assigned to the HVM (using the
same CPA).
In general, we should consider the situation were N
devices from Dom0 shares the same line with M devices from HVM. There are 3
cases possible:
1. N=0, i.e. this line belongs to HVM devices. This
case is already solved with CPA.
2. M=0, i.e. this line belongs to Dom0 devices. This
is basic dom0 functionality.
3. N != 0, M != 0. This is the situation that we want
to handle now, from now on we'll refer to this situation as interdomain shared
interrupt.
Although, our method could be extended to contain
handling for all of the above cases.
Problems related to Interdomain Interrupt Sharing
====================================
* Spurious interrupts.
* Interrupt starvation.
* When we use CPA, we are not getting re-occurring
interrupts, this should be taken into account.
* Even if a shared interrupt was handled by a domain
specific ISR, it is not guaranteed that the pline will be deasserted.
* Interrupt storming - _Physical_ storming is solved
transparently by CPA.
Goals
=====
* Letting both the HVM and DOM0 a chance to handle
the interrupt
* Update the HVM's VLINE correctly when sharing an
interrupt
* Avoid spurious interrupts or at least minimize the
number of such interrupts injected into HVM.
* Stay with a reasonable interrupt
latency.
Proffered Method
=============
1. We gain shared line assertion state by using CPA,
at an assert/deassert event we save the line's state.
2. We perform most of the logic in a periodic timer
module.
Modules
======
1. Timer module. Periodic callback that does all the
logic processing.
2. XEN interrupt handler. Handler is replaced by CPA
that updates PLINE.
3. Dom0 ISR chain. At the end of the chain, we know
whether the interrupt was handled or not, and update the status in Xen using a
hypercall.
States
=====
1. Idle. The PLINE is deasserted. This is "relax
state". We're awaiting the interrupt to come.
2. In Dom0. The interrupt is currently handled by
Dom0. The event was sent into Dom0 and Dom0 ISR is processing it.
3. Process Interrupt. The interrupt was handled by
Dom0. Dom0 got back to us with the results of the handling. Now we need to
decide what to do next. This state can be reached only from state [2].
State machine
===========
The timer callback implement the state machine, it
freezes when we are in the idle state.
The "events" described below are polled by the timer.
We also perform changes in dom0's ISR chain in order to generate these
"events".
The following events are handled:
A. PLINE is deasserted. This event will move state
machine to _Idle_ state from any state. This can happen in one of 2 cases:
1. Initialization.
2. As a result of PLINE deassertion. If PLINE went
down, it means that we're done.
B. Idle state and PLINE is asserted. In this case the
interrupt is injected into DOM0. The state machine moves to "In Dom0". We always
firstly let domain0 try to handle the interrupt, thus logically creating an
interdomain ISR chain beginning with dom0.
C. "In Dom0" and PLINE status is asserted (We read
the status from a timer). Do nothing. We don't know what to do with this
interrupt yet.
D. "Process Interrupt" and PLINE is
asserted.
Few cases are possible:
1. If Dom0 successfully handled the last interrupt
and the interrupt wasn't injected into the HVM, inject the interrupt into Dom0
and move to state "In Dom0". This is the Dom0 interrupt, keep injecting into
Dom0.
2. If Dom0 successfully handled the last interrupt
and the interrupt was injected into the HVM, deassert the HVM vline, and
re-inject the interrupt into Dom0. Move to state "In Dom0".
(This is done in order to solve a case where the HVM
was handling the interrupt, but the line didn't get deasserted because a Dom0
device asserted it before the a PT device deasserted it (as aresult of the HVM
handling). In this case we assume that the HVM is done with it and now it's
Dom0's turn.) 3. If Dom0 didn't successfully handle the last interrupt and the
interrupt was not injected into the HVM, inject the interrupt into the HVM and
stay in the same state. This is an HVM's interrupt. Dom0 rejected it.
4. If Dom0 didn't successfully handle the last
interrupt and the interrupt was injected into HVM, inject interrupt into Dom0
and move to state "in Dom0". HVM is not done yet with current
interrupt.
E."Process Interrupt" and the PLINE is deasserted,-
deassert the HVM interrupt(if neccesary) and move to idle. We handled the
interrupt. Prepare ourself for the new one.
The main idea here is to inject the interrupt into
Dom0 when we don't know what to do with it. If Dom0 takes the ownership, then
let it handle the interrupt. If not, we inject it into the HVM. We recognize
that all of the PT devices are not asserting the line by PLINE deassertion or by
Dom0 taking the ownership back to it.
Any ideas and comments
are wellcome.
Best regards,
Alex
Novik.
Neocleus.