From 7dd9982b9f470a8c3957353119e4832a1f582df3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Jul 2009 12:25:11 -0700 Subject: [PATCH] more .30 patches --- ...-accidental-reset-in-some-boot-modes.patch | 36 +++++ ...ne-corruption-with-debug_doublefault.patch | 56 +++++++ ...kfin-fix-deadlock-in-smp-ipi-handler.patch | 83 +++++++++++ .../blackfin-redo-handling-of-bad-irqs.patch | 117 +++++++++++++++ ...-write-access-fault-problem-for-real.patch | 140 ++++++++++++++++++ ...e-loop-in-get_futex_key-on-huge-page.patch | 44 ++++++ queue-2.6.30/series | 6 + 7 files changed, 482 insertions(+) create mode 100644 queue-2.6.30/blackfin-fix-accidental-reset-in-some-boot-modes.patch create mode 100644 queue-2.6.30/blackfin-fix-command-line-corruption-with-debug_doublefault.patch create mode 100644 queue-2.6.30/blackfin-fix-deadlock-in-smp-ipi-handler.patch create mode 100644 queue-2.6.30/blackfin-redo-handling-of-bad-irqs.patch create mode 100644 queue-2.6.30/futex-fix-the-write-access-fault-problem-for-real.patch create mode 100644 queue-2.6.30/futexes-fix-infinite-loop-in-get_futex_key-on-huge-page.patch diff --git a/queue-2.6.30/blackfin-fix-accidental-reset-in-some-boot-modes.patch b/queue-2.6.30/blackfin-fix-accidental-reset-in-some-boot-modes.patch new file mode 100644 index 00000000000..f0c1b2b2e49 --- /dev/null +++ b/queue-2.6.30/blackfin-fix-accidental-reset-in-some-boot-modes.patch @@ -0,0 +1,36 @@ +From 0de4adfb8c9674fa1572b0ff1371acc94b0be901 Mon Sep 17 00:00:00 2001 +From: Sonic Zhang +Date: Mon, 15 Jun 2009 07:39:19 +0000 +Subject: Blackfin: fix accidental reset in some boot modes + +From: Sonic Zhang + +commit 0de4adfb8c9674fa1572b0ff1371acc94b0be901 upstream. + +We read the SWRST (Software Reset) register to get at the last reset +state, and then we may configure the DOUBLE_FAULT bit to control behavior +when a double fault occurs. But if the lower bits of the register is +already set (like UART boot mode on a BF54x), we inadvertently make the +system reset by writing to the SYSTEM_RESET field at the same time. So +make sure the lower 4 bits are always cleared. + +Signed-off-by: Sonic Zhang +Signed-off-by: Mike Frysinger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/blackfin/kernel/setup.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/blackfin/kernel/setup.c ++++ b/arch/blackfin/kernel/setup.c +@@ -831,7 +831,8 @@ void __init setup_arch(char **cmdline_p) + defined(CONFIG_BF538) || defined(CONFIG_BF539) + _bfin_swrst = bfin_read_SWRST(); + #else +- _bfin_swrst = bfin_read_SYSCR(); ++ /* Clear boot mode field */ ++ _bfin_swrst = bfin_read_SYSCR() & ~0xf; + #endif + + #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT diff --git a/queue-2.6.30/blackfin-fix-command-line-corruption-with-debug_doublefault.patch b/queue-2.6.30/blackfin-fix-command-line-corruption-with-debug_doublefault.patch new file mode 100644 index 00000000000..17c80a5ad22 --- /dev/null +++ b/queue-2.6.30/blackfin-fix-command-line-corruption-with-debug_doublefault.patch @@ -0,0 +1,56 @@ +From 37082511f06108129bd5f96d625a6fae2d5a4ab4 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Tue, 26 May 2009 21:48:38 +0000 +Subject: Blackfin: fix command line corruption with DEBUG_DOUBLEFAULT + +From: Mike Frysinger + +commit 37082511f06108129bd5f96d625a6fae2d5a4ab4 upstream. + +Commit 6b3087c6 (which introduced Blackfin SMP) broke command line passing +when the DEBUG_DOUBLEFAULT config option was enabled. Switch the code to +using a scratch register and not R7 which holds the command line. + +Signed-off-by: Mike Frysinger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/blackfin/mach-common/head.S | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/arch/blackfin/mach-common/head.S ++++ b/arch/blackfin/mach-common/head.S +@@ -126,25 +126,25 @@ ENTRY(__start) + * below + */ + GET_PDA(p0, r0); +- r7 = [p0 + PDA_RETX]; ++ r6 = [p0 + PDA_RETX]; + p1.l = _init_saved_retx; + p1.h = _init_saved_retx; +- [p1] = r7; ++ [p1] = r6; + +- r7 = [p0 + PDA_DCPLB]; ++ r6 = [p0 + PDA_DCPLB]; + p1.l = _init_saved_dcplb_fault_addr; + p1.h = _init_saved_dcplb_fault_addr; +- [p1] = r7; ++ [p1] = r6; + +- r7 = [p0 + PDA_ICPLB]; ++ r6 = [p0 + PDA_ICPLB]; + p1.l = _init_saved_icplb_fault_addr; + p1.h = _init_saved_icplb_fault_addr; +- [p1] = r7; ++ [p1] = r6; + +- r7 = [p0 + PDA_SEQSTAT]; ++ r6 = [p0 + PDA_SEQSTAT]; + p1.l = _init_saved_seqstat; + p1.h = _init_saved_seqstat; +- [p1] = r7; ++ [p1] = r6; + #endif + + /* Initialize stack pointer */ diff --git a/queue-2.6.30/blackfin-fix-deadlock-in-smp-ipi-handler.patch b/queue-2.6.30/blackfin-fix-deadlock-in-smp-ipi-handler.patch new file mode 100644 index 00000000000..6c9e72fbad5 --- /dev/null +++ b/queue-2.6.30/blackfin-fix-deadlock-in-smp-ipi-handler.patch @@ -0,0 +1,83 @@ +From 86f2008bf546af9a434f480710e8d33891616bf5 Mon Sep 17 00:00:00 2001 +From: Sonic Zhang +Date: Wed, 10 Jun 2009 08:42:41 +0000 +Subject: Blackfin: fix deadlock in SMP IPI handler + +From: Sonic Zhang + +commit 86f2008bf546af9a434f480710e8d33891616bf5 upstream. + +When a low priority interrupt (like ethernet) is triggered between 2 high +priority IPI messages, a deadlock in disable_irq() is hit by the second +IPI handler. This is because the second IPI message is queued within the +first IPI handler, but the handler doesn't process all messages, and new +ones are inserted rather than appended. So now we process all the pending +messages, and append new ones to the pending list. + +URL: http://blackfin.uclinux.org/gf/tracker/5226 + +Signed-off-by: Sonic Zhang +Signed-off-by: Mike Frysinger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/blackfin/mach-common/smp.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/arch/blackfin/mach-common/smp.c ++++ b/arch/blackfin/mach-common/smp.c +@@ -139,7 +139,7 @@ static void ipi_call_function(unsigned i + + static irqreturn_t ipi_handler(int irq, void *dev_instance) + { +- struct ipi_message *msg, *mg; ++ struct ipi_message *msg; + struct ipi_message_queue *msg_queue; + unsigned int cpu = smp_processor_id(); + +@@ -149,7 +149,8 @@ static irqreturn_t ipi_handler(int irq, + msg_queue->count++; + + spin_lock(&msg_queue->lock); +- list_for_each_entry_safe(msg, mg, &msg_queue->head, list) { ++ while (!list_empty(&msg_queue->head)) { ++ msg = list_entry(msg_queue->head.next, typeof(*msg), list); + list_del(&msg->list); + switch (msg->type) { + case BFIN_IPI_RESCHEDULE: +@@ -216,7 +217,7 @@ int smp_call_function(void (*func)(void + for_each_cpu_mask(cpu, callmap) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); +- list_add(&msg->list, &msg_queue->head); ++ list_add_tail(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + } +@@ -256,7 +257,7 @@ int smp_call_function_single(int cpuid, + + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); +- list_add(&msg->list, &msg_queue->head); ++ list_add_tail(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + +@@ -287,7 +288,7 @@ void smp_send_reschedule(int cpu) + + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); +- list_add(&msg->list, &msg_queue->head); ++ list_add_tail(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + +@@ -315,7 +316,7 @@ void smp_send_stop(void) + for_each_cpu_mask(cpu, callmap) { + msg_queue = &per_cpu(ipi_msg_queue, cpu); + spin_lock_irqsave(&msg_queue->lock, flags); +- list_add(&msg->list, &msg_queue->head); ++ list_add_tail(&msg->list, &msg_queue->head); + spin_unlock_irqrestore(&msg_queue->lock, flags); + platform_send_ipi_cpu(cpu); + } diff --git a/queue-2.6.30/blackfin-redo-handling-of-bad-irqs.patch b/queue-2.6.30/blackfin-redo-handling-of-bad-irqs.patch new file mode 100644 index 00000000000..5567ba1717f --- /dev/null +++ b/queue-2.6.30/blackfin-redo-handling-of-bad-irqs.patch @@ -0,0 +1,117 @@ +From 26579216f3cdf1ae05f0af8412b444870a167510 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Mon, 15 Jun 2009 06:10:03 -0400 +Subject: Blackfin: redo handling of bad irqs + +From: Mike Frysinger + +commit 26579216f3cdf1ae05f0af8412b444870a167510 upstream. + +With the common IRQ code initializing much more of the irq_desc state, we +can't blindly initialize it ourselves to the local bad_irq state. If we +do, we end up wrongly clobbering many fields. So punt most of the bad irq +code as the common layers will handle the default state, and simply call +handle_bad_irq() directly when the IRQ we are processing is invalid. + +Signed-off-by: Mike Frysinger +Signed-off-by: Greg Kroah-Hartman + +--- + arch/blackfin/kernel/irqchip.c | 50 +++++++++-------------------------------- + 1 file changed, 11 insertions(+), 39 deletions(-) + +--- a/arch/blackfin/kernel/irqchip.c ++++ b/arch/blackfin/kernel/irqchip.c +@@ -38,14 +38,6 @@ + #include + + static atomic_t irq_err_count; +-static spinlock_t irq_controller_lock; +- +-/* +- * Dummy mask/unmask handler +- */ +-void dummy_mask_unmask_irq(unsigned int irq) +-{ +-} + + void ack_bad_irq(unsigned int irq) + { +@@ -53,21 +45,9 @@ void ack_bad_irq(unsigned int irq) + printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq); + } + +-static struct irq_chip bad_chip = { +- .ack = dummy_mask_unmask_irq, +- .mask = dummy_mask_unmask_irq, +- .unmask = dummy_mask_unmask_irq, +-}; +- + static struct irq_desc bad_irq_desc = { +- .status = IRQ_DISABLED, +- .chip = &bad_chip, + .handle_irq = handle_bad_irq, +- .depth = 1, + .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), +-#ifdef CONFIG_SMP +- .affinity = CPU_MASK_ALL +-#endif + }; + + #ifdef CONFIG_CPUMASK_OFFSTACK +@@ -117,21 +97,13 @@ __attribute__((l1_text)) + #endif + asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) + { +- struct pt_regs *old_regs; +- struct irq_desc *desc = irq_desc + irq; + #ifndef CONFIG_IPIPE + unsigned short pending, other_ints; + #endif +- old_regs = set_irq_regs(regs); +- +- /* +- * Some hardware gives randomly wrong interrupts. Rather +- * than crashing, do something sensible. +- */ +- if (irq >= NR_IRQS) +- desc = &bad_irq_desc; ++ struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); ++ + #ifdef CONFIG_DEBUG_STACKOVERFLOW + /* Debugging check for stack overflow: is there less than STACK_WARN free? */ + { +@@ -147,7 +119,15 @@ asmlinkage void asm_do_IRQ(unsigned int + } + } + #endif +- generic_handle_irq(irq); ++ ++ /* ++ * Some hardware gives randomly wrong interrupts. Rather ++ * than crashing, do something sensible. ++ */ ++ if (irq >= NR_IRQS) ++ handle_bad_irq(irq, &bad_irq_desc); ++ else ++ generic_handle_irq(irq); + + #ifndef CONFIG_IPIPE + /* +@@ -171,14 +151,6 @@ asmlinkage void asm_do_IRQ(unsigned int + + void __init init_IRQ(void) + { +- struct irq_desc *desc; +- int irq; +- +- spin_lock_init(&irq_controller_lock); +- for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) { +- *desc = bad_irq_desc; +- } +- + init_arch_irq(); + + #ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND diff --git a/queue-2.6.30/futex-fix-the-write-access-fault-problem-for-real.patch b/queue-2.6.30/futex-fix-the-write-access-fault-problem-for-real.patch new file mode 100644 index 00000000000..6d55ba53cba --- /dev/null +++ b/queue-2.6.30/futex-fix-the-write-access-fault-problem-for-real.patch @@ -0,0 +1,140 @@ +From tglx@linutronix.de Fri Jul 17 12:22:44 2009 +From: Thomas Gleixner +Date: Thu, 2 Jul 2009 18:59:39 +0200 (CEST) +Subject: futex: Fix the write access fault problem for real +To: Greg KH +Cc: stable@kernel.org +Message-ID: + + +commit d0725992c8a6fb63a16bc9e8b2a50094cc4db3cd and aa715284b4d28cabde6c25c568d769a6be712bc8 upstream + +commit 64d1304a64 (futex: setup writeable mapping for futex ops which +modify user space data) did address only half of the problem of write +access faults. + +The patch was made on two wrong assumptions: + +1) access_ok(VERIFY_WRITE,...) would actually check write access. + + On x86 it does _NOT_. It's a pure address range check. + +2) a RW mapped region can not go away under us. + + That's wrong as well. Nobody can prevent another thread to call + mprotect(PROT_READ) on that region where the futex resides. If that + call hits between the get_user_pages_fast() verification and the + actual write access in the atomic region we are toast again. + +The solution is to not rely on access_ok and get_user() for any write +access related fault on private and shared futexes. Instead we need to +fault it in with verification of write access. + +There is no generic non destructive write mechanism which would fault +the user page in trough a #PF, but as we already know that we will +fault we can as well call get_user_pages() directly and avoid the #PF +overhead. + +If get_user_pages() returns -EFAULT we know that we can not fix it +anymore and need to bail out to user space. + +Remove a bunch of confusing comments on this issue as well. + +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/futex.c | 42 +++++++++++++++++++++++------------------- + 1 file changed, 23 insertions(+), 19 deletions(-) + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -278,6 +278,25 @@ void put_futex_key(int fshared, union fu + drop_futex_key_refs(key); + } + ++/* ++ * fault_in_user_writeable - fault in user address and verify RW access ++ * @uaddr: pointer to faulting user space address ++ * ++ * Slow path to fixup the fault we just took in the atomic write ++ * access to @uaddr. ++ * ++ * We have no generic implementation of a non destructive write to the ++ * user address. We know that we faulted in the atomic pagefault ++ * disabled section so we can as well avoid the #PF overhead by ++ * calling get_user_pages() right away. ++ */ ++static int fault_in_user_writeable(u32 __user *uaddr) ++{ ++ int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, ++ 1, 1, 0, NULL, NULL); ++ return ret < 0 ? ret : 0; ++} ++ + static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval) + { + u32 curval; +@@ -739,7 +758,6 @@ retry: + retry_private: + op_ret = futex_atomic_op_inuser(op, uaddr2); + if (unlikely(op_ret < 0)) { +- u32 dummy; + + double_unlock_hb(hb1, hb2); + +@@ -757,7 +775,7 @@ retry_private: + goto out_put_keys; + } + +- ret = get_user(dummy, uaddr2); ++ ret = fault_in_user_writeable(uaddr2); + if (ret) + goto out_put_keys; + +@@ -1097,7 +1115,7 @@ retry: + handle_fault: + spin_unlock(q->lock_ptr); + +- ret = get_user(uval, uaddr); ++ ret = fault_in_user_writeable(uaddr); + + spin_lock(q->lock_ptr); + +@@ -1552,16 +1570,9 @@ out: + return ret; + + uaddr_faulted: +- /* +- * We have to r/w *(int __user *)uaddr, and we have to modify it +- * atomically. Therefore, if we continue to fault after get_user() +- * below, we need to handle the fault ourselves, while still holding +- * the mmap_sem. This can occur if the uaddr is under contention as +- * we have to drop the mmap_sem in order to call get_user(). +- */ + queue_unlock(&q, hb); + +- ret = get_user(uval, uaddr); ++ ret = fault_in_user_writeable(uaddr); + if (ret) + goto out_put_key; + +@@ -1657,17 +1668,10 @@ out: + return ret; + + pi_faulted: +- /* +- * We have to r/w *(int __user *)uaddr, and we have to modify it +- * atomically. Therefore, if we continue to fault after get_user() +- * below, we need to handle the fault ourselves, while still holding +- * the mmap_sem. This can occur if the uaddr is under contention as +- * we have to drop the mmap_sem in order to call get_user(). +- */ + spin_unlock(&hb->lock); + put_futex_key(fshared, &key); + +- ret = get_user(uval, uaddr); ++ ret = fault_in_user_writeable(uaddr); + if (!ret) + goto retry; + diff --git a/queue-2.6.30/futexes-fix-infinite-loop-in-get_futex_key-on-huge-page.patch b/queue-2.6.30/futexes-fix-infinite-loop-in-get_futex_key-on-huge-page.patch new file mode 100644 index 00000000000..ba7d365380d --- /dev/null +++ b/queue-2.6.30/futexes-fix-infinite-loop-in-get_futex_key-on-huge-page.patch @@ -0,0 +1,44 @@ +From ce2ae53b750abfaa012ce408e93da131a5b5649b Mon Sep 17 00:00:00 2001 +From: Sonny Rao +Date: Fri, 10 Jul 2009 18:13:13 -0500 +Subject: futexes: Fix infinite loop in get_futex_key() on huge page + +From: Sonny Rao + +commit ce2ae53b750abfaa012ce408e93da131a5b5649b upstream. + +get_futex_key() can infinitely loop if it is called on a +virtual address that is within a huge page but not aligned to +the beginning of that page. The call to get_user_pages_fast +will return the struct page for a sub-page within the huge page +and the check for page->mapping will always fail. + +The fix is to call compound_head on the page before checking +that it's mapped. + +Signed-off-by: Sonny Rao +Acked-by: Thomas Gleixner +Cc: anton@samba.org +Cc: rajamony@us.ibm.com +Cc: speight@us.ibm.com +Cc: mstephen@us.ibm.com +Cc: grimm@us.ibm.com +Cc: mikey@ozlabs.au.ibm.com +LKML-Reference: <20090710231313.GA23572@us.ibm.com> +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/futex.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -241,6 +241,7 @@ again: + if (err < 0) + return err; + ++ page = compound_head(page); + lock_page(page); + if (!page->mapping) { + unlock_page(page); diff --git a/queue-2.6.30/series b/queue-2.6.30/series index 17805df9401..c4691432df7 100644 --- a/queue-2.6.30/series +++ b/queue-2.6.30/series @@ -2,3 +2,9 @@ add-fno-delete-null-pointer-checks-to-gcc-cflags.patch security-use-mmap_min_addr-indepedently-of-security-models.patch tun-tap-fix-crashes-if-open-dev-net-tun-and-then-poll-it.patch personality-fix-per_clear_on_setid.patch +blackfin-fix-accidental-reset-in-some-boot-modes.patch +blackfin-redo-handling-of-bad-irqs.patch +blackfin-fix-deadlock-in-smp-ipi-handler.patch +blackfin-fix-command-line-corruption-with-debug_doublefault.patch +futex-fix-the-write-access-fault-problem-for-real.patch +futexes-fix-infinite-loop-in-get_futex_key-on-huge-page.patch -- 2.47.2