Expand description
x2APIC Emulation
Background
Advanced Programmable Interrupt Controller
In interrupt handling, the Advanced Programmable Interrupt Controller (APIC) represents a significantly improved alternative to the conventional Programmable Interrupt Controller (PIC). Originally, the 8235 PIC chip was responsible for interrupt processing, but due to speed and functionality considerations, interrupt handling routine was refined and integrated into the CPU in the cases of the local core interrupts.
APIC is implemented as separate Local APIC and IOAPIC components. The former is embedded within each processor, while the latter is located in the system bus. APIC’s primary objective is to process interrupts on processors and forward them to designated cores, as well as facilitate Inter-Processor Interrupt (IPI) communication in multicore environments.
Over time, Intel has enhanced the APIC to newer versions such as xAPIC and x2APIC. One of the main differences between APIC and xAPIC is their functionality (Increased number of interrupt lines and flexibility in handling different types of interrupts), while x2APIC offers the ability to modify performance behavior through the use of MSR registers.
LAPIC
Each core has a dedicated Local APIC assigned to it, which can generate interrupts and trigger Inter-Processor Interrupts (IPIs) as well as handle up to 0-31 interrupt processing and 32-225 designated interrupt processing. Local APIC, which is directly connected to the processor’s cores, performs interrupt-related tasks such as handling I/O devices, APIC Timer, IPI, Performance Monitoring Counter, and Thermal Sensor. LAPIC supports High Precision Event Timer (HPET), which is a high-precision timer that assists each core in obtaining accurate current time values without competing for one timer. If APIC is enabled and HPET is supported, the 8253 PIC is disabled.
The definition of how each interrupt behaves can be configured via the Local Vector Table (LVT). LVT is controlled through memory access via MMIO for APIC, xAPIC, and similar devices, and via MSR registers for x2APIC. The Local Vector Table determines which hardware interrupt is forwarded to the core’s interrupt pin.
I/O APIC
The I/O APIC is an Interrupt Controller that is responsible for delivering external device interrupts to the appropriate cores. Interrupts delivered through the I/O APIC are forwarded to the Local APIC based on the LVT configuration and ultimately delivered to the core. The I/O APIC is connected to the system bus and is responsible for delivering interrupts generated by hardware or I/O devices to the core.
The I/O APIC has a Redirection Table that maps incoming interrupts from each device to a designated interrupt number. Unlike the 8253 interrupt controller, which supports only 16 external interrupts, the APIC supports up to 224 additional interrupts, excluding those assigned to hardware, through redirection.
APIC Timer - TSC deadline mode
APIC Timer modes are separated into three different modes for handling timer interrupts.
Periodic Mode and One-shot Mode
The Periodic Mode is a mode in which software (usually the operating system) requests the APIC to generate periodic timer interrupts by setting a specific time interval. For example, in the Periodic Mode, software requests the APIC to insert a timer interrupt every 1ms.
The One-shot Mode is similar to the Periodic Mode but requests the timer interrupt to occur only once. Software requests the APIC to generate a timer interrupt after a certain time interval. For example, software requests the APIC to insert a timer interrupt 1ms later.
TSC-Deadline Mode
The TSC-Deadline Mode has a slightly different characteristic from the other two timer modes. Rather than sending a specific timer interval, this mode requests a timer interrupt when the value of the Time Stamp Counter (TSC) of the core exceeds a specific value. This method uses the TSC timer, which is more accurate than the other two methods that use the CPU frequency, and has a feature that is easy to avoid race conditions. For example, if the current TSC count is 100000, software requests the APIC to generate a timer interrupt when it becomes 100050, which is 100000 + α. Like one-shot mode, software should reprogram the next timer manually to re-trigger the next timer interrupt.
Note that, the TSC deadline setting and initiate interrupts are separated. Initiate x2APIC timer interrupts are done by setting Model Specific Register (MSR register) with 0x832 to 0x10 (TSC-Deadline Mode). However, setting a deadline for Local APIC’s TSC Deadline Mode is done by setting MSR with 0x6e0 to a timestamp for the next deadline.
Tasks
In this project, you are requested to implement timer interrupt virtualization for guest operating system. You need to implement timer interrupt virtualization for the guest by ensuring that a timer interrupt occurs every tick to schedule threads in the guest operating system.
As the guest is unable to use the APIC timer in the host, the host must handle the initialization of the timer and setting of the deadline from the guest. If the TSC value exceeds the guest deadline, a virtual interrupt should be injected into the guest by a separate thread that runs in the hypervisor. This thread is spawned when the guest requests to set the timer as TSC deadline mode and tries to write the timer mode and interrupt vector into the MSR 0x832 (the MSR write is trapped to guest).
After the thread is spawned,
a deadline setting request via 0x6e0 MSR can be sent to the thread to inject interrupts when the TSC value is more than the set deadline.
To share the deadline value between the created thread and the handler for 0x6e0 MSR, the channel
API provided by KeV is used.
Injection of the interrupt into the VM should only be done when the VM is not running, as the injected interrupt is handled when VmEntry occurs.
To inject the timer interrupt into the running vCPU, the VMM must 1) kick
the vCPU, 2) inject
the interrupt,
and then 3) resume
the vCPU to execute the timer interrupt in the guest.