<feed xmlns='http://www.w3.org/2005/Atom'>
<title>BMC/Intel-BMC/linux.git/arch/x86/kernel/apic/vector.c, branch dev-4.6</title>
<subtitle>Intel OpenBMC Linux kernel source tree (mirror)</subtitle>
<id>https://git.radix-linux.su/BMC/Intel-BMC/linux.git/atom?h=dev-4.6</id>
<link rel='self' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/atom?h=dev-4.6'/>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/'/>
<updated>2016-04-28T07:53:06+00:00</updated>
<entry>
<title>x86/apic: Handle zero vector gracefully in clear_vector_irq()</title>
<updated>2016-04-28T07:53:06+00:00</updated>
<author>
<name>Keith Busch</name>
<email>keith.busch@intel.com</email>
</author>
<published>2016-04-27T20:22:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=1bdb8970392a68489b469c3a330a1adb5ef61beb'/>
<id>urn:sha1:1bdb8970392a68489b469c3a330a1adb5ef61beb</id>
<content type='text'>
If x86_vector_alloc_irq() fails x86_vector_free_irqs() is invoked to cleanup
the already allocated vectors. This subsequently calls clear_vector_irq().

The failed irq has no vector assigned, which triggers the BUG_ON(!vector) in
clear_vector_irq().

We cannot suppress the call to x86_vector_free_irqs() for the failed
interrupt, because the other data related to this irq must be cleaned up as
well. So calling clear_vector_irq() with vector == 0 is legitimate.

Remove the BUG_ON and return if vector is zero,

[ tglx: Massaged changelog ]

Fixes: b5dc8e6c21e7 "x86/irq: Use hierarchical irqdomain to manage CPU interrupt vectors"
Signed-off-by: Keith Busch &lt;keith.busch@intel.com&gt;
Cc: stable@vger.kernel.org
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Cure live lock in fixup_irqs()</title>
<updated>2016-03-18T13:51:06+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2016-03-14T08:40:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=551adc60573cb68e3d55cacca9ba1b7437313df7'/>
<id>urn:sha1:551adc60573cb68e3d55cacca9ba1b7437313df7</id>
<content type='text'>
Harry reported, that he's able to trigger a system freeze with cpu hot
unplug. The freeze turned out to be a live lock caused by recent changes in
irq_force_complete_move().

When fixup_irqs() and from there irq_force_complete_move() is called on the
dying cpu, then all other cpus are in stop machine an wait for the dying cpu
to complete the teardown. If there is a move of an interrupt pending then
irq_force_complete_move() sends the cleanup IPI to the cpus in the old_domain
mask and waits for them to clear the mask. That's obviously impossible as
those cpus are firmly stuck in stop machine with interrupts disabled.

I should have known that, but I completely overlooked it being concentrated on
the locking issues around the vectors. And the existance of the call to
__irq_complete_move() in the code, which actually sends the cleanup IPI made
it reasonable to wait for that cleanup to complete. That call was bogus even
before the recent changes as it was just a pointless distraction.

We have to look at two cases:

1) The move_in_progress flag of the interrupt is set

   This means the ioapic has been updated with the new vector, but it has not
   fired yet. In theory there is a race:

   set_ioapic(new_vector) &lt;-- Interrupt is raised before update is effective,
   			      i.e. it's raised on the old vector. 

   So if the target cpu cannot handle that interrupt before the old vector is
   cleaned up, we get a spurious interrupt and in the worst case the ioapic
   irq line becomes stale, but my experiments so far have only resulted in
   spurious interrupts.

   But in case of cpu hotplug this should be a non issue because if the
   affinity update happens right before all cpus rendevouz in stop machine,
   there is no way that the interrupt can be blocked on the target cpu because
   all cpus loops first with interrupts enabled in stop machine, so the old
   vector is not yet cleaned up when the interrupt fires.

   So the only way to run into this issue is if the delivery of the interrupt
   on the apic/system bus would be delayed beyond the point where the target
   cpu disables interrupts in stop machine. I doubt that it can happen, but at
   least there is a theroretical chance. Virtualization might be able to
   expose this, but AFAICT the IOAPIC emulation is not as stupid as the real
   hardware.

   I've spent quite some time over the weekend to enforce that situation,
   though I was not able to trigger the delayed case.

2) The move_in_progress flag is not set and the old_domain cpu mask is not
   empty.

   That means, that an interrupt was delivered after the change and the
   cleanup IPI has been sent to the cpus in old_domain, but not all CPUs have
   responded to it yet.

In both cases we can assume that the next interrupt will arrive on the new
vector, so we can cleanup the old vectors on the cpus in the old_domain cpu
mask.

Fixes: 98229aa36caa "x86/irq: Plug vector cleanup race"
Reported-by: Harry Junior &lt;harryjr@outlook.fr&gt;
Tested-by: Tony Luck &lt;tony.luck@intel.com&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Cc: Peter Zijlstra &lt;peterz@infradead.org&gt;
Cc: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Borislav Petkov &lt;bp@alien8.de&gt;
Cc: Ben Hutchings &lt;ben@decadent.org.uk&gt;
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/alpine.DEB.2.11.1603140931430.3657@nanos
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;

</content>
</entry>
<entry>
<title>x86/irq: Plug vector cleanup race</title>
<updated>2016-01-15T12:44:02+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:54+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=98229aa36caa9c769b13565523de9b813013c703'/>
<id>urn:sha1:98229aa36caa9c769b13565523de9b813013c703</id>
<content type='text'>
We still can end up with a stale vector due to the following:

CPU0                          CPU1                      CPU2
lock_vector()
data-&gt;move_in_progress=0
sendIPI()                       
unlock_vector()
                              set_affinity()
                              assign_irq_vector()
                              lock_vector()             handle_IPI
                              move_in_progress = 1      lock_vector()
                              unlock_vector()
                                                        move_in_progress == 1

So we need to serialize the vector assignment against a pending cleanup. The
solution is rather simple now. We not only check for the move_in_progress flag
in assign_irq_vector(), we also check whether there is still a cleanup pending
in the old_domain cpumask. If so, we return -EBUSY to the caller and let him
deal with it. Though we have to be careful in the cpu unplug case. If the
cleanout has not yet completed then the following setaffinity() call would
return -EBUSY. Add code which prevents this.

Full context is here: http://lkml.kernel.org/r/5653B688.4050809@stratus.com

Reported-and-tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160107.207265407@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Call irq_force_move_complete with irq descriptor</title>
<updated>2016-01-15T12:44:01+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=90a2282e23f0522e4b3f797ad447c5e91bf7fe32'/>
<id>urn:sha1:90a2282e23f0522e4b3f797ad447c5e91bf7fe32</id>
<content type='text'>
First of all there is no point in looking up the irq descriptor again, but we
also need the descriptor for the final cleanup race fix in the next
patch. Make that change seperate. No functional difference.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160107.125211743@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Remove outgoing CPU from vector cleanup mask</title>
<updated>2016-01-15T12:44:01+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=56d7d2f4bbd00fb198b7907cb3ab657d06115a42'/>
<id>urn:sha1:56d7d2f4bbd00fb198b7907cb3ab657d06115a42</id>
<content type='text'>
We want to synchronize new vector assignments with a pending cleanup. Remove a
dying cpu from a pending cleanup mask.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160107.045961667@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Remove the cpumask allocation from send_cleanup_vector()</title>
<updated>2016-01-15T12:44:01+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=5da0c1217f05d2ccc9a8ed6e6e5c23a8a1d24dd6'/>
<id>urn:sha1:5da0c1217f05d2ccc9a8ed6e6e5c23a8a1d24dd6</id>
<content type='text'>
There is no need to allocate a new cpumask for sending the cleanup vector. The
old_domain mask is now protected by the vector_lock, so we can safely remove
the offline cpus from it and send the IPI with the resulting mask.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.967993932@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Clear move_in_progress before sending cleanup IPI</title>
<updated>2016-01-15T12:44:01+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:51+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=c1684f5035b60e9f98566493e869496fb5de1d89'/>
<id>urn:sha1:c1684f5035b60e9f98566493e869496fb5de1d89</id>
<content type='text'>
send_cleanup_vector() fiddles with the old_domain mask unprotected because it
relies on the protection by the move_in_progress flag. But this is fatal, as
the flag is reset after the IPI has been sent. So a cpu which receives the IPI
can still see the flag set and therefor ignores the cleanup request. If no
other cleanup request happens then the vector stays stale on that cpu and in
case of an irq removal the vector still persists. That can lead to use after
free when the next cleanup IPI happens.

Protect the code with vector_lock and clear move_in_progress before sending
the IPI.

This does not plug the race which Joe reported because:

CPU0                          CPU1                      CPU2
lock_vector()
data-&gt;move_in_progress=0
sendIPI()                       
unlock_vector()
                              set_affinity()
                              assign_irq_vector()
                              lock_vector()             handle_IPI
                              move_in_progress = 1      lock_vector()
                              unlock_vector()
                                                        move_in_progress == 1

The full fix comes with a later patch.

Reported-and-tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.892412198@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Remove offline cpus from vector cleanup</title>
<updated>2016-01-15T12:44:01+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=847667ef10356b824a11c853fc8a8b1b437b6a8d'/>
<id>urn:sha1:847667ef10356b824a11c853fc8a8b1b437b6a8d</id>
<content type='text'>
No point of keeping offline cpus in the cleanup mask.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.808642683@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Get rid of code duplication</title>
<updated>2016-01-15T12:44:00+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=ab25ac02148b600e645f77cfb8b8ea415ed75bb4'/>
<id>urn:sha1:ab25ac02148b600e645f77cfb8b8ea415ed75bb4</id>
<content type='text'>
Reusing an existing vector and assigning a new vector has duplicated
code. Consolidate it.

This is also a preparatory patch for finally plugging the cleanup race.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.721599216@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
<entry>
<title>x86/irq: Copy vectormask instead of an AND operation</title>
<updated>2016-01-15T12:44:00+00:00</updated>
<author>
<name>Thomas Gleixner</name>
<email>tglx@linutronix.de</email>
</author>
<published>2015-12-31T16:30:49+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/BMC/Intel-BMC/linux.git/commit/?id=9ac15b7a8af4cf3337a101498c0ed690d23ade75'/>
<id>urn:sha1:9ac15b7a8af4cf3337a101498c0ed690d23ade75</id>
<content type='text'>
In the case that the new vector mask is a subset of the existing mask there is
no point to do a AND operation of currentmask &amp; newmask. The result is
newmask. So we can simply copy the new mask to the current mask and be done
with it. Preparatory patch for further consolidation.

Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
Tested-by: Borislav Petkov &lt;bp@alien8.de&gt;
Tested-by: Joe Lawrence &lt;joe.lawrence@stratus.com&gt;
Cc: Jiang Liu &lt;jiang.liu@linux.intel.com&gt;
Cc: Jeremiah Mahler &lt;jmmahler@gmail.com&gt;
Cc: andy.shevchenko@gmail.com
Cc: Guenter Roeck &lt;linux@roeck-us.net&gt;
Cc: stable@vger.kernel.org #4.3+
Link: http://lkml.kernel.org/r/20151231160106.640253454@linutronix.de
Signed-off-by: Thomas Gleixner &lt;tglx@linutronix.de&gt;
</content>
</entry>
</feed>
