Closed pengzechen closed 1 month ago
let curr_vcpu_id = call_interface!(VcpuIf::current_vcpu_id());
error!("current vcpu id: {}", curr_vcpu_id);
Passes the vCPU when the interrupt occurs, Before this, we deed define the VCpuIf trait and implement it in AxVCpu
More details about Vint Handle: Processing Flow(1):
The most important is function find_vm_need_inject()
, when pyh irq is not current vm find_vm_need_inject
will find a vm that need to be injected.
@luodeb find_vm_need_inject
this function should be implented in umhv(app).
Software Generated Interrupts (SGIs) are special types of interrupts that originate from software and are typically used to facilitate communication between cores in multi-core systems. The target CPU is specified by the sender, and SGIs can be routed to one or more cores.
In virtualized environments, due to multiple virtual CPUs (vCPUs) potentially sharing the same physical CPU, the hypervisor must virtualize SGIs to ensure isolation and transparency between virtual machines (VMs).
In a virtualized setting, when a VM attempts to send an SGI, it usually does so by modifying the guest's Generic Interrupt Controller (GIC) related registers. The VM itself cannot directly access the physical GIC Distributor (GICD) registers, so these write operations are intercepted by the hypervisor.
During SGI virtualization, the hypervisor is responsible for the following:
To enable VMs to handle interrupts as if they were using a physical GIC, the hypervisor provides a virtual GIC interface (vGIC). The vGIC simulates the operations of the GICD and Generic Interrupt Controller Core (GICC) registers and maps these registers into the VM's address space.
Virtual GIC supports SGI management within the VM, including:
Privileged Peripheral Interrupts (PPIs) are typically used to manage processor-specific peripheral interrupts. In GICv2, each core has its dedicated PPI, usually including timer interrupts and other local peripheral interrupts. In a virtualized environment, the hypervisor must virtualize these interrupts to allow each VM transparent access and usage.
When a vCPU within a VM needs to process a PPI, it is usually done through operations on the GIC registers. For example, a vCPU might read or clear the status of a particular PPI, an operation that requires interception by the hypervisor.
In a virtualized environment, SPI (Shared Peripheral Interrupt) is a type of interrupt designed to handle interrupts generated by peripherals shared among multiple processor cores. Unlike SGI and PPI, SPI pertains to interrupts for shared devices, allowing multiple CPUs to respond to interrupts generated by the same peripheral. When virtualizing SPI, the hypervisor must ensure isolation between VMs while providing correct interrupt management for shared peripherals.
SPI is typically used for peripherals within the system that can be accessed by multiple processors, such as network adapters and storage controllers. In GICv2, SPI is managed by the GIC Distributor (GICD), allowing multiple processor cores to receive interrupts from the same peripheral. In a virtualized environment, the hypervisor must virtualize SPIs in a form suitable for use by multiple VMs.
When a peripheral generates an interrupt, it passes the SPI through the physical GIC to the corresponding processor cores. In a virtualized environment, the physical interrupt first reaches the hypervisor.
For a GIC with virtualization extensions, the hypervisor uses List Registers to maintain some context information about high-priority virtual interrupts.
struct gich_lr {
uint32_t vid : 10; // Virtual IRQ number
uint32_t pid : 10; // This field varies depending on the value of hw
// If hw=1, this indicates the virtual interrupt is associated with a physical interrupt, and pid is the actual physical IRQ number.
// If hw=0, bit19 indicates whether to signal EOI for maintenance interrupts (not discussed here).
// Bits 12-10: If this is an SGI interrupt (i.e., virtual interrupt ID < 15), then this field represents the requesting CPU ID.
uint32_t resv : 3; // Reserved
uint32_t pr : 5; // Priority of the virtual interrupt
uint32_t state : 2; // Indicates the state of the interrupt: invalid, pending, active, pending and active
uint32_t grp1 : 1; // Indicates whether the virtual interrupt is a Group 1 virtual interrupt
// 0 indicates this is a Group 0 virtual interrupt, representing a secure virtual interrupt, configurable to be sent to the vCPU as either a VIRQ or VFIRQ.
// 1 indicates this is a Group 1 virtual interrupt, representing a non-secure virtual interrupt, which triggers as a VIRQ rather than a VFIRQ.
uint32_t hw : 1; // Whether the virtual interrupt is associated with a hardware physical interrupt
// 0 indicates no, meaning it is triggered in software, and when deactivated, it will not notify the distributor.
// 1 indicates yes, meaning deactivating this virtual interrupt will also perform a deactivate operation on the corresponding physical interrupt.
// Specifically, the deactivate operation, if gicv_ctlr.eoimode=0, writing to the gicv_eoir register performs both a drop priority and deactivate operation simultaneously.
// If gicv_ctlr.eoimode=1, writing to the gicv_eoir register performs a drop priority, and writing to GICV_DIR performs a deactivate.
};
Please move these comments to discussions. these can not be treated as Issues
Part 1: Virtual GIC Configuration
For cases 1, 2, and 3, IPI communication is not required. Case 4 requires IPI communication.
These save some attributes of the GIC and the number of PE (processing elements).
getenable: Directly read the content from the structure.
setenable: Set the GIC according to the vtop and ptov settings. For cases 1, 2, and 3, IPI communication is not needed. Case 4 requires IPI communication.
Other vgicd-emu registers is similar to isenabler.
Part 2: Vint Handle
0-15 (sgi): Case 2 does not need IPI, Case 4 requires IPI.
16-1020 (hw): Case 2 does not need IPI, Case 4 requires IPI.
Processing Flow:
2.Implement an int_inject function in the VM to handle physical vectors. Pseudocode is shown in the diagram.
Part 3: Problems to Solve