Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

microblaze_mmu_v2: pgalloc.h and page.h

Signed-off-by: Michal Simek <monstr@monstr.eu>

+314 -43
+123 -43
arch/microblaze/include/asm/page.h
··· 1 1 /* 2 - * Copyright (C) 2008 Michal Simek 3 - * Copyright (C) 2008 PetaLogix 2 + * VM ops 3 + * 4 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 5 + * Copyright (C) 2008-2009 PetaLogix 4 6 * Copyright (C) 2006 Atmark Techno, Inc. 5 7 * Changes for MMU support: 6 8 * Copyright (C) 2007 Xilinx, Inc. All rights reserved. ··· 17 15 18 16 #include <linux/pfn.h> 19 17 #include <asm/setup.h> 18 + #include <linux/const.h> 19 + 20 + #ifdef __KERNEL__ 20 21 21 22 /* PAGE_SHIFT determines the page size */ 22 23 #define PAGE_SHIFT (12) 23 - #define PAGE_SIZE (1UL << PAGE_SHIFT) 24 + #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 24 25 #define PAGE_MASK (~(PAGE_SIZE-1)) 25 - 26 - #ifdef __KERNEL__ 27 26 28 27 #ifndef __ASSEMBLY__ 29 28 ··· 38 35 /* align addr on a size boundary - adjust address up if needed */ 39 36 #define _ALIGN(addr, size) _ALIGN_UP(addr, size) 40 37 38 + #ifndef CONFIG_MMU 41 39 /* 42 40 * PAGE_OFFSET -- the first address of the first page of memory. When not 43 41 * using MMU this corresponds to the first free page in physical memory (aligned ··· 47 43 extern unsigned int __page_offset; 48 44 #define PAGE_OFFSET __page_offset 49 45 50 - #define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) 51 - #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) 52 - #define free_user_page(page, addr) free_page(addr) 46 + #else /* CONFIG_MMU */ 53 47 54 - #define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE) 48 + /* 49 + * PAGE_OFFSET -- the first address of the first page of memory. With MMU 50 + * it is set to the kernel start address (aligned on a page boundary). 51 + * 52 + * CONFIG_KERNEL_START is defined in arch/microblaze/config.in and used 53 + * in arch/microblaze/Makefile. 54 + */ 55 + #define PAGE_OFFSET CONFIG_KERNEL_START 55 56 57 + /* 58 + * MAP_NR -- given an address, calculate the index of the page struct which 59 + * points to the address's page. 60 + */ 61 + #define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT) 56 62 57 - #define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE) 58 - #define copy_user_page(vto, vfrom, vaddr, topg) \ 63 + /* 64 + * The basic type of a PTE - 32 bit physical addressing. 65 + */ 66 + typedef unsigned long pte_basic_t; 67 + #define PTE_SHIFT (PAGE_SHIFT - 2) /* 1024 ptes per page */ 68 + #define PTE_FMT "%.8lx" 69 + 70 + #endif /* CONFIG_MMU */ 71 + 72 + # ifndef CONFIG_MMU 73 + # define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) 74 + # define get_user_page(vaddr) __get_free_page(GFP_KERNEL) 75 + # define free_user_page(page, addr) free_page(addr) 76 + # else /* CONFIG_MMU */ 77 + extern void copy_page(void *to, void *from); 78 + # endif /* CONFIG_MMU */ 79 + 80 + # define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE) 81 + 82 + # define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE) 83 + # define copy_user_page(vto, vfrom, vaddr, topg) \ 59 84 memcpy((vto), (vfrom), PAGE_SIZE) 60 85 61 86 /* ··· 93 60 typedef struct page *pgtable_t; 94 61 typedef struct { unsigned long pte; } pte_t; 95 62 typedef struct { unsigned long pgprot; } pgprot_t; 63 + /* FIXME this can depend on linux kernel version */ 64 + # ifdef CONFIG_MMU 65 + typedef struct { unsigned long pmd; } pmd_t; 66 + typedef struct { unsigned long pgd; } pgd_t; 67 + # else /* CONFIG_MMU */ 96 68 typedef struct { unsigned long ste[64]; } pmd_t; 97 69 typedef struct { pmd_t pue[1]; } pud_t; 98 70 typedef struct { pud_t pge[1]; } pgd_t; 71 + # endif /* CONFIG_MMU */ 99 72 73 + # define pte_val(x) ((x).pte) 74 + # define pgprot_val(x) ((x).pgprot) 100 75 101 - #define pte_val(x) ((x).pte) 102 - #define pgprot_val(x) ((x).pgprot) 103 - #define pmd_val(x) ((x).ste[0]) 104 - #define pud_val(x) ((x).pue[0]) 105 - #define pgd_val(x) ((x).pge[0]) 76 + # ifdef CONFIG_MMU 77 + # define pmd_val(x) ((x).pmd) 78 + # define pgd_val(x) ((x).pgd) 79 + # else /* CONFIG_MMU */ 80 + # define pmd_val(x) ((x).ste[0]) 81 + # define pud_val(x) ((x).pue[0]) 82 + # define pgd_val(x) ((x).pge[0]) 83 + # endif /* CONFIG_MMU */ 106 84 107 - #define __pte(x) ((pte_t) { (x) }) 108 - #define __pmd(x) ((pmd_t) { (x) }) 109 - #define __pgd(x) ((pgd_t) { (x) }) 110 - #define __pgprot(x) ((pgprot_t) { (x) }) 85 + # define __pte(x) ((pte_t) { (x) }) 86 + # define __pmd(x) ((pmd_t) { (x) }) 87 + # define __pgd(x) ((pgd_t) { (x) }) 88 + # define __pgprot(x) ((pgprot_t) { (x) }) 111 89 112 90 /** 113 91 * Conversions for virtual address, physical address, pfn, and struct ··· 138 94 extern unsigned long min_low_pfn; 139 95 extern unsigned long max_pfn; 140 96 141 - #define __pa(vaddr) ((unsigned long) (vaddr)) 142 - #define __va(paddr) ((void *) (paddr)) 97 + extern unsigned long memory_start; 98 + extern unsigned long memory_end; 99 + extern unsigned long memory_size; 143 100 144 - #define phys_to_pfn(phys) (PFN_DOWN(phys)) 145 - #define pfn_to_phys(pfn) (PFN_PHYS(pfn)) 101 + extern int page_is_ram(unsigned long pfn); 146 102 147 - #define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) 148 - #define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) 103 + # define phys_to_pfn(phys) (PFN_DOWN(phys)) 104 + # define pfn_to_phys(pfn) (PFN_PHYS(pfn)) 149 105 150 - #define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr))) 151 - #define page_to_virt(page) (pfn_to_virt(page_to_pfn(page))) 106 + # define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) 107 + # define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) 152 108 153 - #define page_to_phys(page) (pfn_to_phys(page_to_pfn(page))) 154 - #define page_to_bus(page) (page_to_phys(page)) 155 - #define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr))) 109 + # ifdef CONFIG_MMU 110 + # define virt_to_page(kaddr) (mem_map + MAP_NR(kaddr)) 111 + # else /* CONFIG_MMU */ 112 + # define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr))) 113 + # define page_to_virt(page) (pfn_to_virt(page_to_pfn(page))) 114 + # define page_to_phys(page) (pfn_to_phys(page_to_pfn(page))) 115 + # define page_to_bus(page) (page_to_phys(page)) 116 + # define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr))) 117 + # endif /* CONFIG_MMU */ 156 118 157 - extern unsigned int memory_start; 158 - extern unsigned int memory_end; 159 - extern unsigned int memory_size; 119 + # ifndef CONFIG_MMU 120 + # define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) <= max_mapnr) 121 + # define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) 122 + # else /* CONFIG_MMU */ 123 + # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) 124 + # define pfn_valid(pfn) ((pfn) < (max_mapnr + ARCH_PFN_OFFSET)) 125 + # define VALID_PAGE(page) ((page - mem_map) < max_mapnr) 126 + # endif /* CONFIG_MMU */ 160 127 161 - #define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_mapnr) 128 + # endif /* __ASSEMBLY__ */ 162 129 163 - #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) 130 + #define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) 164 131 165 - #else 166 - #define tophys(rd, rs) (addik rd, rs, 0) 167 - #define tovirt(rd, rs) (addik rd, rs, 0) 168 - #endif /* __ASSEMBLY__ */ 169 132 170 - #define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) 133 + # ifndef CONFIG_MMU 134 + # define __pa(vaddr) ((unsigned long) (vaddr)) 135 + # define __va(paddr) ((void *) (paddr)) 136 + # else /* CONFIG_MMU */ 137 + # define __pa(x) __virt_to_phys((unsigned long)(x)) 138 + # define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) 139 + # endif /* CONFIG_MMU */ 171 140 172 - /* Convert between virtual and physical address for MMU. */ 173 - /* Handle MicroBlaze processor with virtual memory. */ 141 + 142 + /* Convert between virtual and physical address for MMU. */ 143 + /* Handle MicroBlaze processor with virtual memory. */ 144 + #ifndef CONFIG_MMU 174 145 #define __virt_to_phys(addr) addr 175 146 #define __phys_to_virt(addr) addr 147 + #define tophys(rd, rs) addik rd, rs, 0 148 + #define tovirt(rd, rs) addik rd, rs, 0 149 + #else 150 + #define __virt_to_phys(addr) \ 151 + ((addr) + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START) 152 + #define __phys_to_virt(addr) \ 153 + ((addr) + CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR) 154 + #define tophys(rd, rs) \ 155 + addik rd, rs, (CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START) 156 + #define tovirt(rd, rs) \ 157 + addik rd, rs, (CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR) 158 + #endif /* CONFIG_MMU */ 176 159 177 160 #define TOPHYS(addr) __virt_to_phys(addr) 161 + 162 + #ifdef CONFIG_MMU 163 + #ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC 164 + #define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */ 165 + #endif 166 + 167 + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 168 + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 169 + #endif /* CONFIG_MMU */ 178 170 179 171 #endif /* __KERNEL__ */ 180 172
+191
arch/microblaze/include/asm/pgalloc.h
··· 1 1 /* 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 2 4 * Copyright (C) 2006 Atmark Techno, Inc. 3 5 * 4 6 * This file is subject to the terms and conditions of the GNU General Public ··· 10 8 11 9 #ifndef _ASM_MICROBLAZE_PGALLOC_H 12 10 #define _ASM_MICROBLAZE_PGALLOC_H 11 + 12 + #ifdef CONFIG_MMU 13 + 14 + #include <linux/kernel.h> /* For min/max macros */ 15 + #include <linux/highmem.h> 16 + #include <asm/setup.h> 17 + #include <asm/io.h> 18 + #include <asm/page.h> 19 + #include <asm/cache.h> 20 + 21 + #define PGDIR_ORDER 0 22 + 23 + /* 24 + * This is handled very differently on MicroBlaze since out page tables 25 + * are all 0's and I want to be able to use these zero'd pages elsewhere 26 + * as well - it gives us quite a speedup. 27 + * -- Cort 28 + */ 29 + extern struct pgtable_cache_struct { 30 + unsigned long *pgd_cache; 31 + unsigned long *pte_cache; 32 + unsigned long pgtable_cache_sz; 33 + } quicklists; 34 + 35 + #define pgd_quicklist (quicklists.pgd_cache) 36 + #define pmd_quicklist ((unsigned long *)0) 37 + #define pte_quicklist (quicklists.pte_cache) 38 + #define pgtable_cache_size (quicklists.pgtable_cache_sz) 39 + 40 + extern unsigned long *zero_cache; /* head linked list of pre-zero'd pages */ 41 + extern atomic_t zero_sz; /* # currently pre-zero'd pages */ 42 + extern atomic_t zeropage_hits; /* # zero'd pages request that we've done */ 43 + extern atomic_t zeropage_calls; /* # zero'd pages request that've been made */ 44 + extern atomic_t zerototal; /* # pages zero'd over time */ 45 + 46 + #define zero_quicklist (zero_cache) 47 + #define zero_cache_sz (zero_sz) 48 + #define zero_cache_calls (zeropage_calls) 49 + #define zero_cache_hits (zeropage_hits) 50 + #define zero_cache_total (zerototal) 51 + 52 + /* 53 + * return a pre-zero'd page from the list, 54 + * return NULL if none available -- Cort 55 + */ 56 + extern unsigned long get_zero_page_fast(void); 57 + 58 + extern void __bad_pte(pmd_t *pmd); 59 + 60 + extern inline pgd_t *get_pgd_slow(void) 61 + { 62 + pgd_t *ret; 63 + 64 + ret = (pgd_t *)__get_free_pages(GFP_KERNEL, PGDIR_ORDER); 65 + if (ret != NULL) 66 + clear_page(ret); 67 + return ret; 68 + } 69 + 70 + extern inline pgd_t *get_pgd_fast(void) 71 + { 72 + unsigned long *ret; 73 + 74 + ret = pgd_quicklist; 75 + if (ret != NULL) { 76 + pgd_quicklist = (unsigned long *)(*ret); 77 + ret[0] = 0; 78 + pgtable_cache_size--; 79 + } else 80 + ret = (unsigned long *)get_pgd_slow(); 81 + return (pgd_t *)ret; 82 + } 83 + 84 + extern inline void free_pgd_fast(pgd_t *pgd) 85 + { 86 + *(unsigned long **)pgd = pgd_quicklist; 87 + pgd_quicklist = (unsigned long *) pgd; 88 + pgtable_cache_size++; 89 + } 90 + 91 + extern inline void free_pgd_slow(pgd_t *pgd) 92 + { 93 + free_page((unsigned long)pgd); 94 + } 95 + 96 + #define pgd_free(mm, pgd) free_pgd_fast(pgd) 97 + #define pgd_alloc(mm) get_pgd_fast() 98 + 99 + #define pmd_pgtable(pmd) pmd_page(pmd) 100 + 101 + /* 102 + * We don't have any real pmd's, and this code never triggers because 103 + * the pgd will always be present.. 104 + */ 105 + #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) 106 + #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) 107 + /* FIXME two definition - look below */ 108 + #define pmd_free(mm, x) do { } while (0) 109 + #define pgd_populate(mm, pmd, pte) BUG() 110 + 111 + static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, 112 + unsigned long address) 113 + { 114 + pte_t *pte; 115 + extern int mem_init_done; 116 + extern void *early_get_page(void); 117 + if (mem_init_done) { 118 + pte = (pte_t *)__get_free_page(GFP_KERNEL | 119 + __GFP_REPEAT | __GFP_ZERO); 120 + } else { 121 + pte = (pte_t *)early_get_page(); 122 + if (pte) 123 + clear_page(pte); 124 + } 125 + return pte; 126 + } 127 + 128 + static inline struct page *pte_alloc_one(struct mm_struct *mm, 129 + unsigned long address) 130 + { 131 + struct page *ptepage; 132 + 133 + #ifdef CONFIG_HIGHPTE 134 + int flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT; 135 + #else 136 + int flags = GFP_KERNEL | __GFP_REPEAT; 137 + #endif 138 + 139 + ptepage = alloc_pages(flags, 0); 140 + if (ptepage) 141 + clear_highpage(ptepage); 142 + return ptepage; 143 + } 144 + 145 + static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, 146 + unsigned long address) 147 + { 148 + unsigned long *ret; 149 + 150 + ret = pte_quicklist; 151 + if (ret != NULL) { 152 + pte_quicklist = (unsigned long *)(*ret); 153 + ret[0] = 0; 154 + pgtable_cache_size--; 155 + } 156 + return (pte_t *)ret; 157 + } 158 + 159 + extern inline void pte_free_fast(pte_t *pte) 160 + { 161 + *(unsigned long **)pte = pte_quicklist; 162 + pte_quicklist = (unsigned long *) pte; 163 + pgtable_cache_size++; 164 + } 165 + 166 + extern inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 167 + { 168 + free_page((unsigned long)pte); 169 + } 170 + 171 + extern inline void pte_free_slow(struct page *ptepage) 172 + { 173 + __free_page(ptepage); 174 + } 175 + 176 + extern inline void pte_free(struct mm_struct *mm, struct page *ptepage) 177 + { 178 + __free_page(ptepage); 179 + } 180 + 181 + #define __pte_free_tlb(tlb, pte) pte_free((tlb)->mm, (pte)) 182 + 183 + #define pmd_populate(mm, pmd, pte) (pmd_val(*(pmd)) = page_address(pte)) 184 + 185 + #define pmd_populate_kernel(mm, pmd, pte) \ 186 + (pmd_val(*(pmd)) = (unsigned long) (pte)) 187 + 188 + /* 189 + * We don't have any real pmd's, and this code never triggers because 190 + * the pgd will always be present.. 191 + */ 192 + #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) 193 + /*#define pmd_free(mm, x) do { } while (0)*/ 194 + #define __pmd_free_tlb(tlb, x) do { } while (0) 195 + #define pgd_populate(mm, pmd, pte) BUG() 196 + 197 + extern int do_check_pgt_cache(int, int); 198 + 199 + #endif /* CONFIG_MMU */ 13 200 14 201 #define check_pgt_cache() do {} while (0) 15 202