highmem: fix SMP preemption bug in kmap_high_l1_vipt
PATCH 1/1 highmem: fix SMP preemption bug in kmap_high_l1_vipt
From: Andrew Howe <[email protected]>
smp_processor_id() must not be called from a preemptible context (this is checked by CONFIG_DEBUG_PREEMPT). kmap_high_l1_vipt() was doing so. This lead to a problem where the wrong per_cpu kmap_high_l1_vipt_depth could be incremented, causing a BUG_ON(*depth <= 0); in kunmap_high_l1_vipt().
The solution is to move the call to smp_processor_id() after the call to preempt_disable().
--- arch/arm/mm/highmem.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)
arch/arm/mm/highmem.c +8 -5
@@ -163,19 +163,22 @@ static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);void *kmap_high_l1_vipt (struct page *page,pte_t *saved_pte) { -unsigned int idx, cpu =smp_processor_id (); -int *depth = &per_cpu (kmap_high_l1_vipt_depth, cpu); +unsigned int idx, cpu; +int *depth;unsigned long vaddr, flags;pte_t pte, *ptep; +if (!in_interrupt ()) +preempt_disable (); + + cpu =smp_processor_id (); + depth = &per_cpu (kmap_high_l1_vipt_depth, cpu); + idx =KM_L1_CACHE +KM_TYPE_NR * cpu; vaddr =__fix_to_virt (FIX_KMAP_BEGIN + idx); ptep =TOP_PTE (vaddr); pte =mk_pte (page, kmap_prot); -if (!in_interrupt ()) -preempt_disable (); -raw_local_irq_save (flags); (*depth)++;if (pte_val (*ptep) ==pte_val (pte)) {
Signature · 9 lines
1.7.0.4 ----------------------------------------------------------------------------------- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. -----------------------------------------------------------------------------------
PATCH 1/1 highmem: fix SMP preemption bug in kmap_high_l1_vipt
Quoted 8 lines · gking at nvidia.com
From: Andrew Howe <[email protected]>
smp_processor_id()must not be called from a preemptible context (this is checked byCONFIG_DEBUG_PREEMPT).kmap_high_l1_vipt()was doing so. This lead to a problem where the wrongper_cpukmap_high_l1_vipt_depthcould be incremented, causing aBUG_ON(*depth <= 0); inkunmap_high_l1_vipt().
Quoted 4 lines
The solution is to move the call to
smp_processor_id()after the call topreempt_disable().Signed-off-by Gary King <[email protected]>
Please forward to RMK's patch system.
Quoted 47 lines
--- arch/arm/mm/highmem.c | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-)arch/arm/mm/highmem.c +8
-5@@ -163,19 +163,22 @@ static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);void *kmap_high_l1_vipt (struct page *page,pte_t *saved_pte) { -unsigned int idx, cpu =smp_processor_id (); -int *depth = &per_cpu (kmap_high_l1_vipt_depth, cpu); +unsigned int idx, cpu; +int *depth;unsigned long vaddr, flags;pte_t pte, *ptep; +if (!in_interrupt ()) +preempt_disable (); + + cpu =smp_processor_id (); + depth = &per_cpu (kmap_high_l1_vipt_depth, cpu); + idx =KM_L1_CACHE +KM_TYPE_NR * cpu; vaddr =__fix_to_virt (FIX_KMAP_BEGIN + idx); ptep =TOP_PTE (vaddr); pte =mk_pte (page, kmap_prot); -if (!in_interrupt ()) -preempt_disable (); -raw_local_irq_save (flags); (*depth)++;if (pte_val (*ptep) ==pte_val (pte)) {Signature · 9 lines
1.7.0.4 ----------------------------------------------------------------------------------- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. -----------------------------------------------------------------------------------
PATCH 1/1 highmem: fix SMP preemption bug in kmap_high_l1_vipt
Quoted 10 lines · Nicolas Pitre
Quoted 8 lines · gking at nvidia.com
From: Andrew Howe <[email protected]>
smp_processor_id()must not be called from a preemptible context (this is checked byCONFIG_DEBUG_PREEMPT).kmap_high_l1_vipt()was doing so. This lead to a problem where the wrongper_cpukmap_high_l1_vipt_depthcould be incremented, causing aBUG_ON(*depth <= 0); inkunmap_high_l1_vipt().
Quoted 8 lines
Quoted 4 lines
The solution is to move the call to
smp_processor_id()after the call topreempt_disable().Signed-off-by Gary King <[email protected]>Acked-by Nicolas Pitre <[email protected]>Please forward to RMK's patch system.
Unfortunately, I suspect that none of the remaining stuff in my master branch will make 2.6.35 (which is due this evening) especially as I've put the fixes for the Versatile/Realview/Versatile Express MMC card detection in there today, and we still don't know what's right for its GPIO-based card detection. (The change to fix the status method may have broken the GPIO-based method.)
So I'm not sending a pull request this evening. Hopefully people can work out what's right for the GPIO based card detection while I'm out tomorrow, and report back so it can be fixed in the evening if necessary.