From 728f5c076ad000e547aa9e00d16792043ee1bfc6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 17 Nov 2005 16:43:14 +0000 Subject: [ARM] Improve comment about ASSERT()s in vmlinux.lds.S Provide folk with an idea what to do if the ASSERT statements fail with their linker. Signed-off-by: Russell King --- arch/arm/kernel/vmlinux.lds.S | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 80c8e4c8cef..9a47770114d 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -172,6 +172,10 @@ SECTIONS .comment 0 : { *(.comment) } } -/* those must never be empty */ +/* + * These must never be empty + * If you have to comment these two assert statements out, your + * binutils is too old (for other reasons as well) + */ ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support") ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined") -- cgit v1.2.3 From 67a1901ff498363e253b90ba132e336c925203ed Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 17 Nov 2005 16:48:00 +0000 Subject: [ARM] __ioremap doesn't use 4th argument The "align" argument in ARMs __ioremap is unused and provides a misleading expectation that it might do something. It doesn't. Remove it. Signed-off-by: Russell King --- arch/arm/mm/ioremap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 0f128c28fee..10901398e4a 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -130,8 +130,7 @@ remap_area_pages(unsigned long start, unsigned long phys_addr, * mapping. See include/asm-arm/proc-armv/pgtable.h for more information. */ void __iomem * -__ioremap(unsigned long phys_addr, size_t size, unsigned long flags, - unsigned long align) +__ioremap(unsigned long phys_addr, size_t size, unsigned long flags) { void * addr; struct vm_struct * area; -- cgit v1.2.3 From 02b30839220fa3ef80a34ed6ee174fa2d9937eac Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 17 Nov 2005 22:43:30 +0000 Subject: [ARM] Fix some corner cases in new mm initialisation Document that the VMALLOC_END address must be aligned to 2MB since it must align with a PGD boundary. Allocate the vectors page early so that the flush_cache_all() later will cause any dirty cache lines in the direct mapping will be safely written back. Move the flush_cache_all() to the second local_flush_cache_tlb() and remove the now redundant first local_flush_cache_tlb(). Signed-off-by: Russell King --- arch/arm/mm/init.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'arch') diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index c168f322ef8..8b276ee38ac 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -420,7 +420,8 @@ static void __init bootmem_init(struct meminfo *mi) * Set up device the mappings. Since we clear out the page tables for all * mappings above VMALLOC_END, we will remove any debug device mappings. * This means you have to be careful how you debug this function, or any - * called function. (Do it by code inspection!) + * called function. This means you can't use any function or debugging + * method which may touch any device, otherwise the kernel _will_ crash. */ static void __init devicemaps_init(struct machine_desc *mdesc) { @@ -428,6 +429,12 @@ static void __init devicemaps_init(struct machine_desc *mdesc) unsigned long addr; void *vectors; + /* + * Allocate the vector page early. + */ + vectors = alloc_bootmem_low_pages(PAGE_SIZE); + BUG_ON(!vectors); + for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) pmd_clear(pmd_off_k(addr)); @@ -461,12 +468,6 @@ static void __init devicemaps_init(struct machine_desc *mdesc) create_mapping(&map); #endif - flush_cache_all(); - local_flush_tlb_all(); - - vectors = alloc_bootmem_low_pages(PAGE_SIZE); - BUG_ON(!vectors); - /* * Create a mapping for the machine vectors at the high-vectors * location (0xffff0000). If we aren't using high-vectors, also @@ -491,12 +492,13 @@ static void __init devicemaps_init(struct machine_desc *mdesc) mdesc->map_io(); /* - * Finally flush the tlb again - this ensures that we're in a - * consistent state wrt the writebuffer if the writebuffer needs - * draining. After this point, we can start to touch devices - * again. + * Finally flush the caches and tlb to ensure that we're in a + * consistent state wrt the writebuffer. This also ensures that + * any write-allocated cache lines in the vector page are written + * back. After this point, we can start to touch devices again. */ local_flush_tlb_all(); + flush_cache_all(); } /* -- cgit v1.2.3 From d2c5b69099ff747f9757da2416383b9a999171b1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 18 Nov 2005 14:22:03 +0000 Subject: [ARM] Fix get_user when passed a const pointer Unfortunately, later gcc versions error out when our get_user is passed a const pointer, since we write to a temporary variable declared as typeof(*(p)) which propagates the const-ness. Signed-off-by: Russell King --- arch/arm/kernel/armksyms.c | 1 - arch/arm/lib/getuser.S | 11 ----------- 2 files changed, 12 deletions(-) (limited to 'arch') diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index 7a3261f0bf7..9997098009a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -120,7 +120,6 @@ EXPORT_SYMBOL(__arch_strncpy_from_user); EXPORT_SYMBOL(__get_user_1); EXPORT_SYMBOL(__get_user_2); EXPORT_SYMBOL(__get_user_4); -EXPORT_SYMBOL(__get_user_8); EXPORT_SYMBOL(__put_user_1); EXPORT_SYMBOL(__put_user_2); diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index d204018070a..c03ea8e666b 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -54,15 +54,6 @@ __get_user_4: mov r0, #0 mov pc, lr - .global __get_user_8 -__get_user_8: -5: ldrt r2, [r0], #4 -6: ldrt r3, [r0] - mov r0, #0 - mov pc, lr - -__get_user_bad_8: - mov r3, #0 __get_user_bad: mov r2, #0 mov r0, #-EFAULT @@ -73,6 +64,4 @@ __get_user_bad: .long 2b, __get_user_bad .long 3b, __get_user_bad .long 4b, __get_user_bad - .long 5b, __get_user_bad_8 - .long 6b, __get_user_bad_8 .previous -- cgit v1.2.3 From a6c61e9dfdd0adf8443932cfc43b0c1e25036ad5 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Sat, 19 Nov 2005 10:01:07 +0000 Subject: [ARM] 3168/1: Update ARM signal delivery and masking Patch from Daniel Jacobowitz After delivering a signal (creating its stack frame) we must check for additional pending unblocked signals before returning to userspace. Otherwise signals may be delayed past the next syscall or reschedule. Once that was fixed it became obvious that the ARM signal mask manipulation was broken. It was a little bit broken before the recent SA_NODEFER changes, and then very broken after them. We must block the requested signals before starting the handler or the same signal can be delivered again before the handler even gets a chance to run. Signed-off-by: Daniel Jacobowitz Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 3 +- arch/arm/kernel/signal.c | 25 +++--- arch/arm/mm/Makefile | 2 +- arch/arm/mm/blockops.c | 185 ----------------------------------------- 4 files changed, 14 insertions(+), 201 deletions(-) delete mode 100644 arch/arm/mm/blockops.c (limited to 'arch') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 066597f4345..f7f18307523 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -48,8 +48,7 @@ work_pending: mov r0, sp @ 'regs' mov r2, why @ 'syscall' bl do_notify_resume - disable_irq @ disable interrupts - b no_work_pending + b ret_slow_syscall @ Check work again work_resched: bl schedule diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index a917e3dd366..765922bcf9e 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -595,23 +595,22 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, */ ret |= !valid_user_regs(regs); - /* - * Block the signal if we were unsuccessful. - */ if (ret != 0) { - spin_lock_irq(&tsk->sighand->siglock); - sigorsets(&tsk->blocked, &tsk->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(&tsk->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(&tsk->sighand->siglock); + force_sigsegv(sig, tsk); + return; } - if (ret == 0) - return; + /* + * Block the signal if we were successful. + */ + spin_lock_irq(&tsk->sighand->siglock); + sigorsets(&tsk->blocked, &tsk->blocked, + &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(&tsk->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(&tsk->sighand->siglock); - force_sigsegv(sig, tsk); } /* diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 59f47d4c2df..ffe73ba2bf1 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -51,4 +51,4 @@ obj-$(CONFIG_CPU_ARM1026) += proc-arm1026.o obj-$(CONFIG_CPU_SA110) += proc-sa110.o obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o -obj-$(CONFIG_CPU_V6) += proc-v6.o blockops.o +obj-$(CONFIG_CPU_V6) += proc-v6.o diff --git a/arch/arm/mm/blockops.c b/arch/arm/mm/blockops.c deleted file mode 100644 index 4f5ee2d0899..00000000000 --- a/arch/arm/mm/blockops.c +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include - -extern struct cpu_cache_fns blk_cache_fns; - -#define HARVARD_CACHE - -/* - * blk_flush_kern_dcache_page(kaddr) - * - * Ensure that the data held in the page kaddr is written back - * to the page in question. - * - * - kaddr - kernel address (guaranteed to be page aligned) - */ -static void __attribute__((naked)) -blk_flush_kern_dcache_page(void *kaddr) -{ - asm( - "add r1, r0, %0 \n\ - sub r1, r1, %1 \n\ -1: .word 0xec401f0e @ mcrr p15, 0, r0, r1, c14, 0 @ blocking \n\ - mov r0, #0 \n\ - mcr p15, 0, r0, c7, c5, 0 \n\ - mcr p15, 0, r0, c7, c10, 4 \n\ - mov pc, lr" - : - : "I" (PAGE_SIZE), "I" (L1_CACHE_BYTES)); -} - -/* - * blk_dma_inv_range(start,end) - * - * Invalidate the data cache within the specified region; we will - * be performing a DMA operation in this region and we want to - * purge old data in the cache. - * - * - start - virtual start address of region - * - end - virtual end address of region - */ -static void __attribute__((naked)) -blk_dma_inv_range_unified(unsigned long start, unsigned long end) -{ - asm( - "tst r0, %0 \n\ - mcrne p15, 0, r0, c7, c11, 1 @ clean unified line \n\ - tst r1, %0 \n\ - mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line\n\ - .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\ - mov r0, #0 \n\ - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ - mov pc, lr" - : - : "I" (L1_CACHE_BYTES - 1)); -} - -static void __attribute__((naked)) -blk_dma_inv_range_harvard(unsigned long start, unsigned long end) -{ - asm( - "tst r0, %0 \n\ - mcrne p15, 0, r0, c7, c10, 1 @ clean D line \n\ - tst r1, %0 \n\ - mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line \n\ - .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\ - mov r0, #0 \n\ - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ - mov pc, lr" - : - : "I" (L1_CACHE_BYTES - 1)); -} - -/* - * blk_dma_clean_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -static void __attribute__((naked)) -blk_dma_clean_range(unsigned long start, unsigned long end) -{ - asm( - ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0 @ blocking \n\ - mov r0, #0 \n\ - mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\ - mov pc, lr"); -} - -/* - * blk_dma_flush_range(start,end) - * - start - virtual start address of region - * - end - virtual end address of region - */ -static void __attribute__((naked)) -blk_dma_flush_range(unsigned long start, unsigned long end) -{ - asm( - ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0 @ blocking \n\ - mov pc, lr"); -} - -static int blockops_trap(struct pt_regs *regs, unsigned int instr) -{ - regs->ARM_r4 |= regs->ARM_r2; - regs->ARM_pc += 4; - return 0; -} - -static char *func[] = { - "Prefetch data range", - "Clean+Invalidate data range", - "Clean data range", - "Invalidate data range", - "Invalidate instr range" -}; - -static struct undef_hook blockops_hook __initdata = { - .instr_mask = 0x0fffffd0, - .instr_val = 0x0c401f00, - .cpsr_mask = PSR_T_BIT, - .cpsr_val = 0, - .fn = blockops_trap, -}; - -static int __init blockops_check(void) -{ - register unsigned int err asm("r4") = 0; - unsigned int err_pos = 1; - unsigned int cache_type; - int i; - - asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_type)); - - printk("Checking V6 block cache operations:\n"); - register_undef_hook(&blockops_hook); - - __asm__ ("mov r0, %0\n\t" - "mov r1, %1\n\t" - "mov r2, #1\n\t" - ".word 0xec401f2c @ mcrr p15, 0, r1, r0, c12, 2\n\t" - "mov r2, #2\n\t" - ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0\n\t" - "mov r2, #4\n\t" - ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0\n\t" - "mov r2, #8\n\t" - ".word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0\n\t" - "mov r2, #16\n\t" - ".word 0xec401f05 @ mcrr p15, 0, r1, r0, c5, 0\n\t" - : - : "r" (PAGE_OFFSET), "r" (PAGE_OFFSET + 128) - : "r0", "r1", "r2"); - - unregister_undef_hook(&blockops_hook); - - for (i = 0; i < ARRAY_SIZE(func); i++, err_pos <<= 1) - printk("%30s: %ssupported\n", func[i], err & err_pos ? "not " : ""); - - if ((err & 8) == 0) { - printk(" --> Using %s block cache invalidate\n", - cache_type & (1 << 24) ? "harvard" : "unified"); - if (cache_type & (1 << 24)) - cpu_cache.dma_inv_range = blk_dma_inv_range_harvard; - else - cpu_cache.dma_inv_range = blk_dma_inv_range_unified; - } - if ((err & 4) == 0) { - printk(" --> Using block cache clean\n"); - cpu_cache.dma_clean_range = blk_dma_clean_range; - } - if ((err & 2) == 0) { - printk(" --> Using block cache clean+invalidate\n"); - cpu_cache.dma_flush_range = blk_dma_flush_range; - cpu_cache.flush_kern_dcache_page = blk_flush_kern_dcache_page; - } - - return 0; -} - -__initcall(blockops_check); -- cgit v1.2.3