diff --git a/doc/acrn.doxyfile b/doc/acrn.doxyfile index 7c317145a..9e32b1946 100644 --- a/doc/acrn.doxyfile +++ b/doc/acrn.doxyfile @@ -800,7 +800,11 @@ INPUT = custom-doxygen/mainpage.md \ ../hypervisor/include/public/acrn_hv_defs.h \ ../hypervisor/include/arch/x86/guest/vcpu.h \ ../hypervisor/arch/x86/trusty.c \ - ../devicemodel/include/virtio.h + ../devicemodel/include/virtio.h \ + ../hypervisor/include/arch/x86/ioapic.h \ + ../hypervisor/include/arch/x86/irq.h \ + ../hypervisor/include/arch/x86/lapic.h \ + ../hypervisor/include/common/irq.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/developer-guides/hld/hv-interrupt.rst b/doc/developer-guides/hld/hv-interrupt.rst index d3091a3aa..0b9691270 100644 --- a/doc/developer-guides/hld/hv-interrupt.rst +++ b/doc/developer-guides/hld/hv-interrupt.rst @@ -470,7 +470,7 @@ related operations. void free_irq(uint32_t irq) /* Free irq num and unregister the irq action. */ - void set_irq_trigger_mode(uint32_t irq, bool is_level_trigger) + void set_irq_trigger_mode(uint32_t irq, bool is_level_triggered) /* Set the irq trigger mode: edge-triggered or level-triggered */ uint32_t irq_to_vector(uint32_t irq) diff --git a/hypervisor/arch/x86/irq.c b/hypervisor/arch/x86/irq.c index daf94a243..ad2a0609a 100644 --- a/hypervisor/arch/x86/irq.c +++ b/hypervisor/arch/x86/irq.c @@ -245,7 +245,7 @@ void free_irq(uint32_t irq) spinlock_irqrestore_release(&desc->lock, rflags); } -void set_irq_trigger_mode(uint32_t irq, bool is_level_trigger) +void set_irq_trigger_mode(uint32_t irq, bool is_level_triggered) { uint64_t rflags; struct irq_desc *desc; @@ -256,7 +256,7 @@ void set_irq_trigger_mode(uint32_t irq, bool is_level_trigger) desc = &irq_desc_array[irq]; spinlock_irqsave_obtain(&desc->lock, &rflags); - if (is_level_trigger == true) { + if (is_level_triggered == true) { desc->flags |= IRQF_LEVEL; } else { desc->flags &= ~IRQF_LEVEL; diff --git a/hypervisor/include/arch/x86/ioapic.h b/hypervisor/include/arch/x86/ioapic.h index 9f9486b02..9a91c51b4 100644 --- a/hypervisor/include/arch/x86/ioapic.h +++ b/hypervisor/include/arch/x86/ioapic.h @@ -20,8 +20,34 @@ void setup_ioapic_irqs(void); bool irq_is_gsi(uint32_t irq); uint8_t irq_to_pin(uint32_t irq); + +/** + * @brief Get irq num from pin num + * + * @param[in] pin The pin number + */ uint32_t pin_to_irq(uint8_t pin); + +/** + * @brief Set the redirection table entry + * + * Set the redirection table entry of an interrupt + * + * @param[in] irq The number of irq to set + * @param[in] rte Union of ioapic_rte to set + */ void ioapic_set_rte(uint32_t irq, union ioapic_rte rte); + +/** + * @brief Get the redirection table entry + * + * Get the redirection table entry of an interrupt + * + * @param[in] irq The number of irq to fetch RTE + * @param[inout] rte Pointer to union ioapic_rte to return result RTE + * + * @pre rte != NULL + */ void ioapic_get_rte(uint32_t irq, union ioapic_rte *rte); void suspend_ioapic(void); @@ -33,6 +59,15 @@ void gsi_unmask_irq(uint32_t irq); extern uint8_t pic_ioapic_pin_map[NR_LEGACY_PIN]; #ifdef HV_DEBUG +/** + * @brief Get information of ioapic + * + * It's for debug only. + * + * @param[in] str_max_len The max size of the string containing + * interrupt info + * @param[inout] str_arg Pointer to the output information + */ int get_ioapic_info(char *str_arg, size_t str_max_len); #endif /* HV_DEBUG */ diff --git a/hypervisor/include/arch/x86/irq.h b/hypervisor/include/arch/x86/irq.h index d22494fd0..7959a7af3 100644 --- a/hypervisor/include/arch/x86/irq.h +++ b/hypervisor/include/arch/x86/irq.h @@ -89,6 +89,12 @@ extern spurious_handler_t spurious_handler; uint32_t alloc_irq_num(uint32_t req_irq); uint32_t alloc_irq_vector(uint32_t irq); + +/** + * @brief Get vector number of an interupt from irq number + * + * @param[in] irq The irq_num to convert + */ uint32_t irq_to_vector(uint32_t irq); /* @@ -122,11 +128,27 @@ int exception_vmexit_handler(struct vcpu *vcpu); int interrupt_window_vmexit_handler(struct vcpu *vcpu); int external_interrupt_vmexit_handler(struct vcpu *vcpu); int acrn_handle_pending_request(struct vcpu *vcpu); + +/** + * @brief Initialize the interrupt + * + * To do interrupt initialization for a cpu, will be called for each physical cpu. + * + * @param[in] pcpu_id The id of physical cpu to initialize + */ void interrupt_init(uint16_t pcpu_id); void cancel_event_injection(struct vcpu *vcpu); #ifdef HV_DEBUG +/** + * @brief Get the interupt statistics + * + * It's for debug only. + * + * @param[in] str_max The max size of the string containing interrupt info + * @param[inout] str_arg Pointer to the output interrupt info + */ void get_cpu_interrupt_info(char *str_arg, size_t str_max); #endif /* HV_DEBUG */ diff --git a/hypervisor/include/arch/x86/lapic.h b/hypervisor/include/arch/x86/lapic.h index e9de759f7..cff933c97 100644 --- a/hypervisor/include/arch/x86/lapic.h +++ b/hypervisor/include/arch/x86/lapic.h @@ -51,17 +51,54 @@ enum intr_cpu_startup_shorthand { INTR_CPU_STARTUP_UNKNOWN, }; + +/** + * @brief Save context of lapic + * + * @param[inout] regs Pointer to struct lapic_regs to hold the + * context of current lapic + */ void save_lapic(struct lapic_regs *regs); void early_init_lapic(void); void init_lapic(uint16_t pcpu_id); void send_lapic_eoi(void); + +/** + * @brief Get the lapic id + * + * @return lapic id + */ uint32_t get_cur_lapic_id(void); + +/** + * @brief Send an SIPI to a specific cpu + * + * Send an Startup IPI to a specific cpu, to notify the cpu to start booting. + * + * @param[in] cpu_startup_shorthand The startup_shorthand + * @param[in] dest_pcpu_id The id of destination physical cpu + * @param[in] cpu_startup_start_address The address for the dest pCPU to start running + * + * @pre cpu_startup_shorthand < INTR_CPU_STARTUP_UNKNOWN + */ void send_startup_ipi(enum intr_cpu_startup_shorthand cpu_startup_shorthand, uint16_t dest_pcpu_id, uint64_t cpu_startup_start_address); -/* API to send an IPI to multiple pCPUs */ + +/** + * @brief Send an IPI to multiple pCPUs + * + * @param[in] dest_mask The mask of destination physical cpus + * @param[in] vector The vector of interrupt + */ void send_dest_ipi_mask(uint32_t dest_mask, uint32_t vector); -/* API to send an IPI to a single pCPU */ + +/** + * @brief Send an IPI to a single pCPU + * + * @param[in] pcpu_id The id of destination physical cpu + * @param[in] vector The vector of interrupt + */ void send_single_ipi(uint16_t pcpu_id, uint32_t vector); void suspend_lapic(void); diff --git a/hypervisor/include/common/irq.h b/hypervisor/include/common/irq.h index 3bedd0853..0b8a0a72e 100644 --- a/hypervisor/include/common/irq.h +++ b/hypervisor/include/common/irq.h @@ -14,14 +14,18 @@ typedef void (*irq_action_t)(uint32_t irq, void *priv_data); -/* any field change in below required irq_lock protection with irqsave */ +/** + * @brief Interrupt descriptor + * + * Any field change in below required lock protection with irqsave + */ struct irq_desc { - uint32_t irq; /* index to irq_desc_base */ - uint32_t vector; /* assigned vector */ + uint32_t irq; /**< index to irq_desc_base */ + uint32_t vector; /**< assigned vector */ - irq_action_t action; /* callback registered from component */ - void *priv_data; /* irq_action private data */ - uint32_t flags; /* flags for trigger mode/ptdev */ + irq_action_t action; /**< callback registered from component */ + void *priv_data; /**< irq_action private data */ + uint32_t flags; /**< flags for trigger mode/ptdev */ spinlock_t lock; #ifdef PROFILING_ON @@ -31,10 +35,43 @@ struct irq_desc { #endif }; +/** + * @brief Request an interrupt + * + * Request interrupt num if not specified, and register irq action for the + * specified/allocated irq. + * + * @param[in] req_irq irq_num to request, if IRQ_INVALID, a free irq + * number will be allocated + * @param[in] action_fn Function to be called when the IRQ occurs + * @param[in] priv_data Private data for action function. + * @param[in] flags Interrupt type flags, including: + * IRQF_NONE; + * IRQF_LEVEL - 1: level trigger; 0: edge trigger; + * IRQF_PT - 1: for passthrough dev + * + * @return valid irq num - on success + * @return IRQ_INVALID - on failure + */ int32_t request_irq(uint32_t req_irq, irq_action_t action_fn, void *priv_data, uint32_t flags); +/** + * @brief Free an interrupt + * + * Free irq num and unregister the irq action. + * + * @param[in] irq irq_num to be freed + */ void free_irq(uint32_t irq); -void set_irq_trigger_mode(uint32_t irq, bool is_level_trigger); +/** + * @brief Set interrupt trigger mode + * + * Set the irq trigger mode: edge-triggered or level-triggered + * + * @param[in] irq irq_num of interupt to be set + * @param[in] is_level_triggered Trigger mode to set + */ +void set_irq_trigger_mode(uint32_t irq, bool is_level_triggered); #endif /* COMMON_IRQ_H */