diff options
Diffstat (limited to 'arch/arm/mm')
29 files changed, 788 insertions, 667 deletions
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index ab5f7a21350..d490f3773c0 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -10,8 +10,7 @@ config CPU_32 # ARM610 config CPU_ARM610 - bool "Support ARM610 processor" - depends on ARCH_RPC + bool "Support ARM610 processor" if ARCH_RPC select CPU_32v3 select CPU_CACHE_V3 select CPU_CACHE_VIVT @@ -43,8 +42,7 @@ config CPU_ARM7TDMI # ARM710 config CPU_ARM710 - bool "Support ARM710 processor" if !ARCH_CLPS7500 && ARCH_RPC - default y if ARCH_CLPS7500 + bool "Support ARM710 processor" if ARCH_RPC select CPU_32v3 select CPU_CACHE_V3 select CPU_CACHE_VIVT @@ -63,8 +61,7 @@ config CPU_ARM710 # ARM720T config CPU_ARM720T - bool "Support ARM720T processor" if !ARCH_CLPS711X && !ARCH_L7200 && !ARCH_CDB89712 && ARCH_INTEGRATOR - default y if ARCH_CLPS711X || ARCH_L7200 || ARCH_CDB89712 || ARCH_H720X + bool "Support ARM720T processor" if ARCH_INTEGRATOR select CPU_32v4T select CPU_ABRT_LV4T select CPU_PABRT_NOIFAR @@ -114,9 +111,7 @@ config CPU_ARM9TDMI # ARM920T config CPU_ARM920T - bool "Support ARM920T processor" - depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200 - default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200 + bool "Support ARM920T processor" if ARCH_INTEGRATOR select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -138,8 +133,6 @@ config CPU_ARM920T # ARM922T config CPU_ARM922T bool "Support ARM922T processor" if ARCH_INTEGRATOR - depends on ARCH_LH7A40X || ARCH_INTEGRATOR || ARCH_KS8695 - default y if ARCH_LH7A40X || ARCH_KS8695 select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -159,8 +152,6 @@ config CPU_ARM922T # ARM925T config CPU_ARM925T bool "Support ARM925T processor" if ARCH_OMAP1 - depends on ARCH_OMAP15XX - default y if ARCH_OMAP15XX select CPU_32v4T select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -179,22 +170,7 @@ config CPU_ARM925T # ARM926T config CPU_ARM926T - bool "Support ARM926T processor" - depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || \ - MACH_VERSATILE_AB || ARCH_OMAP730 || \ - ARCH_OMAP16XX || MACH_REALVIEW_EB || \ - ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \ - ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || \ - ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || \ - ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \ - ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2 - default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || \ - ARCH_OMAP730 || ARCH_OMAP16XX || \ - ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || \ - ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || \ - ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || \ - ARCH_AT91SAM9G20 || ARCH_AT91CAP9 || \ - ARCH_NS9XXX || ARCH_DAVINCI || ARCH_MX2 + bool "Support ARM926T processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v5 select CPU_ABRT_EV5TJ select CPU_PABRT_NOIFAR @@ -247,8 +223,7 @@ config CPU_ARM946E # ARM1020 - needs validating config CPU_ARM1020 - bool "Support ARM1020T (rev 0) processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1020T (rev 0) processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -266,8 +241,7 @@ config CPU_ARM1020 # ARM1020E - needs validating config CPU_ARM1020E - bool "Support ARM1020E processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1020E processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -280,8 +254,7 @@ config CPU_ARM1020E # ARM1022E config CPU_ARM1022 - bool "Support ARM1022E processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1022E processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV4T select CPU_PABRT_NOIFAR @@ -299,8 +272,7 @@ config CPU_ARM1022 # ARM1026EJ-S config CPU_ARM1026 - bool "Support ARM1026EJ-S processor" - depends on ARCH_INTEGRATOR + bool "Support ARM1026EJ-S processor" if ARCH_INTEGRATOR select CPU_32v5 select CPU_ABRT_EV5T # But need Jazelle, but EV5TJ ignores bit 10 select CPU_PABRT_NOIFAR @@ -317,8 +289,7 @@ config CPU_ARM1026 # SA110 config CPU_SA110 - bool "Support StrongARM(R) SA-110 processor" if !ARCH_EBSA110 && !FOOTBRIDGE && !ARCH_TBOX && !ARCH_SHARK && !ARCH_NEXUSPCI && ARCH_RPC - default y if ARCH_EBSA110 || FOOTBRIDGE || ARCH_TBOX || ARCH_SHARK || ARCH_NEXUSPCI + bool "Support StrongARM(R) SA-110 processor" if ARCH_RPC select CPU_32v3 if ARCH_RPC select CPU_32v4 if !ARCH_RPC select CPU_ABRT_EV4 @@ -340,8 +311,6 @@ config CPU_SA110 # SA1100 config CPU_SA1100 bool - depends on ARCH_SA1100 - default y select CPU_32v4 select CPU_ABRT_EV4 select CPU_PABRT_NOIFAR @@ -353,8 +322,6 @@ config CPU_SA1100 # XScale config CPU_XSCALE bool - depends on ARCH_IOP32X || ARCH_IOP33X || PXA25x || PXA27x || ARCH_IXP4XX || ARCH_IXP2000 - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -365,8 +332,6 @@ config CPU_XSCALE # XScale Core Version 3 config CPU_XSC3 bool - depends on ARCH_IXP23XX || ARCH_IOP13XX || PXA3xx - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -378,8 +343,6 @@ config CPU_XSC3 # Feroceon config CPU_FEROCEON bool - depends on ARCH_ORION5X || ARCH_LOKI || ARCH_KIRKWOOD || ARCH_MV78XX0 - default y select CPU_32v5 select CPU_ABRT_EV5T select CPU_PABRT_NOIFAR @@ -399,10 +362,7 @@ config CPU_FEROCEON_OLD_ID # ARMv6 config CPU_V6 - bool "Support ARM V6 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP2 || ARCH_MX3 || ARCH_MSM || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 - default y if ARCH_MX3 - default y if ARCH_MSM + bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v6 select CPU_ABRT_EV6 select CPU_PABRT_NOIFAR @@ -427,8 +387,7 @@ config CPU_32v6K # ARMv7 config CPU_V7 - bool "Support ARM V7 processor" - depends on ARCH_INTEGRATOR || MACH_REALVIEW_EB || ARCH_OMAP3 + bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB select CPU_32v6K select CPU_32v7 select CPU_ABRT_EV7 @@ -745,7 +704,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" - depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 + depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || REALVIEW_EB_A9MP default y select OUTER_CACHE help diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 133e65d166b..3a398befed4 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -17,6 +17,7 @@ #include <linux/string.h> #include <linux/proc_fs.h> #include <linux/init.h> +#include <linux/sched.h> #include <linux/uaccess.h> #include <asm/unaligned.h> @@ -70,6 +71,10 @@ static unsigned long ai_dword; static unsigned long ai_multi; static int ai_usermode; +#define UM_WARN (1 << 0) +#define UM_FIXUP (1 << 1) +#define UM_SIGNAL (1 << 2) + #ifdef CONFIG_PROC_FS static const char *usermode_action[] = { "ignored", @@ -754,7 +759,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) user: ai_user += 1; - if (ai_usermode & 1) + if (ai_usermode & UM_WARN) printk("Alignment trap: %s (%d) PC=0x%08lx Instr=0x%0*lx " "Address=0x%08lx FSR 0x%03x\n", current->comm, task_pid_nr(current), instrptr, @@ -762,10 +767,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) thumb_mode(regs) ? tinstr : instr, addr, fsr); - if (ai_usermode & 2) + if (ai_usermode & UM_FIXUP) goto fixup; - if (ai_usermode & 4) + if (ai_usermode & UM_SIGNAL) force_sig(SIGBUS, current); else set_cr(cr_no_alignment); @@ -796,6 +801,22 @@ static int __init alignment_init(void) res->write_proc = proc_alignment_write; #endif + /* + * ARMv6 and later CPUs can perform unaligned accesses for + * most single load and store instructions up to word size. + * LDM, STM, LDRD and STRD still need to be handled. + * + * Ignoring the alignment fault is not an option on these + * CPUs since we spin re-faulting the instruction without + * making any progress. + */ + if (cpu_architecture() >= CPU_ARCH_ARMv6 && (cr_alignment & CR_U)) { + cr_alignment &= ~CR_A; + cr_no_alignment &= ~CR_A; + set_cr(cr_alignment); + ai_usermode = UM_FIXUP; + } + hook_fault_code(1, do_alignment, SIGILL, "alignment exception"); hook_fault_code(3, do_alignment, SIGILL, "alignment exception"); diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index 3b3639eb7ca..8a4abebc478 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -9,7 +9,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index 5786adf1004..3668611cb40 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -9,7 +9,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 51a9b0b273b..c54fa2cc40e 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -13,7 +13,6 @@ */ #include <linux/linkage.h> #include <linux/init.h> -#include <mach/hardware.h> #include <asm/page.h> #include "proc-macros.S" diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index d19c2bec2b1..be93ff02a98 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -26,6 +26,7 @@ * - mm - mm_struct describing address space */ ENTRY(v7_flush_dcache_all) + dmb @ ensure ordering with previous memory accesses mrc p15, 1, r0, c0, c0, 1 @ read clidr ands r3, r0, #0x7000000 @ extract loc from clidr mov r3, r3, lsr #23 @ left align loc bit field @@ -64,6 +65,7 @@ skip: finished: mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + dsb isb mov pc, lr ENDPROC(v7_flush_dcache_all) diff --git a/arch/arm/mm/copypage-feroceon.S b/arch/arm/mm/copypage-feroceon.S deleted file mode 100644 index 7eb0d320d24..00000000000 --- a/arch/arm/mm/copypage-feroceon.S +++ /dev/null @@ -1,95 +0,0 @@ -/* - * linux/arch/arm/lib/copypage-feroceon.S - * - * Copyright (C) 2008 Marvell Semiconductors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This handles copy_user_page and clear_user_page on Feroceon - * more optimally than the generic implementations. - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - - .text - .align 5 - -ENTRY(feroceon_copy_user_page) - stmfd sp!, {r4-r9, lr} - mov ip, #PAGE_SZ -1: mov lr, r1 - ldmia r1!, {r2 - r9} - pld [lr, #32] - pld [lr, #64] - pld [lr, #96] - pld [lr, #128] - pld [lr, #160] - pld [lr, #192] - pld [lr, #224] - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - ldmia r1!, {r2 - r9} - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - stmia r0, {r2 - r9} - subs ip, ip, #(32 * 8) - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - bne 1b - mcr p15, 0, ip, c7, c10, 4 @ drain WB - ldmfd sp!, {r4-r9, pc} - - .align 5 - -ENTRY(feroceon_clear_user_page) - stmfd sp!, {r4-r7, lr} - mov r1, #PAGE_SZ/32 - mov r2, #0 - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov ip, #0 - mov lr, #0 -1: stmia r0, {r2-r7, ip, lr} - subs r1, r1, #1 - mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line - add r0, r0, #32 - bne 1b - mcr p15, 0, r1, c7, c10, 4 @ drain WB - ldmfd sp!, {r4-r7, pc} - - __INITDATA - - .type feroceon_user_fns, #object -ENTRY(feroceon_user_fns) - .long feroceon_clear_user_page - .long feroceon_copy_user_page - .size feroceon_user_fns, . - feroceon_user_fns diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c new file mode 100644 index 00000000000..c3ba6a94da0 --- /dev/null +++ b/arch/arm/mm/copypage-feroceon.c @@ -0,0 +1,111 @@ +/* + * linux/arch/arm/mm/copypage-feroceon.S + * + * Copyright (C) 2008 Marvell Semiconductors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This handles copy_user_highpage and clear_user_page on Feroceon + * more optimally than the generic implementations. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +static void __attribute__((naked)) +feroceon_copy_user_page(void *kto, const void *kfrom) +{ + asm("\ + stmfd sp!, {r4-r9, lr} \n\ + mov ip, %0 \n\ +1: mov lr, r1 \n\ + ldmia r1!, {r2 - r9} \n\ + pld [lr, #32] \n\ + pld [lr, #64] \n\ + pld [lr, #96] \n\ + pld [lr, #128] \n\ + pld [lr, #160] \n\ + pld [lr, #192] \n\ + pld [lr, #224] \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + ldmia r1!, {r2 - r9} \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + stmia r0, {r2 - r9} \n\ + subs ip, ip, #(32 * 8) \n\ + mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D line\n\ + add r0, r0, #32 \n\ + bne 1b \n\ + mcr p15, 0, ip, c7, c10, 4 @ drain WB\n\ + ldmfd sp!, {r4-r9, pc}" + : + : "I" (PAGE_SIZE)); +} + +void feroceon_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + feroceon_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +void feroceon_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile ("\ + mov r1, %2 \n\ + mov r2, #0 \n\ + mov r3, #0 \n\ + mov r4, #0 \n\ + mov r5, #0 \n\ + mov r6, #0 \n\ + mov r7, #0 \n\ + mov ip, #0 \n\ + mov lr, #0 \n\ +1: stmia %0, {r2-r7, ip, lr} \n\ + subs r1, r1, #1 \n\ + mcr p15, 0, %0, c7, c14, 1 @ clean and invalidate D line\n\ + add %0, %0, #32 \n\ + bne 1b \n\ + mcr p15, 0, r1, c7, c10, 4 @ drain WB" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 32) + : "r1", "r2", "r3", "r4", "r5", "r6", "r7", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns feroceon_user_fns __initdata = { + .cpu_clear_user_highpage = feroceon_clear_user_highpage, + .cpu_copy_user_highpage = feroceon_copy_user_highpage, +}; + diff --git a/arch/arm/mm/copypage-v3.S b/arch/arm/mm/copypage-v3.S deleted file mode 100644 index 2ee394b11bc..00000000000 --- a/arch/arm/mm/copypage-v3.S +++ /dev/null @@ -1,67 +0,0 @@ -/* - * linux/arch/arm/lib/copypage.S - * - * Copyright (C) 1995-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/assembler.h> -#include <asm/asm-offsets.h> - - .text - .align 5 -/* - * ARMv3 optimised copy_user_page - * - * FIXME: do we need to handle cache stuff... - */ -ENTRY(v3_copy_user_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 -1: stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - ldmfd sp!, {r4, pc} @ 3 - - .align 5 -/* - * ARMv3 optimised clear_user_page - * - * FIXME: do we need to handle cache stuff... - */ -ENTRY(v3_clear_user_page) - str lr, [sp, #-4]! - mov r1, #PAGE_SZ/64 @ 1 - mov r2, #0 @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 -1: stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - subs r1, r1, #1 @ 1 - bne 1b @ 1 - ldr pc, [sp], #4 - - __INITDATA - - .type v3_user_fns, #object -ENTRY(v3_user_fns) - .long v3_clear_user_page - .long v3_copy_user_page - .size v3_user_fns, . - v3_user_fns diff --git a/arch/arm/mm/copypage-v3.c b/arch/arm/mm/copypage-v3.c new file mode 100644 index 00000000000..70ed96c8af8 --- /dev/null +++ b/arch/arm/mm/copypage-v3.c @@ -0,0 +1,81 @@ +/* + * linux/arch/arm/mm/copypage-v3.c + * + * Copyright (C) 1995-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/init.h> +#include <linux/highmem.h> + +/* + * ARMv3 optimised copy_user_highpage + * + * FIXME: do we need to handle cache stuff... + */ +static void __attribute__((naked)) +v3_copy_user_page(void *kto, const void *kfrom) +{ + asm("\n\ + stmfd sp!, {r4, lr} @ 2\n\ + mov r2, %2 @ 1\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ +1: stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4+1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmia %0!, {r3, r4, ip, lr} @ 4\n\ + subs r2, r2, #1 @ 1\n\ + stmia %1!, {r3, r4, ip, lr} @ 4\n\ + ldmneia %0!, {r3, r4, ip, lr} @ 4\n\ + bne 1b @ 1\n\ + ldmfd sp!, {r4, pc} @ 3" + : + : "r" (kfrom), "r" (kto), "I" (PAGE_SIZE / 64)); +} + +void v3_copy_user_highpage(struct page *to, struct page *from, + unsigned long vaddr) +{ + void *kto, *kfrom; + + kto = kmap_atomic(to, KM_USER0); + kfrom = kmap_atomic(from, KM_USER1); + v3_copy_user_page(kto, kfrom); + kunmap_atomic(kfrom, KM_USER1); + kunmap_atomic(kto, KM_USER0); +} + +/* + * ARMv3 optimised clear_user_page + * + * FIXME: do we need to handle cache stuff... + */ +void v3_clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\n\ + mov r1, %2 @ 1\n\ + mov r2, #0 @ 1\n\ + mov r3, #0 @ 1\n\ + mov ip, #0 @ 1\n\ + mov lr, #0 @ 1\n\ +1: stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + subs r1, r1, #1 @ 1\n\ + bne 1b @ 1" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); +} + +struct cpu_user_fns v3_user_fns __initdata = { + .cpu_clear_user_highpage = v3_clear_user_highpage, + .cpu_copy_user_highpage = v3_copy_user_highpage, +}; diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c index 8d33e254934..bdb5fd983b1 100644 --- a/arch/arm/mm/copypage-v4mc.c +++ b/arch/arm/mm/copypage-v4mc.c @@ -15,8 +15,8 @@ */ #include <linux/init.h> #include <linux/mm.h> +#include <linux/highmem.h> -#include <asm/page.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> #include <asm/cacheflush.h> @@ -33,7 +33,7 @@ static DEFINE_SPINLOCK(minicache_lock); /* - * ARMv4 mini-dcache optimised copy_user_page + * ARMv4 mini-dcache optimised copy_user_highpage * * We flush the destination cache lines just before we write the data into the * corresponding address. Since the Dcache is read-allocate, this removes the @@ -42,7 +42,7 @@ static DEFINE_SPINLOCK(minicache_lock); * * Note: We rely on all ARMv4 processors implementing the "invalidate D line" * instruction. If your processor does not supply this, you have to write your - * own copy_user_page that does the right thing. + * own copy_user_highpage that does the right thing. */ static void __attribute__((naked)) mc_copy_user_page(void *from, void *to) @@ -68,50 +68,53 @@ mc_copy_user_page(void *from, void *to) : "r" (from), "r" (to), "I" (PAGE_SIZE / 64)); } -void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr) +void v4_mc_copy_user_highpage(struct page *from, struct page *to, + unsigned long vaddr) { - struct page *page = virt_to_page(kfrom); + void *kto = kmap_atomic(to, KM_USER1); - if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) - __flush_dcache_page(page_mapping(page), page); + if (test_and_clear_bit(PG_dcache_dirty, &from->flags)) + __flush_dcache_page(page_mapping(from), from); spin_lock(&minicache_lock); - set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot), 0); + set_pte_ext(TOP_PTE(0xffff8000), pfn_pte(page_to_pfn(from), minicache_pgprot), 0); flush_tlb_kernel_page(0xffff8000); mc_copy_user_page((void *)0xffff8000, kto); spin_unlock(&minicache_lock); + + kunmap_atomic(kto, KM_USER1); } /* * ARMv4 optimised clear_user_page */ -void __attribute__((naked)) -v4_mc_clear_user_page(void *kaddr, unsigned long vaddr) +void v4_mc_clear_user_highpage(struct page *page, unsigned long vaddr) { - asm volatile( - "str lr, [sp, #-4]!\n\ - mov r1, %0 @ 1\n\ + void *ptr, *kaddr = kmap_atomic(page, KM_USER0); + asm volatile("\ + mov r1, %2 @ 1\n\ mov r2, #0 @ 1\n\ mov r3, #0 @ 1\n\ mov ip, #0 @ 1\n\ mov lr, #0 @ 1\n\ -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ - stmia r0!, {r2, r3, ip, lr} @ 4\n\ +1: mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + mcr p15, 0, %0, c7, c6, 1 @ 1 invalidate D line\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ + stmia %0!, {r2, r3, ip, lr} @ 4\n\ subs r1, r1, #1 @ 1\n\ - bne 1b @ 1\n\ - ldr pc, [sp], #4" - : - : "I" (PAGE_SIZE / 64)); + bne 1b @ 1" + : "=r" (ptr) + : "0" (kaddr), "I" (PAGE_SIZE / 64) + : "r1", "r2", "r3", "ip", "lr"); + kunmap_atomic(kaddr, KM_USER0); } struct cpu_user_fns v4_mc_user_fns __initdata = { - .cpu_clear_user_page = v4_mc_clear_user_page, - .cpu_copy_user_page = v4_mc_copy_user_page, + .cpu_clear_user_highpage = v4_mc_clear_user_highpage, + .cpu_copy_user_highpage = v4_mc_copy_user_highpage, }; diff --git a/arch/arm/mm/copypage-v4wb.S b/arch/arm/mm/copypage-v4wb.S deleted file mode 100644 index 83117354b1c..00000000000 --- a/arch/arm/mm/copypage-v4wb.S +++ /dev/null @@ -1,79 +0,0 @@ -/* - * linux/arch/arm/lib/copypage.S - * - * Copyright (C) 1995-1999 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ASM optimised string functions - */ -#include <linux/linkage.h> -#include <linux/init.h> -#include <asm/asm-offsets.h> - - .text - .align 5 -/* - * ARMv4 optimised copy_user_page - * - * We flush the destination cache lines just before we write the data into the - * corresponding address. Since the Dcache is read-allocate, this removes the - * Dcache aliasing issue. The writes will be forwarded to the write buffer, - * and merged as appropriate. - * - * Note: We rely on all ARMv4 processors implementing the "invalidate D line" - * instruction. If your processor does not supply this, you have to write your - * own copy_user_page that does the right thing. - */ -ENTRY(v4wb_copy_user_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 - ldmia r1!, {r3, r4, ip, lr} @ 4 -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmneia r1!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB - ldmfd sp!, {r4, pc} @ 3 - - .align 5 -/* - * ARMv4 optimised clear_user_page - * - * Same story as above. - */ -ENTRY(v4wb_clear_user_page) - str lr, [sp, #-4]! - mov r1, #PAGE_SZ/64 @ 1 - mov r2, #0 @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 -1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line - stmia r0!, {r2, r3, ip, lr} @ 4 - stmia r0!, {r2, r3, ip, lr} @ 4 - subs r1, r1, #1 @ 1 - bne 1b @ 1 - mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB - ldr pc, [sp], #4 - - __INITDATA - - .type v4wb_user_fns, #object -ENTRY(v4wb_user_fns) - .long v4wb_clear_user_page - .long v4wb_copy_user_page - .size v4wb_user_fns, . - v4wb_user_fns diff --git a/arch/arm/mm/copypage-v4wb.c b/arch/arm/mm/copypage-v4wb.c new file mode 100644 index 00000000000..3ec93dab765 --- /dev/null +++ b/arch/arm/mm/copypage-v4wb.c @@ -0,0 +1,94 @@ +/* + * linux/arch/arm/mm/copypage-v4wb.c + * + * Copyright (C) 1995-1999 Russell King + * + * This program is f |