hv: vLAPIC ICR write and destination mask matching for x2APIC

When guest uses vLAPIC in x2APIC mode, ICR write is a single MSR write.
Also, the destination field for device interrupts and IPIs should not be
handled in the same way as xAPIC mode. This patch adds support for x2APIC
mode operation of guest vLAPIC.

Tracked-On: #1626
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Reviewed-by: Xu Anthony <anthony.xu@intel.com>
This commit is contained in:
Sainath Grandhi 2018-11-01 14:53:09 -07:00 committed by lijinxia
parent 6a4dcce390
commit e9fe6efd81

View File

@ -1009,6 +1009,26 @@ vlapic_calcdest(struct vm *vm, uint64_t *dmask, uint32_t dest,
if (vcpu_id < vm->hw.created_vcpus) { if (vcpu_id < vm->hw.created_vcpus) {
bitmap_set_lock(vcpu_id, dmask); bitmap_set_lock(vcpu_id, dmask);
} }
} else {
/*
* Logical mode: match each APIC that has a bit set
* in its LDR that matches a bit in the ldest.
*/
*dmask = 0UL;
amask = vm_active_cpus(vm);
for (vcpu_id = 0U; vcpu_id < vm->hw.created_vcpus; vcpu_id++) {
if (amask & (1U << vcpu_id)) {
vlapic = vm_lapic_from_vcpu_id(vm, vcpu_id);
if (is_x2apic_enabled(vlapic)){
ldr = vlapic->apic_page.ldr.v;
ldest = ldr & 0xFFFFU;
mda_cluster_id = (dest >> 16U) & 0xFFFFU;
mda_ldest = dest & 0xFFFFU;
if (mda_cluster_id != ((ldr >> 16U) & 0xFFFFU)) {
continue;
}
} else { } else {
/* /*
* In the "Flat Model" the MDA is interpreted as an 8-bit wide * In the "Flat Model" the MDA is interpreted as an 8-bit wide
@ -1023,15 +1043,6 @@ vlapic_calcdest(struct vm *vm, uint64_t *dmask, uint32_t dest,
mda_cluster_id = (dest >> 4U) & 0xfU; mda_cluster_id = (dest >> 4U) & 0xfU;
mda_cluster_ldest = dest & 0xfU; mda_cluster_ldest = dest & 0xfU;
/*
* Logical mode: match each APIC that has a bit set
* in its LDR that matches a bit in the ldest.
*/
*dmask = 0UL;
amask = vm_active_cpus(vm);
for (vcpu_id = 0U; vcpu_id < vm->hw.created_vcpus; vcpu_id++) {
if (amask & (1U << vcpu_id)) {
vlapic = vm_lapic_from_vcpu_id(vm, vcpu_id);
dfr = vlapic->apic_page.dfr.v; dfr = vlapic->apic_page.dfr.v;
ldr = vlapic->apic_page.ldr.v; ldr = vlapic->apic_page.ldr.v;
@ -1060,7 +1071,7 @@ vlapic_calcdest(struct vm *vm, uint64_t *dmask, uint32_t dest,
"vlapic has bad logical model %x", dfr); "vlapic has bad logical model %x", dfr);
continue; continue;
} }
}
if ((mda_ldest & ldest) != 0U) { if ((mda_ldest & ldest) != 0U) {
if (lowprio) { if (lowprio) {
if (target == NULL) { if (target == NULL) {
@ -1152,7 +1163,11 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
icr_low = lapic->icr_lo.v; icr_low = lapic->icr_lo.v;
icr_high = lapic->icr_hi.v; icr_high = lapic->icr_hi.v;
if (is_x2apic_enabled(vlapic)) {
dest = icr_high;
} else {
dest = icr_high >> APIC_ID_SHIFT; dest = icr_high >> APIC_ID_SHIFT;
}
vec = icr_low & APIC_VECTOR_MASK; vec = icr_low & APIC_VECTOR_MASK;
mode = icr_low & APIC_DELMODE_MASK; mode = icr_low & APIC_DELMODE_MASK;
phys = ((icr_low & APIC_DESTMODE_LOG) == 0UL); phys = ((icr_low & APIC_DESTMODE_LOG) == 0UL);
@ -1542,7 +1557,12 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset,
vlapic_svr_write_handler(vlapic); vlapic_svr_write_handler(vlapic);
break; break;
case APIC_OFFSET_ICR_LOW: case APIC_OFFSET_ICR_LOW:
if (is_x2apic_enabled(vlapic)) {
lapic->icr_hi.v = (uint32_t)(data >> 32U);
lapic->icr_lo.v = data32; lapic->icr_lo.v = data32;
} else {
lapic->icr_lo.v = data32;
}
retval = vlapic_icrlo_write_handler(vlapic); retval = vlapic_icrlo_write_handler(vlapic);
break; break;
case APIC_OFFSET_ICR_HI: case APIC_OFFSET_ICR_HI: