mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-06 19:30:46 +00:00
hv:enable APICv-Posted Interrupt
to enable APICv Posted interrupt supported, following the specifications defined in Intel SDM Section #29.6, Volume3. Posted-interrupt processing is a feature by which a processor processes the virtual interrupts by recording them as pending on the virtual-APIC page. Injecting interrupts to VCPU from remote CPU without causing VM exit on the destination, following steps in SDM Section 29.6,volume3: Tracked-On: #1447 Signed-off-by: Yonghua Huang <yonghua.huang@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
committed by
Xie, Nanlin
parent
a028567b9c
commit
38d5df723d
@@ -483,6 +483,7 @@ static void bsp_boot_post(void)
|
||||
|
||||
timer_init();
|
||||
setup_notification();
|
||||
setup_posted_intr_notification();
|
||||
ptdev_init();
|
||||
|
||||
init_scheduler();
|
||||
@@ -860,6 +861,10 @@ bool is_apicv_intr_delivery_supported(void)
|
||||
return ((cpu_caps.apicv_features & VAPIC_FEATURE_INTR_DELIVERY) != 0U);
|
||||
}
|
||||
|
||||
bool is_apicv_posted_intr_supported(void)
|
||||
{
|
||||
return ((cpu_caps.apicv_features & VAPIC_FEATURE_POST_INTR) != 0U);
|
||||
}
|
||||
|
||||
static void cpu_xsave_init(void)
|
||||
{
|
||||
|
@@ -460,6 +460,7 @@ vlapic_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
|
||||
struct lapic_reg *irrptr, *tmrptr;
|
||||
uint32_t mask;
|
||||
uint32_t idx;
|
||||
int pending_intr;
|
||||
|
||||
ASSERT(vector <= NR_MAX_VECTOR,
|
||||
"invalid vector %u", vector);
|
||||
@@ -480,7 +481,26 @@ vlapic_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
|
||||
}
|
||||
|
||||
if (is_apicv_intr_delivery_supported()) {
|
||||
return apicv_set_intr_ready(vlapic, vector);
|
||||
pending_intr = apicv_set_intr_ready(vlapic, vector);
|
||||
if ((pending_intr != 0)
|
||||
&& is_apicv_posted_intr_supported()
|
||||
&& (get_cpu_id() != vlapic->vcpu->pcpu_id)) {
|
||||
/*
|
||||
* Send interrupt to vCPU via posted interrupt way:
|
||||
* 1. If target vCPU is in non-root mode(running),
|
||||
* send PI notification to vCPU and hardware will
|
||||
* sync PIR to vIRR automatically.
|
||||
* 2. If target vCPU is in root mode(isn't running),
|
||||
* record this request as ACRN_REQUEST_EVENT,then
|
||||
* will pick up the interrupt from PIR and inject
|
||||
* it to vCPU in next vmentry.
|
||||
*/
|
||||
bitmap_set_lock(ACRN_REQUEST_EVENT,
|
||||
&vlapic->vcpu->arch_vcpu.pending_req);
|
||||
vlapic_post_intr(vlapic->vcpu->pcpu_id);
|
||||
return 0;
|
||||
}
|
||||
return pending_intr;
|
||||
}
|
||||
|
||||
idx = vector >> 5U;
|
||||
@@ -508,6 +528,20 @@ vlapic_set_intr_ready(struct acrn_vlapic *vlapic, uint32_t vector, bool level)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Post an interrupt to the vcpu running on 'hostcpu'. */
|
||||
void vlapic_post_intr(uint16_t dest_pcpu_id)
|
||||
{
|
||||
send_single_ipi(dest_pcpu_id, VECTOR_POSTED_INTR);
|
||||
}
|
||||
|
||||
uint64_t apicv_get_pir_desc_paddr(struct vcpu *vcpu)
|
||||
{
|
||||
struct acrn_vlapic *vlapic;
|
||||
|
||||
vlapic = &vcpu->arch_vcpu.vlapic;
|
||||
return hva2hpa(&(vlapic->pir_desc));
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre offset value shall be one of the folllowing values:
|
||||
* APIC_OFFSET_CMCI_LVT
|
||||
@@ -1817,8 +1851,6 @@ vlapic_set_intr(struct vcpu *vcpu, uint32_t vector, bool level)
|
||||
vlapic = vcpu_vlapic(vcpu);
|
||||
if (vlapic_set_intr_ready(vlapic, vector, level) != 0) {
|
||||
vcpu_make_request(vcpu, ACRN_REQUEST_EVENT);
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@@ -25,6 +25,7 @@ struct static_mapping_table {
|
||||
static struct static_mapping_table irq_static_mappings[NR_STATIC_MAPPINGS] = {
|
||||
{TIMER_IRQ, VECTOR_TIMER},
|
||||
{NOTIFY_IRQ, VECTOR_NOTIFY_VCPU},
|
||||
{POSTED_INTR_NOTIFY_IRQ, VECTOR_POSTED_INTR},
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -96,3 +96,22 @@ void setup_notification(void)
|
||||
dev_dbg(ACRN_DBG_PTIRQ, "NOTIFY: irq[%d] setup vector %x",
|
||||
notification_irq, irq_to_vector(notification_irq));
|
||||
}
|
||||
|
||||
static void posted_intr_notification(__unused uint32_t irq, __unused void *data)
|
||||
{
|
||||
/* Dummy IRQ handler for case that Posted-Interrupt Notification
|
||||
* is sent to vCPU in root mode(isn't running),interrupt will be
|
||||
* picked up in next vmentry,do nothine here.
|
||||
*/
|
||||
}
|
||||
|
||||
/*pre-conditon: be called only by BSP initialization proccess*/
|
||||
void setup_posted_intr_notification(void)
|
||||
{
|
||||
if (request_irq(POSTED_INTR_NOTIFY_IRQ,
|
||||
posted_intr_notification,
|
||||
NULL, IRQF_NONE) < 0) {
|
||||
pr_err("Failed to setup posted-intr notification");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -773,6 +773,10 @@ static void init_exec_ctrl(struct vcpu *vcpu)
|
||||
value32 = check_vmx_ctrl(MSR_IA32_VMX_PINBASED_CTLS,
|
||||
VMX_PINBASED_CTLS_IRQ_EXIT);
|
||||
|
||||
if (is_apicv_posted_intr_supported()) {
|
||||
value32 |= VMX_PINBASED_CTLS_POST_IRQ;
|
||||
}
|
||||
|
||||
exec_vmwrite32(VMX_PIN_VM_EXEC_CONTROLS, value32);
|
||||
pr_dbg("VMX_PIN_VM_EXEC_CONTROLS: 0x%x ", value32);
|
||||
|
||||
@@ -864,6 +868,12 @@ static void init_exec_ctrl(struct vcpu *vcpu)
|
||||
exec_vmwrite64(VMX_EOI_EXIT3_FULL, 0UL);
|
||||
|
||||
exec_vmwrite16(VMX_GUEST_INTR_STATUS, 0U);
|
||||
if (is_apicv_posted_intr_supported()) {
|
||||
exec_vmwrite16(VMX_POSTED_INTR_VECTOR,
|
||||
VECTOR_POSTED_INTR);
|
||||
exec_vmwrite64(VMX_PIR_DESC_ADDR_FULL,
|
||||
apicv_get_pir_desc_paddr(vcpu));
|
||||
}
|
||||
}
|
||||
|
||||
/* Load EPTP execution control
|
||||
|
Reference in New Issue
Block a user