hv: vlapic: wrap a function to calculate destination vcpu mask by shorthand

1. Rename vlapic_calc_dest to vlapic_calc_dest_noshort
2. Remove vlapic_calc_dest_lapic_pt, use vlapic_calc_dest_noshort instead
3. Wrap vlapic_calc_dest to calculate destination vcpu mask according shorthand

Tracked-On: #5923
Signed-off-by: Zide Chen <zide.chen@intel.com>
Signed-off-by: Li Fei1 <fei1.li@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Li Fei1 2021-05-20 10:31:24 +08:00 committed by wenlingz
parent b068656e71
commit a69e67b58b
4 changed files with 43 additions and 70 deletions

View File

@ -32,7 +32,7 @@ static struct acrn_vcpu *is_single_destination(struct acrn_vm *vm, const struct
uint16_t vid; uint16_t vid;
struct acrn_vcpu *vcpu = NULL; struct acrn_vcpu *vcpu = NULL;
vlapic_calc_dest(vm, &vdmask, false, (uint32_t)(info->addr.bits.dest_field), vdmask = vlapic_calc_dest_noshort(vm, false, (uint32_t)(info->addr.bits.dest_field),
(bool)(info->addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS), (bool)(info->addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS),
(bool)(info->data.bits.delivery_mode == MSI_DATA_DELMODE_LOPRI)); (bool)(info->data.bits.delivery_mode == MSI_DATA_DELMODE_LOPRI));
@ -105,7 +105,7 @@ static void ptirq_build_physical_msi(struct acrn_vm *vm,
dest = entry->vmsi.addr.bits.dest_field; dest = entry->vmsi.addr.bits.dest_field;
phys = (entry->vmsi.addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS); phys = (entry->vmsi.addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS);
vlapic_calc_dest(vm, &vdmask, false, dest, phys, false); vdmask = vlapic_calc_dest_noshort(vm, false, dest, phys, false);
pdmask = vcpumask2pcpumask(vm, vdmask); pdmask = vcpumask2pcpumask(vm, vdmask);
/* get physical delivery mode */ /* get physical delivery mode */
@ -204,7 +204,7 @@ ptirq_build_physical_rte(struct acrn_vm *vm, struct ptirq_remapping_info *entry)
/* physical destination cpu mask */ /* physical destination cpu mask */
phys = (virt_rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY); phys = (virt_rte.bits.dest_mode == IOAPIC_RTE_DESTMODE_PHY);
dest = (uint32_t)virt_rte.bits.dest_field; dest = (uint32_t)virt_rte.bits.dest_field;
vlapic_calc_dest(vm, &vdmask, false, dest, phys, false); vdmask = vlapic_calc_dest_noshort(vm, false, dest, phys, false);
pdmask = vcpumask2pcpumask(vm, vdmask); pdmask = vcpumask2pcpumask(vm, vdmask);
/* physical delivery mode */ /* physical delivery mode */

View File

@ -997,21 +997,21 @@ static inline bool is_dest_field_matched(const struct acrn_vlapic *vlapic, uint3
* This function populates 'dmask' with the set of vcpus that match the * This function populates 'dmask' with the set of vcpus that match the
* addressing specified by the (dest, phys, lowprio) tuple. * addressing specified by the (dest, phys, lowprio) tuple.
*/ */
void uint64_t
vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast, vlapic_calc_dest_noshort(struct acrn_vm *vm, bool is_broadcast,
uint32_t dest, bool phys, bool lowprio) uint32_t dest, bool phys, bool lowprio)
{ {
uint64_t dmask = 0UL;
struct acrn_vlapic *vlapic, *lowprio_dest = NULL; struct acrn_vlapic *vlapic, *lowprio_dest = NULL;
struct acrn_vcpu *vcpu; struct acrn_vcpu *vcpu;
uint16_t vcpu_id; uint16_t vcpu_id;
*dmask = 0UL;
if (is_broadcast) { if (is_broadcast) {
/* Broadcast in both logical and physical modes. */ /* Broadcast in both logical and physical modes. */
*dmask = vm_active_cpus(vm); dmask = vm_active_cpus(vm);
} else if (phys) { } else if (phys) {
/* Physical mode: "dest" is local APIC ID. */ /* Physical mode: "dest" is local APIC ID. */
set_dest_mask_phys(vm, dmask, dest); set_dest_mask_phys(vm, &dmask, dest);
} else { } else {
/* /*
* Logical mode: "dest" is message destination addr * Logical mode: "dest" is message destination addr
@ -1036,52 +1036,47 @@ vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
/* No other state currently, do nothing */ /* No other state currently, do nothing */
} }
} else { } else {
bitmap_set_nolock(vcpu_id, dmask); bitmap_set_nolock(vcpu_id, &dmask);
} }
} }
if (lowprio && (lowprio_dest != NULL)) { if (lowprio && (lowprio_dest != NULL)) {
bitmap_set_nolock(vlapic2vcpu(lowprio_dest)->vcpu_id, dmask); bitmap_set_nolock(vlapic2vcpu(lowprio_dest)->vcpu_id, &dmask);
} }
} }
return dmask;
} }
/* uint64_t
* This function populates 'dmask' with the set of "possible" destination vcpu when lapic is passthru. vlapic_calc_dest(struct acrn_vcpu *vcpu, uint32_t shorthand, bool is_broadcast,
* Hardware will handle the real delivery mode among all "possible" dest processors: uint32_t dest, bool phys, bool lowprio)
* deliver to the lowprio one for lowprio mode.
*
* @pre is_x2apic_enabled(vlapic) == true
*/
void
vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
uint32_t dest, bool phys)
{ {
struct acrn_vlapic *vlapic; uint64_t dmask = 0UL;
struct acrn_vcpu *vcpu;
uint16_t vcpu_id;
*dmask = 0UL; switch (shorthand) {
if (is_broadcast) { case APIC_DEST_NOSHORT:
/* Broadcast in both logical and physical modes. */ dmask = vlapic_calc_dest_noshort(vcpu->vm, is_broadcast, dest, phys, lowprio);
*dmask = vm_active_cpus(vm); break;
} else if (phys) { case APIC_DEST_SELF:
/* Physical mode: "dest" is local APIC ID. */ bitmap_set_nolock(vcpu->vcpu_id, &dmask);
set_dest_mask_phys(vm, dmask, dest); break;
} else { case APIC_DEST_ALLISELF:
dmask = vm_active_cpus(vcpu->vm);
break;
case APIC_DEST_ALLESELF:
dmask = vm_active_cpus(vcpu->vm);
bitmap_clear_nolock(vcpu->vcpu_id, &dmask);
break;
default:
/* /*
* Logical mode: "dest" is message destination addr * All possible values of 'shorthand' has been handled in prior
* to be compared with the logical APIC ID in LDR. * case clauses.
*/ */
foreach_vcpu(vcpu_id, vm, vcpu) { break;
vlapic = vm_lapic_from_vcpu_id(vm, vcpu_id);
if (!is_dest_field_matched(vlapic, dest)) {
continue;
}
bitmap_set_nolock(vcpu_id, dmask);
}
dev_dbg(DBG_LEVEL_LAPICPT, "%s: logical destmod, dmask: 0x%016lx", __func__, *dmask);
} }
return dmask;
} }
static void static void
@ -1139,7 +1134,7 @@ static void vlapic_write_icrlo(struct acrn_vlapic *vlapic)
{ {
uint16_t vcpu_id; uint16_t vcpu_id;
bool phys = false, is_broadcast = false; bool phys = false, is_broadcast = false;
uint64_t dmask = 0UL; uint64_t dmask;
uint32_t icr_low, icr_high, dest; uint32_t icr_low, icr_high, dest;
uint32_t vec, mode, shorthand; uint32_t vec, mode, shorthand;
struct lapic_regs *lapic; struct lapic_regs *lapic;
@ -1176,27 +1171,7 @@ static void vlapic_write_icrlo(struct acrn_vlapic *vlapic)
"icrlo 0x%08x icrhi 0x%08x triggered ipi %u", "icrlo 0x%08x icrhi 0x%08x triggered ipi %u",
icr_low, icr_high, vec); icr_low, icr_high, vec);
switch (shorthand) { dmask = vlapic_calc_dest(vcpu, shorthand, is_broadcast, dest, phys, false);
case APIC_DEST_DESTFLD:
vlapic_calc_dest(vcpu->vm, &dmask, is_broadcast, dest, phys, false);
break;
case APIC_DEST_SELF:
bitmap_set_nolock(vcpu->vcpu_id, &dmask);
break;
case APIC_DEST_ALLISELF:
dmask = vm_active_cpus(vcpu->vm);
break;
case APIC_DEST_ALLESELF:
dmask = vm_active_cpus(vcpu->vm);
bitmap_clear_nolock(vlapic2vcpu(vlapic)->vcpu_id, &dmask);
break;
default:
/*
* All possible values of 'shorthand' has been handled in prior
* case clauses.
*/
break;
}
for (vcpu_id = 0U; vcpu_id < vcpu->vm->hw.created_vcpus; vcpu_id++) { for (vcpu_id = 0U; vcpu_id < vcpu->vm->hw.created_vcpus; vcpu_id++) {
if ((dmask & (1UL << vcpu_id)) != 0UL) { if ((dmask & (1UL << vcpu_id)) != 0UL) {
@ -1774,7 +1749,7 @@ vlapic_receive_intr(struct acrn_vm *vm, bool level, uint32_t dest, bool phys,
* all interrupts originating from the ioapic or MSI specify the * all interrupts originating from the ioapic or MSI specify the
* 'dest' in the legacy xAPIC format. * 'dest' in the legacy xAPIC format.
*/ */
vlapic_calc_dest(vm, &dmask, false, dest, phys, lowprio); dmask = vlapic_calc_dest_noshort(vm, false, dest, phys, lowprio);
for (vcpu_id = 0U; vcpu_id < vm->hw.created_vcpus; vcpu_id++) { for (vcpu_id = 0U; vcpu_id < vm->hw.created_vcpus; vcpu_id++) {
struct acrn_vlapic *vlapic; struct acrn_vlapic *vlapic;
@ -1943,7 +1918,7 @@ static void inject_msi_for_lapic_pt(struct acrn_vm *vm, uint64_t addr, uint64_t
* the delivery mode of vmsi will be forwarded to ICR delievry field * the delivery mode of vmsi will be forwarded to ICR delievry field
* and handled by hardware. * and handled by hardware.
*/ */
vlapic_calc_dest_lapic_pt(vm, &vdmask, false, vdest, phys); vdmask = vlapic_calc_dest_noshort(vm, false, vdest, phys, false);
dev_dbg(DBG_LEVEL_LAPICPT, "%s: vcpu destination mask 0x%016lx", __func__, vdmask); dev_dbg(DBG_LEVEL_LAPICPT, "%s: vcpu destination mask 0x%016lx", __func__, vdmask);
vcpu_id = ffs64(vdmask); vcpu_id = ffs64(vdmask);
@ -2077,7 +2052,7 @@ vlapic_x2apic_pt_icr_access(struct acrn_vm *vm, uint64_t val)
phys = ((icr_low & APIC_DESTMODE_LOG) == 0UL); phys = ((icr_low & APIC_DESTMODE_LOG) == 0UL);
shorthand = icr_low & APIC_DEST_MASK; shorthand = icr_low & APIC_DEST_MASK;
if (!phys || (shorthand != APIC_DEST_DESTFLD)) { if (!phys || (shorthand != APIC_DEST_NOSHORT)) {
pr_err("Logical destination mode or shorthands \ pr_err("Logical destination mode or shorthands \
not supported in ICR forpartition mode\n"); not supported in ICR forpartition mode\n");
/* /*

View File

@ -325,7 +325,7 @@ union ioapic_rte {
#define APIC_RRSTAT_RESV 0x00030000U #define APIC_RRSTAT_RESV 0x00030000U
#define APIC_DEST_MASK 0x000c0000U #define APIC_DEST_MASK 0x000c0000U
#define APIC_DEST_DESTFLD 0x00000000U #define APIC_DEST_NOSHORT 0x00000000U
#define APIC_DEST_SELF 0x00040000U #define APIC_DEST_SELF 0x00040000U
#define APIC_DEST_ALLISELF 0x00080000U #define APIC_DEST_ALLISELF 0x00080000U
#define APIC_DEST_ALLESELF 0x000c0000U #define APIC_DEST_ALLESELF 0x000c0000U

View File

@ -188,10 +188,8 @@ int32_t apic_write_vmexit_handler(struct acrn_vcpu *vcpu);
int32_t veoi_vmexit_handler(struct acrn_vcpu *vcpu); int32_t veoi_vmexit_handler(struct acrn_vcpu *vcpu);
void vlapic_update_tpr_threshold(const struct acrn_vlapic *vlapic); void vlapic_update_tpr_threshold(const struct acrn_vlapic *vlapic);
int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu); int32_t tpr_below_threshold_vmexit_handler(struct acrn_vcpu *vcpu);
void vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast, uint64_t vlapic_calc_dest_noshort(struct acrn_vm *vm, bool is_broadcast,
uint32_t dest, bool phys, bool lowprio); uint32_t dest, bool phys, bool lowprio);
void vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
uint32_t dest, bool phys);
bool is_x2apic_enabled(const struct acrn_vlapic *vlapic); bool is_x2apic_enabled(const struct acrn_vlapic *vlapic);
bool is_xapic_enabled(const struct acrn_vlapic *vlapic); bool is_xapic_enabled(const struct acrn_vlapic *vlapic);
/** /**