···11 Kernel Memory Layout on ARM Linux2233 Russell King <rmk@arm.linux.org.uk>44- May 21, 2004 (2.6.6)44+ November 17, 2005 (2.6.15)5566This document describes the virtual memory layout which the Linux77kernel uses for ARM processors. It indicates which regions are···3737 mapping region.38383939VMALLOC_END feffffff Free for platform use, recommended.4040+ VMALLOC_END must be aligned to a 2MB4141+ boundary.40424143VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space.4244 Memory returned by vmalloc/ioremap will
···4848 mov r0, sp @ 'regs'4949 mov r2, why @ 'syscall'5050 bl do_notify_resume5151- disable_irq @ disable interrupts5252- b no_work_pending5151+ b ret_slow_syscall @ Check work again53525453work_resched:5554 bl schedule
+12-13
arch/arm/kernel/signal.c
···595595 */596596 ret |= !valid_user_regs(regs);597597598598- /*599599- * Block the signal if we were unsuccessful.600600- */601598 if (ret != 0) {602602- spin_lock_irq(&tsk->sighand->siglock);603603- sigorsets(&tsk->blocked, &tsk->blocked,604604- &ka->sa.sa_mask);605605- if (!(ka->sa.sa_flags & SA_NODEFER))606606- sigaddset(&tsk->blocked, sig);607607- recalc_sigpending();608608- spin_unlock_irq(&tsk->sighand->siglock);599599+ force_sigsegv(sig, tsk);600600+ return;609601 }610602611611- if (ret == 0)612612- return;603603+ /*604604+ * Block the signal if we were successful.605605+ */606606+ spin_lock_irq(&tsk->sighand->siglock);607607+ sigorsets(&tsk->blocked, &tsk->blocked,608608+ &ka->sa.sa_mask);609609+ if (!(ka->sa.sa_flags & SA_NODEFER))610610+ sigaddset(&tsk->blocked, sig);611611+ recalc_sigpending();612612+ spin_unlock_irq(&tsk->sighand->siglock);613613614614- force_sigsegv(sig, tsk);615614}616615617616/*
+5-1
arch/arm/kernel/vmlinux.lds.S
···172172 .comment 0 : { *(.comment) }173173}174174175175-/* those must never be empty */175175+/*176176+ * These must never be empty177177+ * If you have to comment these two assert statements out, your178178+ * binutils is too old (for other reasons as well)179179+ */176180ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")177181ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")
···11-#include <linux/kernel.h>22-#include <linux/init.h>33-#include <linux/errno.h>44-#include <linux/mm.h>55-66-#include <asm/memory.h>77-#include <asm/ptrace.h>88-#include <asm/cacheflush.h>99-#include <asm/traps.h>1010-1111-extern struct cpu_cache_fns blk_cache_fns;1212-1313-#define HARVARD_CACHE1414-1515-/*1616- * blk_flush_kern_dcache_page(kaddr)1717- *1818- * Ensure that the data held in the page kaddr is written back1919- * to the page in question.2020- *2121- * - kaddr - kernel address (guaranteed to be page aligned)2222- */2323-static void __attribute__((naked))2424-blk_flush_kern_dcache_page(void *kaddr)2525-{2626- asm(2727- "add r1, r0, %0 \n\2828- sub r1, r1, %1 \n\2929-1: .word 0xec401f0e @ mcrr p15, 0, r0, r1, c14, 0 @ blocking \n\3030- mov r0, #0 \n\3131- mcr p15, 0, r0, c7, c5, 0 \n\3232- mcr p15, 0, r0, c7, c10, 4 \n\3333- mov pc, lr"3434- :3535- : "I" (PAGE_SIZE), "I" (L1_CACHE_BYTES));3636-}3737-3838-/*3939- * blk_dma_inv_range(start,end)4040- *4141- * Invalidate the data cache within the specified region; we will4242- * be performing a DMA operation in this region and we want to4343- * purge old data in the cache.4444- *4545- * - start - virtual start address of region4646- * - end - virtual end address of region4747- */4848-static void __attribute__((naked))4949-blk_dma_inv_range_unified(unsigned long start, unsigned long end)5050-{5151- asm(5252- "tst r0, %0 \n\5353- mcrne p15, 0, r0, c7, c11, 1 @ clean unified line \n\5454- tst r1, %0 \n\5555- mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line\n\5656- .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\5757- mov r0, #0 \n\5858- mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\5959- mov pc, lr"6060- :6161- : "I" (L1_CACHE_BYTES - 1));6262-}6363-6464-static void __attribute__((naked))6565-blk_dma_inv_range_harvard(unsigned long start, unsigned long end)6666-{6767- asm(6868- "tst r0, %0 \n\6969- mcrne p15, 0, r0, c7, c10, 1 @ clean D line \n\7070- tst r1, %0 \n\7171- mcrne p15, 0, r1, c7, c14, 1 @ clean & invalidate D line \n\7272- .word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0 @ blocking \n\7373- mov r0, #0 \n\7474- mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\7575- mov pc, lr"7676- :7777- : "I" (L1_CACHE_BYTES - 1));7878-}7979-8080-/*8181- * blk_dma_clean_range(start,end)8282- * - start - virtual start address of region8383- * - end - virtual end address of region8484- */8585-static void __attribute__((naked))8686-blk_dma_clean_range(unsigned long start, unsigned long end)8787-{8888- asm(8989- ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0 @ blocking \n\9090- mov r0, #0 \n\9191- mcr p15, 0, r0, c7, c10, 4 @ drain write buffer \n\9292- mov pc, lr");9393-}9494-9595-/*9696- * blk_dma_flush_range(start,end)9797- * - start - virtual start address of region9898- * - end - virtual end address of region9999- */100100-static void __attribute__((naked))101101-blk_dma_flush_range(unsigned long start, unsigned long end)102102-{103103- asm(104104- ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0 @ blocking \n\105105- mov pc, lr");106106-}107107-108108-static int blockops_trap(struct pt_regs *regs, unsigned int instr)109109-{110110- regs->ARM_r4 |= regs->ARM_r2;111111- regs->ARM_pc += 4;112112- return 0;113113-}114114-115115-static char *func[] = {116116- "Prefetch data range",117117- "Clean+Invalidate data range",118118- "Clean data range",119119- "Invalidate data range",120120- "Invalidate instr range"121121-};122122-123123-static struct undef_hook blockops_hook __initdata = {124124- .instr_mask = 0x0fffffd0,125125- .instr_val = 0x0c401f00,126126- .cpsr_mask = PSR_T_BIT,127127- .cpsr_val = 0,128128- .fn = blockops_trap,129129-};130130-131131-static int __init blockops_check(void)132132-{133133- register unsigned int err asm("r4") = 0;134134- unsigned int err_pos = 1;135135- unsigned int cache_type;136136- int i;137137-138138- asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_type));139139-140140- printk("Checking V6 block cache operations:\n");141141- register_undef_hook(&blockops_hook);142142-143143- __asm__ ("mov r0, %0\n\t"144144- "mov r1, %1\n\t"145145- "mov r2, #1\n\t"146146- ".word 0xec401f2c @ mcrr p15, 0, r1, r0, c12, 2\n\t"147147- "mov r2, #2\n\t"148148- ".word 0xec401f0e @ mcrr p15, 0, r1, r0, c14, 0\n\t"149149- "mov r2, #4\n\t"150150- ".word 0xec401f0c @ mcrr p15, 0, r1, r0, c12, 0\n\t"151151- "mov r2, #8\n\t"152152- ".word 0xec401f06 @ mcrr p15, 0, r1, r0, c6, 0\n\t"153153- "mov r2, #16\n\t"154154- ".word 0xec401f05 @ mcrr p15, 0, r1, r0, c5, 0\n\t"155155- :156156- : "r" (PAGE_OFFSET), "r" (PAGE_OFFSET + 128)157157- : "r0", "r1", "r2");158158-159159- unregister_undef_hook(&blockops_hook);160160-161161- for (i = 0; i < ARRAY_SIZE(func); i++, err_pos <<= 1)162162- printk("%30s: %ssupported\n", func[i], err & err_pos ? "not " : "");163163-164164- if ((err & 8) == 0) {165165- printk(" --> Using %s block cache invalidate\n",166166- cache_type & (1 << 24) ? "harvard" : "unified");167167- if (cache_type & (1 << 24))168168- cpu_cache.dma_inv_range = blk_dma_inv_range_harvard;169169- else170170- cpu_cache.dma_inv_range = blk_dma_inv_range_unified;171171- }172172- if ((err & 4) == 0) {173173- printk(" --> Using block cache clean\n");174174- cpu_cache.dma_clean_range = blk_dma_clean_range;175175- }176176- if ((err & 2) == 0) {177177- printk(" --> Using block cache clean+invalidate\n");178178- cpu_cache.dma_flush_range = blk_dma_flush_range;179179- cpu_cache.flush_kern_dcache_page = blk_flush_kern_dcache_page;180180- }181181-182182- return 0;183183-}184184-185185-__initcall(blockops_check);
+13-11
arch/arm/mm/init.c
···420420 * Set up device the mappings. Since we clear out the page tables for all421421 * mappings above VMALLOC_END, we will remove any debug device mappings.422422 * This means you have to be careful how you debug this function, or any423423- * called function. (Do it by code inspection!)423423+ * called function. This means you can't use any function or debugging424424+ * method which may touch any device, otherwise the kernel _will_ crash.424425 */425426static void __init devicemaps_init(struct machine_desc *mdesc)426427{427428 struct map_desc map;428429 unsigned long addr;429430 void *vectors;431431+432432+ /*433433+ * Allocate the vector page early.434434+ */435435+ vectors = alloc_bootmem_low_pages(PAGE_SIZE);436436+ BUG_ON(!vectors);430437431438 for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)432439 pmd_clear(pmd_off_k(addr));···468461 create_mapping(&map);469462#endif470463471471- flush_cache_all();472472- local_flush_tlb_all();473473-474474- vectors = alloc_bootmem_low_pages(PAGE_SIZE);475475- BUG_ON(!vectors);476476-477464 /*478465 * Create a mapping for the machine vectors at the high-vectors479466 * location (0xffff0000). If we aren't using high-vectors, also···492491 mdesc->map_io();493492494493 /*495495- * Finally flush the tlb again - this ensures that we're in a496496- * consistent state wrt the writebuffer if the writebuffer needs497497- * draining. After this point, we can start to touch devices498498- * again.494494+ * Finally flush the caches and tlb to ensure that we're in a495495+ * consistent state wrt the writebuffer. This also ensures that496496+ * any write-allocated cache lines in the vector page are written497497+ * back. After this point, we can start to touch devices again.499498 */500499 local_flush_tlb_all();500500+ flush_cache_all();501501}502502503503/*
+1-2
arch/arm/mm/ioremap.c
···130130 * mapping. See include/asm-arm/proc-armv/pgtable.h for more information.131131 */132132void __iomem *133133-__ioremap(unsigned long phys_addr, size_t size, unsigned long flags,134134- unsigned long align)133133+__ioremap(unsigned long phys_addr, size_t size, unsigned long flags)135134{136135 void * addr;137136 struct vm_struct * area;