From fc163ff04a8fea2b1ada5c47cc1c4c517cbd0c91 Mon Sep 17 00:00:00 2001 From: Haiwei Li Date: Mon, 2 Sep 2024 11:14:32 +0800 Subject: [PATCH 1/3] doc: move closing markers before endif Move the closing markers in the '#define .. #endif' to match the opening markers. Tracked-On: #8665 Signed-off-by: Haiwei Li --- hypervisor/include/arch/x86/asm/page.h | 5 +++-- hypervisor/include/arch/x86/asm/pgtable.h | 4 ++-- hypervisor/include/dm/vrtc.h | 5 ++--- hypervisor/include/dm/vuart.h | 5 +++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hypervisor/include/arch/x86/asm/page.h b/hypervisor/include/arch/x86/asm/page.h index 5ed63a9c7b..ea4f78e247 100644 --- a/hypervisor/include/arch/x86/asm/page.h +++ b/hypervisor/include/arch/x86/asm/page.h @@ -132,8 +132,9 @@ struct page_pool { struct page *alloc_page(struct page_pool *pool); void free_page(struct page_pool *pool, struct page *page); -#endif /* PAGE_H */ /** * @} - */ \ No newline at end of file + */ + +#endif /* PAGE_H */ diff --git a/hypervisor/include/arch/x86/asm/pgtable.h b/hypervisor/include/arch/x86/asm/pgtable.h index a3f819676c..47b1dde977 100644 --- a/hypervisor/include/arch/x86/asm/pgtable.h +++ b/hypervisor/include/arch/x86/asm/pgtable.h @@ -553,8 +553,8 @@ void pgtable_add_map(uint64_t *pml4_page, uint64_t paddr_base, void pgtable_modify_or_del_map(uint64_t *pml4_page, uint64_t vaddr_base, uint64_t size, uint64_t prot_set, uint64_t prot_clr, const struct pgtable *table, uint32_t type); -#endif /* PGTABLE_H */ /** * @} - */ \ No newline at end of file + */ +#endif /* PGTABLE_H */ \ No newline at end of file diff --git a/hypervisor/include/dm/vrtc.h b/hypervisor/include/dm/vrtc.h index 27be540236..52b94504e8 100644 --- a/hypervisor/include/dm/vrtc.h +++ b/hypervisor/include/dm/vrtc.h @@ -74,8 +74,7 @@ struct acrn_vrtc { struct rtcdev rtcdev; /**< Register layout of RTC. */ }; -#endif /* VRTC_H */ - /** * @} - */ \ No newline at end of file + */ +#endif /* VRTC_H */ \ No newline at end of file diff --git a/hypervisor/include/dm/vuart.h b/hypervisor/include/dm/vuart.h index 52f2360d00..ddb07ef11c 100644 --- a/hypervisor/include/dm/vuart.h +++ b/hypervisor/include/dm/vuart.h @@ -119,8 +119,9 @@ bool is_vuart_intx(const struct acrn_vm *vm, uint32_t intx_gsi); uint8_t vuart_read_reg(struct acrn_vuart *vu, uint16_t offset); void vuart_write_reg(struct acrn_vuart *vu, uint16_t offset, uint8_t value); -#endif /* VUART_H */ /** * @} - */ \ No newline at end of file + */ + +#endif /* VUART_H */ \ No newline at end of file From c2e88f4d6464e640a99d3408c40026ee51d4e09c Mon Sep 17 00:00:00 2001 From: Haiwei Li Date: Fri, 27 Sep 2024 23:34:31 +0800 Subject: [PATCH 2/3] hv: vioapic: refactor some codes in vioapic This patch is to: * Trim trailing whitespaces * Use macro and add comments * Add lock around `reset_one_vioapic()` Tracked-On: #8740 Signed-off-by: Haiwei Li --- hypervisor/dm/vioapic.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hypervisor/dm/vioapic.c b/hypervisor/dm/vioapic.c index 6c5992f34d..533f3ba3d7 100644 --- a/hypervisor/dm/vioapic.c +++ b/hypervisor/dm/vioapic.c @@ -122,7 +122,7 @@ vgsi_to_vioapic_and_vpin(const struct acrn_vm *vm, uint32_t vgsi, uint32_t *vpin if (is_service_vm(vm)) { /* * Utilize platform ioapic_info for Service VM - */ + */ vioapic_index = get_gsi_to_ioapic_index(vgsi); if (vpin != NULL) { *vpin = gsi_to_ioapic_pin(vgsi); @@ -241,7 +241,9 @@ vioapic_indirect_read(struct acrn_single_vioapic *vioapic, uint32_t addr) if ((addr_offset & 0x1U) != 0U) { ret = vioapic->rtbl[pin].u.hi_32; } else { - if (is_lapic_pt_configured(vioapic->vm) && (vioapic->rtbl[pin].bits.trigger_mode != 0UL)) { + /* RIRR is only used for level triggered interrupts and it's undefined for edge triggered. */ + if (is_lapic_pt_configured(vioapic->vm) && + (vioapic->rtbl[pin].bits.trigger_mode == IOAPIC_RTE_TRGRMODE_LEVEL)) { /* * For local APIC passthrough case, EOI would not trigger VM-exit. So virtual * 'Remote IRR' would not be updated. Needs to read physical IOxAPIC RTE to @@ -510,10 +512,13 @@ static void reset_one_vioapic(struct acrn_single_vioapic *vioapic) void reset_vioapics(const struct acrn_vm *vm) { struct acrn_vioapics *vioapics = vm_ioapics(vm); + uint64_t rflags; uint8_t vioapic_index; for (vioapic_index = 0U; vioapic_index < vioapics->ioapic_num; vioapic_index++) { + spinlock_irqsave_obtain(&(vioapics->vioapic_array[vioapic_index].lock), &rflags); reset_one_vioapic(&vioapics->vioapic_array[vioapic_index]); + spinlock_irqrestore_release(&(vioapics->vioapic_array[vioapic_index].lock), rflags); } } From 13ac8bd0debfd66e21fbcb05761c647ff1055c38 Mon Sep 17 00:00:00 2001 From: Haiwei Li Date: Fri, 6 Sep 2024 09:28:40 +0800 Subject: [PATCH 3/3] doc: add module design for vioapic GAI Tooling Notice: These contents may have been developed with support from one or more generative artificial intelligence solutions. This patch is to add doxygen style comments for some elements in vp-dm_vioapic module. Tracked-On: #8665 Signed-off-by: Haiwei Li --- hypervisor/dm/vioapic.c | 242 +++++++++++++++++++++++++++++--- hypervisor/include/dm/vioapic.h | 84 +++++++---- 2 files changed, 278 insertions(+), 48 deletions(-) diff --git a/hypervisor/dm/vioapic.c b/hypervisor/dm/vioapic.c index 533f3ba3d7..c9325c1004 100644 --- a/hypervisor/dm/vioapic.c +++ b/hypervisor/dm/vioapic.c @@ -1,7 +1,7 @@ /*- * Copyright (c) 2013 Tycho Nightingale * Copyright (c) 2013 Neel Natu - * Copyright (c) 2017-2022 Intel Corporation. + * Copyright (c) 2017-2024 Intel Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,11 +37,32 @@ #include #include +/** + * @addtogroup vp-dm_vioapic + * + * @{ + */ + +/** + * @file + * @brief Implementation of the virtual I/O APIC. + * + * This file contains the implementation of the virtual I/O APIC. It also defines some helper functions to simulate + * the virtual I/O APIC that are commonly used in this file. + */ + #define RTBL_RO_BITS ((uint32_t)0x00004000U | (uint32_t)0x00001000U) /*Remote IRR and Delivery Status bits*/ #define DBG_LEVEL_VIOAPIC 6U #define ACRN_IOAPIC_VERSION 0x11U +/** + * @brief The default definition of a RTE. + * + * It emulates the virtual I/O APIC as a "82093AA I/O Advanced Programmable Interrupt Controller". Per spec, the default + * value of the redirection table entry (RTE) is xxx1xxxxxxxxxxxxh. The 'mask' (bit 16) is also set to mask the + * interrupt. + */ #define MASK_ALL_INTERRUPTS 0x0001000000010000UL static inline struct acrn_vioapics *vm_ioapics(const struct acrn_vm *vm) @@ -137,19 +158,37 @@ vgsi_to_vioapic_and_vpin(const struct acrn_vm *vm, uint32_t vgsi, uint32_t *vpin } /** - * @brief Set vIOAPIC IRQ line status. + * @brief Set virtual I/O APIC IRQ line status for the specified GSI. * - * Similar with vioapic_set_irqline_lock(),but would not make sure - * operation be done with ioapic lock. + * This function sets the corresponding IRQ line status but would not make sure the set be done with I/O APIC lock. It + * will assert or deassert the IRQ. * - * @param[in] vm Pointer to target VM - * @param[in] vgsi Target GSI number - * @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/ - * GSI_RAISING_PULSE/GSI_FALLING_PULSE + * The operation option is limited to one of GSI_SET_HIGH/GSI_SET_LOW/GSI_RAISING_PULSE/GSI_FALLING_PULSE. Otherwise, + * it does nothing. + * It first gets the corresponding virtual I/O APIC and pin number (index in the Redirection Table) based on the input + * GSI number. + * - For the Service VM, it utilizes the platform I/O APIC information to get the virtual I/O APIC and the pin number. + * - For other VMs, it directly uses virtual I/O APIC 0 and the GSI number as the pin number. + * It sets the corresponding pin state based on the input operation option. + * - GSI_SET_HIGH: Set corresponding pin state to high. + * - GSI_SET_LOW: Set corresponding pin state to low. + * - GSI_RAISING_PULSE: Set corresponding pin state to high and then to low. + * - GSI_FALLING_PULSE: Set corresponding pin state to low and then to high. + * After every set operation, it checks the polarity of the corresponding RTE and the other conditions to determine + * whether to generate an interrupt. If the polarity is active, the RTE is not masked, and the remote irr bit is + * cleared, it generates an interrupt and deliver the interrupt to the local APIC. For detailed local APIC operation, + * see vlapic_receive_intr(). + * + * @param[inout] vm Pointer to the VM for which the virtual I/O APIC IRQ line status is set. + * @param[in] vgsi The GSI number to locate the virtual I/O APIC and the offset in the Redirection Table (RT). + * @param[in] operation The action option to set the virtual I/O APIC IRQ line status. * - * @pre vgsi < get_vm_gsicount(vm) - * @pre vm != NULL * @return None + * + * @pre vm != NULL + * @pre vgsi < get_vm_gsicount(vm) + * + * @post N/A */ void vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation) @@ -183,15 +222,27 @@ vioapic_set_irqline_nolock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t ope } /** - * @brief Set vIOAPIC IRQ line status. + * @brief Set IRQ line status with I/O APIC lock for the specified GSI. * - * @param[in] vm Pointer to target VM - * @param[in] vgsi Target GSI number - * @param[in] operation Action options: GSI_SET_HIGH/GSI_SET_LOW/ - * GSI_RAISING_PULSE/GSI_FALLING_PULSE + * This function sets the corresponding IRQ line status with the I/O APIC lock. It will assert or deassert the IRQ. + * + * It first gets the corresponding virtual I/O APIC and pin number (index in the Redirection Table) based on the input + * GSI number. + * - For the Service VM, it utilizes the platform I/O APIC information to get the virtual I/O APIC and the pin number. + * - For other VMs, it directly uses virtual I/O APIC 0 and the GSI number as the pin number. + * It sets the IRQ line status witch the virtual I/O APIC lock. For detailed set operation, see + * vioapic_set_irqline_nolock(). + * + * @param[inout] vm Pointer to the VM for which the virtual I/O APIC IRQ line status is set. + * @param[in] vgsi The GSI number to locate the virtual I/O APIC and the offset in the Redirection Table (RT). + * @param[in] operation The action option to set the virtual I/O APIC IRQ line status. + * + * @return None * - * @pre vgsi < get_vm_gsicount(vm) * @pre vm != NULL + * @pre vgsi < get_vm_gsicount(vm) + * + * @post N/A */ void vioapic_set_irqline_lock(const struct acrn_vm *vm, uint32_t vgsi, uint32_t operation) @@ -370,7 +421,6 @@ static void vioapic_indirect_write(struct acrn_single_vioapic *vioapic, uint32_t if ((new.bits.intr_mask == IOAPIC_RTE_MASK_CLR) || (last.bits.intr_mask == IOAPIC_RTE_MASK_CLR)) { /* VM enable intr */ /* NOTE: only support max 256 pin */ - (void)ptirq_intx_pin_remap(vioapic->vm, vioapic->chipinfo.gsi_base + pin, INTX_CTLR_IOAPIC); } @@ -480,6 +530,28 @@ vioapic_process_eoi(struct acrn_single_vioapic *vioapic, uint32_t vector) spinlock_irqrestore_release(&(vioapic->lock), rflags); } +/** + * @brief Broadcasts End of Interrupt (EOI) message to all virtual I/O APICs in the VM. + * + * This function is used to emulate the behavior of broadcasting an EOI message from the Local APIC (LAPIC) to all I/O + * APICs in the specified VM. It is typically called when the LAPIC receives an EOI command and broadcasts the EOI + * message to all virtual I/O APICs for a level triggered interrupt. + * + * It iterates through all virtual I/O APICs in the specified VM, and EOI message is valid only for the RTEs with the + * same vector as the specified vector and the remote IRR bit is set. + * For a pass-through device, it deasserts the pin level to make the interrupt inactive and unmask the corresponding + * RTE. For detailed operations, see ptirq_intx_ack(). + * It clears the remote IRR bit of the corresponding RTE and generates an interrupt if the pin level is asserted. + * + * @param[inout] vm Pointer to the VM for which the EOI message is broadcast to. + * @param[in] vector The vector within the EOI message to be broadcast. + * + * @return None + * + * @pre vm != NULL + * + * @post N/A + */ void vioapic_broadcast_eoi(const struct acrn_vm *vm, uint32_t vector) { struct acrn_single_vioapic *vioapic; @@ -509,6 +581,24 @@ static void reset_one_vioapic(struct acrn_single_vioapic *vioapic) vioapic->ioregsel = 0U; } +/** + * @brief Reset all virtual I/O APICs for a given VM. + * + * This function resets all virtual I/O APICs for a given VM. It reinitializes the state of each virtual IOAPIC to its + * default state. This function is typically called during VM reset. + * + * It iterates over all virtual I/O APICs of the specified VM and resets each virtual I/O APIC to its default state. + * Per spec, it initializes every redirection table entry (RTE) to the default value which is 0x0001000000000000. And + * it masks the interrupt by setting the 'mask' (bit 16). + * + * @param[inout] vm Pointer to the VM for which the virtual IOAPICs are to be reset. + * + * @return None + * + * @pre vm != NULL + * + * @post N/A + */ void reset_vioapics(const struct acrn_vm *vm) { struct acrn_vioapics *vioapics = vm_ioapics(vm); @@ -522,6 +612,36 @@ void reset_vioapics(const struct acrn_vm *vm) } } +/** + * @brief Initialize all virtual I/O APICs for a given VM. + * + * This function initializes all virtual I/O APICs for a given VM. It sets up the necessary data structures and + * resources for the virtual I/O APICs to function properly within the VM. This function is usually called during the + * initialization of the VM. + * + * This function emulates every virtual I/O APIC as a "82093AA I/O Advanced Programmable Interrupt Controller" and all + * virtual I/O APICs are stored in the VM data structure (vm->arch_vm.vioapics). + * Different VMs, different emulated I/O APIC information: + * - For the Service VM, the number of virtual I/O APICs is determined by the platform and the I/O APIC information is + * retrieved from the platform. + * - Otherwise, only one virtual I/O APIC is emulated for the VM. The number of redirection table entries (RTEs) is set + * to 48 and the default base address of the virtual I/O APIC is set to 0xFEC00000. + * And for every virtual I/O APIC: + * - Per spec, it initializes every redirection table entry (RTE) to the default value which is 0x0001000000000000. And + * it masks the interrupt by setting the 'mask' (bit 16). + * - It registers the MMIO emulation handler for all the registers and remove the EPT mapping for the registers address + * range. + * The GSI of a RTE is computed as the GSI base of the I/O APIC plus the RTE index (IRQ number). It sets the maximum + * number of GSI as the GSI base of the last I/O APIC plus the number of interrupt pins of that I/O APIC. + * + * @param[inout] vm Pointer to the VM for which the virtual I/O APICs are to be initialized. + * + * @return None + * + * @pre vm != NULL + * + * @post N/A + */ void vioapic_init(struct acrn_vm *vm) { @@ -563,14 +683,76 @@ vioapic_init(struct acrn_vm *vm) } } +/** + * @brief Get the maximum number of GSI for a given VM. + * + * This function returns the maximum number of GSI that the VM can support. + * + * It returns the maximum number of GSI of the given VM. The value is computed during the initialization of all the + * virtual I/O APICs for the VM. For details, see vioapic_init(). + * + * @param[in] vm Pointer to the VM for which the GSI count is to be retrieved. + * + * @return An unsigned integer value that indicates the GSI count of the given VM. + * + * @pre vm != NULL + * + * @post retval >= 0 + */ uint32_t get_vm_gsicount(const struct acrn_vm *vm) { return vm->arch_vm.vioapics.nr_gsi; } -/* +/** + * @brief Handle MMIO (Memory-Mapped I/O) access for the virtual I/O APIC. + * + * This function handles MMIO (Memory-Mapped I/O) read and write operations for the virtual I/O APIC registers. The I/O + * APIC is accessed using an indirect addressing scheme. This function is typically called when the guest performs MMIO + * operations on the virtual I/O APIC. + * + * All operations must follow the operation rules of the 82093AA I/O APIC spec. + * It will do nothing and return -EINVAL if the access size is not 32 bits or the operation is not read or write. + * - For a read operation: + * - If the offset is IOAPIC_REGSEL (Index Register), it will return the value of the index register. + * - If the offset is IOAPIC_WINDOW (Data Register), and according to the index register cached in the last write, the + * operation will have different behaviors: + * - If the index is in the range of ACPI Indriect Registers (including ID Register, Version Register, Arbitration + * ID Register, Redirection Table Register, and Redirection Table), the read operation is emulated and the return + * value is set to corresponding value. And if the trigger mode is level sensitive and LAPIC passthrough is + * configured, the remote irr bit is updated from physical IOAPIC RTE for a pass-through device. + * - Otherwise, the return value is set to 0. + * - For other offsets, the read operation is invalid and the return value is set to 0xFFFFFFFF. + * - It stores the return value of the read in input MMIO request structure. + * - For a write operation: + * - If the offset is IOAPIC_REGSEL (Index Register), it will store the value as the register index to be accessed. + * - If the offset is IOAPIC_WINDOW (Data Register), and according to the index register cached in the last write, + * - it updates the virtual ID register if the index is IOAPIC_ID (ID Register); + * - it updates the redirection table entry if the index is in the range of IOAPIC_REDTBL (Redirection Table + * Register). + * - Some OSes simulate EOI message manually using mask+edge followed by unmask+level, so it clears the remote irr + * bit if the trigger mode is edge sensitive. + * - It adds the virtual GSI to physical GSI mapping for the Service VM if the write RTE is unmasked or the + * previous RTE is unmasked. For detailed operation, see ptirq_intx_pin_remap(). + * - If the RTE is not masked, the remote irr bit is cleared and the pin level is asserted, it generates an + * interrupt and delivers it to the local APIC. For detailed local APIC operation, see vlapic_receive_intr(). + * - For other offsets, it ignores the write operation to indicate that the offset is read-only or reserved. + * Finally, the function returns 0 to indicate that the MMIO operation is successful. + * + * @param[inout] io_req Pointer to the I/O request structure that contains the MMIO request information. For a read + * operation, the read value is stored in this structure. + * @param[inout] handler_private_data Pointer to the acrn_single_vioapic structure that is treated as an I/O APIC. + * + * @return An integer value that indicates the status of the MMIO operation. + * + * @retval -EINVAL If the access size is not 32 bits or the operation is not read or write. + * @retval 0 The MMIO operation is successful. + * + * @pre io_req != NULL * @pre handler_private_data != NULL + * + * @post retval <= 0 */ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_private_data) { @@ -600,9 +782,29 @@ int32_t vioapic_mmio_access_handler(struct io_request *io_req, void *handler_pri } /** + * @brief Retrieves the Redirection Table Entry (RTE) for a specified GSI. + * + * This function is used to get the RTE for a specific GSI in the virtual I/O APIC. The RTE information is used to + * translate the interrupt manifestation on the corresponding interrupt pin into an APIC message. + * + * It first gets the corresponding virtual I/O APIC and pin number (index in the Redirection Table) based on the input + * GSI number. + * - For the Service VM, it utilizes the platform I/O APIC information to get the virtual I/O APIC and the pin number. + * - For other VMs, it directly uses virtual I/O APIC 0 and the GSI number as the pin number. + * Finally it retrieves the RTE for the pin and stores it in the provided rte parameter. + * + * @param[inout] vm Pointer to the VM for which the RTE is to be retrieved. + * @param[in] vgsi The GSI number to locate the virtual I/O APIC and the offset in the Redirection Table (RT). + * @param[out] rte Pointer to the variable where the RTE will be stored. + * + * @return None + * + * @pre vm != NULL * @pre vm->arch_vm.vioapics != NULL * @pre vgsi < get_vm_gsicount(vm) * @pre rte != NULL + * + * @post N/A */ void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte *rte) { @@ -612,3 +814,7 @@ void vioapic_get_rte(const struct acrn_vm *vm, uint32_t vgsi, union ioapic_rte * *rte = vioapic->rtbl[pin]; } + +/** + * @} + */ \ No newline at end of file diff --git a/hypervisor/include/dm/vioapic.h b/hypervisor/include/dm/vioapic.h index cabd4a8a2c..c312a7d938 100644 --- a/hypervisor/include/dm/vioapic.h +++ b/hypervisor/include/dm/vioapic.h @@ -1,7 +1,7 @@ /*- * Copyright (c) 2013 Tycho Nightingale * Copyright (c) 2013 Neel Natu - * Copyright (c) 2017-2022 Intel Corporation. + * Copyright (c) 2017-2024 Intel Corporation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,15 +30,27 @@ #ifndef VIOAPIC_H #define VIOAPIC_H +#include +#include +#include + /** - * @file vioapic.h + * @defgroup vp-dm_vioapic vp-dm.vioapic + * @ingroup vp-dm + * @brief Implementation of the virtual I/O APIC in hypervisor. * - * @brief public APIs for virtual I/O APIC + * This module emulates the virtual I/O APIC in the hypervisor. The I/O APIC is responsible for receiving interrupts + * generated by system hardware and I/O devices and forwarding them to the local APIC as interrupt messages. + * + * @{ */ -#include -#include -#include +/** + * @file + * @brief All APIs to support virtual IOAPIC. + * + * This file defines macros, structures and function declarations for the virtual I/O APIC. + */ #define VIOAPIC_BASE 0xFEC00000UL #define VIOAPIC_SIZE 4096UL @@ -48,42 +60,53 @@ #define IOAPIC_RTE_LOW_INTVEC ((uint32_t)IOAPIC_RTE_INTVEC) -/* - * id field is used to emulate the IOAPIC_ID register of vIOAPIC +/** + * @brief Data structure to illustrate a I/O APIC for a VM. + * + * This data structure contains the information of one I/O APIC for a VM. The I/O APIC is responsible for receiving + * interrupts generated by system hardware and I/O devices and forwarding them to local APICs as interrupt messages. + * + * @consistency self.vm->arch_vm.vioapics.vioapic_array[X] == self + * @alignment N/A + * + * @remark N/A */ - struct acrn_single_vioapic { - spinlock_t lock; - struct acrn_vm *vm; - struct ioapic_info chipinfo; - uint32_t ioregsel; - union ioapic_rte rtbl[REDIR_ENTRIES_HW]; - /* pin_state status bitmap: 1 - high, 0 - low */ - uint64_t pin_state[STATE_BITMAP_SIZE]; + spinlock_t lock; /**< The spinlock to protect simultaneous access of all elements. */ + struct acrn_vm *vm; /**< Pointer to the VM that owns this I/O APIC. */ + struct ioapic_info chipinfo; /**< The information of this I/O APIC. */ + /** + * @brief The register to read or write. + * + * Except for IOREGSEL (index) and IOWIN (data) registers, all other registers are indirect registers. To access + * I/O APIC indirect registers, the guest writes the register index to the index register and then reads/writes + * the register value from/to the data register. This field is used to store the register index. + */ + uint32_t ioregsel; + union ioapic_rte rtbl[REDIR_ENTRIES_HW]; /**< The redirection table of this I/O APIC. */ + uint64_t pin_state[STATE_BITMAP_SIZE]; /**< The status bitmap of all pins: 1 - high, 0 - low. */ }; -/* - * ioapic_num represents the number of IO-APICs emulated for the VM. - * nr_gsi represents the maximum number of GSI emulated for the VM. +/** + * @brief Data structure to illustrate all I/O APICs for a VM. + * + * This data structure contains the information of all I/O APICs for a VM. + * + * @consistency self.vioapic_array[X].vm->arch_vm.vioapics == self + * @alignment N/A + * + * @remark N/A */ struct acrn_vioapics { - uint8_t ioapic_num; - uint32_t nr_gsi; - struct acrn_single_vioapic vioapic_array[CONFIG_MAX_IOAPIC_NUM]; + uint8_t ioapic_num; /**< The number of I/O APICs emulated for the VM. */ + uint32_t nr_gsi; /**< The maximum number of GSI emulated for the VM. */ + struct acrn_single_vioapic vioapic_array[CONFIG_MAX_IOAPIC_NUM]; /**< The array of virtual I/O APICs. */ }; void dump_vioapic(struct acrn_vm *vm); void vioapic_init(struct acrn_vm *vm); void reset_vioapics(const struct acrn_vm *vm); - -/** - * @brief virtual I/O APIC - * - * @addtogroup acrn_vioapic ACRN vIOAPIC - * @{ - */ - /** * @brief Set vIOAPIC IRQ line status. * @@ -120,5 +143,6 @@ struct acrn_single_vioapic *vgsi_to_vioapic_and_vpin(const struct acrn_vm *vm, u /** * @} */ + /* End of acrn_vioapic */ #endif /* VIOAPIC_H */