diff -ruN linux-2.4.19-rmk6-pxa1-hh30/Documentation/Configure.help linux-2.4.19-rmk6-pxa1-hh30-fass6/Documentation/Configure.help --- linux-2.4.19-rmk6-pxa1-hh30/Documentation/Configure.help 2003-12-05 11:43:59.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/Documentation/Configure.help 2004-03-08 17:34:14.000000000 +1100 @@ -23180,6 +23180,35 @@ Say Y if you want support for the SA-110 processor. Otherwise, say N. +Enable Fast Address Space Switching +CONFIG_CPU_FASS_ENABLE + This option enables Fast Address Space Switching (FASS). FASS uses a + number of features available in later-model ARM processors, namely + domains and the fast context switch extension, to optimise + context-switching times of user processes. You can find more + information on FASS in . + + FASS is currently an experimental feature: it may be best to say N, + unless you would like to help debug ARM Linux to make it even faster + than before! + +Number of Process ID slots to use with FASS +CONFIG_CPU_FASS_SLOTS + This option specifies the number of Process ID slots to use with Fast + Address Space Switching (FASS) for the ARM processor. Process ID slots + are also called Process Blocks in ARM documentation; each slot is 32MB + in size. + + The number of Process ID slots you can use depends on the ARM processor + for which you are compiling. The StrongARM SA1100 supports a maximum of + 64 slots; every other ARM processor that supports FASS can use up to 95 + slots. You can find more information in . + + If you are not sure of the number of slots to use, accept the default of + 64. You should never specify more than 95 (64 on the SA1100), and it + does not make sense to specify a value less than 2. You may want to + experiment with values of 16, 32, 48, 64 or 80. + Tulsa CONFIG_SA1100_PFS168 The Radisys Corp. PFS-168 (aka Tulsa) is an IntelŪ StrongArmŪ SA-1110 based diff -ruN linux-2.4.19-rmk6-pxa1-hh30/Documentation/arm/fass linux-2.4.19-rmk6-pxa1-hh30-fass6/Documentation/arm/fass --- linux-2.4.19-rmk6-pxa1-hh30/Documentation/arm/fass 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/Documentation/arm/fass 2004-03-01 14:51:01.000000000 +1100 @@ -0,0 +1,4 @@ +Fast Address Space Switching for the ARM Linux Kernel +===================================================== + +@@@ To be completed diff -ruN linux-2.4.19-rmk6-pxa1-hh30/Makefile linux-2.4.19-rmk6-pxa1-hh30-fass6/Makefile --- linux-2.4.19-rmk6-pxa1-hh30/Makefile 2003-12-05 11:43:59.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/Makefile 2004-02-02 10:39:24.000000000 +1100 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 19 -EXTRAVERSION = -rmk6-pxa1-hh30 +EXTRAVERSION = -rmk6-pxa1-hh30-fass6 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -ruN linux-2.4.19-rmk6-pxa1-hh30/arch/arm/config.in linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/config.in --- linux-2.4.19-rmk6-pxa1-hh30/arch/arm/config.in 2003-12-05 11:43:59.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/config.in 2004-03-08 16:42:34.000000000 +1100 @@ -508,7 +508,15 @@ if [ "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" ]; then bool 'Disable branch prediction' CONFIG_CPU_BPREDICT_DISABLE fi - +if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \ + "$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \ + "$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_ARM1026" = "y" -o \ + "$CONFIG_CPU_SA1100" = "y" -o "$CONFIG_CPU_XSCALE" = "y" ]; then + dep_bool 'Enable Fast Address Space Switching (EXPERIMENTAL)' CONFIG_CPU_FASS_ENABLE $CONFIG_EXPERIMENTAL + if [ "$CONFIG_CPU_FASS_ENABLE" = "y" ]; then + int ' Number of Process ID slots to use with FASS' CONFIG_CPU_FASS_SLOTS 64 + fi +fi # Select various configuration options depending on the machine type if [ "$CONFIG_ARCH_EDB7211" = "y" -o \ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/arch/arm/mm/Makefile linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/mm/Makefile --- linux-2.4.19-rmk6-pxa1-hh30/arch/arm/mm/Makefile 2003-10-27 10:20:55.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/mm/Makefile 2004-03-06 16:23:26.000000000 +1100 @@ -26,6 +26,7 @@ obj-$(CONFIG_CPU_26) += fault-armo.o mm-armo.o small_page.o +obj-$(CONFIG_CPU_FASS_ENABLE) += cpd.o pid.o obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o obj-$(CONFIG_DISCONTIGMEM) += discontig.o diff -ruN linux-2.4.19-rmk6-pxa1-hh30/arch/arm/tools/getconstants.c linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/tools/getconstants.c --- linux-2.4.19-rmk6-pxa1-hh30/arch/arm/tools/getconstants.c 2001-10-12 02:04:57.000000000 +1000 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/arch/arm/tools/getconstants.c 2004-03-08 20:03:26.000000000 +1100 @@ -1,12 +1,16 @@ /* - * linux/arch/arm/tools/getconsdata.c + * linux/arch/arm/tools/getconstants.c * * Copyright (C) 1995-2001 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. + * + * Changelog: + * 06-Mar-2004 JNZ Modified for FASS, based on Adam Wiggin's patches */ + #include #include #include @@ -25,6 +29,7 @@ #endif #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n) +#define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n) #define DEFN(name,off) asm("\n#define "name" %0" :: "I" (off)) @@ -40,7 +45,11 @@ DEFN("TSS_FPESAVE", OFF_TSK(thread.fpstate.soft.save)); #ifdef CONFIG_CPU_32 +#ifdef CONFIG_CPU_FASS_ENABLE +DEFN("TSS_DACR", OFF_TSK(thread.dacr)); +#else DEFN("TSS_DOMAIN", OFF_TSK(thread.domain)); +#endif DEFN("HPTE_TYPE_SMALL", PTE_TYPE_SMALL); DEFN("HPTE_AP_READ", PTE_AP_READ); @@ -54,8 +63,15 @@ DEFN("LPTE_WRITE", L_PTE_WRITE); DEFN("LPTE_EXEC", L_PTE_EXEC); DEFN("LPTE_DIRTY", L_PTE_DIRTY); + +#ifdef CONFIG_CPU_FASS_ENABLE +DEFN("TSK_MM", OFF_TSK(mm)); +DEFN("MM_CONTEXT_DACR", OFF_MM(context.dacr)); +DEFN("MM_CONTEXT_PID", OFF_MM(context.pid)); #endif +#endif /* CONFIG_CPU_32 */ + #ifdef CONFIG_CPU_26 DEFN("PAGE_PRESENT", _PAGE_PRESENT); DEFN("PAGE_READONLY", _PAGE_READONLY); diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/mmu.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/mmu.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/mmu.h 2003-10-27 10:19:32.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/mmu.h 2004-03-06 21:12:17.000000000 +1100 @@ -1,9 +1,58 @@ +/* + * linux/include/asm-arm/mmu.h + * + * Copyright (C) 2001, Adam Wiggins + * Copyright (C) 2003-04, John Zaitseff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of Version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Changelog: + * 20-Jun-2001 AGW Modified by Adam Wiggins for FASS. + * 11-Oct-2001 AGW Added PID field for PID register relocation support. + * 26-Apr-2002 AGW Added domain_timestamp field allow lazy clearing of the + * DACR. This is required to keep track of clean domains + * and to disable access to unallocated domains. + * 15-Sep-2003 JNZ Modified by John Zaitseff for Linux kernel 2.4.21-rmk1 + * 05-Mar-2004 JNZ Clean-up of the FASS code. + */ + #ifndef __ARM_MMU_H #define __ARM_MMU_H +#include + +#ifdef CONFIG_CPU_FASS_ENABLE + /* - * The ARM doesn't have a mmu context + * Fast Address Space Switch (FASS) requires keeping track of the Process + * ID register (PID) and Domain Access Control Register (DACR) for each + * process address space. + */ + +struct pid_struct; /* include/asm-arm/proc-armv/pid.h */ +struct region_struct; /* include/asm-arm/proc-armv/cpd.h */ + +struct fass_struct { + unsigned long pid; /* Process ID register value */ + unsigned long dacr; /* Domain Access Control Register */ +//@@@ unsigned long long domain_timestamp; /* Timestamp of last DACR check */ + + struct armpid_struct *pid_p; /* PID associated with address space */ + struct region_struct *region_p; /* Address space's private region */ +}; + +typedef struct fass_struct mm_context_t; + + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + +/* + * When not using FASS, the ARM does not need an MMU context */ typedef struct { } mm_context_t; -#endif +#endif /* CONFIG_CPU_FASS_ENABLE */ + +#endif /* ! __ARM_MMU_H */ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/mmu_context.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/mmu_context.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/mmu_context.h 2003-10-27 10:19:32.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/mmu_context.h 2004-03-06 22:27:39.000000000 +1100 @@ -8,18 +8,58 @@ * published by the Free Software Foundation. * * Changelog: - * 27-06-1996 RMK Created + * 27-Jun-1996 RMK Created + * 20-Jun-2001 AGW Defined destroy_context and init_new_context for FASS + * 05-Mar-2004 JNZ Code clean-up for FASS; make it dependant on config + * option CONFIG_CPU_FASS_ENABLE */ + #ifndef __ASM_ARM_MMU_CONTEXT_H #define __ASM_ARM_MMU_CONTEXT_H +#include + #include #include #include + +#ifdef CONFIG_CPU_FASS_ENABLE + +#include +#include + +static inline void +destroy_context(struct mm_struct *mm) +{ + cpd_unallocate_region(mm->context.region_p); + if (mm->context.pid_p) + armpid_unallocate(mm->context.pid_p); +} + +static inline int +init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + if ((mm->context.region_p = cpd_allocate_region()) == NULL) + return 1; + + mm->context.pid = ARMPID_UNUSED; + mm->context.dacr = DOMAIN_UNALLOC; + mm->context.pid_p = NULL; + + armpid_allocate(tsk, mm); + + return 0; +} + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + #define destroy_context(mm) do { } while(0) #define init_new_context(tsk,mm) 0 +#endif /* CONFIG_CPU_FASS_ENABLE */ + + /* * This is called when "tsk" is about to enter lazy TLB mode. * @@ -34,6 +74,8 @@ { } +#ifdef CONFIG_CPU_FASS_ENABLE + /* * This is the actual mm switch as far as the scheduler * is concerned. No registers are touched. @@ -43,10 +85,23 @@ struct task_struct *tsk, unsigned int cpu) { if (prev != next) + cpd_switch(next); +} + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + +static inline void +switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk, unsigned int cpu) +{ + if (prev != next) cpu_switch_mm(next->pgd, tsk); } +#endif /* CONFIG_CPU_FASS_ENABLE */ + + #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL,smp_processor_id()) -#endif +#endif /* ! __ASM_ARM_MMU_CONTEXT_H */ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/cpd.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/cpd.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/cpd.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/cpd.h 2004-03-08 20:50:30.000000000 +1100 @@ -0,0 +1,97 @@ +/* + * linux/include/asm-arm/proc-armv/cpd.h + * + * Copyright (C) 2001-02, Adam Wiggins + * Copyright (C) 2004, John Zaitseff + * + * This file declares constants, types and functions dealing with the + * Caching Page Directory (CPD) as used by Fast Address Space Switching. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of Version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Changelog: + * 20-Jun-2001 AGW Created by Adam Wiggins. + * 19-Feb-2002 AGW Added helper macros; cpd_struct updated to include + * a doubly-linked list of other cpd_structs + * allocated to the same domain. + * 19-Mar-2002 AGW Started modifications to support shared domains. + * 26-Apr-2002 AGW Changed per-address-space domain disabling to be lazy + * instead of disabling all domains on a context switch. + * 06-Mar-2004 JNZ Almost a complete rewrite by John Zaitseff; removed + * shared-domains support as it was quite buggy and did + * not give much performance benefit in any case. + */ + +#ifndef __ASM_ARM_PROC_CPD_H +#define __ASM_ARM_PROC_CPD_H + +#include + +#ifdef CONFIG_CPU_FASS_ENABLE + +#include +#include + +/* + * Constant definitions + */ + +/* Base address for mmap() allocations: end of Processor ID slots area */ +#define CPD_UNMAPPED_BASE TOTAL_ARMPIDS_AREA + + +/* + * Cache coherence macros + */ + +#define cpd_is_domain_coherent(domain) \ + (cpd_is_domain_tlb_coherent(domain) && \ + cpd_is_domain_cache_coherent(domain)) +#define cpd_is_domain_tlb_coherent(domain) \ + (! domain_active(domain_tlb_coherence, (domain))) +#define cpd_is_domain_cache_coherent(domain) \ + (cpd_is_domain_dcache_coherent(domain) && \ + cpd_is_domain_icache_coherent(domain)) +#define cpd_is_domain_dcache_coherent(domain) \ + (! domain_active(domain_dcache_coherence, (domain))) +#define cpd_is_domain_icache_coherent(domain) \ + (! domain_active(domain_icache_coherence, (domain))) + +#define cpd_is_mm_coherent(mm) \ + (cpd_is_mm_tlb_coherent(mm) && \ + cpd_is_mm_cache_coherent(mm)) +#define cpd_is_mm_tlb_coherent(mm) \ + (! ((mm)->context.dacr & domain_tlb_coherence & \ + (~SYSTEM_DOMAINS_MASK))) +#define cpd_is_mm_cache_coherent(mm) \ + (cpd_is_mm_dcache_coherent(mm) && \ + cpd_is_mm_icache_coherent(mm)) +#define cpd_is_mm_dcache_coherent(mm) \ + (! ((mm)->context.dacr & domain_dcache_coherence & \ + (~SYSTEM_DOMAINS_MASK))) +#define cpd_is_mm_icache_coherent(mm) \ + (! ((mm)->context.dacr & domain_icache_coherence & \ + (~SYSTEM_DOMAINS_MASK))) + +/* + * Domain clock recycling algorithm macros + */ + +#define cpd_domain_touched(domain) \ + (domain_active(domain_touched_val, (domain))) +#define cpd_set_domain_touched_val(domain) \ + do { \ + domain_touched_val |= domain_val((domain), DOMAIN_MASK); \ + } while (0); +#define cpd_clear_domain_touched_val(domain) \ + do { \ + domain_touched_val &= ~domain_val((domain), DOMAIN_MASK); \ + } while (0); + + + +#endif /* CONFIG_CPU_FASS_ENABLE */ + +#endif /* ! __ASM_ARM_PROC_CPD_H */ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/domain.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/domain.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/domain.h 2000-09-19 09:15:24.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/domain.h 2004-03-08 20:40:30.000000000 +1100 @@ -6,12 +6,50 @@ * 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. + * + * Changelog: + * 20-Jun-2001 AGW Modified by Adam Wiggins + * for Fast Address Space Switching (FASS) + * 05-Mar-2004 JNZ FASS clean-up by John Zaitseff */ + #ifndef __ASM_PROC_DOMAIN_H #define __ASM_PROC_DOMAIN_H +#include +#include +#include + +#ifdef CONFIG_CPU_FASS_ENABLE + +/* + * Domain numbers when Fast Address Space Switching (FASS) is in use. + * + * The current FASS scheme uses domains 3-15 for user processes + * (equivalent of DOMAIN_USER in the old scheme) and domains 1-2 for + * kernel and I/O spaces respectively. Domain 0 is to allow for easier + * debugging. + * + * Eventually (once FASS has been fully debugged), DOMAIN_UNALLOC and + * DOMAIN_USER should go away, DOMAIN_KERNEL and DOMAIN_IO should be set + * to 0, and DOMAIN_START should be set to 1. This will give domain 0 for + * kernel spaces and domains 1-15 for user spaces. NB: Need to consider + * whether setting DOMAIN_IO to be the same as DOMAIN_KERNEL has any + * security implications. + */ +#define DOMAIN_UNALLOC 0 /* Debugging: don't tag user pg_dir */ +#define DOMAIN_USER 0 /* Essentially only for debugging */ +#define DOMAIN_KERNEL 1 /* Includes all kernel memory only */ +#define DOMAIN_IO 2 /* Includes all I/O memory only */ + +#define NUM_DOMAINS 16 +#define DOMAIN_START 3 +#define DOMAIN_END (NUM_DOMAINS - 1) + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + /* - * Domain numbers + * Domain numbers when FASS is not used * * DOMAIN_IO - domain 2 includes all IO only * DOMAIN_KERNEL - domain 1 includes all kernel memory only @@ -19,17 +57,96 @@ */ #define DOMAIN_USER 0 #define DOMAIN_KERNEL 1 -#define DOMAIN_TABLE 1 #define DOMAIN_IO 2 +#endif /* CONFIG_CPU_FASS_ENABLE */ + + /* * Domain types */ +#define DOMAIN_MASK 0x03 #define DOMAIN_NOACCESS 0 #define DOMAIN_CLIENT 1 #define DOMAIN_MANAGER 3 #define domain_val(dom,type) ((type) << 2*(dom)) +#define domain_active(dacr,dom) (((dacr) >> 2*(dom)) & DOMAIN_MASK) + +#ifdef CONFIG_CPU_FASS_ENABLE + +#define DIRTY 0xFFFFFFFF +#define CLEAN 0x00000000 + +#define SYSTEM_DOMAINS_MASK (domain_val(DOMAIN_UNALLOC, DOMAIN_MASK) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MASK) | \ + domain_val(DOMAIN_IO, DOMAIN_MASK)) + +/* External variables, defined in arch/arm/mm/cpd.c */ +extern unsigned long domain_tlb_coherence; +extern unsigned long domain_dcache_coherence; +extern unsigned long domain_icache_coherence; +extern unsigned long domain_touched_val; + +/* + * Set/Modify the Domain Access Control Register (DACR) when FASS is enabled + */ + +/* Retrieve the current value of the Domain Access Control Register */ +static inline unsigned long +get_domain(void) +{ + unsigned long dacr; + + __asm__ __volatile__( + "mrc p15, 0, %0, c3, c0 @ Get current DACR" + : "=&r" (dacr) : ); + return dacr; +} + +/* Set the Domain Access Control Register */ +static inline void +set_dacr_update_coherence(unsigned long dacr) +{ + domain_tlb_coherence |= dacr; + domain_dcache_coherence |= dacr; + domain_icache_coherence |= dacr; + + __asm__ __volatile__( + "mcr p15, 0, %0, c3, c0 @ Set the DACR" + : : "r" (dacr)); +} + +/* Update DACR to include DOMAIN_CLIENT access to a domain */ +/* @@@ change update_dacr name to something better */ +static inline void +update_dacr(unsigned long dom) +{ + unsigned long dacr; + + current->mm->context.dacr |= domain_val(dom, DOMAIN_CLIENT); + dacr = current->mm->context.dacr | current->thread.dacr; + domain_touched_val |= dacr; + set_dacr_update_coherence(dacr); +} + +/* Change the thread's DACR (domain) to a new value */ +static inline void +modify_domain(unsigned long dom, unsigned long type) +{ + unsigned long dacr = current->thread.dacr; + + dacr &= ~domain_val(dom, DOMAIN_MASK); + dacr |= domain_val(dom, type); + current->thread.dacr = dacr; + set_dacr_update_coherence(current->thread.dacr); +} + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + +/* + * Set the Domain Access Control Register (DACR) without FASS + */ #define set_domain(x) \ do { \ @@ -41,10 +158,12 @@ #define modify_domain(dom,type) \ do { \ unsigned int domain = current->thread.domain; \ - domain &= ~domain_val(dom, DOMAIN_MANAGER); \ + domain &= ~domain_val(dom, DOMAIN_MASK); \ domain |= domain_val(dom, type); \ current->thread.domain = domain; \ set_domain(current->thread.domain); \ } while (0) -#endif +#endif /* CONFIG_CPU_FASS_ENABLE */ + +#endif /* ! __ASM_PROC_DOMAIN_H */ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/pgtable.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/pgtable.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/pgtable.h 2003-12-05 11:44:01.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/pgtable.h 2004-03-06 16:11:05.000000000 +1100 @@ -11,7 +11,12 @@ * now possible to combine ARM6, ARM7 and StrongARM versions. * 17-Apr-1999 RMK Now pass an area size to clean_cache_area and * flush_icache_area. + * + * 03-Oct-2003 JNZ Modified for Fast Address Space Switching (FASS) by + * John Zaitseff, based on Adam Wiggin's patches. + * 06-Mar-2004 JNZ Minor code clean-up for FASS */ + #ifndef __ASM_PROC_PGTABLE_H #define __ASM_PROC_PGTABLE_H @@ -101,6 +106,8 @@ #ifndef __ASSEMBLY__ +#include + #include #include @@ -108,7 +115,19 @@ #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL)) #define pmd_bad(pmd) (pmd_val(pmd) & 2) -#define set_pmd(pmdp,pmd) cpu_set_pmd(pmdp, pmd) + +#ifdef CONFIG_CPU_FASS_ENABLE + +/* arch_get_unmapped_area() is defined in arch/arm/mm/cpd.c */ +#define HAVE_ARCH_UNMAPPED_AREA + +/* NB: cpd_XXX, not cpu_XXX: use Caching Page Directory function */ +#define set_pmd(pmdp, pmd) cpd_set_pmd(pmdp, pmd) +#define pmd_domain(pmd) ((pmd_val(pmd) >> 5) & (NUM_DOMAINS - 1)) + +#else /* ! CONFIG_CPU_FASS_ENABLE */ +#define set_pmd(pmdp, pmd) cpu_set_pmd(pmdp, pmd) +#endif static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot) { diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/pid.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/pid.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/pid.h 1970-01-01 10:00:00.000000000 +1000 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/pid.h 2004-03-08 17:41:05.000000000 +1100 @@ -0,0 +1,194 @@ +/* + * linux/include/asm-arm/proc-armv/pid.h + * + * Copyright (C) 2001-02, Adam Wiggins + * Copyright (C) 2004, John Zaitseff + * + * This file deals with ARM's Process ID register (register C13 in the + * MMU) and Process ID slots (a 32MB region of memory that can be aliased + * to addresses 0x00000000-0x1FFFFFFF; ARM calls these "process blocks"). + * + * The Process ID register and associated slots are used to implement + * Fast Address Space Switching (FASS). Please note you need an ARM CPU + * that supports the Fast Context Switch Extension for this to work --- + * see the file Documentation/arm/fass for more information. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of Version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * Changelog: + * 14-Oct-2001 AGW Created by Adam Wiggins. + * 19-Feb-2002 AGW Macros added. + * 06-Mar-2004 JNZ Extensive code clean-up and rewrite. + */ + +#ifndef __ASM_ARM_PROC_PID_H +#define __ASM_ARM_PROC_PID_H + +#include + +#ifdef CONFIG_CPU_FASS_ENABLE + +/* + * Constant definitions + */ + +/* Only bits 25-31 of PID are defined; this gives a slot size of 32MB */ +#define ARMPID_SHIFT 25 +#define ARMPID_SLOT_SIZE (1UL << ARMPID_SHIFT) +#define ARMPID_MASK (~(ARMPID_SLOT_SIZE - 1)) + +/* Number of Process ID slots available for use on this CPU. Note that + * most ARM CPUs capable of FASS have 128 slots covering the whole 4GB + * address space. We don't want to use all of this, as memory above + * PAGE_OFFSET/TASK_SIZE (typ. 0xC0000000) is used for the kernel. In + * addition, we DO want to leave room for non-MAP_FIXED areas. We should + * experiment with values of 16, 32, 48, 64 or 80 */ + +#ifndef CONFIG_CPU_FASS_SLOTS +# error "CONFIG_CPU_FASS_SLOTS should have been defined during configuration" +#endif + +#if CONFIG_CPU_FASS_SLOTS < 2 +# error "CONFIG_CPU_FASS_SLOTS must be >= 2" +#endif + +#if CONFIG_CPU_SA1100 +# if CONFIG_CPU_FASS_SLOTS > 64 +# error "CONFIG_CPU_FASS_SLOTS must be <= 64 on the Intel StrongARM SA1100" +# endif +#else /* ! CONFIG_CPU_SA1100 */ +# if CONFIG_CPU_FASS_SLOTS > 95 +# error "CONFIG_CPU_FASS_SLOTS must be <= 95" +# endif +#endif + +#define NUM_ARMPIDS (CONFIG_CPU_FASS_SLOTS) +#define TOTAL_ARMPIDS_AREA (NUM_ARMPIDS * ARMPID_SLOT_SIZE) + +#define ARMPID_TASK_SIZE ARMPID_SLOT_SIZE +#define ARMPID_UNUSED 0 +#define FIRST_ARMPID_NR 1 +#define ARMPID_PTRS_PER_PGD (ARMPID_TASK_SIZE / PGDIR_SIZE) + +/* Limit the process's brk()-able area to PGDIR_SIZE (1MB) less than the + * 32MB task size, ie, to the 31MB mark. This is done by allocating a + * dummy vm_area at the ARMPID_BRK_LIMIT mark. This gives a maximum of + * 1MB for the process's stack. Must be a multiple of PGDIR_SIZE as ARM + * domains cover a whole 1MB section in the page tables */ +#define ARMPID_BRK_LIMIT (ARMPID_TASK_SIZE - PGDIR_SIZE) + +/* + * Macro definitions + */ + +#define armpid_used(pid) ((pid) != 0) + +/* Convert between PID numbers (0 - NUM_ARMPIDS) to the PID register values */ +#define pidnum_to_pid(pidnum) ((pidnum) << ARMPID_SHIFT) +#define pid_to_pidnum(pid) ((pid) >> ARMPID_SHIFT) + +/* Convert between Modified Virtual Addresses (MVAs), PID register values + * and PID numbers */ +#define mva_to_pid(mva) ((mva) & ARMPID_MASK) +#define mva_to_pidnum(mva) (pid_to_pidnum(mva_to_pid(mva))) + +/* Calculate Caching Page Directory (CPD) index offset due to PID relocation */ +#define ARMPID_CPD_OFFSET(pid) ((pid) >> PGDIR_SHIFT) + +/* + * Structure definitions + */ + +/* Process ID context */ +struct armpid_struct { + unsigned int pidnum; /* ARM Process ID number, 0 - NUM_ARMPIDS */ + unsigned int mm_count; /* Number of address spaces using this PID */ +}; + +/* + * External definitions + */ + +extern struct armpid_struct armpids[NUM_ARMPIDS]; /* arch/arm/mm/pid.h */ + +/* + * Inline functions + */ + +/* Get the current value of the Process ID register */ +static inline unsigned long +get_armpid(void) +{ + unsigned long armpid; + + __asm__ __volatile__( + "mrc p15, 0, %0, c13, c0, 0 @ Get current Process ID" + : "=&r" (armpid) : ); + /* Note that bits 0-24 of C13 are unpredictable, according to ARM */ + return armpid & ARMPID_MASK; +} + +/* Set the Process ID register */ +static inline void +set_armpid(unsigned long armpid) +{ + __asm__ __volatile__( + "mcr p15, 0, %0, c13, c0, 0 @ Set PID register" + : : "r" (armpid)); + + /* + * The ARM Architecture Reference Manual states, in section B6.4, + * that a restricted form of an Instruction Memory Barrier must + * follow setting the ARM PID register. Other documents (eg, the + * ARM1020T Technical Reference Manual) state that between 2-5 + * instructions following the "mcr" may be fetched with the old + * PID register value. + * + * We are ignoring this (perhaps unwisely). If need be, you may + * uncomment the following lines. + */ + + /* Pause after setting the Process ID register */ + /* + __asm__ __volatile__( + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop" : : ); + */ +} + +/* Convert a Modified Virtual Address (MVA) back to a Virtual Address (VA) */ +static inline unsigned long +mva_to_va(unsigned long mva) +{ + unsigned long pid = get_armpid(); + + return (armpid_used(pid) && (pid == mva_to_pid(mva))) + ? (mva & (~ARMPID_MASK)) + : mva; +} + +/* Convert a Virtual Address (VA) to a Modified Virtual Address (MVA), + * in the same way that the Fast Context Switch Extension does */ +static inline unsigned long +va_to_mva(unsigned long va) +{ + return (va < ARMPID_SLOT_SIZE) + ? (va | get_armpid()) + : va; +} + +/* + * Function prototypes + */ + +void armpid_allocate(struct task_struct *tsk, struct mm_struct *mm); +void armpid_unallocate(struct armpid_struct *armpid_p); + +#endif /* CONFIG_CPU_FASS_ENABLE */ + +#endif /* ! __ASM_ARM_PROC_PID_H */ diff -ruN linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/processor.h linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/processor.h --- linux-2.4.19-rmk6-pxa1-hh30/include/asm-arm/proc-armv/processor.h 2003-10-27 10:20:56.000000000 +1100 +++ linux-2.4.19-rmk6-pxa1-hh30-fass6/include/asm-arm/proc-armv/processor.h 2004-03-08 20:11:45.000000000 +1100 @@ -8,13 +8,16 @@ * published by the Free Software Foundation. * * Changelog: - * 20-09-1996 RMK Created - * 26-09-1996 RMK Added 'EXTRA_THREAD_STRUCT*' - * 28-09-1996 RMK Moved start_thread into the processor dependencies - * 09-09-1998 PJB Delete redundant `wp_works_ok' - * 30-05-1999 PJB Save sl across context switches - * 31-07-1999 RMK Added 'domain' stuff + * 20-Sep-1996 RMK Created + * 26-Sep-1996 RMK Added 'EXTRA_THREAD_STRUCT*' + * 28-Sep-1996 RMK Moved start_thread into the processor dependencies + * 09-Sep-1998 PJB Delete redundant `wp_works_ok' + * 30-May-1999 PJB Save sl across context switches + * 31-Jul-1999 RMK Added 'domain' stuff + * 09-Oct-2001 AGW Rename thread.domain to thread.dacr to avoid confusion + * 08-Mar-2004 JNZ Code clean-up to depend on CONFIG_CPU_FASS_ENABLE */ + #ifndef __ASM_PROC_PROCESSOR_H #define __ASM_PROC_PROCESSOR_H @@ -44,14 +47,32 @@ #define INIT_CSS (struct context_save_struct){ SVC_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0 } #endif +#ifdef CONFIG_CPU_FASS_ENABLE + +/* In FASS, thread.dacr is used to store the actual contents of the Domain + * Access Control Register, not just the DOMAIN_xxx macro value; hence the + * different name from the non-FASS version */ + #define EXTRA_THREAD_STRUCT \ - unsigned int domain; + unsigned long dacr; + +#define EXTRA_THREAD_STRUCT_INIT \ + dacr: domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \ + domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ + domain_val(DOMAIN_IO, DOMAIN_CLIENT) + +#else /* ! CONFIG_CPU_FASS_ENABLE */ + +#define EXTRA_THREAD_STRUCT \ + unsigned long domain; #define EXTRA_THREAD_STRUCT_INIT \ domain: domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ domain_val(DOMAIN_IO, DOMAIN_CLIENT) +#endif /* CONFIG_CPU_FASS_ENABLE */ + #define start_thread(regs,pc,sp) \ ({ \ unsigned long *stack = (unsigned long *)sp; \