I am writing a virtual machine for aarch64. My system is using gicv2. Now I am dealing with virutal interrupt. I have implemented a virtual gicd and mapped gicv to guest gicc. When I booted linux, I found the interrupt only triggered once . After debugging, I suppose there are some problems with deactive virtual interrupt. The debug process is as follows:
The processing of virtual interrupts is as follows: Using the virtual timer interrupt (interrupt number 27) as an example. Upon receiving the interrupt, the system traps from the guest to the Hypervisor (EL2). The Hypervisor then performs operations on the Virtual Generic Interrupt Controller (GICH) to inject the interrupt. In this case, the value of my GICH_LR register is 0x9a006c1b, indicating that this is a hardware interrupt because its HW, bit [31] is set to 1, and the pINTID, bits [19:10] is 27.
After injecting this interrupt into the virtual machine, I added logging in Linux and found that the interrupt was executed successfully, and the EOI register was written. Since I directly mapped GICV to the guest as GICC, the guest should write to GICV_EOIR in this context. Theoretically, triggering the EOI for the virtual interrupt should lead to a maintenance interrupt, but it does not. I observed that the value of the GICH_MISR register is also 0.
For debugging purposes, I modified the Linux code. After writing EOI to the interrupt, I manually set the GICC_EOIR register by trapping through HVC to EL2. After making this modification, the system can boot successfully. To rule out the possibility that the guest did not successfully write to GICV_EOIR, I attempted trapping to the hypervisor without writing to the GICC_EOIR register, instead writing to GICV_EOIR, but this also proved unsuccessful.
I currently have two questions:
1. Why doesn't the writing to GICV_EOIR trigger a maintenance interrupt while my GICH_HCR is properly set to 0b101? The related GICH_HCR documentation:
2. According to the documentation,
After the virtual machine completes processing the corresponding virtual interrupt, it writes to the GICV_EOIR or GICV_AEOIR to deactivate the interrupt. This deactivates both the virtual interrupt and the corresponding physical interrupt, provided that both of the following conditions are true:
I have verified that the value of GICV_CTLR is 1, EOImode is not set, and I monitored the corresponding GICH_LR values. During guest's asserting interrupt, processing interrupt, and deactivating interrupt, only the state value changes from 01 (pending) to 10 (active) and finally to 00 (deactivated), while the 31st bit HW remains 1. Why doesn't the guest writing to GICV_EOIR result in the interrupt being deactivated?
My linux kernel version is 6.2.15 and I was use qemu to emulating a real aarch64 machine, which means I run my hypervisor in qemu. The qemu version is QEMU emulator version 7.2.5.