mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-05-02 05:34:04 +00:00
hv: bugfix: skip invalid ffs64 return value
ffs64() returns INVALID_BIT_INDEX (0xffffU) when it tries to deal with
zero input value. This may happen In calculate_logical_dest_mask() when
the guest tries to write some illegal destination IDs to MSI config
registers of a pt-device. The ffs64() return value is used as per_cpu
array index, and it would cause a page fault.
This patch adds protection to the per_cpu array, making this function
return zero on illegal value. As in logical destination's definition, a
zero logical designation would point to no CPU.
Fixes: 1334349f8
Tracked-On: #8454
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
parent
b38003b870
commit
a9860fad05
@ -53,30 +53,32 @@ static struct acrn_vcpu *is_single_destination(struct acrn_vm *vm, const struct
|
||||
|
||||
static uint32_t calculate_logical_dest_mask(uint64_t pdmask)
|
||||
{
|
||||
uint32_t dest_cluster_id, cluster_id, logical_id_mask = 0U;
|
||||
uint32_t dest_cluster_id = 0U, cluster_id, logical_id_mask = 0U;
|
||||
uint64_t pcpu_mask = pdmask;
|
||||
uint16_t pcpu_id;
|
||||
|
||||
/* Guest using Guests working in xAPIC mode may use 'Flat Model' to select an
|
||||
* arbitrary list of CPUs. But as the HW is woring in x2APIC mode and can only
|
||||
* use 'Cluster Model', destination mask can only be assigned to pCPUs within
|
||||
* one Cluster. So some pCPUs may not be included.
|
||||
* Here we use the first Cluster of all the requested pCPUs.
|
||||
*/
|
||||
pcpu_id = ffs64(pcpu_mask);
|
||||
dest_cluster_id = per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_CLUSTER_ID_MASK;
|
||||
while (pcpu_id < MAX_PCPU_NUM) {
|
||||
bitmap_clear_nolock(pcpu_id, &pcpu_mask);
|
||||
cluster_id = per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_CLUSTER_ID_MASK;
|
||||
if (cluster_id == dest_cluster_id) {
|
||||
logical_id_mask |= (per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_LOGICAL_ID_MASK);
|
||||
} else {
|
||||
pr_warn("The cluster ID of pCPU %d is %d which differs from that (%d) of "
|
||||
"the previous cores in the guest logical destination.\n"
|
||||
"Ignore that pCPU in the logical destination for physical interrupts.",
|
||||
pcpu_id, cluster_id >> 16U, dest_cluster_id >> 16U);
|
||||
}
|
||||
pcpu_id = ffs64(pcpu_mask);
|
||||
if (pcpu_id < MAX_PCPU_NUM) {
|
||||
/* Guests working in xAPIC mode may use 'Flat Model' to select an
|
||||
* arbitrary list of CPUs. But as the HW is woring in x2APIC mode and can only
|
||||
* use 'Cluster Model', destination mask can only be assigned to pCPUs within
|
||||
* one Cluster. So some pCPUs may not be included.
|
||||
* Here we use the first Cluster of all the requested pCPUs.
|
||||
*/
|
||||
dest_cluster_id = per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_CLUSTER_ID_MASK;
|
||||
do {
|
||||
bitmap_clear_nolock(pcpu_id, &pcpu_mask);
|
||||
cluster_id = per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_CLUSTER_ID_MASK;
|
||||
if (cluster_id == dest_cluster_id) {
|
||||
logical_id_mask |= (per_cpu(lapic_ldr, pcpu_id) & X2APIC_LDR_LOGICAL_ID_MASK);
|
||||
} else {
|
||||
pr_warn("The cluster ID of pCPU %d is %d which differs from that (%d) of "
|
||||
"the previous cores in the guest logical destination.\n"
|
||||
"Ignore that pCPU in the logical destination for physical interrupts.",
|
||||
pcpu_id, cluster_id >> 16U, dest_cluster_id >> 16U);
|
||||
}
|
||||
pcpu_id = ffs64(pcpu_mask);
|
||||
} while (pcpu_id < MAX_PCPU_NUM);
|
||||
}
|
||||
|
||||
return (dest_cluster_id | logical_id_mask);
|
||||
|
Loading…
Reference in New Issue
Block a user