From 998de4acb2ba188d20768d1065658377a2e7d29b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 11 May 2012 17:42:37 +0100 Subject: ARM: 7417/1: vfp: ensure preemption is disabled when enabling VFP access The vfp_enable function enables access to the VFP co-processor register space (cp10 and cp11) on the current CPU and must be called with preemption disabled. Unfortunately, the vfp_init late initcall does not disable preemption and can lead to an oops during boot if thread migration occurs at the wrong time and we end up attempting to access the FPSID on a CPU with VFP access disabled. This patch fixes the initcall to call vfp_enable from a non-preemptible context on each CPU and adds a BUG_ON(preemptible) to ensure that any similar problems are easily spotted in the future. Cc: stable@vger.kernel.org Reported-by: Hyungwoo Yang Signed-off-by: Hyungwoo Yang Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/vfp/vfpmodule.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index bc683b8219b5..c5767b5a4318 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -432,7 +433,10 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) static void vfp_enable(void *unused) { - u32 access = get_copro_access(); + u32 access; + + BUG_ON(preemptible()); + access = get_copro_access(); /* * Enable full access to VFP (cp10 and cp11) @@ -657,7 +661,7 @@ static int __init vfp_init(void) unsigned int cpu_arch = cpu_architecture(); if (cpu_arch >= CPU_ARCH_ARMv6) - vfp_enable(NULL); + on_each_cpu(vfp_enable, NULL, 1); /* * First check that there is a VFP that we can use. @@ -678,8 +682,6 @@ static int __init vfp_init(void) } else { hotcpu_notifier(vfp_hotplug, 0); - smp_call_function(vfp_enable, NULL, 1); - VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ printk("implementor %02x architecture %d part %02x variant %x rev %x\n", (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT, -- cgit v1.2.3 From 97e7abc5e04bea6a5db8d54ad34407bb46e85403 Mon Sep 17 00:00:00 2001 From: Peter De Schrijver Date: Mon, 14 May 2012 13:27:09 +0300 Subject: ARM: tegra: Fix flow controller accesses flowctrl_write_cpu_csr uses the cpu halt offsets and vice versa. This patch fixes this bug. Reported-by: Dan Willemsen Signed-off-by: Peter De Schrijver [swarren: This problem was introduced in v3.4-rc1, in commit 26fe681 "ARM: tegra: functions to access the flowcontroller", when this file was first added] Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/flowctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c index fef66a7486ed..f07488e0bd32 100644 --- a/arch/arm/mach-tegra/flowctrl.c +++ b/arch/arm/mach-tegra/flowctrl.c @@ -53,10 +53,10 @@ static void flowctrl_update(u8 offset, u32 value) void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value) { - return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); + return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); } void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) { - return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value); + return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value); } -- cgit v1.2.3 From 9b61a4d1b2064dbd0c9e61754305ac852170509f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 16 May 2012 15:19:20 +0100 Subject: ARM: prevent VM_GROWSDOWN mmaps extending below FIRST_USER_ADDRESS Cc: Reported-by: Al Viro Signed-off-by: Russell King --- arch/arm/mm/fault.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index f07467533365..5bb48356d217 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -247,7 +247,9 @@ good_area: return handle_mm_fault(mm, vma, addr & PAGE_MASK, flags); check_stack: - if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) + /* Don't allow expansion below FIRST_USER_ADDRESS */ + if (vma->vm_flags & VM_GROWSDOWN && + addr >= FIRST_USER_ADDRESS && !expand_stack(vma, addr)) goto good_area; out: return fault; -- cgit v1.2.3 From ad3b8a83933e83e5a2a08956211343bda269e778 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Thu, 17 May 2012 11:28:55 +0800 Subject: ARM: PRIMA2: fix irq domain size and IRQ mask of internal interrupt controller the old codes will cause 3.4 kernel warning as irq domain size is wrong: ------------[ cut here ]------------ WARNING: at kernel/irq/irqdomain.c:74 irq_domain_legacy_revmap+0x24/0x48() Modules linked in: [] (unwind_backtrace+0x0/0xf8) from [] (warn_slowpath_common+0x54/0x64) [] (warn_slowpath_common+0x54/0x64) from [] (warn_slowpath_null+0x1c/0x24) [] (warn_slowpath_null+0x1c/0x24) from [] (irq_domain_legacy_revmap+0x24/0x48) [] (irq_domain_legacy_revmap+0x24/0x48) from [] (irq_create_mapping+0x20/0x120) [] (irq_create_mapping+0x20/0x120) from [] (irq_create_of_mapping+0x7c/0xf0) [] (irq_create_of_mapping+0x7c/0xf0) from [] (irq_of_parse_and_map+0x2c/0x34) [] (irq_of_parse_and_map+0x2c/0x34) from [] (of_irq_to_resource+0x18/0x74) [] (of_irq_to_resource+0x18/0x74) from [] (of_irq_count+0x24/0x34) [] (of_irq_count+0x24/0x34) from [] (of_device_alloc+0x58/0x158) [] (of_device_alloc+0x58/0x158) from [] (of_platform_device_create_pdata+0x3c/0x80) [] (of_platform_device_create_pdata+0x3c/0x80) from [] (of_platform_bus_create+0xc8/0x190) [] (of_platform_bus_create+0xc8/0x190) from [] (of_platform_bus_create+0x12c/0x190) ---[ end trace 1b75b31a2719ed32 ]--- Signed-off-by: Barry Song Signed-off-by: Olof Johansson --- arch/arm/mach-prima2/irq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c index 37c2de9b6f26..a7b9415d30f8 100644 --- a/arch/arm/mach-prima2/irq.c +++ b/arch/arm/mach-prima2/irq.c @@ -42,7 +42,8 @@ sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) static __init void sirfsoc_irq_init(void) { sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); - sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32); + sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, + SIRFSOC_INTENAL_IRQ_END + 1 - 32); writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); @@ -68,7 +69,8 @@ void __init sirfsoc_of_irq_init(void) if (!sirfsoc_intc_base) panic("unable to map intc cpu registers\n"); - irq_domain_add_legacy(np, 32, 0, 0, &irq_domain_simple_ops, NULL); + irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0, + &irq_domain_simple_ops, NULL); of_node_put(np); -- cgit v1.2.3 From 1a3abcf41f13666d4ed241c8cc7f48bd38e7b543 Mon Sep 17 00:00:00 2001 From: Vitaly Andrianov Date: Tue, 15 May 2012 15:01:16 +0100 Subject: ARM: 7418/1: LPAE: fix access flag setup in mem_type_table A zero value for prot_sect in the memory types table implies that section mappings should never be created for the memory type in question. This is checked for in alloc_init_section(). With LPAE, we set a bit to mask access flag faults for kernel mappings. This breaks the aforementioned (!prot_sect) check in alloc_init_section(). This patch fixes this bug by first checking for a non-zero prot_sect before setting the PMD_SECT_AF flag. Signed-off-by: Vitaly Andrianov Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/mm/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm') diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 2c7cf2f9c837..aa78de8bfdd3 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -489,7 +489,8 @@ static void __init build_mem_type_table(void) */ for (i = 0; i < ARRAY_SIZE(mem_types); i++) { mem_types[i].prot_pte |= PTE_EXT_AF; - mem_types[i].prot_sect |= PMD_SECT_AF; + if (mem_types[i].prot_sect) + mem_types[i].prot_sect |= PMD_SECT_AF; } kern_pgprot |= PTE_EXT_AF; vecs_pgprot |= PTE_EXT_AF; -- cgit v1.2.3 From 56cb248428ead13a6b423ed3f3cf9e4aa01244b1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 15 May 2012 15:51:54 +0100 Subject: ARM: 7419/1: vfp: fix VFP flushing regression on sigreturn path Commit ff9a184c ("ARM: 7400/1: vfp: clear fpscr length and stride bits on entry to sig handler") flushes the VFP state prior to entering a signal handler so that a VFP operation inside the handler will trap and force a restore of ABI-compliant registers. Reflushing and disabling VFP on the sigreturn path is predicated on the saved thread state indicating that VFP was used by the handler -- however for SMP platforms this is only set on context-switch, making the check unreliable and causing VFP register corruption in userspace since the register values are not necessarily those restored from the sigframe. This patch unconditionally flushes the VFP state after a signal handler. Since we already perform the flush before the handler and the flushing itself happens lazily, the redundant flush when VFP is not used by the handler is essentially a nop. Reported-by: Jon Medhurst Signed-off-by: Jon Medhurst Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/vfp/vfpmodule.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index c5767b5a4318..b0197b2c857d 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -577,12 +577,6 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp, * entry. */ hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK); - - /* - * Disable VFP in the hwstate so that we can detect if it gets - * used. - */ - hwstate->fpexc &= ~FPEXC_EN; return 0; } @@ -595,12 +589,8 @@ int vfp_restore_user_hwstate(struct user_vfp __user *ufp, unsigned long fpexc; int err = 0; - /* - * If VFP has been used, then disable it to avoid corrupting - * the new thread state. - */ - if (hwstate->fpexc & FPEXC_EN) - vfp_flush_hwstate(thread); + /* Disable VFP to avoid corrupting the new thread state. */ + vfp_flush_hwstate(thread); /* * Copy the floating point registers. There can be unused -- cgit v1.2.3