hv: revise interfaces description in vlapic

Add comments for APIs:
 - vlapic_pending_intr();
 - vlapic_pending_accepted();
 - vlapic_post_intr();
 - lapicv_get_pir_desc_paddr();
 - vlapic_intr_level();
 - vlapic_intr_edge();
 - vlapic_set_local_intr();
 - vlapic_intr_msi();

Tracked-On: #1595
Signed-off-by: Yonghua Huang <yonghua.huang@intel.com>
This commit is contained in:
Yonghua Huang 2018-10-31 00:09:57 +08:00 committed by David Kinder
parent 469496311c
commit c41f286085
2 changed files with 188 additions and 19 deletions

View File

@ -531,12 +531,35 @@ vlapic_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
return 1; return 1;
} }
/* Post an interrupt to the vcpu running on 'hostcpu'. */ /**
* @brief Send notification vector to target pCPU.
*
* If APICv Posted-Interrupt is enabled and target pCPU is in non-root mode,
* pCPU will sync pending virtual interrupts from PIR to vIRR automatically,
* without VM exit.
* If pCPU in root-mode, virtual interrupt will be injected in next VM entry.
*
* @param[in] dest_pcpu_id Target CPU ID.
*
* @return void
*/
void vlapic_post_intr(uint16_t dest_pcpu_id) void vlapic_post_intr(uint16_t dest_pcpu_id)
{ {
send_single_ipi(dest_pcpu_id, VECTOR_POSTED_INTR); send_single_ipi(dest_pcpu_id, VECTOR_POSTED_INTR);
} }
/**
* @brief Get physical address to PIR description.
*
* If APICv Posted-interrupt is supported, this address will be configured
* to VMCS "Posted-interrupt descriptor address" field.
*
* @param[in] vcpu Target vCPU
*
* @return physicall address to PIR
*
* @pre vcpu != NULL
*/
uint64_t apicv_get_pir_desc_paddr(struct vcpu *vcpu) uint64_t apicv_get_pir_desc_paddr(struct vcpu *vcpu)
{ {
struct acrn_vlapic *vlapic; struct acrn_vlapic *vlapic;
@ -1286,6 +1309,19 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
return 0; /* handled completely in the kernel */ return 0; /* handled completely in the kernel */
} }
/**
* @brief Get pending virtual interrupts for vLAPIC.
*
* @param[in] vlapic Pointer to target vLAPIC data structure
* @param[inout] vecptr Pointer to vector buffer and will be filled
* with eligible vector if any.
*
* @return 0 - There is no eligible pending vector.
* @return 1 - There is pending vector.
*
* @remark The vector does not automatically transition to the ISR as a
* result of calling this function.
*/
int int
vlapic_pending_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr) vlapic_pending_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr)
{ {
@ -1318,6 +1354,21 @@ vlapic_pending_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr)
return 0; return 0;
} }
/**
* @brief Accept virtual interrupt.
*
* Transition 'vector' from IRR to ISR. This function is called with the
* vector returned by 'vlapic_pending_intr()' when the guest is able to
* accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that
* block interrupt delivery).
*
* @param[in] vlapic Pointer to target vLAPIC data structure
* @param[in] vector Target virtual interrupt vector
*
* @return void
*
* @pre vlapic != NULL
*/
void void
vlapic_intr_accepted(struct acrn_vlapic *vlapic, uint32_t vector) vlapic_intr_accepted(struct acrn_vlapic *vlapic, uint32_t vector)
{ {
@ -1879,17 +1930,12 @@ int
vlapic_set_intr(struct vcpu *vcpu, uint32_t vector, bool level) vlapic_set_intr(struct vcpu *vcpu, uint32_t vector, bool level)
{ {
struct acrn_vlapic *vlapic; struct acrn_vlapic *vlapic;
int ret = 0;
if (vcpu == NULL) {
return -EINVAL;
}
/* /*
* According to section "Maskable Hardware Interrupts" in Intel SDM * According to section "Maskable Hardware Interrupts" in Intel SDM
* vectors 16 through 255 can be delivered through the local APIC. * vectors 16 through 255 can be delivered through the local APIC.
*/ */
if (vector > 255U) { if ((vcpu == NULL) || (vector > 255U)) {
return -EINVAL; return -EINVAL;
} }
@ -1905,9 +1951,22 @@ vlapic_set_intr(struct vcpu *vcpu, uint32_t vector, bool level)
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT); vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
} }
return ret; return 0;
} }
/**
* @brief Triggers LAPIC local interrupt(LVT).
*
* @param[in] vm Pointer to VM data structure
* @param[in] vcpu_id_arg ID of vCPU, BROADCAST_CPU_ID means triggering
* interrupt to all vCPUs.
* @param[in] vector Vector to be fired.
*
* @return 0 on success.
* @return -EINVAL on error that vcpu_id_arg or vector is invalid.
*
* @pre vm != NULL
*/
int int
vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id_arg, uint32_t vector) vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id_arg, uint32_t vector)
{ {
@ -1939,6 +1998,18 @@ vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id_arg, uint32_t vector)
return error; return error;
} }
/**
* @brief Inject MSI to target VM.
*
* @param[in] vm Pointer to VM data structure
* @param[in] addr MSI address.
* @param[in] msg MSI data.
*
* @return 0 on success.
* @return non-zero on error that addr is invalid.
*
* @pre vm != NULL
*/
int int
vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg) vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg)
{ {

View File

@ -30,6 +30,14 @@
#ifndef VLAPIC_H #ifndef VLAPIC_H
#define VLAPIC_H #define VLAPIC_H
/**
* @file vlapic.h
*
* @brief public APIs for virtual LAPIC
*/
/* /*
* 16 priority levels with at most one vector injected per level. * 16 priority levels with at most one vector injected per level.
*/ */
@ -103,26 +111,72 @@ struct acrn_vlapic {
void vlapic_set_cr8(struct acrn_vlapic *vlapic, uint64_t val); void vlapic_set_cr8(struct acrn_vlapic *vlapic, uint64_t val);
uint64_t vlapic_get_cr8(const struct acrn_vlapic *vlapic); uint64_t vlapic_get_cr8(const struct acrn_vlapic *vlapic);
/* /**
* Returns 0 if there is no eligible vector that can be delivered to the * @brief virtual LAPIC
* guest at this time and non-zero otherwise.
* *
* If an eligible vector number is found and 'vecptr' is not NULL then it will * @addtogroup acrn_vlapic ACRN vLAPIC
* be stored in the location pointed to by 'vecptr'. * @{
*/
/**
* @brief Get pending virtual interrupts for vLAPIC.
* *
* Note that the vector does not automatically transition to the ISR as a * @param[in] vlapic Pointer to target vLAPIC data structure
* result of calling this function. * @param[inout] vecptr Pointer to vector buffer and will be filled
* with eligible vector if any.
*
* @return 0 - There is no eligible pending vector.
* @return 1 - There is pending vector.
*
* @remark The vector does not automatically transition to the ISR as a
* result of calling this function.
*/ */
int vlapic_pending_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr); int vlapic_pending_intr(const struct acrn_vlapic *vlapic, uint32_t *vecptr);
/* /**
* @brief Accept virtual interrupt.
*
* Transition 'vector' from IRR to ISR. This function is called with the * Transition 'vector' from IRR to ISR. This function is called with the
* vector returned by 'vlapic_pending_intr()' when the guest is able to * vector returned by 'vlapic_pending_intr()' when the guest is able to
* accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that * accept this interrupt (i.e. RFLAGS.IF = 1 and no conditions exist that
* block interrupt delivery). * block interrupt delivery).
*
* @param[in] vlapic Pointer to target vLAPIC data structure
* @param[in] vector Target virtual interrupt vector
*
* @return void
*
* @pre vlapic != NULL
*/ */
void vlapic_intr_accepted(struct acrn_vlapic *vlapic, uint32_t vector); void vlapic_intr_accepted(struct acrn_vlapic *vlapic, uint32_t vector);
/**
* @brief Send notification vector to target pCPU.
*
* If APICv Posted-Interrupt is enabled and target pCPU is in non-root mode,
* pCPU will sync pending virtual interrupts from PIR to vIRR automatically,
* without VM exit.
* If pCPU in root-mode, virtual interrupt will be injected in next VM entry.
*
* @param[in] dest_pcpu_id Target CPU ID.
*
* @return void
*/
void vlapic_post_intr(uint16_t dest_pcpu_id); void vlapic_post_intr(uint16_t dest_pcpu_id);
/**
* @brief Get physical address to PIR description.
*
* If APICv Posted-interrupt is supported, this address will be configured
* to VMCS "Posted-interrupt descriptor address" field.
*
* @param[in] vcpu Target vCPU
*
* @return physicall address to PIR
*
* @pre vcpu != NULL
*/
uint64_t apicv_get_pir_desc_paddr(struct vcpu *vcpu); uint64_t apicv_get_pir_desc_paddr(struct vcpu *vcpu);
int vlapic_rdmsr(struct vcpu *vcpu, uint32_t msr, uint64_t *rval); int vlapic_rdmsr(struct vcpu *vcpu, uint32_t msr, uint64_t *rval);
@ -136,24 +190,63 @@ int vlapic_set_intr(struct vcpu *vcpu, uint32_t vector, bool level);
#define LAPIC_TRIG_LEVEL true #define LAPIC_TRIG_LEVEL true
#define LAPIC_TRIG_EDGE false #define LAPIC_TRIG_EDGE false
/**
* @brief Pend level-trigger mode virtual interrupt to vCPU.
*
* @param[in] vcpu Pointer to target vCPU data structure
* @param[in] vector Vector to be injected.
*
* @return 0 on success.
* @return -EINVAL on error that vector is invalid or vcpu is NULL.
*/
static inline int static inline int
vlapic_intr_level(struct vcpu *vcpu, uint32_t vector) vlapic_intr_level(struct vcpu *vcpu, uint32_t vector)
{ {
return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_LEVEL); return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_LEVEL);
} }
/**
* @brief Pend edge-trigger mode virtual interrupt to vCPU.
*
* @param[in] vcpu Pointer to target vCPU data structure
* @param[in] vector Vector to be injected.
*
* @return 0 on success.
* @return -EINVAL on error that vector is invalid or vcpu is NULL.
*/
static inline int static inline int
vlapic_intr_edge(struct vcpu *vcpu, uint32_t vector) vlapic_intr_edge(struct vcpu *vcpu, uint32_t vector)
{ {
return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_EDGE); return vlapic_set_intr(vcpu, vector, LAPIC_TRIG_EDGE);
} }
/* /**
* Triggers the LAPIC local interrupt (LVT) 'vector' on 'cpu'. 'cpu' can * @brief Triggers LAPIC local interrupt(LVT).
* be set to -1 to trigger the interrupt on all CPUs. *
* @param[in] vm Pointer to VM data structure
* @param[in] vcpu_id_arg ID of vCPU, BROADCAST_CPU_ID means triggering
* interrupt to all vCPUs.
* @param[in] vector Vector to be fired.
*
* @return 0 on success.
* @return -EINVAL on error that vcpu_id_arg or vector is invalid.
*
* @pre vm != NULL
*/ */
int vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id_arg, uint32_t vector); int vlapic_set_local_intr(struct vm *vm, uint16_t vcpu_id_arg, uint32_t vector);
/**
* @brief Inject MSI to target VM.
*
* @param[in] vm Pointer to VM data structure
* @param[in] addr MSI address.
* @param[in] msg MSI data.
*
* @return 0 on success.
* @return non-zero on error that addr is invalid.
*
* @pre vm != NULL
*/
int vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg); int vlapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg);
void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest,
@ -189,4 +282,9 @@ int apic_write_vmexit_handler(struct vcpu *vcpu);
int veoi_vmexit_handler(struct vcpu *vcpu); int veoi_vmexit_handler(struct vcpu *vcpu);
int tpr_below_threshold_vmexit_handler(__unused struct vcpu *vcpu); int tpr_below_threshold_vmexit_handler(__unused struct vcpu *vcpu);
void calcvdest(struct vm *vm, uint64_t *dmask, uint32_t dest, bool phys); void calcvdest(struct vm *vm, uint64_t *dmask, uint32_t dest, bool phys);
/**
* @}
*/
/* End of acrn_vlapic */
#endif /* VLAPIC_H */ #endif /* VLAPIC_H */