1.. _virtual-interrupt-hld:
2
3Virtual Interrupt
4#################
5
6This section introduces the ACRN guest virtual interrupt
7management, which includes:
8
9- vCPU request for virtual interrupt kickoff
10- vPIC, vIOAPIC, and vLAPIC for virtual interrupt injection interfaces
11- physical-to-virtual interrupt mapping for a passthrough device
12- the process of VMX interrupt and exception injection
13
14A standard VM never owns any physical interrupts. All interrupts received by the
15guest OS come from a virtual interrupt injected by vLAPIC, vIOAPIC, or
16vPIC. Such virtual interrupts are triggered either from a passthrough
17device or from I/O mediators in the Service VM via hypercalls. The
18:ref:`interrupt-remapping` section describes how the hypervisor manages
19the mapping between physical and virtual interrupts for passthrough
20devices. However, a hard RTVM with LAPIC passthrough does own the physical
21maskable external interrupts. On its physical CPUs, interrupts are disabled
22in VMX root mode. While in VMX non-root mode, physical interrupts are
23delivered to the RTVM directly.
24
25Devices are emulated inside the Service VM Device Model, i.e.,
26``acrn-dm``. However, for performance consideration, vLAPIC, vIOAPIC, and vPIC
27are emulated inside the hypervisor directly.
28
29From the guest OS point of view, vPIC is Virtual Wire Mode via vIOAPIC. The
30symmetric I/O Mode is shown in :numref:`pending-virt-interrupt` later in
31this section.
32
33The following command-line options to a Linux guest affect whether it uses PIC
34or IOAPIC:
35
36-  **Kernel boot parameter with vPIC**: Add ``maxcpu=0``. The guest OS will use
37   PIC.
38-  **Kernel boot parameter with vIOAPIC**: Add ``maxcpu=1`` (as long as not
39   "0"). The guest OS will use IOAPIC and keep IOAPIC pin 2 as the source of
40   PIC.
41
42.. _vcpu-request-interrupt-injection:
43
44vCPU Request for Interrupt Injection
45************************************
46
47The vCPU request mechanism (described in :ref:`pending-request-handlers`) is
48used to inject interrupts to a certain vCPU. As mentioned in
49:ref:`ipi-management`, physical vector 0xF0 is used to kick the vCPU out of its
50VMX non-root mode. Physical vector 0xF0 is also used to make a request for
51virtual interrupt injection or other requests such as flush EPT.
52
53.. note:: The IPI-based vCPU request mechanism doesn't work for the hard RTVM.
54
55The eventid supported for virtual interrupt injection includes:
56
57.. doxygengroup:: virt_int_injection
58   :project: Project ACRN
59   :content-only:
60
61
62The *vcpu_make_request* is necessary for a virtual interrupt
63injection. If the target vCPU is running under VMX non-root mode, it
64sends an IPI to kick it out, which leads to an external-interrupt
65VM-Exit. In some cases, there is no need to send an IPI when making a request,
66because the CPU making the request itself is the target vCPU. For
67example, the #GP exception request always happens on the current CPU when it
68finds an invalid emulation has happened. An external interrupt for a passthrough
69device always happens on the vCPUs of the VM that the device belongs to.
70After it triggers an external-interrupt VM-Exit, the current CPU is the
71target vCPU.
72
73Virtual LAPIC
74*************
75
76LAPIC is virtualized for all guest types: Service VM and User VMs. Given support
77by the physical processor, APICv virtual interrupt delivery (VID) is enabled
78and supports the Posted-Interrupt feature. Otherwise, it falls back to
79the legacy virtual interrupt injection mode.
80
81vLAPIC provides the same features as the native LAPIC:
82
83-  Vector mask/unmask
84-  Virtual vector injections (Level or Edge trigger mode) to vCPU
85-  vIOAPIC notification of EOI processing
86-  TSC Timer service
87-  vLAPIC support CR8 to update TPR
88-  INIT/STARTUP handling
89
90vLAPIC APIs
91===========
92
93APIs are invoked when an interrupt source from vLAPIC needs to inject
94an interrupt, for example:
95
96- from LVT like LAPIC timer
97- from vIOAPIC for a passthrough device interrupt
98- from an emulated device for an MSI
99
100These APIs finish by making a vCPU request.
101
102.. doxygenfunction:: vlapic_inject_intr
103  :project: Project ACRN
104
105.. doxygenfunction:: vlapic_set_intr
106  :project: Project ACRN
107
108.. doxygenfunction:: vlapic_set_local_intr
109  :project: Project ACRN
110
111.. doxygenfunction:: vlapic_inject_msi
112  :project: Project ACRN
113
114.. doxygenfunction:: vlapic_receive_intr
115  :project: Project ACRN
116
117EOI Processing
118==============
119
120If APICv virtual interrupt delivery is supported, EOI virtualization is enabled.
121Except for level triggered interrupts, the VM will not exit in case of EOI.
122
123If APICv virtual interrupt delivery is not supported, vLAPIC requires
124EOI from the guest OS whenever a vector is acknowledged and processed by the
125guest. vLAPIC behavior is the same as hardware LAPIC. Once an EOI is received,
126it clears the highest priority vector in ISR, and updates PPR
127status. vLAPIC sends an EOI message to vIOAPIC if the TMR bit is set to
128indicate that is a level triggered interrupt.
129
130.. _lapic_passthru:
131
132LAPIC Passthrough Based on vLAPIC
133=================================
134
135LAPIC passthrough is supported based on vLAPIC. The guest OS first boots with
136vLAPIC in xAPIC mode and then switches to x2APIC mode to enable the LAPIC
137passthrough.
138
139If LAPIC passthrough is based on vLAPIC, the system has the
140following characteristics:
141
142* IRQs received by the LAPIC can be handled by the guest VM without ``vmexit``.
143* Guest VM always sees virtual LAPIC IDs for security consideration.
144* Most MSRs are directly accessible from the guest VM except for ``XAPICID``,
145  ``LDR``, and ``ICR``. Write operations to ``ICR`` are trapped to avoid
146  malicious IPIs. Read operations to ``XAPIC`` and ``LDR`` are trapped,
147  so that the guest VM always sees the virtual LAPIC IDs instead of the
148  physical ones.
149
150Virtual IOAPIC
151**************
152
153The hypervisor emulates vIOAPIC when the guest accesses the MMIO GPA range:
1540xFEC00000-0xFEC01000. vIOAPIC for the Service VM should match the native
155hardware IOAPIC pin numbers. vIOAPIC for a guest VM provides 48 pins. As the
156vIOAPIC is always associated with vLAPIC, the virtual interrupt injection from
157vIOAPIC triggers a request for a vLAPIC event by calling vLAPIC APIs.
158
159**Supported APIs:**
160
161.. doxygenfunction:: vioapic_set_irqline_lock
162  :project: Project ACRN
163
164.. doxygenfunction:: vioapic_set_irqline_nolock
165  :project: Project ACRN
166
167Virtual PIC
168***********
169
170vPIC is required for TSC calculation. Normally the guest OS boots with
171vIOAPIC and vPIC as the source of external interrupts. On every
172VM Exit, the hypervisor checks for pending external PIC interrupts.
173Usage of vPIC APIs is similar to that of vIOAPIC.
174
175ACRN hypervisor emulates a vPIC for each VM based on I/O range 0x20~0x21,
1760xa0~0xa1, and 0x4d0~0x4d1.
177
178If an interrupt source from vPIC needs to inject an interrupt, the
179following APIs need be called, which will finally make a request for
180``ACRN_REQUEST_EXTINT`` or ``ACRN_REQUEST_EVENT``:
181
182.. doxygenfunction:: vpic_set_irqline
183  :project: Project ACRN
184
185The following APIs are used to query the vector that needs to be injected and
186ACK the service (move the interrupt from request service - IRR to in
187service - ISR):
188
189.. doxygenfunction:: vpic_pending_intr
190  :project: Project ACRN
191
192.. doxygenfunction:: vpic_intr_accepted
193  :project: Project ACRN
194
195Virtual Exception
196*****************
197
198When doing emulation, an exception may need to be triggered in the
199hypervisor for these reasons:
200
201- The guest accesses an invalid vMSR register.
202- The hypervisor needs to inject a #GP.
203- The hypervisor needs to inject a #PF when an instruction accesses a
204  non-existent page from ``rip_gva`` during instruction emulation.
205
206ACRN hypervisor implements virtual exception injection using these APIs:
207
208.. doxygenfunction:: vcpu_queue_exception
209  :project: Project ACRN
210
211.. doxygenfunction:: vcpu_inject_gp
212  :project: Project ACRN
213
214.. doxygenfunction:: vcpu_inject_pf
215  :project: Project ACRN
216
217.. doxygenfunction:: vcpu_inject_ud
218  :project: Project ACRN
219
220.. doxygenfunction:: vcpu_inject_ss
221  :project: Project ACRN
222
223ACRN hypervisor uses the ``vcpu_inject_gp`` and ``vcpu_inject_pf`` functions to
224queue an exception request. The hypervisor follows `Intel® 64 and IA-32 Architectures Software Developer's Manual <https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html>`__, Volume 3, Section 6.15, Table 6-5, to
225generate a double fault if the condition is met.
226
227ACRN hypervisor can inject ``extint`` and ``nmi`` using similar vCPU APIs:
228
229.. doxygenfunction:: vcpu_inject_extint
230  :project: Project ACRN
231
232.. doxygenfunction:: vcpu_inject_nmi
233  :project: Project ACRN
234
235
236.. _virt-interrupt-injection:
237
238Virtual Interrupt Injection
239***************************
240
241Virtual interrupts come from the DM or assigned
242devices.
243
244-  **For Service VM assigned devices**: Whenever a physical interrupt
245   is from an assigned
246   device, the corresponding virtual interrupt is injected to the Service
247   VM via vLAPIC/vIOAPIC. See :ref:`device-assignment`.
248
249-  **For User VM assigned devices**: Only PCI devices can be assigned to
250   User VMs. For the standard VM and soft RTVM, the virtual interrupt
251   injection process is the same way as for the Service VM. A virtual interrupt
252   injection
253   operation is triggered when a device's physical interrupt occurs. For the
254   hard RTVM, the physical interrupts are delivered to the VM directly without
255   causing VM-exit.
256
257-  **For User VM emulated devices**: DM manages the interrupt lifecycle of
258   emulated devices. DM knows when
259   an emulated device needs to assert a virtual IOAPIC/PIC pin or
260   needs to send a virtual MSI vector to the guest. The logic is
261   entirely handled by DM. Hard RTVMs should not have
262   emulated devices.
263
264.. figure:: images/virtint-image64.png
265   :align: center
266   :name: pending-virt-interrupt
267
268   Handle pending virtual interrupt
269
270Before APICv virtual interrupt delivery, a virtual interrupt can be
271injected only if the guest interrupt is allowed. In many cases,
272the guest ``RFLAGS.IF`` gets cleared and does not accept any further
273interrupts. The hypervisor checks for the available guest IRQ windows before
274injection.
275
276NMI is an unmaskable interrupt and its injection is always allowed
277regardless of the guest IRQ window status. If the current IRQ
278window is not present, the hypervisor enables
279``MSR_IA32_VMX_PROCBASED_CTLS_IRQ_WIN (PROCBASED_CTRL.bit[2])`` and
280VM Enter directly. The injection will be done on the next VM Exit once the guest
281issues ``STI (GuestRFLAG.IF=1)``.
282
283Data Structures and Interfaces
284******************************
285
286No data structure is exported to the other components in the
287hypervisor for virtual interrupts. The APIs listed in the previous
288sections are meant to be called whenever a virtual interrupt should be
289injected or acknowledged.
290