diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 17:59:33 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-06 17:59:33 -0800 |
commit | c77417132c12af338a7d37956809b2b98d20413c (patch) | |
tree | 02cb0ef1f8dfa1af8ce0965883dd449adf33eb2c /arch/m68k/include/asm | |
parent | e4e88f31bcb5f05f24b9ae518d4ecb44e1a7774d (diff) | |
parent | 1f7034b9616e6f14dc7b6aa280210421428f31af (diff) |
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu: (56 commits)
m68k: allow ColdFire 547x and 548x CPUs to be built with MMU enabled
m68k/Kconfig: Separate classic m68k and coldfire early
m68k: add ColdFire with MMU enabled support to the m68k mem init code
m68k: do not use m68k startup or interrupt code for ColdFire CPUs
m68k: add ColdFire FPU support for the V4e ColdFire CPUs
m68k: adjustments to stack frame for ColdFire with MMU enabled
m68k: use non-MMU linker script for ColdFire MMU builds
m68k: ColdFire with MMU enabled uses same clocking code as non-MMU
m68k: add code to setup a ColdFire 54xx platform when MMU enabled
m68k: use non-MMU entry.S code when compiling for ColdFire CPU
m68k: create ColdFire MMU pgalloc code
m68k: compile appropriate mm arch files for ColdFire MMU support
m68k: ColdFire V4e MMU paging init code and miss handler
m68k: use ColdFire MMU read/write bit flags when ioremapping
m68k: modify cache push and clear code for ColdFire with MMU enable
m68k: use tracehook_report_syscall_entry/exit for ColdFire MMU ptrace path
m68k: ColdFire V4e MMU context support code
m68k: MMU enabled ColdFire needs 8k ELF alignment
m68k: set ColdFire MMU page size
m68k: define PAGE_OFFSET_RAW for ColdFire CPU with MMU enabled
...
Diffstat (limited to 'arch/m68k/include/asm')
30 files changed, 1121 insertions, 302 deletions
diff --git a/arch/m68k/include/asm/anchor.h b/arch/m68k/include/asm/anchor.h deleted file mode 100644 index 871c0d5cfc3..00000000000 --- a/arch/m68k/include/asm/anchor.h +++ /dev/null @@ -1,112 +0,0 @@ -/****************************************************************************/ - -/* - * anchor.h -- Anchor CO-MEM Lite PCI host bridge part. - * - * (C) Copyright 2000, Moreton Bay (www.moreton.com.au) - */ - -/****************************************************************************/ -#ifndef anchor_h -#define anchor_h -/****************************************************************************/ - -/* - * Define basic addressing info. - */ -#if defined(CONFIG_M5407C3) -#define COMEM_BASE 0xFFFF0000 /* Base of CO-MEM address space */ -#define COMEM_IRQ 25 /* IRQ of anchor part */ -#else -#define COMEM_BASE 0x80000000 /* Base of CO-MEM address space */ -#define COMEM_IRQ 25 /* IRQ of anchor part */ -#endif - -/****************************************************************************/ - -/* - * 4-byte registers of CO-MEM, so adjust register addresses for - * easy access. Handy macro for word access too. - */ -#define LREG(a) ((a) >> 2) -#define WREG(a) ((a) >> 1) - - -/* - * Define base addresses within CO-MEM Lite register address space. - */ -#define COMEM_I2O 0x0000 /* I2O registers */ -#define COMEM_OPREGS 0x0400 /* Operation registers */ -#define COMEM_PCIBUS 0x2000 /* Direct access to PCI bus */ -#define COMEM_SHMEM 0x4000 /* Shared memory region */ - -#define COMEM_SHMEMSIZE 0x4000 /* Size of shared memory */ - - -/* - * Define CO-MEM Registers. - */ -#define COMEM_I2OHISR 0x0030 /* I2O host interrupt status */ -#define COMEM_I2OHIMR 0x0034 /* I2O host interrupt mask */ -#define COMEM_I2OLISR 0x0038 /* I2O local interrupt status */ -#define COMEM_I2OLIMR 0x003c /* I2O local interrupt mask */ -#define COMEM_IBFPFIFO 0x0040 /* I2O inbound free/post FIFO */ -#define COMEM_OBPFFIFO 0x0044 /* I2O outbound post/free FIFO */ -#define COMEM_IBPFFIFO 0x0048 /* I2O inbound post/free FIFO */ -#define COMEM_OBFPFIFO 0x004c /* I2O outbound free/post FIFO */ - -#define COMEM_DAHBASE 0x0460 /* Direct access base address */ - -#define COMEM_NVCMD 0x04a0 /* I2C serial command */ -#define COMEM_NVREAD 0x04a4 /* I2C serial read */ -#define COMEM_NVSTAT 0x04a8 /* I2C status */ - -#define COMEM_DMALBASE 0x04b0 /* DMA local base address */ -#define COMEM_DMAHBASE 0x04b4 /* DMA host base address */ -#define COMEM_DMASIZE 0x04b8 /* DMA size */ -#define COMEM_DMACTL 0x04bc /* DMA control */ - -#define COMEM_HCTL 0x04e0 /* Host control */ -#define COMEM_HINT 0x04e4 /* Host interrupt control/status */ -#define COMEM_HLDATA 0x04e8 /* Host to local data mailbox */ -#define COMEM_LINT 0x04f4 /* Local interrupt contole status */ -#define COMEM_LHDATA 0x04f8 /* Local to host data mailbox */ - -#define COMEM_LBUSCFG 0x04fc /* Local bus configuration */ - - -/* - * Commands and flags for use with Direct Access Register. - */ -#define COMEM_DA_IACK 0x00000000 /* Interrupt acknowledge (read) */ -#define COMEM_DA_SPCL 0x00000010 /* Special cycle (write) */ -#define COMEM_DA_MEMRD 0x00000004 /* Memory read cycle */ -#define COMEM_DA_MEMWR 0x00000004 /* Memory write cycle */ -#define COMEM_DA_IORD 0x00000002 /* I/O read cycle */ -#define COMEM_DA_IOWR 0x00000002 /* I/O write cycle */ -#define COMEM_DA_CFGRD 0x00000006 /* Configuration read cycle */ -#define COMEM_DA_CFGWR 0x00000006 /* Configuration write cycle */ - -#define COMEM_DA_ADDR(a) ((a) & 0xffffe000) - -#define COMEM_DA_OFFSET(a) ((a) & 0x00001fff) - - -/* - * The PCI bus will be limited in what slots will actually be used. - * Define valid device numbers for different boards. - */ -#if defined(CONFIG_M5407C3) -#define COMEM_MINDEV 14 /* Minimum valid DEVICE */ -#define COMEM_MAXDEV 14 /* Maximum valid DEVICE */ -#define COMEM_BRIDGEDEV 15 /* Slot bridge is in */ -#else -#define COMEM_MINDEV 0 /* Minimum valid DEVICE */ -#define COMEM_MAXDEV 3 /* Maximum valid DEVICE */ -#endif - -#define COMEM_MAXPCI (COMEM_MAXDEV+1) /* Maximum PCI devices */ - - -/****************************************************************************/ -#endif /* anchor_h */ diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h index 65c6be6c818..4eba796c00d 100644 --- a/arch/m68k/include/asm/atomic.h +++ b/arch/m68k/include/asm/atomic.h @@ -55,6 +55,16 @@ static inline int atomic_dec_and_test(atomic_t *v) return c != 0; } +static inline int atomic_dec_and_test_lt(atomic_t *v) +{ + char c; + __asm__ __volatile__( + "subql #1,%1; slt %0" + : "=d" (c), "=m" (*v) + : "m" (*v)); + return c != 0; +} + static inline int atomic_inc_and_test(atomic_t *v) { char c; diff --git a/arch/m68k/include/asm/cacheflush_mm.h b/arch/m68k/include/asm/cacheflush_mm.h index 73de7c89d8e..8104bd87464 100644 --- a/arch/m68k/include/asm/cacheflush_mm.h +++ b/arch/m68k/include/asm/cacheflush_mm.h @@ -2,23 +2,89 @@ #define _M68K_CACHEFLUSH_H #include <linux/mm.h> +#ifdef CONFIG_COLDFIRE +#include <asm/mcfsim.h> +#endif /* cache code */ #define FLUSH_I_AND_D (0x00000808) #define FLUSH_I (0x00000008) +#ifndef ICACHE_MAX_ADDR +#define ICACHE_MAX_ADDR 0 +#define ICACHE_SET_MASK 0 +#define DCACHE_MAX_ADDR 0 +#define DCACHE_SETMASK 0 +#endif + +static inline void flush_cf_icache(unsigned long start, unsigned long end) +{ + unsigned long set; + + for (set = start; set <= end; set += (0x10 - 3)) { + __asm__ __volatile__ ( + "cpushl %%ic,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%ic,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%ic,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%ic,(%0)" + : "=a" (set) + : "a" (set)); + } +} + +static inline void flush_cf_dcache(unsigned long start, unsigned long end) +{ + unsigned long set; + + for (set = start; set <= end; set += (0x10 - 3)) { + __asm__ __volatile__ ( + "cpushl %%dc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%dc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%dc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%dc,(%0)" + : "=a" (set) + : "a" (set)); + } +} + +static inline void flush_cf_bcache(unsigned long start, unsigned long end) +{ + unsigned long set; + + for (set = start; set <= end; set += (0x10 - 3)) { + __asm__ __volatile__ ( + "cpushl %%bc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%bc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%bc,(%0)\n\t" + "addq%.l #1,%0\n\t" + "cpushl %%bc,(%0)" + : "=a" (set) + : "a" (set)); + } +} + /* * Cache handling functions */ static inline void flush_icache(void) { - if (CPU_IS_040_OR_060) + if (CPU_IS_COLDFIRE) { + flush_cf_icache(0, ICACHE_MAX_ADDR); + } else if (CPU_IS_040_OR_060) { asm volatile ( "nop\n" " .chip 68040\n" " cpusha %bc\n" " .chip 68k"); - else { + } else { unsigned long tmp; asm volatile ( "movec %%cacr,%0\n" " or.w %1,%0\n" @@ -51,12 +117,14 @@ extern void cache_push_v(unsigned long vaddr, int len); process changes. */ #define __flush_cache_all() \ ({ \ - if (CPU_IS_040_OR_060) \ + if (CPU_IS_COLDFIRE) { \ + flush_cf_dcache(0, DCACHE_MAX_ADDR); \ + } else if (CPU_IS_040_OR_060) { \ __asm__ __volatile__("nop\n\t" \ ".chip 68040\n\t" \ "cpusha %dc\n\t" \ ".chip 68k"); \ - else { \ + } else { \ unsigned long _tmp; \ __asm__ __volatile__("movec %%cacr,%0\n\t" \ "orw %1,%0\n\t" \ @@ -112,7 +180,17 @@ static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vm /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */ static inline void __flush_page_to_ram(void *vaddr) { - if (CPU_IS_040_OR_060) { + if (CPU_IS_COLDFIRE) { + unsigned long addr, start, end; + addr = ((unsigned long) vaddr) & ~(PAGE_SIZE - 1); + start = addr & ICACHE_SET_MASK; + end = (addr + PAGE_SIZE - 1) & ICACHE_SET_MASK; + if (start > end) { + flush_cf_bcache(0, end); + end = ICACHE_MAX_ADDR; + } + flush_cf_bcache(start, end); + } else if (CPU_IS_040_OR_060) { __asm__ __volatile__("nop\n\t" ".chip 68040\n\t" "cpushp %%bc,(%0)\n\t" diff --git a/arch/m68k/include/asm/checksum.h b/arch/m68k/include/asm/checksum.h index ec514485c8b..2f88d867c71 100644 --- a/arch/m68k/include/asm/checksum.h +++ b/arch/m68k/include/asm/checksum.h @@ -3,6 +3,10 @@ #include <linux/in6.h> +#ifdef CONFIG_GENERIC_CSUM +#include <asm-generic/checksum.h> +#else + /* * computes the checksum of a memory block at buff, length len, * and adds in "sum" (32-bit) @@ -34,30 +38,6 @@ extern __wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); - -#ifdef CONFIG_COLDFIRE - -/* - * The ColdFire cores don't support all the 68k instructions used - * in the optimized checksum code below. So it reverts back to using - * more standard C coded checksums. The fast checksum code is - * significantly larger than the optimized version, so it is not - * inlined here. - */ -__sum16 ip_fast_csum(const void *iph, unsigned int ihl); - -static inline __sum16 csum_fold(__wsum sum) -{ - unsigned int tmp = (__force u32)sum; - - tmp = (tmp & 0xffff) + (tmp >> 16); - tmp = (tmp & 0xffff) + (tmp >> 16); - - return (__force __sum16)~tmp; -} - -#else - /* * This is a version of ip_fast_csum() optimized for IP headers, * which always checksum on 4 octet boundaries. @@ -97,8 +77,6 @@ static inline __sum16 csum_fold(__wsum sum) return (__force __sum16)~sum; } -#endif /* CONFIG_COLDFIRE */ - static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) @@ -167,4 +145,5 @@ csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, return csum_fold(sum); } +#endif /* CONFIG_GENERIC_CSUM */ #endif /* _M68K_CHECKSUM_H */ diff --git a/arch/m68k/include/asm/div64.h b/arch/m68k/include/asm/div64.h index edb66148a71..444ea8a09e9 100644 --- a/arch/m68k/include/asm/div64.h +++ b/arch/m68k/include/asm/div64.h @@ -1,7 +1,9 @@ #ifndef _M68K_DIV64_H #define _M68K_DIV64_H -#ifdef CONFIG_MMU +#ifdef CONFIG_CPU_HAS_NO_MULDIV64 +#include <asm-generic/div64.h> +#else #include <linux/types.h> @@ -27,8 +29,6 @@ __rem; \ }) -#else -#include <asm-generic/div64.h> -#endif /* CONFIG_MMU */ +#endif /* CONFIG_CPU_HAS_NO_MULDIV64 */ #endif /* _M68K_DIV64_H */ diff --git a/arch/m68k/include/asm/elf.h b/arch/m68k/include/asm/elf.h index 01c193d9141..e9b7cda5974 100644 --- a/arch/m68k/include/asm/elf.h +++ b/arch/m68k/include/asm/elf.h @@ -59,10 +59,10 @@ typedef struct user_m68kfp_struct elf_fpregset_t; is actually used on ASV. */ #define ELF_PLAT_INIT(_r, load_addr) _r->a1 = 0 -#ifndef CONFIG_SUN3 -#define ELF_EXEC_PAGESIZE 4096 -#else +#if defined(CONFIG_SUN3) || defined(CONFIG_COLDFIRE) #define ELF_EXEC_PAGESIZE 8192 +#else +#define ELF_EXEC_PAGESIZE 4096 #endif /* This is the location that an ET_DYN program is loaded if exec'ed. Typical diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h index c3c5a8643e1..622138dc728 100644 --- a/arch/m68k/include/asm/entry.h +++ b/arch/m68k/include/asm/entry.h @@ -222,16 +222,24 @@ * Non-MMU systems do not reserve %a2 in this way, and this definition is * not used for them. */ +#ifdef CONFIG_MMU + #define curptr a2 #define GET_CURRENT(tmp) get_current tmp .macro get_current reg=%d0 movel %sp,\reg - andw #-THREAD_SIZE,\reg + andl #-THREAD_SIZE,\reg movel \reg,%curptr movel %curptr@,%curptr .endm +#else + +#define GET_CURRENT(tmp) + +#endif /* CONFIG_MMU */ + #else /* C source */ #define STR(X) STR1(X) diff --git a/arch/m68k/include/asm/fpu.h b/arch/m68k/include/asm/fpu.h index ffb6b8cfc6d..526db9da9e4 100644 --- a/arch/m68k/include/asm/fpu.h +++ b/arch/m68k/include/asm/fpu.h @@ -12,6 +12,8 @@ #define FPSTATESIZE (96) #elif defined(CONFIG_M68KFPU_EMU) #define FPSTATESIZE (28) +#elif defined(CONFIG_COLDFIRE) && defined(CONFIG_MMU) +#define FPSTATESIZE (16) #elif defined(CONFIG_M68060) #define FPSTATESIZE (12) #else diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h index b2046839f4b..00d0071de4c 100644 --- a/arch/m68k/include/asm/gpio.h +++ b/arch/m68k/include/asm/gpio.h @@ -225,7 +225,8 @@ static inline void gpio_set_value(unsigned gpio, int value) static inline int gpio_to_irq(unsigned gpio) { - return (gpio < MCFGPIO_IRQ_MAX) ? gpio + MCFGPIO_IRQ_VECBASE : -EINVAL; + return (gpio < MCFGPIO_IRQ_MAX) ? gpio + MCFGPIO_IRQ_VECBASE + : __gpio_to_irq(gpio); } static inline int irq_to_gpio(unsigned irq) diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h index 6198df5ff24..0e89fa05de0 100644 --- a/arch/m68k/include/asm/irq.h +++ b/arch/m68k/include/asm/irq.h @@ -25,7 +25,8 @@ #define NR_IRQS 0 #endif -#ifdef CONFIG_MMU +#if defined(CONFIG_M68020) || defined(CONFIG_M68030) || \ + defined(CONFIG_M68040) || defined(CONFIG_M68060) /* * Interrupt source definitions @@ -80,7 +81,7 @@ extern unsigned int irq_canonicalize(unsigned int irq); #else #define irq_canonicalize(irq) (irq) -#endif /* CONFIG_MMU */ +#endif /* !(CONFIG_M68020 || CONFIG_M68030 || CONFIG_M68040 || CONFIG_M68060) */ asmlinkage void do_IRQ(int irq, struct pt_regs *regs); extern atomic_t irq_err_count; diff --git a/arch/m68k/include/asm/m54xxacr.h b/arch/m68k/include/asm/m54xxacr.h index 16a1835f9b2..47906aafbf6 100644 --- a/arch/m68k/include/asm/m54xxacr.h +++ b/arch/m68k/include/asm/m54xxacr.h @@ -39,8 +39,12 @@ #define ACR_CM_OFF_PRE 0x00000040 /* No cache, precise */ #define ACR_CM_OFF_IMP 0x00000060 /* No cache, imprecise */ #define ACR_CM 0x00000060 /* Cache mode mask */ +#define ACR_SP 0x00000008 /* Supervisor protect */ #define ACR_WPROTECT 0x00000004 /* Write protect */ +#define ACR_BA(x) ((x) & 0xff000000) +#define ACR_ADMSK(x) ((((x) - 1) & 0xff000000) >> 8) + #if defined(CONFIG_M5407) #define ICACHE_SIZE 0x4000 /* instruction - 16k */ @@ -56,6 +60,11 @@ #define CACHE_LINE_SIZE 0x0010 /* 16 bytes */ #define CACHE_WAYS 4 /* 4 ways */ +#define ICACHE_SET_MASK ((ICACHE_SIZE / 64 - 1) << CACHE_WAYS) +#define DCACHE_SET_MASK ((DCACHE_SIZE / 64 - 1) << CACHE_WAYS) +#define ICACHE_MAX_ADDR ICACHE_SET_MASK +#define DCACHE_MAX_ADDR DCACHE_SET_MASK + /* * Version 4 cores have a true harvard style separate instruction * and data cache. Enable data and instruction caches, also enable write @@ -73,6 +82,27 @@ #else #define CACHE_MODE (CACR_DEC+CACR_DESB+CACR_DDCM_P+CACR_BEC+CACR_IEC+CACR_EUSP) #endif +#define CACHE_INIT (CACR_DCINVA+CACR_BCINVA+CACR_ICINVA) + +#if defined(CONFIG_MMU) +/* + * If running with the MMU enabled then we need to map the internal + * register region as non-cacheable. And then we map all our RAM as + * cacheable and supervisor access only. + */ +#define ACR0_MODE (ACR_BA(CONFIG_MBAR)+ACR_ADMSK(0x1000000)+ \ + ACR_ENABLE+ACR_SUPER+ACR_CM_OFF_PRE+ACR_SP) +#define ACR1_MODE (ACR_BA(CONFIG_RAMBASE)+ACR_ADMSK(CONFIG_RAMSIZE)+ \ + ACR_ENABLE+ACR_SUPER+ACR_SP) +#define ACR2_MODE 0 +#define ACR3_MODE (ACR_BA(CONFIG_RAMBASE)+ACR_ADMSK(CONFIG_RAMSIZE)+ \ + ACR_ENABLE+ACR_SUPER+ACR_SP) + +#else + +/* + * For the non-MMU enabled case we map all of RAM as cacheable. + */ #if defined(CONFIG_CACHE_COPYBACK) #define DATA_CACHE_MODE (ACR_ENABLE+ACR_ANY+ACR_CM_CP) #else @@ -80,7 +110,6 @@ #endif #define INSN_CACHE_MODE (ACR_ENABLE+ACR_ANY) -#define CACHE_INIT (CACR_DCINVA+CACR_BCINVA+CACR_ICINVA) #define CACHE_INVALIDATE (CACHE_MODE+CACR_DCINVA+CACR_BCINVA+CACR_ICINVA) #define CACHE_INVALIDATEI (CACHE_MODE+CACR_BCINVA+CACR_ICINVA) #define CACHE_INVALIDATED (CACHE_MODE+CACR_DCINVA) @@ -94,4 +123,5 @@ #define CACHE_PUSH #endif +#endif /* CONFIG_MMU */ #endif /* m54xxacr_h */ diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h new file mode 100644 index 00000000000..313f3dd23cd --- /dev/null +++ b/arch/m68k/include/asm/mcf_pgalloc.h @@ -0,0 +1,102 @@ +#ifndef M68K_MCF_PGALLOC_H +#define M68K_MCF_PGALLOC_H + +#include <asm/tlb.h> +#include <asm/tlbflush.h> + +extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + free_page((unsigned long) pte); +} + +extern const char bad_pmd_string[]; + +extern inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, + unsigned long address) +{ + unsigned long page = __get_free_page(GFP_DMA|__GFP_REPEAT); + + if (!page) + return NULL; + + memset((void *)page, 0, PAGE_SIZE); + return (pte_t *) (page); +} + +extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address) +{ + return (pmd_t *) pgd; +} + +#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) +#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) + +#define pte_alloc_one_fast(mm, addr) pte_alloc_one(mm, addr) + +#define pmd_populate(mm, pmd, page) (pmd_val(*pmd) = \ + (unsigned long)(page_address(page))) + +#define pmd_populate_kernel(mm, pmd, pte) (pmd_val(*pmd) = (unsigned long)(pte)) + +#define pmd_pgtable(pmd) pmd_page(pmd) + +static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page, + unsigned long address) +{ + __free_page(page); +} + +#define __pmd_free_tlb(tlb, pmd, address) do { } while (0) + +static inline struct page *pte_alloc_one(struct mm_struct *mm, + unsigned long address) +{ + struct page *page = alloc_pages(GFP_DMA|__GFP_REPEAT, 0); + pte_t *pte; + + if (!page) + return NULL; + + pte = kmap(page); + if (pte) { + clear_page(pte); + __flush_page_to_ram(pte); + flush_tlb_kernel_page(pte); + nocache_page(pte); + } + kunmap(page); + + return page; +} + +extern inline void pte_free(struct mm_struct *mm, struct page *page) +{ + __free_page(page); +} + +/* + * In our implementation, each pgd entry contains 1 pmd that is never allocated + * or freed. pgd_present is always 1, so this should never be called. -NL + */ +#define pmd_free(mm, pmd) BUG() + +static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) +{ + free_page((unsigned long) pgd); +} + +static inline pgd_t *pgd_alloc(struct mm_struct *mm) +{ + pgd_t *new_pgd; + + new_pgd = (pgd_t *)__get_free_page(GFP_DMA | __GFP_NOWARN); + if (!new_pgd) + return NULL; + memcpy(new_pgd, swapper_pg_dir, PAGE_SIZE); + memset(new_pgd, 0, PAGE_OFFSET >> PGDIR_SHIFT); + return new_pgd; +} + +#define pgd_populate(mm, pmd, pte) BUG() + +#endif /* M68K_MCF_PGALLOC_H */ diff --git a/arch/m68k/include/asm/mcf_pgtable.h b/arch/m68k/include/asm/mcf_pgtable.h new file mode 100644 index 00000000000..756bde4fb4f --- /dev/null +++ b/arch/m68k/include/asm/mcf_pgtable.h @@ -0,0 +1,425 @@ +#ifndef _MCF_PGTABLE_H +#define _MCF_PGTABLE_H + +#include <asm/mcfmmu.h> +#include <asm/page.h> + +/* + * MMUDR bits, in proper place. We write these directly into the MMUDR + * after masking from the pte. + */ +#define CF_PAGE_LOCKED MMUDR_LK /* 0x00000002 */ +#define CF_PAGE_EXEC MMUDR_X /* 0x00000004 */ +#define CF_PAGE_WRITABLE MMUDR_W /* 0x00000008 */ +#define CF_PAGE_READABLE MMUDR_R /* 0x00000010 */ +#define CF_PAGE_SYSTEM MMUDR_SP /* 0x00000020 */ +#define CF_PAGE_COPYBACK MMUDR_CM_CCB /* 0x00000040 */ +#define CF_PAGE_NOCACHE MMUDR_CM_NCP /* 0x00000080 */ + +#define CF_CACHEMASK (~MMUDR_CM_CCB) +#define CF_PAGE_MMUDR_MASK 0x000000fe + +#define _PAGE_NOCACHE030 CF_PAGE_NOCACHE + +/* + * MMUTR bits, need shifting down. + */ +#define CF_PAGE_MMUTR_MASK 0x00000c00 +#define CF_PAGE_MMUTR_SHIFT 10 + +#define CF_PAGE_VALID (MMUTR_V << CF_PAGE_MMUTR_SHIFT) +#define CF_PAGE_SHARED (MMUTR_SG << CF_PAGE_MMUTR_SHIFT) + +/* + * Fake bits, not implemented in CF, will get masked out before + * hitting hardware. + */ +#define CF_PAGE_DIRTY 0x00000001 +#define CF_PAGE_FILE 0x00000200 +#define CF_PAGE_ACCESSED 0x00001000 + +#define _PAGE_CACHE040 0x020 /* 68040 cache mode, cachable, copyback */ +#define _PAGE_NOCACHE_S 0x040 /* 68040 no-cache mode, serialized */ +#define _PAGE_NOCACHE 0x060 /* 68040 cache mode, non-serialized */ +#define _PAGE_CACHE040W 0x000 /* 68040 cache mode, cachable, write-through */ +#define _DESCTYPE_MASK 0x003 +#define _CACHEMASK040 (~0x060) +#define _PAGE_GLOBAL040 0x400 /* 68040 global bit, used for kva descs */ + +/* + * Externally used page protection values. + */ +#define _PAGE_PRESENT (CF_PAGE_VALID) +#define _PAGE_ACCESSED (CF_PAGE_ACCESSED) +#define _PAGE_DIRTY (CF_PAGE_DIRTY) +#define _PAGE_READWRITE (CF_PAGE_READABLE \ + | CF_PAGE_WRITABLE \ + | CF_PAGE_SYSTEM \ + | CF_PAGE_SHARED) + +/* + * Compound page protection values. + */ +#define PAGE_NONE __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED) + +#define PAGE_SHARED __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_SHARED) + +#define PAGE_INIT __pgprot(CF_PAGE_VALID \ + | CF_PAGE_READABLE \ + | CF_PAGE_WRITABLE \ + | CF_PAGE_EXEC \ + | CF_PAGE_SYSTEM) + +#define PAGE_KERNEL __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_WRITABLE \ + | CF_PAGE_EXEC \ + | CF_PAGE_SYSTEM) + +#define PAGE_COPY __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_DIRTY) + +/* + * Page protections for initialising protection_map. See mm/mmap.c + * for use. In general, the bit positions are xwr, and P-items are + * private, the S-items are shared. + */ +#define __P000 PAGE_NONE +#define __P001 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE) +#define __P010 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_WRITABLE) +#define __P011 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_WRITABLE) +#define __P100 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_EXEC) +#define __P101 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_EXEC) +#define __P110 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_WRITABLE \ + | CF_PAGE_EXEC) +#define __P111 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_WRITABLE \ + | CF_PAGE_EXEC) + +#define __S000 PAGE_NONE +#define __S001 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE) +#define __S010 PAGE_SHARED +#define __S011 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_SHARED \ + | CF_PAGE_READABLE) +#define __S100 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_EXEC) +#define __S101 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_READABLE \ + | CF_PAGE_EXEC) +#define __S110 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_SHARED \ + | CF_PAGE_EXEC) +#define __S111 __pgprot(CF_PAGE_VALID \ + | CF_PAGE_ACCESSED \ + | CF_PAGE_SHARED \ + | CF_PAGE_READABLE \ + | CF_PAGE_EXEC) + +#define PTE_MASK PAGE_MASK +#define CF_PAGE_CHG_MASK (PTE_MASK | CF_PAGE_ACCESSED | CF_PAGE_DIRTY) + +#ifndef __ASSEMBLY__ + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte_val(pte) = (pte_val(pte) & CF_PAGE_CHG_MASK) | pgprot_val(newprot); + return pte; +} + +#define pmd_set(pmdp, ptep) do {} while (0) + +static inline void pgd_set(pgd_t *pgdp, pmd_t *pmdp) +{ + pgd_val(*pgdp) = virt_to_phys(pmdp); +} + +#define __pte_page(pte) ((unsigned long) (pte_val(pte) & PAGE_MASK)) +#define __pmd_page(pmd) ((unsigned long) (pmd_val(pmd))) + +static inline int pte_none(pte_t pte) +{ + return !pte_val(pte); +} + +static inline int pte_present(pte_t pte) +{ + return pte_val(pte) & CF_PAGE_VALID; +} + +static inline void pte_clear(struct mm_struct *mm, unsigned long addr, + pte_t *ptep) +{ + pte_val(*ptep) = 0; +} + +#define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT) |