Skip to contentSkip to conversation

Patch "genirq/cpuhotplug: Enforce affinity setting on startup of managed irqs" has been added to the 4.13-stable tree

PATCH [email protected] 1 participant 1 message Oct 15, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

genirq/cpuhotplug: Enforce affinity setting on startup of managed irqs

to the 4.13-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
genirq-cpuhotplug-enforce-affinity-setting-on-startup-of-managed-irqs.patch
and it can be found in the queue-4.13 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From e43b3b58548051f8809391eb7bec7a27ed3003ea Mon Sep 17 00:00:00 2001

From: Thomas Gleixner <[email protected]>
Date: Wed, 4 Oct 2017 21:07:38 +0200
Subject: genirq/cpuhotplug: Enforce affinity setting on startup of managed irqs

From: Thomas Gleixner <[email protected]>

commit e43b3b58548051f8809391eb7bec7a27ed3003ea upstream.

Managed interrupts can end up in a stale state on CPU hotplug. If the interrupt is not targeting a single CPU, i.e. the affinity mask spawns multiple CPUs then the following can happen:

After boot:

dstate: 0x01601200
IRQD_ACTIVATED
IRQD_IRQ_STARTED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_SET
IRQD_AFFINITY_MANAGED

node:     0
affinity: 24-31
effectiv: 24
pending:  0

After offlining CPU 31 - 24

dstate: 0x01a31000
IRQD_IRQ_DISABLED
IRQD_IRQ_MASKED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_SET
IRQD_AFFINITY_MANAGED
IRQD_MANAGED_SHUTDOWN

node:     0
affinity: 24-31
effectiv: 24
pending:  0

Now CPU 25 gets onlined again, so it should get the effective interrupt affinity for this interruopt, but due to the x86 interrupt affinity setter restrictions this ends up after restarting the interrupt with:

dstate: 0x01601300
IRQD_ACTIVATED
IRQD_IRQ_STARTED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_SET
IRQD_SETAFFINITY_PENDING
IRQD_AFFINITY_MANAGED

node:     0
affinity: 24-31
effectiv: 24
pending:  24-31

So the interrupt is still affine to CPU 24, which was the last CPU to go offline of that affinity set and the move to an online CPU within 24-31, in this case 25, is pending. This mechanism is x86/ia64 specific as those architectures cannot move interrupts from thread context and do this when an interrupt is actually handled. So the move is set to pending.

Whats worse is that offlining CPU 25 again results in:

dstate: 0x01601300
IRQD_ACTIVATED
IRQD_IRQ_STARTED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_SET
IRQD_SETAFFINITY_PENDING
IRQD_AFFINITY_MANAGED

node:     0
affinity: 24-31
effectiv: 24
pending:  24-31

This means the interrupt has not been shut down, because the outgoing CPU is not in the effective affinity mask, but of course nothing notices that the effective affinity mask is pointing at an offline CPU.

In the case of restarting a managed interrupt the move restriction does not apply, so the affinity setting can be made unconditional. This needs to be done _before_ the interrupt is started up as otherwise the condition for moving it from thread context would not longer be fulfilled.

With that change applied onlining CPU 25 after offlining 31-24 results in:

dstate: 0x01600200
IRQD_ACTIVATED
IRQD_IRQ_STARTED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_MANAGED

node:     0
affinity: 24-31
effectiv: 25

pending:

And after offlining CPU 25:

dstate: 0x01a30000
IRQD_IRQ_DISABLED
IRQD_IRQ_MASKED
IRQD_SINGLE_TARGET
IRQD_AFFINITY_MANAGED
IRQD_MANAGED_SHUTDOWN

node:     0
affinity: 24-31
effectiv: 25

pending:

which is the correct and expected result.

Fixes 761ea388e8c4 ("genirq: Handle managed irqs gracefully in irq_startup()")
Cc Sumit Saxena <[email protected]>
Cc Marc Zyngier <[email protected]>
Cc Shivasharan Srikanteshwara <[email protected]>
Cc Kashyap Desai <[email protected]>
Cc Hannes Reinecke <[email protected]>
Cc Christoph Hellwig <[email protected]>
---
 kernel/irq/chip.c   |    2 +-
 kernel/irq/manage.c |    3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)
kernel/irq/chip.c +1 -1
@@ -265,8 +265,8 @@ int irq_startup(struct irq_desc *desc, b
 			irq_setup_affinity(desc);
 			break;
 		case IRQ_STARTUP_MANAGED:
+			irq_do_set_affinity(d, aff, false);
 			ret = __irq_startup(desc);
-			irq_set_affinity_locked(d, aff, false);
 			break;
 		case IRQ_STARTUP_ABORT:
 			return 0;
kernel/irq/manage.c +3 -0
@@ -175,6 +175,9 @@ int irq_do_set_affinity(struct irq_data
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
 	int ret;
 
+	if (!chip || !chip->irq_set_affinity)
+		return -EINVAL;
+
 	ret = chip->irq_set_affinity(data, mask, force);
 	switch (ret) {
 	case IRQ_SET_MASK_OK:

Patches currently in stable-queue which might be from [email protected] are

queue-4.13/genirq-cpuhotplug-add-sanity-check-for-effective-affinity-mask.patch queue-4.13/genirq-cpuhotplug-enforce-affinity-setting-on-startup-of-managed-irqs.patch