mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-13 05:47:39 +00:00
vlapic: refine IPI broadcast to support x2APIC mode
According to SDM 10.6.1, if dest fields is 0xffU for register ICR operation, that means the IPI is for broadcast. According to SDM 10.12.9, 0xffffffffU of dest fields for x2APIC means IPI is for broadcast. We add new parameter to vlapic_calc_dest() to show whether the dest is for broadcast. For IPI, we will set it according to dest fields. For ioapic and MSI, we hardcode it to false because no broadcast for ioapic and MSI. Tracked-On: #3003 Signed-off-by: Yin Fengwei <fengwei.yin@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
581c0a239a
commit
578592b566
@ -89,7 +89,7 @@ static void ptirq_build_physical_msi(struct acrn_vm *vm, struct ptirq_msi_info *
|
|||||||
dest = info->vmsi_addr.bits.dest_field;
|
dest = info->vmsi_addr.bits.dest_field;
|
||||||
phys = (info->vmsi_addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS);
|
phys = (info->vmsi_addr.bits.dest_mode == MSI_ADDR_DESTMODE_PHYS);
|
||||||
|
|
||||||
vlapic_calc_dest(vm, &vdmask, dest, phys, false);
|
vlapic_calc_dest(vm, &vdmask, false, dest, phys, false);
|
||||||
pdmask = vcpumask2pcpumask(vm, vdmask);
|
pdmask = vcpumask2pcpumask(vm, vdmask);
|
||||||
|
|
||||||
/* get physical delivery mode */
|
/* get physical delivery mode */
|
||||||
@ -183,7 +183,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, dest, phys, false);
|
vlapic_calc_dest(vm, &vdmask, false, dest, phys, false);
|
||||||
pdmask = vcpumask2pcpumask(vm, vdmask);
|
pdmask = vcpumask2pcpumask(vm, vdmask);
|
||||||
|
|
||||||
/* physical delivery mode */
|
/* physical delivery mode */
|
||||||
|
@ -1094,14 +1094,15 @@ static inline bool is_dest_field_matched(const struct acrn_vlapic *vlapic, uint3
|
|||||||
* addressing specified by the (dest, phys, lowprio) tuple.
|
* addressing specified by the (dest, phys, lowprio) tuple.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, uint32_t dest, bool phys, bool lowprio)
|
vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
|
||||||
|
uint32_t dest, bool phys, bool lowprio)
|
||||||
{
|
{
|
||||||
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;
|
*dmask = 0UL;
|
||||||
if (dest == 0xffU) {
|
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) {
|
||||||
@ -1149,14 +1150,15 @@ vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, uint32_t dest, bool phys,
|
|||||||
* @pre is_x2apic_enabled(vlapic) == true
|
* @pre is_x2apic_enabled(vlapic) == true
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, uint32_t dest, bool phys)
|
vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
|
||||||
|
uint32_t dest, bool phys)
|
||||||
{
|
{
|
||||||
struct acrn_vlapic *vlapic;
|
struct acrn_vlapic *vlapic;
|
||||||
struct acrn_vcpu *vcpu;
|
struct acrn_vcpu *vcpu;
|
||||||
uint16_t vcpu_id;
|
uint16_t vcpu_id;
|
||||||
|
|
||||||
*dmask = 0UL;
|
*dmask = 0UL;
|
||||||
if (dest == 0xffU) {
|
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) {
|
||||||
@ -1227,7 +1229,7 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode,
|
|||||||
static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
||||||
{
|
{
|
||||||
uint16_t vcpu_id;
|
uint16_t vcpu_id;
|
||||||
bool phys;
|
bool phys = false, is_broadcast = false;
|
||||||
uint64_t dmask = 0UL;
|
uint64_t dmask = 0UL;
|
||||||
uint32_t icr_low, icr_high, dest;
|
uint32_t icr_low, icr_high, dest;
|
||||||
uint32_t vec, mode, shorthand;
|
uint32_t vec, mode, shorthand;
|
||||||
@ -1241,8 +1243,10 @@ static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
|||||||
icr_high = lapic->icr_hi.v;
|
icr_high = lapic->icr_hi.v;
|
||||||
if (is_x2apic_enabled(vlapic)) {
|
if (is_x2apic_enabled(vlapic)) {
|
||||||
dest = icr_high;
|
dest = icr_high;
|
||||||
|
is_broadcast = (dest == 0xffffffffU);
|
||||||
} else {
|
} else {
|
||||||
dest = icr_high >> APIC_ID_SHIFT;
|
dest = icr_high >> APIC_ID_SHIFT;
|
||||||
|
is_broadcast = (dest == 0xffU);
|
||||||
}
|
}
|
||||||
vec = icr_low & APIC_VECTOR_MASK;
|
vec = icr_low & APIC_VECTOR_MASK;
|
||||||
mode = icr_low & APIC_DELMODE_MASK;
|
mode = icr_low & APIC_DELMODE_MASK;
|
||||||
@ -1264,7 +1268,7 @@ static void vlapic_icrlo_write_handler(struct acrn_vlapic *vlapic)
|
|||||||
|
|
||||||
switch (shorthand) {
|
switch (shorthand) {
|
||||||
case APIC_DEST_DESTFLD:
|
case APIC_DEST_DESTFLD:
|
||||||
vlapic_calc_dest(vlapic->vm, &dmask, dest, phys, false);
|
vlapic_calc_dest(vlapic->vm, &dmask, is_broadcast, dest, phys, false);
|
||||||
break;
|
break;
|
||||||
case APIC_DEST_SELF:
|
case APIC_DEST_SELF:
|
||||||
bitmap_set_nolock(vlapic->vcpu->vcpu_id, &dmask);
|
bitmap_set_nolock(vlapic->vcpu->vcpu_id, &dmask);
|
||||||
@ -1802,7 +1806,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, dest, phys, lowprio);
|
vlapic_calc_dest(vm, &dmask, 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;
|
||||||
|
@ -432,7 +432,7 @@ static void inject_msi_lapic_pt(struct acrn_vm *vm, const struct acrn_msi_entry
|
|||||||
* 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, vdest, phys);
|
vlapic_calc_dest_lapic_pt(vm, &vdmask, false, vdest, phys);
|
||||||
dev_dbg(ACRN_DBG_LAPICPT, "%s: vcpu destination mask 0x%016llx", __func__, vdmask);
|
dev_dbg(ACRN_DBG_LAPICPT, "%s: vcpu destination mask 0x%016llx", __func__, vdmask);
|
||||||
|
|
||||||
vcpu_id = ffs64(vdmask);
|
vcpu_id = ffs64(vdmask);
|
||||||
|
@ -206,8 +206,10 @@ 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, uint32_t dest, bool phys, bool lowprio);
|
void vlapic_calc_dest(struct acrn_vm *vm, uint64_t *dmask, bool is_broadcast,
|
||||||
void vlapic_calc_dest_lapic_pt(struct acrn_vm *vm, uint64_t *dmask, uint32_t dest, bool phys);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
Loading…
Reference in New Issue
Block a user