Skip to content

Commit e9fe6ef

Browse files
Sainath Grandhilijinxia
authored andcommitted
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>
1 parent 6a4dcce commit e9fe6ef

File tree

1 file changed

+59
-39
lines changed

1 file changed

+59
-39
lines changed

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ static inline uint32_t prio(uint32_t x)
4949
#define APICBASE_BSP 0x00000100UL
5050
#define APICBASE_X2APIC 0x00000400U
5151
#define APICBASE_ENABLED 0x00000800UL
52-
#define LOGICAL_ID_MASK 0xFU
53-
#define CLUSTER_ID_MASK 0xFFFF0U
52+
#define LOGICAL_ID_MASK 0xFU
53+
#define CLUSTER_ID_MASK 0xFFFF0U
5454

55-
#define ACRN_DBG_LAPIC 6U
55+
#define ACRN_DBG_LAPIC 6U
5656

5757
#if VLAPIC_VERBOS
5858
static inline void vlapic_dump_irr(struct acrn_vlapic *vlapic, char *msg)
@@ -1010,19 +1010,6 @@ vlapic_calcdest(struct vm *vm, uint64_t *dmask, uint32_t dest,
10101010
bitmap_set_lock(vcpu_id, dmask);
10111011
}
10121012
} else {
1013-
/*
1014-
* In the "Flat Model" the MDA is interpreted as an 8-bit wide
1015-
* bitmask. This model is only available in the xAPIC mode.
1016-
*/
1017-
mda_flat_ldest = dest & 0xffU;
1018-
1019-
/*
1020-
* In the "Cluster Model" the MDA is used to identify a
1021-
* specific cluster and a set of APICs in that cluster.
1022-
*/
1023-
mda_cluster_id = (dest >> 4U) & 0xfU;
1024-
mda_cluster_ldest = dest & 0xfU;
1025-
10261013
/*
10271014
* Logical mode: match each APIC that has a bit set
10281015
* in its LDR that matches a bit in the ldest.
@@ -1032,35 +1019,59 @@ vlapic_calcdest(struct vm *vm, uint64_t *dmask, uint32_t dest,
10321019
for (vcpu_id = 0U; vcpu_id < vm->hw.created_vcpus; vcpu_id++) {
10331020
if (amask & (1U << vcpu_id)) {
10341021
vlapic = vm_lapic_from_vcpu_id(vm, vcpu_id);
1035-
dfr = vlapic->apic_page.dfr.v;
1036-
ldr = vlapic->apic_page.ldr.v;
1037-
1038-
if ((dfr & APIC_DFR_MODEL_MASK) ==
1039-
APIC_DFR_MODEL_FLAT) {
1040-
ldest = ldr >> 24U;
1041-
mda_ldest = mda_flat_ldest;
1042-
} else if ((dfr & APIC_DFR_MODEL_MASK) ==
1043-
APIC_DFR_MODEL_CLUSTER) {
10441022

1045-
cluster = ldr >> 28U;
1046-
ldest = (ldr >> 24U) & 0xfU;
1023+
if (is_x2apic_enabled(vlapic)){
1024+
ldr = vlapic->apic_page.ldr.v;
1025+
ldest = ldr & 0xFFFFU;
10471026

1048-
if (cluster != mda_cluster_id) {
1027+
mda_cluster_id = (dest >> 16U) & 0xFFFFU;
1028+
mda_ldest = dest & 0xFFFFU;
1029+
if (mda_cluster_id != ((ldr >> 16U) & 0xFFFFU)) {
10491030
continue;
10501031
}
1051-
mda_ldest = mda_cluster_ldest;
10521032
} else {
10531033
/*
1054-
* Guest has configured a bad logical
1055-
* model for this vcpu - skip it.
1034+
* In the "Flat Model" the MDA is interpreted as an 8-bit wide
1035+
* bitmask. This model is only available in the xAPIC mode.
10561036
*/
1057-
dev_dbg(ACRN_DBG_LAPIC,
1058-
"CANNOT deliver interrupt");
1059-
dev_dbg(ACRN_DBG_LAPIC,
1060-
"vlapic has bad logical model %x", dfr);
1061-
continue;
1062-
}
1037+
mda_flat_ldest = dest & 0xffU;
1038+
1039+
/*
1040+
* In the "Cluster Model" the MDA is used to identify a
1041+
* specific cluster and a set of APICs in that cluster.
1042+
*/
1043+
mda_cluster_id = (dest >> 4U) & 0xfU;
1044+
mda_cluster_ldest = dest & 0xfU;
1045+
1046+
dfr = vlapic->apic_page.dfr.v;
1047+
ldr = vlapic->apic_page.ldr.v;
10631048

1049+
if ((dfr & APIC_DFR_MODEL_MASK) ==
1050+
APIC_DFR_MODEL_FLAT) {
1051+
ldest = ldr >> 24U;
1052+
mda_ldest = mda_flat_ldest;
1053+
} else if ((dfr & APIC_DFR_MODEL_MASK) ==
1054+
APIC_DFR_MODEL_CLUSTER) {
1055+
1056+
cluster = ldr >> 28U;
1057+
ldest = (ldr >> 24U) & 0xfU;
1058+
1059+
if (cluster != mda_cluster_id) {
1060+
continue;
1061+
}
1062+
mda_ldest = mda_cluster_ldest;
1063+
} else {
1064+
/*
1065+
* Guest has configured a bad logical
1066+
* model for this vcpu - skip it.
1067+
*/
1068+
dev_dbg(ACRN_DBG_LAPIC,
1069+
"CANNOT deliver interrupt");
1070+
dev_dbg(ACRN_DBG_LAPIC,
1071+
"vlapic has bad logical model %x", dfr);
1072+
continue;
1073+
}
1074+
}
10641075
if ((mda_ldest & ldest) != 0U) {
10651076
if (lowprio) {
10661077
if (target == NULL) {
@@ -1152,7 +1163,11 @@ vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
11521163

11531164
icr_low = lapic->icr_lo.v;
11541165
icr_high = lapic->icr_hi.v;
1155-
dest = icr_high >> APIC_ID_SHIFT;
1166+
if (is_x2apic_enabled(vlapic)) {
1167+
dest = icr_high;
1168+
} else {
1169+
dest = icr_high >> APIC_ID_SHIFT;
1170+
}
11561171
vec = icr_low & APIC_VECTOR_MASK;
11571172
mode = icr_low & APIC_DELMODE_MASK;
11581173
phys = ((icr_low & APIC_DESTMODE_LOG) == 0UL);
@@ -1542,7 +1557,12 @@ vlapic_write(struct acrn_vlapic *vlapic, uint32_t offset,
15421557
vlapic_svr_write_handler(vlapic);
15431558
break;
15441559
case APIC_OFFSET_ICR_LOW:
1545-
lapic->icr_lo.v = data32;
1560+
if (is_x2apic_enabled(vlapic)) {
1561+
lapic->icr_hi.v = (uint32_t)(data >> 32U);
1562+
lapic->icr_lo.v = data32;
1563+
} else {
1564+
lapic->icr_lo.v = data32;
1565+
}
15461566
retval = vlapic_icrlo_write_handler(vlapic);
15471567
break;
15481568
case APIC_OFFSET_ICR_HI:

0 commit comments

Comments
 (0)