x86: Provide stub for programming VT-d interrupt remapping table entries

This allows us to step-wise build up the infrastructure on the IOAPIC
and PCI subsystem side.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
configs: Prepare h87i for interrupt remapping

Add the missing configuration bits that will allow us to remap IOAPIC
interrupts and MSIs.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Factor out ioapic_reg_read/write

There will be more spots where we need to talk to the IOAPIC. These
helpers enable and coordinate the access.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Define access moderation for IOAPIC EOI register

There is no point in virtualizating this register. Only avoid that a
cell without any business with the IOAPIC can write to it.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
core: Report root cell as added/removed on initial config commit

This aligns the initial config commit with those performed on non-root
cell creation and destruction. We only need to avoid some then redundant
operations on the root cell in x86's arch_config_commit and
vtd_config_commit.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Virtualize IOAPIC redir table for interrupt remapping support

Handover the IOAPIC on hypervisor setup by first masking all pins, then
requesting interrupt remapping from VT-d and finally reprogramming them
according to the index that VT-d reported. If vtd_map_interrupt returns
-ENOSYS, unconditionally right now due to a missing implementation,
later on when running in QEMU, we continue to write the redirection
table entry unmodified.

As we may lose edge-triggered interrupts while they are makes, we inject
them unconditionally into the target CPU. This may cause one spurious
interrupt per handover to/from the hypervisor, but Linux can deal with
that.

Whenever a cell is added or removed, we rewrite all root cell IOAPIC
redir table entries in oder to validate them regarding the target CPU
masks.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
core: Virtualize legacy MSI for interrupt remapping support

Analogously to edge-triggered IOAPIC interrupts, handover all legacy
MSIs by disabling them first, programming the VT-d remapping table and
then writing remappable parameters into the MSI capability registers.
An additional triggering of active vector unsures that we do not lose
events during handover.

Disabling is done on x86 via a trick: we program an empty CPU mask in
logical destination mode.

MSI-X remains on the to-do list. Thus, once enabling interrupt
remapping, systems that use MSI-X will become unsupported for the time
being.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Perform VT-d interrupt remapping table programming

This fills vtd_map_interrupt with the missing logic to set entries in
the interrupt remapping table and programs the hardware to use that
table, blocking all non-remappable interrupts.

vtd_map_interrupt performs the required entry validation and rejects any
improper settings. There is one exception: CPU masks in logical
destination mode will silently be adjusted instead of failing the
service call. The reason is that Linux may have these masks set for
practically inactive interrupt vectors programmed  (e.g. enabled MSI
vectors of PCIe ports without any port service using them) and will only
update them when they may be used again. Failing such settings would
stop Linux prematurely.

We reserve remapping table entries for the IOAPIC upon cell creation. We
also reserve as many entries as MSI vectors are reported for each PCI
device of a cell. IOAPIC reservation happens only once, and the region
is kept over the lifetime of the hypervisor as the IOAPIC may be shared
between cells (though this is not recommended). PCI device reservations
are released again when the device is removed from its owning cell.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>