diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/Makefile | 26 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 54 | ||||
-rw-r--r-- | arch/arm/mm/fault-common.c | 15 | ||||
-rw-r--r-- | arch/arm/mm/init.c | 6 | ||||
-rw-r--r-- | arch/arm/mm/ioremap.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/mm-armv.c | 2 | ||||
-rw-r--r-- | arch/arm/mm/mm-rpc.c | 6 | ||||
-rw-r--r-- | arch/arm/mm/proc-arm2,3.S | 71 | ||||
-rw-r--r-- | arch/arm/mm/proc-arm6,7.S | 281 | ||||
-rw-r--r-- | arch/arm/mm/proc-sa110.S | 220 |
10 files changed, 432 insertions, 251 deletions
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index 665c7c0b1..42a92201f 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile @@ -7,17 +7,24 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -all: lib first_rule +O_TARGET := mm.o +O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o -O_TARGET := mm.o -O_OBJS := init.o extable.o fault-$(PROCESSOR).o small_page.o - -ifeq ($(PROCESSOR),armo) - O_OBJS += proc-arm2,3.o +ifeq ($(CONFIG_CPU_26),y) + O_OBJS += proc-arm2,3.o endif -ifeq ($(PROCESSOR),armv) - O_OBJS += mm-$(MACHINE).o proc-arm6,7.o proc-sa110.o ioremap.o +ifeq ($(CONFIG_CPU_32),y) + ifeq ($(CONFIG_CPU_ARM6),y) + P_OBJS += proc-arm6,7.o + endif + ifeq ($(CONFIG_CPU_ARM7),y) + P_OBJS += proc-arm6,7.o + endif + ifeq ($(CONFIG_CPU_SA110),y) + P_OBJS += proc-sa110.o + endif + O_OBJS += mm-$(MACHINE).o ioremap.o $(sort $(P_OBJS)) endif include $(TOPDIR)/Rules.make @@ -25,9 +32,6 @@ include $(TOPDIR)/Rules.make %.o: %.S $(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $< -.PHONY: lib -lib:; @$(MAKE) -C ../lib constants.h - # Special dependencies fault-armv.o: fault-common.c fault-armo.o: fault-common.c diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index d57d4fb20..0c5582fb7 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -32,13 +32,14 @@ #include "fault-common.c" +/* + * need to get a 16k page for level 1 + */ pgd_t *get_pgd_slow(void) { - /* - * need to get a 16k page for level 1 - */ pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL,2); pgd_t *init; + pmd_t *new_pmd; if (pgd) { init = pgd_offset(&init_mm, 0); @@ -46,8 +47,32 @@ pgd_t *get_pgd_slow(void) memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR); clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR); + + /* + * On ARM, first page must always be allocated + */ + if (!pmd_alloc(pgd, 0)) + goto nomem; + else { + pmd_t *old_pmd = pmd_offset(init, 0); + new_pmd = pmd_offset(pgd, 0); + + if (!pte_alloc(new_pmd, 0)) + goto nomem_pmd; + else { + pte_t *new_pte = pte_offset(new_pmd, 0); + pte_t *old_pte = pte_offset(old_pmd, 0); + + set_pte (new_pte, *old_pte); + } + } } return pgd; + +nomem_pmd: + pmd_free(new_pmd); +nomem: + return NULL; } pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) @@ -180,6 +205,7 @@ static int proc_alignment_read(char *page, char **start, off_t off, return len; } +#ifdef CONFIG_SYSCTL /* * This needs to be done after sysctl_init, otherwise sys/ * will be overwritten. @@ -194,6 +220,9 @@ void __init alignment_init(void) e->read_proc = proc_alignment_read; } +__initcall(alignment_init); +#endif + static int do_alignment_exception(struct pt_regs *regs) { @@ -380,8 +409,25 @@ do_alignment_exception(struct pt_regs *regs) asmlinkage void do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) { - if (user_mode(regs)) + if (user_mode(regs)) { + if (addr == regs->ARM_pc) { + static int first = 1; + if (first) { + /* + * I want statistical information on this problem! + */ + printk(KERN_ERR "Buggy processor (%08X), " + "trying to continue.\n" + "Please send contents of /proc/cpuinfo " + "and this message to linux@arm.linux.org.uk", + fsr); + first = 0; + } + return; + } + error_code |= FAULT_CODE_USER; + } #define DIE(signr,nam)\ force_sig(signr, current);\ diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index 1251525da..a536515af 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -85,7 +85,10 @@ kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", reason, addr); - printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd); + if (!mm) + mm = &init_mm; + + printk(KERN_ALERT "pgd = %p\n", mm->pgd); show_pte(mm, addr); die("Oops", regs, mode); @@ -106,7 +109,7 @@ static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || mm == &init_mm) + if (in_interrupt() || !mm) goto no_context; down(&mm->mmap_sem); @@ -151,8 +154,8 @@ bad_area: /* User mode accesses just cause a SIGSEGV */ if (mode & FAULT_CODE_USER) { - tsk->tss.error_code = mode; - tsk->tss.trap_no = 14; + tsk->thread.error_code = mode; + tsk->thread.trap_no = 14; #ifdef CONFIG_DEBUG_USER printk("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n", tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); @@ -186,8 +189,8 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ - tsk->tss.error_code = mode; - tsk->tss.trap_no = 14; + tsk->thread.error_code = mode; + tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); /* Kernel mode? Handle exceptions or die */ diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8db4e7923..4fa1ca498 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -123,7 +123,7 @@ void show_mem(void) /* * paging_init() sets up the page tables... */ -__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)) +unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem) { extern unsigned long free_area_init(unsigned long, unsigned long); @@ -156,7 +156,7 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_ * memory is free. This is done after various parts of the system have * claimed their memory after the kernel image. */ -__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) +void __init mem_init(unsigned long start_mem, unsigned long end_mem) { extern void sound_init(void); int codepages = 0; @@ -247,7 +247,7 @@ void free_initmem (void) (unsigned long)(&__netwinder_end), "netwinder"); - if (!machine_is_ebsa285() && !machine_is_cats()) + if (!machine_is_ebsa285() && !machine_is_cats() && !machine_is_co285()) free_area((unsigned long)(&__ebsa285_begin), (unsigned long)(&__ebsa285_end), "ebsa285/cats"); diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 48e34214e..e4c84fa71 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -143,7 +143,7 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag return (void *) (offset + (char *)addr); } -void iounmap(void *addr) +void __iounmap(void *addr) { return vfree((void *) (PAGE_MASK & (unsigned long) addr)); } diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 4481fc32b..02890c55b 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -25,7 +25,7 @@ static const struct mapping { #define SIZEOFMAP (sizeof(mapping) / sizeof(mapping[0])) -__initfunc(unsigned long setup_io_pagetables(unsigned long start_mem)) +unsigned long __init setup_io_pagetables(unsigned long start_mem) { const struct mapping *mp; int i; diff --git a/arch/arm/mm/mm-rpc.c b/arch/arm/mm/mm-rpc.c index 1c755faaf..80f821245 100644 --- a/arch/arm/mm/mm-rpc.c +++ b/arch/arm/mm/mm-rpc.c @@ -68,8 +68,8 @@ unsigned long __phys_to_virt(unsigned long phys) return phys + rambank[bank].phys_offset; } -__initfunc(void -init_dram_banks(struct param_struct *params)) +void __init +init_dram_banks(struct param_struct *params) { unsigned int bank; unsigned int bytes = 0; @@ -85,8 +85,6 @@ init_dram_banks(struct param_struct *params)) rambank[FIRST_VRAM_BANK].phys_offset = 0xd6000000; rambank[FIRST_VRAM_BANK].virt_addr = 0xd8000000; - - current->tss.memmap = __virt_to_phys((unsigned long)swapper_pg_dir); } #define MAPPING \ diff --git a/arch/arm/mm/proc-arm2,3.S b/arch/arm/mm/proc-arm2,3.S index 7e4871fe2..6ec34b612 100644 --- a/arch/arm/mm/proc-arm2,3.S +++ b/arch/arm/mm/proc-arm2,3.S @@ -1,14 +1,14 @@ /* - * linux/arch/arm/mm/arm2,3.S: MMU functions for ARM2,3 + * linux/arch/arm/mm/proc-arm2,3.S: MMU functions for ARM2,3 * - * (C) 1997 Russell King + * (C) 1997-1999 Russell King * * These are the low level assembler for performing cache * and memory functions on ARM2, ARM250 and ARM3 processors. */ #include <linux/linkage.h> - #include <asm/assembler.h> +#include <asm/procinfo.h> #include "../lib/constants.h" /* @@ -424,17 +424,18 @@ _arm3_xchg_4: swp r0, r0, [r1] movs pc, lr +armvlsi_name: .asciz "ARM/VLSI" +_arm2_name: .asciz "arm2" +_arm250_name: .asciz "arm250" +_arm3_name: .asciz "arm3" + + .section ".text.init", #alloc, #execinstr /* * Purpose : Function pointers used to access above functions - all calls * come through these */ -_arm2_name: - .ascii "arm2\0" - .align - .globl SYMBOL_NAME(arm2_processor_functions) SYMBOL_NAME(arm2_processor_functions): - .word _arm2_name @ 0 .word _arm2_switch_to @ 4 .word _arm2_3_data_abort @ 8 .word _arm2_3_check_bugs @ 12 @@ -448,13 +449,8 @@ SYMBOL_NAME(arm2_processor_functions): .word SYMBOL_NAME(abort) @ 40 .word _arm2_xchg_4 @ 44 -_arm250_name: - .ascii "arm250\0" - .align - .globl SYMBOL_NAME(arm250_processor_functions) SYMBOL_NAME(arm250_processor_functions): - .word _arm250_name @ 0 .word _arm2_switch_to @ 4 .word _arm2_3_data_abort @ 8 .word _arm2_3_check_bugs @ 12 @@ -468,13 +464,8 @@ SYMBOL_NAME(arm250_processor_functions): .word SYMBOL_NAME(abort) @ 40 .word _arm3_xchg_4 @ 44 -_arm3_name: - .ascii "arm3\0" - .align - .globl SYMBOL_NAME(arm3_processor_functions) SYMBOL_NAME(arm3_processor_functions): - .word _arm3_name @ 0 .word _arm3_switch_to @ 4 .word _arm2_3_data_abort @ 8 .word _arm2_3_check_bugs @ 12 @@ -488,3 +479,47 @@ SYMBOL_NAME(arm3_processor_functions): .word SYMBOL_NAME(abort) @ 40 .word _arm3_xchg_4 @ 44 +cpu_arm2_info: + .long armvlsi_name + .long _arm2_name + +cpu_arm250_info: + .long armvlsi_name + .long _arm250_name + +cpu_arm3_info: + .long armvlsi_name + .long _arm3_name + +arm2_arch_name: .asciz "armv1" +arm3_arch_name: .asciz "armv2" +arm2_elf_name: .asciz "v1" +arm3_elf_name: .asciz "v2" + .align + + .section ".proc.info", #alloc + + .long 0x41560200 + .long 0xfffffff0 + .long arm2_arch_name + .long arm2_elf_name + .long 0 + .long cpu_arm2_info + .long SYMBOL_NAME(arm2_processor_functions) + + .long 0x41560250 + .long 0xfffffff0 + .long arm3_arch_name + .long arm3_elf_name + .long 0 + .long cpu_arm250_info + .long SYMBOL_NAME(arm250_processor_functions) + + .long 0x41560300 + .long 0xfffffff0 + .long arm3_arch_name + .long arm3_elf_name + .long 0 + .long cpu_arm3_info + .long SYMBOL_NAME(arm3_processor_functions) + diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S index d1f31e35d..67fb0aa8b 100644 --- a/arch/arm/mm/proc-arm6,7.S +++ b/arch/arm/mm/proc-arm6,7.S @@ -1,13 +1,14 @@ /* - * linux/arch/arm/mm/arm6.S: MMU functions for ARM6 + * linux/arch/arm/mm/proc-arm6,7.S: MMU functions for ARM6 * - * (C) 1997 Russell King + * (C) 1997-1999 Russell King * * These are the low level assembler for performing cache and TLB * functions on the ARM6 & ARM7. */ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/procinfo.h> #include "../lib/constants.h" /* @@ -20,10 +21,24 @@ * * Purpose : Flush all cache lines */ -_arm6_7_flush_cache: +ENTRY(cpu_arm6_flush_cache_all) +ENTRY(cpu_arm7_flush_cache_all) +ENTRY(cpu_arm6_flush_cache_area) +ENTRY(cpu_arm7_flush_cache_area) +ENTRY(cpu_arm6_flush_cache_entry) +ENTRY(cpu_arm7_flush_cache_entry) +ENTRY(cpu_arm6_flush_icache_area) +ENTRY(cpu_arm7_flush_icache_area) +ENTRY(cpu_arm6_cache_wback_area) +ENTRY(cpu_arm7_cache_wback_area) +ENTRY(cpu_arm6_cache_purge_area) +ENTRY(cpu_arm7_cache_purge_area) mov r0, #0 mcr p15, 0, r0, c7, c0, 0 @ flush cache -_arm6_7_null: +ENTRY(cpu_arm6_clean_cache_area) +ENTRY(cpu_arm7_clean_cache_area) +ENTRY(cpu_arm6_flush_ram_page) +ENTRY(cpu_arm7_flush_ram_page) mov pc, lr /* @@ -31,7 +46,8 @@ _arm6_7_null: * * Purpose : flush all TLB entries in all caches */ -_arm6_7_flush_tlb_all: +ENTRY(cpu_arm6_flush_tlb_all) +ENTRY(cpu_arm7_flush_tlb_all) mov r0, #0 mcr p15, 0, r0, c5, c0, 0 @ flush TLB mov pc, lr @@ -45,7 +61,8 @@ _arm6_7_flush_tlb_all: * * Purpose : flush a TLB entry */ -_arm6_7_flush_tlb_area: +ENTRY(cpu_arm6_flush_tlb_area) +ENTRY(cpu_arm7_flush_tlb_area) 1: mcr p15, 0, r0, c6, c0, 0 @ flush TLB add r0, r0, #4096 cmp r0, r1 @@ -53,41 +70,6 @@ _arm6_7_flush_tlb_area: mov pc, lr /* - * Function: arm6_7_switch_to (struct task_struct *prev, struct task_struct *next) - * - * Params : prev Old task structure - * : next New task structure for process to run - * - * Returns : prev - * - * Purpose : Perform a task switch, saving the old processes state, and restoring - * the new. - * - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. - */ -_arm6_7_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - mrs ip, cpsr - stmfd sp!, {ip} @ Save cpsr_SVC - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldr r2, [r1, #TSK_ADDR_LIMIT] - ldr r3, [r1, #TSS_MEMMAP] @ Page table pointer - teq r2, #0 - moveq r2, #DOM_KERNELDOMAIN - movne r2, #DOM_USERDOMAIN - mcr p15, 0, r2, c3, c0 @ Set domain reg - mov r1, #0 - mcr p15, 0, r1, c7, c0, 0 @ flush cache - mcr p15, 0, r3, c2, c0, 0 @ update page table ptr - mcr p15, 0, r1, c5, c0, 0 @ flush TLBs - ldmfd sp!, {ip} - msr spsr, ip @ Save tasks CPSR into SPSR for this return - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously - -/* * Function: arm6_7_data_abort () * * Params : r0 = address of aborted instruction @@ -106,7 +88,7 @@ Lukabttxt: .ascii "Unknown data abort code %d [pc=%p, *pc=%p] LR=%p\0" msg: .ascii "DA*%p=%p\n\0" .align -_arm6_data_abort: +ENTRY(cpu_arm6_data_abort) ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L and r1, r4, #15 << 24 @@ -137,7 +119,7 @@ Ldata_unknown: @ Part of jumptable bl SYMBOL_NAME(panic) Lstop: b Lstop -_arm7_data_abort: +ENTRY(cpu_arm7_data_abort) ldr r4, [r0] @ read instruction causing problem mov r2, r4, lsr #19 @ r2 b1 = L and r1, r4, #15 << 24 @@ -332,12 +314,29 @@ Ldata_lateldrprereg: * * Notes : This processor does not require these */ -_arm6_7_check_bugs: +ENTRY(cpu_arm6_check_bugs) +ENTRY(cpu_arm7_check_bugs) mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, ip -_arm6_7_proc_init: -_arm6_7_proc_fin: +ENTRY(cpu_arm6_proc_init) +ENTRY(cpu_arm7_proc_init) +ENTRY(cpu_arm6_proc_fin) +ENTRY(cpu_arm7_proc_fin) + mov pc, lr + +/* + * Function: arm6_7_set_pgd(unsigned long pgd_phys) + * Params : pgd_phys Physical address of page table + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. + */ +ENTRY(cpu_arm6_set_pgd) +ENTRY(cpu_arm7_set_pgd) + mov r1, #0 + mcr p15, 0, r1, c7, c0, 0 @ flush cache + mcr p15, 0, r0, c2, c0, 0 @ update page table ptr + mcr p15, 0, r1, c5, c0, 0 @ flush TLBs mov pc, lr /* @@ -348,7 +347,8 @@ _arm6_7_proc_fin: * * Purpose : Set a PMD and flush it out of any WB cache */ -_arm6_set_pmd: and r2, r1, #11 +ENTRY(cpu_arm6_set_pmd) + and r2, r1, #11 teq r2, #1 teqne r2, #9 teqne r2, #10 @@ -364,7 +364,8 @@ _arm6_set_pmd: and r2, r1, #11 * * Purpose : Set a PMD and flush it out of any WB cache */ -_arm7_set_pmd: tst r1, #3 +ENTRY(cpu_arm7_set_pmd) + tst r1, #3 orrne r1, r1, #16 @ Updatable bit is always set on ARM7 str r1, [r0] mov pc, lr @@ -376,7 +377,8 @@ _arm7_set_pmd: tst r1, #3 * Purpose : Set a PTE and flush it out of any WB cache */ .align 5 -_arm6_7_set_pte: +ENTRY(cpu_arm6_set_pte) +ENTRY(cpu_arm7_set_pte) str r1, [r0], #-1024 @ linux version bic r2, r1, #0xff0 @@ -403,7 +405,9 @@ _arm6_7_set_pte: * * Notes : This sets up everything for a reset */ -_arm6_7_reset: mrs r1, cpsr +ENTRY(cpu_arm6_reset) +ENTRY(cpu_arm7_reset) + mrs r1, cpsr orr r1, r1, #F_BIT|I_BIT msr cpsr, r1 mov r0, #0 @@ -412,62 +416,145 @@ _arm6_7_reset: mrs r1, cpsr mov r1, #F_BIT | I_BIT | 3 mov pc, lr +cpu_armvlsi_name: + .asciz "ARM/VLSI" +cpu_arm6_name: .asciz "arm6" +cpu_arm610_name: + .asciz "arm610" +cpu_arm7_name: .asciz "arm7" +cpu_arm710_name: + .asciz "arm710" + .align + + .section ".text.init", #alloc, #execinstr + /* * Purpose : Function pointers used to access above functions - all calls * come through these */ -_arm6_name: .ascii "arm6\0" - .align - + .type arm6_processor_functions, #object ENTRY(arm6_processor_functions) - .word _arm6_name @ 0 - .word _arm6_7_switch_to @ 4 - .word _arm6_data_abort @ 8 - .word _arm6_7_check_bugs @ 12 - .word _arm6_7_proc_init @ 16 - .word _arm6_7_proc_fin @ 20 - - .word _arm6_7_flush_cache @ 24 - .word _arm6_7_flush_cache @ 28 - .word _arm6_7_flush_cache @ 32 - .word _arm6_7_null @ 36 - .word _arm6_7_flush_cache @ 40 - .word _arm6_7_flush_tlb_all @ 44 - .word _arm6_7_flush_tlb_area @ 48 - .word _arm6_set_pmd @ 52 - .word _arm6_7_set_pte @ 56 - .word _arm6_7_reset @ 60 - .word _arm6_7_flush_cache @ 64 - - .word _arm6_7_flush_cache @ 68 - .word _arm6_7_flush_cache @ 72 + .word cpu_arm6_data_abort + .word cpu_arm6_check_bugs + .word cpu_arm6_proc_init + .word cpu_arm6_proc_fin + .word cpu_arm6_flush_cache_all + .word cpu_arm6_flush_cache_area + .word cpu_arm6_flush_cache_entry + .word cpu_arm6_clean_cache_area + .word cpu_arm6_flush_ram_page + .word cpu_arm6_flush_tlb_all + .word cpu_arm6_flush_tlb_area + .word cpu_arm6_set_pgd + .word cpu_arm6_set_pmd + .word cpu_arm6_set_pte + .word cpu_arm6_reset + .word cpu_arm6_flush_icache_area + .word cpu_arm6_cache_wback_area + .word cpu_arm6_cache_purge_area + .size arm6_processor_functions, . - arm6_processor_functions /* * Purpose : Function pointers used to access above functions - all calls * come through these */ -_arm7_name: .ascii "arm7\0" + .type arm7_processor_functions, #object +ENTRY(arm7_processor_functions) + .word cpu_arm7_data_abort + .word cpu_arm7_check_bugs + .word cpu_arm7_proc_init + .word cpu_arm7_proc_fin + .word cpu_arm7_flush_cache_all + .word cpu_arm7_flush_cache_area + .word cpu_arm7_flush_cache_entry + .word cpu_arm7_clean_cache_area + .word cpu_arm7_flush_ram_page + .word cpu_arm7_flush_tlb_all + .word cpu_arm7_flush_tlb_area + .word cpu_arm7_set_pgd + .word cpu_arm7_set_pmd + .word cpu_arm7_set_pte + .word cpu_arm7_reset + .word cpu_arm7_flush_icache_area + .word cpu_arm7_cache_wback_area + .word cpu_arm7_cache_purge_area + .size arm7_processor_functions, . - arm7_processor_functions + + .type cpu_arm6_info, #object +cpu_arm6_info: + .long cpu_armvlsi_name + .long cpu_arm6_name + .size cpu_arm6_info, . - cpu_arm6_info + + .type cpu_arm610_info, #object +cpu_arm610_info: + .long cpu_armvlsi_name + .long cpu_arm610_name + .size cpu_arm610_info, . - cpu_Arm610_info + + .type cpu_arm7_info, #object +cpu_arm7_info: + .long cpu_armvlsi_name + .long cpu_arm7_name + .size cpu_arm7_info, . - cpu_arm7_info + + .type cpu_arm710_info, #object +cpu_arm710_info: + .long cpu_armvlsi_name + .long cpu_arm710_name + .size cpu_arm710_info, . - cpu_arm710_info + + .type cpu_arch_name, #object +cpu_arch_name: .asciz "armv3" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: .asciz "v3" + .size cpu_elf_name, . - cpu_elf_name .align -ENTRY(arm7_processor_functions) - .word _arm7_name @ 0 - .word _arm6_7_switch_to @ 4 - .word _arm7_data_abort @ 8 - .word _arm6_7_check_bugs @ 12 - .word _arm6_7_proc_init @ 16 - .word _arm6_7_proc_fin @ 20 - - .word _arm6_7_flush_cache @ 24 - .word _arm6_7_flush_cache @ 28 - .word _arm6_7_flush_cache @ 32 - .word _arm6_7_null @ 36 - .word _arm6_7_flush_cache @ 40 - .word _arm6_7_flush_tlb_all @ 44 - .word _arm6_7_flush_tlb_area @ 48 - .word _arm7_set_pmd @ 52 - .word _arm6_7_set_pte @ 56 - .word _arm6_7_reset @ 60 - .word _arm6_7_flush_cache @ 64 - - .word _arm6_7_flush_cache @ 68 - .word _arm6_7_flush_cache @ 72 + .section ".proc.info", #alloc + + .type __arm6_proc_info, #object +__arm6_proc_info: + .long 0x41560600 + .long 0xfffffff0 + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP + .long cpu_arm6_info + .long arm6_processor_functions + .size __arm6_proc_info, . - __arm6_proc_info + + .type __arm610_proc_info, #object +__arm610_proc_info: + .long 0x41560610 + .long 0xfffffff0 + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP + .long cpu_arm610_info + .long arm6_processor_functions + .size __arm610_proc_info, . - __arm610_proc_info + + .type __arm7_proc_info, #object +__arm7_proc_info: + .long 0x41007000 + .long 0xffffff00 + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP + .long cpu_arm7_info + .long arm7_processor_functions + .size __arm7_proc_info, . - __arm7_proc_info + + .type __arm710_proc_info, #object +__arm710_proc_info: + .long 0x41007100 + .long 0xfff8ff00 + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP + .long cpu_arm710_info + .long arm7_processor_functions + .size __arm710_proc_info, . - __arm710_proc_info diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index be9fad45e..aecc223af 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -1,13 +1,14 @@ /* - * linux/arch/arm/mm/sa110.S: MMU functions for SA110 + * linux/arch/arm/mm/proc-sa110.S: MMU functions for SA110 * - * (C) 1997 Russell King + * (C) 1997-1999 Russell King * * These are the low level assembler for performing cache and TLB * functions on the sa110. */ #include <linux/linkage.h> #include <asm/assembler.h> +#include <asm/procinfo.h> #include <asm/hardware.h> #include "../lib/constants.h" @@ -25,9 +26,9 @@ Lclean_switch: .long 0 * Purpose : Flush all cache lines */ .align 5 -_sa110_flush_cache_all: @ preserves r0 +ENTRY(cpu_sa110_flush_cache_all) @ preserves r0 mov r2, #1 -_sa110_flush_cache_all_r2: +cpu_sa110_flush_cache_all_r2: ldr r3, =Lclean_switch ldr ip, =FLUSH_BASE ldr r1, [r3] @@ -53,10 +54,10 @@ _sa110_flush_cache_all_r2: * Purpose : clean & flush all cache lines associated with this area of memory */ .align 5 -_sa110_flush_cache_area: +ENTRY(cpu_sa110_flush_cache_area) sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE - bgt _sa110_flush_cache_all_r2 + bgt cpu_sa110_flush_cache_all_r2 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c6, 1 @ flush D entry add r0, r0, #32 @@ -78,11 +79,11 @@ _sa110_flush_cache_area: * written out to memory (for DMA) */ .align 5 -_sa110_cache_wback_area: +ENTRY(cpu_sa110_cache_wback_area) sub r3, r1, r0 cmp r3, #MAX_AREA_SIZE mov r2, #0 - bgt _sa110_flush_cache_all_r2 + bgt cpu_sa110_flush_cache_all_r2 bic r0, r0, #31 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry add r0, r0, #32 @@ -103,7 +104,7 @@ _sa110_cache_wback_area: * start and/or end address are not cache aligned. */ .align 5 -_sa110_cache_purge_area: +ENTRY(cpu_sa110_cache_purge_area) tst r0, #31 bic r0, r0, #31 mcrne p15, 0, r0, c7, c10, 1 @ clean D entry @@ -121,7 +122,7 @@ _sa110_cache_purge_area: * Purpose : clean & flush an entry */ .align 5 -_sa110_flush_cache_entry: +ENTRY(cpu_sa110_flush_cache_entry) mov r1, #0 mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r1, c7, c10, 4 @ drain WB @@ -134,7 +135,7 @@ _sa110_flush_cache_entry: * Purpose : Ensure that physical memory reflects cache at this location * for page table purposes. */ -_sa110_clean_cache_area: +ENTRY(cpu_sa110_clean_cache_area) 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) add r0, r0, #32 subs r1, r1, #32 @@ -143,25 +144,24 @@ _sa110_clean_cache_area: /* * Function: sa110_flush_ram_page (unsigned long page) - * Params : address Area start address - * : size size of area - * : flags b0 = I cache as well - * Purpose : clean & flush all cache lines associated with this area of memory + * Params : page Area start address + * Purpose : clean all cache lines associated with this area of memory */ .align 5 -_sa110_flush_ram_page: +ENTRY(cpu_sa110_flush_ram_page) mov r1, #4096 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c6, 1 @ flush D entry add r0, r0, #32 mcr p15, 0, r0, c7, c10, 1 @ clean D entry - mcr p15, 0, r0, c7, c6, 1 @ flush D entry add r0, r0, #32 - subs r1, r1, #64 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #32 + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + add r0, r0, #32 + subs r1, r1, #128 bne 1b mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB - mcr p15, 0, r0, c7, c5, 0 @ flush I cache mov pc, lr /* @@ -169,7 +169,7 @@ _sa110_flush_ram_page: * Purpose : flush all TLB entries in all caches */ .align 5 -_sa110_flush_tlb_all: +ENTRY(cpu_sa110_flush_tlb_all) mov r0, #0 mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c8, c7, 0 @ flush I & D tlbs @@ -179,11 +179,11 @@ _sa110_flush_tlb_all: * Function: sa110_flush_tlb_area (unsigned long address, unsigned long end, int flags) * Params : address Area start address * : end Area end address - * : flags b0 = I cache as well + * : flags b0 = I-TLB as well * Purpose : flush a TLB entry */ .align 5 -_sa110_flush_tlb_area: +ENTRY(cpu_sa110_flush_tlb_area) mov r3, #0 mcr p15, 0, r3, c7, c10, 4 @ drain WB 1: cmp r0, r1 @@ -198,7 +198,7 @@ _sa110_flush_tlb_area: mov pc, lr .align 5 -_sa110_flush_icache_area: +ENTRY(cpu_sa110_flush_icache_area) 1: mcr p15, 0, r0, c7, c10, 1 @ Clean D entry add r0, r0, #32 subs r1, r1, #32 @@ -207,40 +207,35 @@ _sa110_flush_icache_area: mcr p15, 0, r0, c7, c10, 4 @ drain WB mcr p15, 0, r0, c7, c5, 0 @ flush I cache mov pc, lr + /* - * Function: sa110_switch_to (struct task_struct *prev, struct task_struct *next) - * Params : prev Old task structure - * : next New task structure for process to run - * Returns : prev - * Purpose : Perform a task switch, saving the old processes state, and restoring - * the new. - * Notes : We don't fiddle with the FP registers here - we postpone this until - * the new task actually uses FP. This way, we don't swap FP for tasks - * that do not require it. + * Function: sa110_data_abort () + * Params : r0 = address of aborted instruction + * Purpose : obtain information about current aborted instruction + * Returns : r0 = address of abort + * : r1 = FSR + * : r2 != 0 if writing */ .align 5 -_sa110_switch_to: - stmfd sp!, {r4 - r9, fp, lr} @ Store most regs on stack - mrs ip, cpsr - stmfd sp!, {ip} @ Save cpsr_SVC - ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables - str sp, [r0, #TSS_SAVE] @ Save sp_SVC - ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldr r5, [r1, #TSK_ADDR_LIMIT] - ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer - teq r5, #0 - moveq r5, #DOM_KERNELDOMAIN - movne r5, #DOM_USERDOMAIN - mcr p15, 0, r5, c3, c0 @ Set segment +ENTRY(cpu_sa110_data_abort) + ldr r2, [r0] @ read instruction causing problem + mrc p15, 0, r0, c6, c0, 0 @ get FAR + mov r2, r2, lsr #19 @ b1 = L + and r3, r2, #0x69 << 2 + and r2, r2, #2 + mrc p15, 0, r1, c5, c0, 0 @ get FSR + and r1, r1, #255 + mov pc, lr + + .align 5 /* - * Flushing the cache is nightmarishly slow, so we take any excuse - * to get out of it. If the old page table is the same as the new, - * this is a CLONE_VM relative of the old task and there is no need - * to flush. The overhead of the tests isn't even on the radar - * compared to the cost of the flush itself. + * Function: sa110_set_pgd(unsigned long pgd_phys) + * Params : pgd_phys Physical address of page table + * Purpose : Perform a task switch, saving the old processes state, and restoring + * the new. */ - teq r4, r2 - beq 2f + .align 5 +ENTRY(cpu_sa110_set_pgd) ldr r3, =Lclean_switch ldr r2, [r3] ands r2, r2, #1 @@ -255,29 +250,8 @@ _sa110_switch_to: mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ flush I cache mcr p15, 0, r1, c7, c10, 4 @ drain WB - mcr p15, 0, r4, c2, c0, 0 @ load page table pointer + mcr p15, 0, r0, c2, c0, 0 @ load page table pointer mcr p15, 0, r1, c8, c7, 0 @ flush TLBs -2: ldmfd sp!, {ip} - msr spsr, ip @ Save tasks CPSR into SPSR for this return - ldmfd sp!, {r4 - r9, fp, pc}^ @ Load all regs saved previously - -/* - * Function: sa110_data_abort () - * Params : r0 = address of aborted instruction - * Purpose : obtain information about current aborted instruction - * Returns : r0 = address of abort - * : r1 = FSR - * : r2 != 0 if writing - */ - .align 5 -_sa110_data_abort: - ldr r2, [r0] @ read instruction causing problem - mrc p15, 0, r0, c6, c0, 0 @ get FAR - mov r2, r2, lsr #19 @ b1 = L - and r3, r2, #0x69 << 2 - and r2, r2, #2 - mrc p15, 0, r1, c5, c0, 0 @ get FSR - and r1, r1, #255 mov pc, lr /* @@ -287,7 +261,8 @@ _sa110_data_abort: * Purpose : Set a PMD and flush it out */ .align 5 -_sa110_set_pmd: str r1, [r0] +ENTRY(cpu_sa110_set_pmd) + str r1, [r0] mcr p15, 0, r0, c7, c10, 1 @ clean D entry mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB) mov pc, lr @@ -299,7 +274,8 @@ _sa110_set_pmd: str r1, [r0] * Purpose : Set a PTE and flush it out */ .align 5 -_sa110_set_pte: str r1, [r0], #-1024 @ linux version +ENTRY(cpu_sa110_set_pte) + str r1, [r0], #-1024 @ linux version eor r1, r1, #LPTE_PRESENT | LPTE_YOUNG | LPTE_WRITE | LPTE_DIRTY @@ -328,26 +304,27 @@ _sa110_set_pte: str r1, [r0], #-1024 @ linux version * : sa110_proc_fin (void) * Notes : This processor does not require these */ -_sa110_check_bugs: +ENTRY(cpu_sa110_check_bugs) mrs ip, cpsr bic ip, ip, #F_BIT msr cpsr, ip -_sa110_proc_init: -_sa110_proc_fin: +ENTRY(cpu_sa110_proc_init) +ENTRY(cpu_sa110_proc_fin) mov pc, lr /* * Function: sa110_reset * Notes : This sets up everything for a reset */ -_sa110_reset: mrs r1, cpsr +ENTRY(cpu_sa110_reset) + mrs r1, cpsr orr r1, r1, #F_BIT | I_BIT msr cpsr, r1 stmfd sp!, {r1, lr} mov r2, #1 - bl _sa110_flush_cache_all - bl _sa110_flush_tlb_all + bl cpu_sa110_flush_cache_all + bl cpu_sa110_flush_tlb_all mcr p15, 0, ip, c7, c7, 0 @ flush I,D caches mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1800 @@ -357,29 +334,60 @@ _sa110_reset: mrs r1, cpsr * Purpose : Function pointers used to access above functions - all calls * come through these */ -_sa110_name: .ascii "sa110\0" + +cpu_manu_name: .asciz "Intel" +ENTRY(cpu_sa110_name) + .asciz "sa110" .align + .section ".text.init", #alloc, #execinstr + + .type sa110_processor_functions, #object ENTRY(sa110_processor_functions) - .word _sa110_name @ 0 - .word _sa110_switch_to @ 4 - .word _sa110_data_abort @ 8 - .word _sa110_check_bugs @ 12 - .word _sa110_proc_init @ 16 - .word _sa110_proc_fin @ 20 - - .word _sa110_flush_cache_all @ 24 - .word _sa110_flush_cache_area @ 28 - .word _sa110_flush_cache_entry @ 32 - .word _sa110_clean_cache_area @ 36 - .word _sa110_flush_ram_page @ 40 - .word _sa110_flush_tlb_all @ 44 - .word _sa110_flush_tlb_area @ 48 - - .word _sa110_set_pmd @ 52 - .word _sa110_set_pte @ 56 - .word _sa110_reset @ 60 - .word _sa110_flush_icache_area @ 64 - - .word _sa110_cache_wback_area @ 68 - .word _sa110_cache_purge_area @ 72 + .word cpu_sa110_data_abort + .word cpu_sa110_check_bugs + .word cpu_sa110_proc_init + .word cpu_sa110_proc_fin + .word cpu_sa110_flush_cache_all + .word cpu_sa110_flush_cache_area + .word cpu_sa110_flush_cache_entry + .word cpu_sa110_clean_cache_area + .word cpu_sa110_flush_ram_page + .word cpu_sa110_flush_tlb_all + .word cpu_sa110_flush_tlb_area + .word cpu_sa110_set_pgd + .word cpu_sa110_set_pmd + .word cpu_sa110_set_pte + .word cpu_sa110_reset + .word cpu_sa110_flush_icache_area + .word cpu_sa110_cache_wback_area + .word cpu_sa110_cache_purge_area + + .size sa110_processor_functions, . - sa110_processor_functions + + .type cpu_sa110_info, #object +cpu_sa110_info: + .long cpu_manu_name + .long cpu_sa110_name + .size cpu_sa110_info, . - cpu_sa110_info + + .type cpu_arch_name, #object +cpu_arch_name: .asciz "armv4" + .size cpu_arch_name, . - cpu_arch_name + + .type cpu_elf_name, #object +cpu_elf_name: .asciz "v4" + .size cpu_elf_name, . - cpu_elf_name + .align + + .section ".proc.info", #alloc, #execinstr + .type __sa110_proc_info,#object +__sa110_proc_info: + .long 0x4401a100 + .long 0xfffffff0 + .long cpu_arch_name + .long cpu_elf_name + .long HWCAP_SWP | HWCAP_HALF + .long cpu_sa110_info + .long sa110_processor_functions + .size __sa110_proc_info, . - __sa110_proc_info |