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