hv: vioapic: expose ioapic to guest unconditionally

Some OSes assume the platform must have the IOAPIC. For example:
Linux Kernel allocates IRQ force from GSI (0 if there's no PIC and IOAPIC) on x86.
And it thinks IRQ 0 is an architecture special IRQ, not for device driver. As a
result, the device driver may goes wrong if the allocated IRQ is 0 for RTVM.

This patch expose vIOAPIC to RTVM with LAPIC passthru even though the RTVM can't
use IOAPIC, it servers as a place holder to fullfil the guest assumption.

After vIOAPIC has exposed to guest unconditionally, the 'ready' field could be
removed since we do vIOAPIC initialization for each guest.

Tracked-On: #4691
Signed-off-by: Li Fei1 <fei1.li@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Li Fei1 2020-04-21 10:18:10 +08:00 committed by wenlingz
parent f2479f6489
commit 80c7da8f1c
4 changed files with 19 additions and 24 deletions

View File

@ -272,17 +272,17 @@ basl_fwrite_madt(FILE *fp, struct vmctx *ctx)
EFPRINTF(fp, "\n"); EFPRINTF(fp, "\n");
} }
if (!is_rtvm) { /* Always a single IOAPIC entry, with ID 0 */
/* Always a single IOAPIC entry, with ID 0 */ EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n"); EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
EFPRINTF(fp, "[0001]\t\tLength : 0C\n"); /* iasl expects a hex value for the i/o apic id */
/* iasl expects a hex value for the i/o apic id */ EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0);
EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0); EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
EFPRINTF(fp, "[0001]\t\tReserved : 00\n"); EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n");
EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n"); EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n");
EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n"); EFPRINTF(fp, "\n");
EFPRINTF(fp, "\n");
if (!is_rtvm) {
/* Legacy IRQ0 is connected to pin 2 of the IOAPIC */ /* Legacy IRQ0 is connected to pin 2 of the IOAPIC */
EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); EFPRINTF(fp, "[0001]\t\tLength : 0A\n");

View File

@ -471,10 +471,12 @@ int32_t create_vm(uint16_t vm_id, uint64_t pcpu_bitmap, struct acrn_vm_config *v
/* vpic wire_mode default is INTR */ /* vpic wire_mode default is INTR */
vm->wire_mode = VPIC_WIRE_INTR; vm->wire_mode = VPIC_WIRE_INTR;
/* Init full emulated vIOAPIC instance */ /* Init full emulated vIOAPIC instance:
if (!is_lapic_pt_configured(vm)) { * Present a virtual IOAPIC to guest, as a placeholder interrupt controller,
vioapic_init(vm); * even if the guest uses PT LAPIC. This is to satisfy the guest OSes,
} * in some cases, though the functionality of vIOAPIC doesn't work.
*/
vioapic_init(vm);
/* Populate return VM handle */ /* Populate return VM handle */
*rtn_vm = vm; *rtn_vm = vm;

View File

@ -150,7 +150,6 @@ vgsi_to_vioapic_and_vpin(const struct acrn_vm *vm, uint32_t vgsi, uint32_t *vpin
* *
* @pre vgsi < get_vm_gsicount(vm) * @pre vgsi < get_vm_gsicount(vm)
* @pre vm != NULL * @pre vm != NULL
* @pre vioapic->ready == true
* @return None * @return None
*/ */
void void
@ -204,11 +203,9 @@ vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t opera
struct acrn_single_vioapic *vioapic; struct acrn_single_vioapic *vioapic;
vioapic = vgsi_to_vioapic_and_vpin(vm, vgsi, NULL); vioapic = vgsi_to_vioapic_and_vpin(vm, vgsi, NULL);
if (vioapic->ready) { spinlock_irqsave_obtain(&(vioapic->lock), &rflags);
spinlock_irqsave_obtain(&(vioapic->lock), &rflags); vioapic_set_irqline_nolock(vm, vgsi, operation);
vioapic_set_irqline_nolock(vm, vgsi, operation); spinlock_irqrestore_release(&(vioapic->lock), rflags);
spinlock_irqrestore_release(&(vioapic->lock), rflags);
}
} }
static uint32_t static uint32_t
@ -420,7 +417,6 @@ vioapic_mmio_rw(struct acrn_single_vioapic *vioapic, uint64_t gpa,
/* /*
* @pre vm != NULL * @pre vm != NULL
* @pre vioapic->ready == true
*/ */
static void static void
vioapic_process_eoi(struct acrn_single_vioapic *vioapic, uint32_t vector) vioapic_process_eoi(struct acrn_single_vioapic *vioapic, uint32_t vector)
@ -537,7 +533,6 @@ vioapic_init(struct acrn_vm *vm)
register_mmio_emulation_handler(vm, vioapic_mmio_access_handler, (uint64_t)vioapic->chipinfo.addr, register_mmio_emulation_handler(vm, vioapic_mmio_access_handler, (uint64_t)vioapic->chipinfo.addr,
(uint64_t)vioapic->chipinfo.addr + VIOAPIC_SIZE, (void *)vioapic, false); (uint64_t)vioapic->chipinfo.addr + VIOAPIC_SIZE, (void *)vioapic, false);
ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, (uint64_t)vioapic->chipinfo.addr, VIOAPIC_SIZE); ept_del_mr(vm, (uint64_t *)vm->arch_vm.nworld_eptp, (uint64_t)vioapic->chipinfo.addr, VIOAPIC_SIZE);
vioapic->ready = true;
} }
/* /*
@ -557,7 +552,6 @@ get_vm_gsicount(const struct acrn_vm *vm)
/* /*
* @pre handler_private_data != NULL * @pre handler_private_data != NULL
* @pre vioapic->ready == true
*/ */
int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data) int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data)
{ {

View File

@ -57,7 +57,6 @@ struct acrn_single_vioapic {
spinlock_t lock; spinlock_t lock;
struct acrn_vm *vm; struct acrn_vm *vm;
struct ioapic_info chipinfo; struct ioapic_info chipinfo;
bool ready;
uint32_t ioregsel; uint32_t ioregsel;
union ioapic_rte rtbl[REDIR_ENTRIES_HW]; union ioapic_rte rtbl[REDIR_ENTRIES_HW];
/* pin_state status bitmap: 1 - high, 0 - low */ /* pin_state status bitmap: 1 - high, 0 - low */