Skip to content

Commit af9acbf

Browse files
Marc ZyngierKAGA-KOKO
authored andcommitted
irqchip/gic-v3-its: Fix GICv4.1 VPE affinity update
When updating the affinity of a VPE, the VMOVP command is currently skipped if the two CPUs are part of the same VPE affinity. But this is wrong, as the doorbell corresponding to this VPE is still delivered on the 'old' CPU, which screws up the balancing. Furthermore, offlining that 'old' CPU results in doorbell interrupts generated for this VPE being discarded. The harsh reality is that VMOVP cannot be elided when a set_affinity() request occurs. It needs to be obeyed, and if an optimisation is to be made, it is at the point where the affinity change request is made (such as in KVM). Drop the VMOVP elision altogether, and only use the vpe_table_mask to try and stay within the same ITS affinity group if at all possible. Fixes: dd3f050 (irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP) Reported-by: Kunkun Jiang <jiangkunkun@huawei.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240213101206.2137483-4-maz@kernel.org
1 parent 8b02da0 commit af9acbf

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3826,8 +3826,9 @@ static int its_vpe_set_affinity(struct irq_data *d,
38263826
bool force)
38273827
{
38283828
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3829-
int from, cpu = cpumask_first(mask_val);
3829+
struct cpumask common, *table_mask;
38303830
unsigned long flags;
3831+
int from, cpu;
38313832

38323833
/*
38333834
* Changing affinity is mega expensive, so let's be as lazy as
@@ -3843,19 +3844,22 @@ static int its_vpe_set_affinity(struct irq_data *d,
38433844
* taken on any vLPI handling path that evaluates vpe->col_idx.
38443845
*/
38453846
from = vpe_to_cpuid_lock(vpe, &flags);
3846-
if (from == cpu)
3847-
goto out;
3848-
3849-
vpe->col_idx = cpu;
3847+
table_mask = gic_data_rdist_cpu(from)->vpe_table_mask;
38503848

38513849
/*
3852-
* GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD
3853-
* is sharing its VPE table with the current one.
3850+
* If we are offered another CPU in the same GICv4.1 ITS
3851+
* affinity, pick this one. Otherwise, any CPU will do.
38543852
*/
3855-
if (gic_data_rdist_cpu(cpu)->vpe_table_mask &&
3856-
cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask))
3853+
if (table_mask && cpumask_and(&common, mask_val, table_mask))
3854+
cpu = cpumask_test_cpu(from, &common) ? from : cpumask_first(&common);
3855+
else
3856+
cpu = cpumask_first(mask_val);
3857+
3858+
if (from == cpu)
38573859
goto out;
38583860

3861+
vpe->col_idx = cpu;
3862+
38593863
its_send_vmovp(vpe);
38603864
its_vpe_db_proxy_move(vpe, from, cpu);
38613865

0 commit comments

Comments
 (0)