selection depending on processor features.
#ifdef MULTI_TLB
struct cpu_tlb_fns cpu_tlb;
#endif
+#ifdef MULTI_USER
+struct cpu_user_fns cpu_user;
+#endif
unsigned char aux_device_present;
char elf_platform[ELF_PLATFORM_SIZE];
#ifdef MULTI_TLB
cpu_tlb = *list->tlb;
#endif
+#ifdef MULTI_USER
+ cpu_user = *list->user;
+#endif
printk("Processor: %s %s revision %d\n",
proc_info.manufacturer, proc_info.cpu_name,
*
* FIXME: do we need to handle cache stuff...
*/
-ENTRY(armv3_copy_user_page)
+ENTRY(v3_copy_user_page)
stmfd sp!, {r4, lr} @ 2
mov r2, #PAGE_SZ/64 @ 1
ldmia r1!, {r3, r4, ip, lr} @ 4+1
*
* FIXME: do we need to handle cache stuff...
*/
-ENTRY(armv3_clear_user_page)
+ENTRY(v3_clear_user_page)
str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1
bne 1b @ 1
ldr pc, [sp], #4
+ .section ".text.init", #alloc, #execinstr
+
+ENTRY(v3_user_fns)
+ .long v3_clear_user_page
+ .long v3_copy_user_page
* instruction. If your processor does not supply this, you have to write your
* own copy_user_page that does the right thing.
*/
-ENTRY(armv4_copy_user_page)
+ENTRY(v4_copy_user_page)
stmfd sp!, {r4, lr} @ 2
mov r2, #PAGE_SZ/64 @ 1
ldmia r1!, {r3, r4, ip, lr} @ 4
*
* Same story as above.
*/
-ENTRY(armv4_clear_user_page)
+ENTRY(v4_clear_user_page)
str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1
bne 1b @ 1
mcr p15, 0, r1, c7, c10, 4 @ 1 drain WB
ldr pc, [sp], #4
+
+ .section ".text.init", #alloc, #execinstr
+
+ENTRY(v4_user_fns)
+ .long v4_clear_user_page
+ .long v4_copy_user_page
+
* instruction. If your processor does not supply this, you have to write your
* own copy_user_page that does the right thing.
*/
-ENTRY(armv4_mc_copy_user_page)
+ENTRY(v4_mc_copy_user_page)
stmfd sp!, {r4, lr} @ 2
mov r4, r0
mov r0, r1
*
* Same story as above.
*/
-ENTRY(armv4_mc_clear_user_page)
+ENTRY(v4_mc_clear_user_page)
str lr, [sp, #-4]!
mov r1, #PAGE_SZ/64 @ 1
mov r2, #0 @ 1
subs r1, r1, #1 @ 1
bne 1b @ 1
ldr pc, [sp], #4
+
+ .section ".text.init", #alloc, #execinstr
+
+ENTRY(v4_mc_user_fns)
+ .long v4_mc_clear_user_page
+ .long v4_mc_copy_user_page
+
* page. We rely on the mini-cache being smaller than one page, so we'll
* cycle through the complete cache anyway.
*/
-ENTRY(armv5te_copy_user_page)
+ENTRY(v5te_mc_copy_user_page)
stmfd sp!, {r4, r5, lr}
mov r5, r0
mov r0, r1
* r0 = destination
* r1 = virtual user address of ultimate destination page
*/
-ENTRY(armv5te_clear_user_page)
+ENTRY(v5te_mc_clear_user_page)
str lr, [sp, #-4]!
mov r1, #PAGE_SZ/32
mov r2, #0
subs r1, r1, #1
bne 1b
ldr pc, [sp], #4
+
+ .section ".text.init", #alloc, #execinstr
+
+ENTRY(v5te_mc_user_fns)
+ .long v5te_mc_clear_user_page
+ .long v5te_mc_copy_user_page
.word cpu_arm1020_set_pmd
.word cpu_arm1020_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size arm1020_processor_functions, . - arm1020_processor_functions
.type cpu_arm1020_info, #object
.long cpu_arm1020_info
.long arm1020_processor_functions
.long v4wbi_tlb_fns
+ .long v4_user_fns
.size __arm1020_proc_info, . - __arm1020_proc_info
.long cpu_arm2_info
.long SYMBOL_NAME(arm2_processor_functions)
.long 0
+ .long 0
.long 0x41560250
.long 0xfffffff0
.long cpu_arm250_info
.long SYMBOL_NAME(arm250_processor_functions)
.long 0
+ .long 0
.long 0x41560300
.long 0xfffffff0
.long cpu_arm3_info
.long SYMBOL_NAME(arm3_processor_functions)
.long 0
+ .long 0
+
.word cpu_arm6_set_pmd
.word cpu_arm6_set_pte
- /* other */
- .word armv3_clear_user_page
- .word armv3_copy_user_page
-
.size arm6_processor_functions, . - arm6_processor_functions
/*
.word cpu_arm7_set_pmd
.word cpu_arm7_set_pte
- /* other */
- .word armv3_clear_user_page
- .word armv3_copy_user_page
-
.size arm7_processor_functions, . - arm7_processor_functions
.type cpu_arm6_info, #object
.long cpu_arm6_info
.long arm6_processor_functions
.long v3_tlb_fns
+ .long v3_user_fns
.size __arm6_proc_info, . - __arm6_proc_info
.type __arm610_proc_info, #object
.long cpu_arm610_info
.long arm6_processor_functions
.long v3_tlb_fns
+ .long v3_user_fns
.size __arm610_proc_info, . - __arm610_proc_info
.type __arm7_proc_info, #object
.long cpu_arm7_info
.long arm7_processor_functions
.long v3_tlb_fns
+ .long v3_user_fns
.size __arm7_proc_info, . - __arm7_proc_info
.type __arm710_proc_info, #object
.long cpu_arm710_info
.long arm7_processor_functions
.long v3_tlb_fns
+ .long v3_user_fns
.size __arm710_proc_info, . - __arm710_proc_info
.word cpu_arm720_set_pmd
.word cpu_arm720_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size arm720_processor_functions, . - arm720_processor_functions
.type cpu_arm720_info, #object
.long cpu_arm720_info @ info
.long arm720_processor_functions
.long v4_tlb_fns
+ .long v4_user_fns
.size __arm720_proc_info, . - __arm720_proc_info
.word cpu_arm920_set_pmd
.word cpu_arm920_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size arm920_processor_functions, . - arm920_processor_functions
.type cpu_arm920_info, #object
.long cpu_arm920_info
.long arm920_processor_functions
.long v4wbi_tlb_fns
+ .long v4_user_fns
.size __arm920_proc_info, . - __arm920_proc_info
.word cpu_arm922_set_pmd
.word cpu_arm922_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size arm922_processor_functions, . - arm922_processor_functions
.type cpu_arm922_info, #object
.long cpu_arm922_info
.long arm922_processor_functions
.long v4wbi_tlb_fns
+ .long v4_user_fns
.size __arm922_proc_info, . - __arm922_proc_info
.word cpu_arm926_set_pmd
.word cpu_arm926_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size arm926_processor_functions, . - arm926_processor_functions
.type cpu_arm926_info, #object
.long cpu_arm926_info
.long arm926_processor_functions
.long v4wbi_tlb_fns
+ .long v4_user_fns
.size __arm926_proc_info, . - __arm926_proc_info
.word cpu_sa110_set_pmd
.word cpu_sa110_set_pte
- /* misc */
- .word armv4_clear_user_page
- .word armv4_copy_user_page
-
.size sa110_processor_functions, . - sa110_processor_functions
.type cpu_sa110_info, #object
.word cpu_sa1100_set_pmd
.word cpu_sa1100_set_pte
- /* misc */
- .word armv4_mc_clear_user_page
- .word armv4_mc_copy_user_page
-
.size sa1100_processor_functions, . - sa1100_processor_functions
cpu_sa1100_info:
.long cpu_sa110_info
.long sa110_processor_functions
.long v4wb_tlb_fns
+ .long v4_user_fns
.size __sa110_proc_info, . - __sa110_proc_info
.type __sa1100_proc_info,#object
.long cpu_sa1100_info
.long sa1100_processor_functions
.long v4wb_tlb_fns
+ .long v4_mc_user_fns
.size __sa1100_proc_info, . - __sa1100_proc_info
.type __sa1110_proc_info,#object
.long cpu_sa1110_info
.long sa1100_processor_functions
.long v4wb_tlb_fns
+ .long v4_mc_user_fns
.size __sa1110_proc_info, . - __sa1110_proc_info
.word cpu_xscale_set_pmd
.word cpu_xscale_set_pte
- /* misc */
- .word armv5te_clear_user_page
- .word armv5te_copy_user_page
-
.size xscale_processor_functions, . - xscale_processor_functions
.type cpu_80200_info, #object
.long cpu_80200_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
+ .long v5te_mc_user_fns
.size __80200_proc_info, . - __80200_proc_info
.type __pxa250_proc_info,#object
.long cpu_pxa250_info
.long xscale_processor_functions
.long v4wbi_tlb_fns
+ .long v5te_mc_user_fns
.size __cotulla_proc_info, . - __cotulla_proc_info
.size __pxa250_proc_info, . - __pxa250_proc_info
*/
void (*set_pte)(pte_t *ptep, pte_t pte);
} pgtable;
-
- struct { /* other */
- void (*clear_user_page)(void *page, unsigned long u_addr);
- void (*copy_user_page)(void *to, void *from, unsigned long u_addr);
- } misc;
} processor;
extern const struct processor arm6_processor_functions;
#define cpu_set_pmd(pmdp, pmd) processor.pgtable.set_pmd(pmdp, pmd)
#define cpu_set_pte(ptep, pte) processor.pgtable.set_pte(ptep, pte)
-#define cpu_copy_user_page(to,from,uaddr) processor.misc.copy_user_page(to,from,uaddr)
-#define cpu_clear_user_page(page,uaddr) processor.misc.clear_user_page(page,uaddr)
-
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#define cpu_get_pgd() \
#define cpu_set_pgd __cpu_fn(CPU_NAME,_set_pgd)
#define cpu_set_pmd __cpu_fn(CPU_NAME,_set_pmd)
#define cpu_set_pte __cpu_fn(CPU_NAME,_set_pte)
-#define cpu_copy_user_page __cpu_fn(MMU_ARCH,_copy_user_page)
-#define cpu_clear_user_page __cpu_fn(MMU_ARCH,_clear_user_page)
#ifndef __ASSEMBLY__
extern void cpu_set_pmd(pmd_t *pmdp, pmd_t pmd);
extern void cpu_set_pte(pte_t *ptep, pte_t pte);
-extern void cpu_copy_user_page(void *to, void *from, unsigned long u_addr);
-extern void cpu_clear_user_page(void *page, unsigned long u_addr);
-
extern volatile void cpu_reset(unsigned long addr);
#define cpu_switch_mm(pgd,tsk) cpu_set_pgd(__virt_to_phys((unsigned long)(pgd)))
#error Unknown data abort handler type
#endif
+
+/*
+ * User Space Model
+ * ================
+ *
+ * This section selects the correct set of functions for dealing with
+ * page-based copying and clearing for user space for the particular
+ * processor(s) we're building for.
+ *
+ * We have the following to choose from:
+ * v3 - ARMv3
+ * v4 - ARMv4 without minicache
+ * v4_mc - ARMv4 with minicache
+ * v5te_mc - ARMv5TE with minicache
+ */
+#undef _USER
+#undef MULTI_USER
+
+#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM720T) || defined(CONFIG_CPU_ARM920T) || \
+ defined(CONFIG_CPU_ARM922T) || defined(CONFIG_CPU_ARM926T) || \
+ defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_ARM1020)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v4
+# endif
+#endif
+
+#if defined(CONFIG_CPU_SA1100)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v4_mc
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v5te_mc
+# endif
+#endif
+
+#ifndef _USER
+#error Unknown user operations model
+#endif
+
#endif
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
-#define STRICT_MM_TYPECHECKS
+#include <asm/glue.h>
-#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
-extern void copy_page(void *to, void *from);
+struct cpu_user_fns {
+ void (*cpu_clear_user_page)(void *p, unsigned long user);
+ void (*cpu_copy_user_page)(void *to, const void *from,
+ unsigned long user);
+};
+
+#ifdef MULTI_USER
+extern struct cpu_user_fns cpu_user;
+
+#define __cpu_clear_user_page cpu_user.cpu_clear_user_page
+#define __cpu_copy_user_page cpu_user.cpu_copy_user_page
+
+#else
+
+#define __cpu_clear_user_page __glue(_USER,_clear_user_page)
+#define __cpu_copy_user_page __glue(_USER,_copy_user_page)
+
+extern void __cpu_clear_user_page(void *p, unsigned long user);
+extern void __cpu_copy_user_page(void *to, const void *from,
+ unsigned long user);
+#endif
#define clear_user_page(addr,vaddr) \
do { \
preempt_disable(); \
- cpu_clear_user_page(addr, vaddr); \
+ __cpu_clear_user_page(addr, vaddr); \
preempt_enable(); \
} while (0)
#define copy_user_page(to,from,vaddr) \
do { \
preempt_disable(); \
- cpu_copy_user_page(to, from, vaddr); \
+ __cpu_copy_user_page(to, from, vaddr); \
preempt_enable(); \
} while (0)
+#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
+extern void copy_page(void *to, void *from);
+
+#undef STRICT_MM_TYPECHECKS
+
#ifdef STRICT_MM_TYPECHECKS
/*
* These are used to make use of C type-checking..
/*
* CPU_NAME - the prefix for CPU related functions
- * MMU_ARCH - the prefix for copy_user_page/clear_user_page
*/
#ifdef CONFIG_CPU_32
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm6
-# define MMU_ARCH armv3
# endif
# endif
# ifdef CONFIG_CPU_ARM710
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm7
-# define MMU_ARCH armv3
# endif
# endif
# ifdef CONFIG_CPU_ARM720T
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm720
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_ARM920T
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm920
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_ARM922T
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm922
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_ARM926T
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm926
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_SA110
# define MULTI_CPU
# else
# define CPU_NAME cpu_sa110
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_SA1100
# define MULTI_CPU
# else
# define CPU_NAME cpu_sa1100
-# define MMU_ARCH armv4_mc
# endif
# endif
# ifdef CONFIG_CPU_ARM1020
# define MULTI_CPU
# else
# define CPU_NAME cpu_arm1020
-# define MMU_ARCH armv4
# endif
# endif
# ifdef CONFIG_CPU_XSCALE
# define MULTI_CPU
# else
# define CPU_NAME cpu_xscale
-# define MMU_ARCH armv5te
# endif
# endif
#endif
#include <asm/proc-fns.h>
struct cpu_tlb_fns;
+struct cpu_user_fns;
struct processor;
struct proc_info_item {
* arch/arm/mm/proc-*.S and arch/arm/kernel/head-armv.S
*/
struct proc_info_list {
- unsigned int cpu_val;
- unsigned int cpu_mask;
- unsigned long __cpu_mmu_flags; /* used by head-armv.S */
- unsigned long __cpu_flush; /* used by head-armv.S */
- const char *arch_name;
- const char *elf_name;
- unsigned int elf_hwcap;
- struct proc_info_item *info;
- struct processor *proc;
- struct cpu_tlb_fns *tlb;
+ unsigned int cpu_val;
+ unsigned int cpu_mask;
+ unsigned long __cpu_mmu_flags; /* used by head-armv.S */
+ unsigned long __cpu_flush; /* used by head-armv.S */
+ const char *arch_name;
+ const char *elf_name;
+ unsigned int elf_hwcap;
+ struct proc_info_item *info;
+ struct processor *proc;
+ struct cpu_tlb_fns *tlb;
+ struct cpu_user_fns *user;
};
#endif /* __ASSEMBLY__ */
-#define PROC_INFO_SZ 40
+#define PROC_INFO_SZ 44
#define HWCAP_SWP 1
#define HWCAP_HALF 2