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

OpenRISC: Memory management

Signed-off-by: Jonas Bonn <jonas@southpole.se>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>

+2279
+29
arch/openrisc/include/asm/cache.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_CACHE_H 20 + #define __ASM_OPENRISC_CACHE_H 21 + 22 + /* FIXME: How can we replace these with values from the CPU... 23 + * they shouldn't be hard-coded! 24 + */ 25 + 26 + #define L1_CACHE_BYTES 16 27 + #define L1_CACHE_SHIFT 4 28 + 29 + #endif /* __ASM_OPENRISC_CACHE_H */
+87
arch/openrisc/include/asm/fixmap.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_FIXMAP_H 20 + #define __ASM_OPENRISC_FIXMAP_H 21 + 22 + /* Why exactly do we need 2 empty pages between the top of the fixed 23 + * addresses and the top of virtual memory? Something is using that 24 + * memory space but not sure what right now... If you find it, leave 25 + * a comment here. 26 + */ 27 + #define FIXADDR_TOP ((unsigned long) (-2*PAGE_SIZE)) 28 + 29 + #include <linux/kernel.h> 30 + #include <asm/page.h> 31 + 32 + /* 33 + * On OpenRISC we use these special fixed_addresses for doing ioremap 34 + * early in the boot process before memory initialization is complete. 35 + * This is used, in particular, by the early serial console code. 36 + * 37 + * It's not really 'fixmap', per se, but fits loosely into the same 38 + * paradigm. 39 + */ 40 + enum fixed_addresses { 41 + /* 42 + * FIX_IOREMAP entries are useful for mapping physical address 43 + * space before ioremap() is useable, e.g. really early in boot 44 + * before kmalloc() is working. 45 + */ 46 + #define FIX_N_IOREMAPS 32 47 + FIX_IOREMAP_BEGIN, 48 + FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1, 49 + __end_of_fixed_addresses 50 + }; 51 + 52 + #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) 53 + /* FIXADDR_BOTTOM might be a better name here... */ 54 + #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) 55 + 56 + #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) 57 + #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) 58 + 59 + /* 60 + * 'index to address' translation. If anyone tries to use the idx 61 + * directly without tranlation, we catch the bug with a NULL-deference 62 + * kernel oops. Illegal ranges of incoming indices are caught too. 63 + */ 64 + static __always_inline unsigned long fix_to_virt(const unsigned int idx) 65 + { 66 + /* 67 + * this branch gets completely eliminated after inlining, 68 + * except when someone tries to use fixaddr indices in an 69 + * illegal way. (such as mixing up address types or using 70 + * out-of-range indices). 71 + * 72 + * If it doesn't get removed, the linker will complain 73 + * loudly with a reasonably clear error message.. 74 + */ 75 + if (idx >= __end_of_fixed_addresses) 76 + BUG(); 77 + 78 + return __fix_to_virt(idx); 79 + } 80 + 81 + static inline unsigned long virt_to_fix(const unsigned long vaddr) 82 + { 83 + BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); 84 + return __virt_to_fix(vaddr); 85 + } 86 + 87 + #endif
+24
arch/openrisc/include/asm/memblock.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_MEMBLOCK_H 20 + #define __ASM_OPENRISC_MEMBLOCK_H 21 + 22 + /* empty */ 23 + 24 + #endif /* __ASM_OPENRISC_MEMBLOCK_H */
+26
arch/openrisc/include/asm/mmu.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_MMU_H 20 + #define __ASM_OPENRISC_MMU_H 21 + 22 + #ifndef __ASSEMBLY__ 23 + typedef unsigned long mm_context_t; 24 + #endif 25 + 26 + #endif
+43
arch/openrisc/include/asm/mmu_context.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_MMU_CONTEXT_H 20 + #define __ASM_OPENRISC_MMU_CONTEXT_H 21 + 22 + #include <asm-generic/mm_hooks.h> 23 + 24 + extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); 25 + extern void destroy_context(struct mm_struct *mm); 26 + extern void switch_mm(struct mm_struct *prev, struct mm_struct *next, 27 + struct task_struct *tsk); 28 + 29 + #define deactivate_mm(tsk, mm) do { } while (0) 30 + 31 + #define activate_mm(prev, next) switch_mm((prev), (next), NULL) 32 + 33 + /* current active pgd - this is similar to other processors pgd 34 + * registers like cr3 on the i386 35 + */ 36 + 37 + extern volatile pgd_t *current_pgd; /* defined in arch/openrisc/mm/fault.c */ 38 + 39 + static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) 40 + { 41 + } 42 + 43 + #endif
+110
arch/openrisc/include/asm/page.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_PAGE_H 20 + #define __ASM_OPENRISC_PAGE_H 21 + 22 + 23 + /* PAGE_SHIFT determines the page size */ 24 + 25 + #define PAGE_SHIFT 13 26 + #ifdef __ASSEMBLY__ 27 + #define PAGE_SIZE (1 << PAGE_SHIFT) 28 + #else 29 + #define PAGE_SIZE (1UL << PAGE_SHIFT) 30 + #endif 31 + #define PAGE_MASK (~(PAGE_SIZE-1)) 32 + 33 + #define PAGE_OFFSET 0xc0000000 34 + #define KERNELBASE PAGE_OFFSET 35 + 36 + /* This is not necessarily the right place for this, but it's needed by 37 + * drivers/of/fdt.c 38 + */ 39 + #include <asm/setup.h> 40 + 41 + #ifndef __ASSEMBLY__ 42 + 43 + #define get_user_page(vaddr) __get_free_page(GFP_KERNEL) 44 + #define free_user_page(page, addr) free_page(addr) 45 + 46 + #define clear_page(page) memset((page), 0, PAGE_SIZE) 47 + #define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) 48 + 49 + #define clear_user_page(page, vaddr, pg) clear_page(page) 50 + #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) 51 + 52 + /* 53 + * These are used to make use of C type-checking.. 54 + */ 55 + typedef struct { 56 + unsigned long pte; 57 + } pte_t; 58 + typedef struct { 59 + unsigned long pgd; 60 + } pgd_t; 61 + typedef struct { 62 + unsigned long pgprot; 63 + } pgprot_t; 64 + typedef struct page *pgtable_t; 65 + 66 + #define pte_val(x) ((x).pte) 67 + #define pgd_val(x) ((x).pgd) 68 + #define pgprot_val(x) ((x).pgprot) 69 + 70 + #define __pte(x) ((pte_t) { (x) }) 71 + #define __pgd(x) ((pgd_t) { (x) }) 72 + #define __pgprot(x) ((pgprot_t) { (x) }) 73 + 74 + extern unsigned long memory_start; 75 + extern unsigned long memory_end; 76 + 77 + #endif /* !__ASSEMBLY__ */ 78 + 79 + 80 + #ifndef __ASSEMBLY__ 81 + 82 + #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) 83 + #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) 84 + 85 + #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) 86 + #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) 87 + 88 + #define virt_to_page(addr) \ 89 + (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) 90 + #define page_to_virt(page) \ 91 + ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) 92 + 93 + #define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) 94 + 95 + #define pfn_valid(pfn) ((pfn) < max_mapnr) 96 + 97 + #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ 98 + ((void *)(kaddr) < (void *)memory_end)) 99 + 100 + #endif /* __ASSEMBLY__ */ 101 + 102 + 103 + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 104 + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 105 + 106 + 107 + #include <asm-generic/memory_model.h> 108 + #include <asm-generic/getorder.h> 109 + 110 + #endif /* __ASM_OPENRISC_PAGE_H */
+102
arch/openrisc/include/asm/pgalloc.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_PGALLOC_H 20 + #define __ASM_OPENRISC_PGALLOC_H 21 + 22 + #include <asm/page.h> 23 + #include <linux/threads.h> 24 + #include <linux/mm.h> 25 + #include <linux/memblock.h> 26 + #include <linux/bootmem.h> 27 + 28 + extern int mem_init_done; 29 + 30 + #define pmd_populate_kernel(mm, pmd, pte) \ 31 + set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte))) 32 + 33 + static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, 34 + struct page *pte) 35 + { 36 + set_pmd(pmd, __pmd(_KERNPG_TABLE + 37 + ((unsigned long)page_to_pfn(pte) << 38 + (unsigned long) PAGE_SHIFT))); 39 + } 40 + 41 + /* 42 + * Allocate and free page tables. 43 + */ 44 + static inline pgd_t *pgd_alloc(struct mm_struct *mm) 45 + { 46 + pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL); 47 + 48 + if (ret) { 49 + memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t)); 50 + memcpy(ret + USER_PTRS_PER_PGD, 51 + swapper_pg_dir + USER_PTRS_PER_PGD, 52 + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 53 + 54 + } 55 + return ret; 56 + } 57 + 58 + #if 0 59 + /* FIXME: This seems to be the preferred style, but we are using 60 + * current_pgd (from mm->pgd) to load kernel pages so we need it 61 + * initialized. This needs to be looked into. 62 + */ 63 + extern inline pgd_t *pgd_alloc(struct mm_struct *mm) 64 + { 65 + return (pgd_t *)get_zeroed_page(GFP_KERNEL); 66 + } 67 + #endif 68 + 69 + static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) 70 + { 71 + free_page((unsigned long)pgd); 72 + } 73 + 74 + extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address); 75 + 76 + static inline struct page *pte_alloc_one(struct mm_struct *mm, 77 + unsigned long address) 78 + { 79 + struct page *pte; 80 + pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); 81 + if (pte) 82 + clear_page(page_address(pte)); 83 + return pte; 84 + } 85 + 86 + static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) 87 + { 88 + free_page((unsigned long)pte); 89 + } 90 + 91 + static inline void pte_free(struct mm_struct *mm, struct page *pte) 92 + { 93 + __free_page(pte); 94 + } 95 + 96 + 97 + #define __pte_free_tlb(tlb, pte, addr) tlb_remove_page((tlb), (pte)) 98 + #define pmd_pgtable(pmd) pmd_page(pmd) 99 + 100 + #define check_pgt_cache() do { } while (0) 101 + 102 + #endif
+463
arch/openrisc/include/asm/pgtable.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + /* or32 pgtable.h - macros and functions to manipulate page tables 20 + * 21 + * Based on: 22 + * include/asm-cris/pgtable.h 23 + */ 24 + 25 + #ifndef __ASM_OPENRISC_PGTABLE_H 26 + #define __ASM_OPENRISC_PGTABLE_H 27 + 28 + #include <asm-generic/pgtable-nopmd.h> 29 + 30 + #ifndef __ASSEMBLY__ 31 + #include <asm/mmu.h> 32 + #include <asm/fixmap.h> 33 + 34 + /* 35 + * The Linux memory management assumes a three-level page table setup. On 36 + * or32, we use that, but "fold" the mid level into the top-level page 37 + * table. Since the MMU TLB is software loaded through an interrupt, it 38 + * supports any page table structure, so we could have used a three-level 39 + * setup, but for the amounts of memory we normally use, a two-level is 40 + * probably more efficient. 41 + * 42 + * This file contains the functions and defines necessary to modify and use 43 + * the or32 page table tree. 44 + */ 45 + 46 + extern void paging_init(void); 47 + 48 + /* Certain architectures need to do special things when pte's 49 + * within a page table are directly modified. Thus, the following 50 + * hook is made available. 51 + */ 52 + #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval)) 53 + #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval) 54 + /* 55 + * (pmds are folded into pgds so this doesn't get actually called, 56 + * but the define is needed for a generic inline function.) 57 + */ 58 + #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) 59 + 60 + #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-2)) 61 + #define PGDIR_SIZE (1UL << PGDIR_SHIFT) 62 + #define PGDIR_MASK (~(PGDIR_SIZE-1)) 63 + 64 + /* 65 + * entries per page directory level: we use a two-level, so 66 + * we don't really have any PMD directory physically. 67 + * pointers are 4 bytes so we can use the page size and 68 + * divide it by 4 (shift by 2). 69 + */ 70 + #define PTRS_PER_PTE (1UL << (PAGE_SHIFT-2)) 71 + 72 + #define PTRS_PER_PGD (1UL << (PAGE_SHIFT-2)) 73 + 74 + /* calculate how many PGD entries a user-level program can use 75 + * the first mappable virtual address is 0 76 + * (TASK_SIZE is the maximum virtual address space) 77 + */ 78 + 79 + #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) 80 + #define FIRST_USER_ADDRESS 0 81 + 82 + /* 83 + * Kernels own virtual memory area. 84 + */ 85 + 86 + /* 87 + * The size and location of the vmalloc area are chosen so that modules 88 + * placed in this area aren't more than a 28-bit signed offset from any 89 + * kernel functions that they may need. This greatly simplifies handling 90 + * of the relocations for l.j and l.jal instructions as we don't need to 91 + * introduce any trampolines for reaching "distant" code. 92 + * 93 + * 64 MB of vmalloc area is comparable to what's available on other arches. 94 + */ 95 + 96 + #define VMALLOC_START (PAGE_OFFSET-0x04000000) 97 + #define VMALLOC_END (PAGE_OFFSET) 98 + #define VMALLOC_VMADDR(x) ((unsigned long)(x)) 99 + 100 + /* Define some higher level generic page attributes. 101 + * 102 + * If you change _PAGE_CI definition be sure to change it in 103 + * io.h for ioremap_nocache() too. 104 + */ 105 + 106 + /* 107 + * An OR32 PTE looks like this: 108 + * 109 + * | 31 ... 10 | 9 | 8 ... 6 | 5 | 4 | 3 | 2 | 1 | 0 | 110 + * Phys pg.num L PP Index D A WOM WBC CI CC 111 + * 112 + * L : link 113 + * PPI: Page protection index 114 + * D : Dirty 115 + * A : Accessed 116 + * WOM: Weakly ordered memory 117 + * WBC: Write-back cache 118 + * CI : Cache inhibit 119 + * CC : Cache coherent 120 + * 121 + * The protection bits below should correspond to the layout of the actual 122 + * PTE as per above 123 + */ 124 + 125 + #define _PAGE_CC 0x001 /* software: pte contains a translation */ 126 + #define _PAGE_CI 0x002 /* cache inhibit */ 127 + #define _PAGE_WBC 0x004 /* write back cache */ 128 + #define _PAGE_FILE 0x004 /* set: pagecache, unset: swap (when !PRESENT) */ 129 + #define _PAGE_WOM 0x008 /* weakly ordered memory */ 130 + 131 + #define _PAGE_A 0x010 /* accessed */ 132 + #define _PAGE_D 0x020 /* dirty */ 133 + #define _PAGE_URE 0x040 /* user read enable */ 134 + #define _PAGE_UWE 0x080 /* user write enable */ 135 + 136 + #define _PAGE_SRE 0x100 /* superuser read enable */ 137 + #define _PAGE_SWE 0x200 /* superuser write enable */ 138 + #define _PAGE_EXEC 0x400 /* software: page is executable */ 139 + #define _PAGE_U_SHARED 0x800 /* software: page is shared in user space */ 140 + 141 + /* 0x001 is cache coherency bit, which should always be set to 142 + * 1 - for SMP (when we support it) 143 + * 0 - otherwise 144 + * 145 + * we just reuse this bit in software for _PAGE_PRESENT and 146 + * force it to 0 when loading it into TLB. 147 + */ 148 + #define _PAGE_PRESENT _PAGE_CC 149 + #define _PAGE_USER _PAGE_URE 150 + #define _PAGE_WRITE (_PAGE_UWE | _PAGE_SWE) 151 + #define _PAGE_DIRTY _PAGE_D 152 + #define _PAGE_ACCESSED _PAGE_A 153 + #define _PAGE_NO_CACHE _PAGE_CI 154 + #define _PAGE_SHARED _PAGE_U_SHARED 155 + #define _PAGE_READ (_PAGE_URE | _PAGE_SRE) 156 + 157 + #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) 158 + #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED) 159 + #define _PAGE_ALL (_PAGE_PRESENT | _PAGE_ACCESSED) 160 + #define _KERNPG_TABLE \ 161 + (_PAGE_BASE | _PAGE_SRE | _PAGE_SWE | _PAGE_ACCESSED | _PAGE_DIRTY) 162 + 163 + #define PAGE_NONE __pgprot(_PAGE_ALL) 164 + #define PAGE_READONLY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE) 165 + #define PAGE_READONLY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC) 166 + #define PAGE_SHARED \ 167 + __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \ 168 + | _PAGE_SHARED) 169 + #define PAGE_SHARED_X \ 170 + __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_UWE | _PAGE_SWE \ 171 + | _PAGE_SHARED | _PAGE_EXEC) 172 + #define PAGE_COPY __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE) 173 + #define PAGE_COPY_X __pgprot(_PAGE_ALL | _PAGE_URE | _PAGE_SRE | _PAGE_EXEC) 174 + 175 + #define PAGE_KERNEL \ 176 + __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \ 177 + | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC) 178 + #define PAGE_KERNEL_RO \ 179 + __pgprot(_PAGE_ALL | _PAGE_SRE \ 180 + | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC) 181 + #define PAGE_KERNEL_NOCACHE \ 182 + __pgprot(_PAGE_ALL | _PAGE_SRE | _PAGE_SWE \ 183 + | _PAGE_SHARED | _PAGE_DIRTY | _PAGE_EXEC | _PAGE_CI) 184 + 185 + #define __P000 PAGE_NONE 186 + #define __P001 PAGE_READONLY_X 187 + #define __P010 PAGE_COPY 188 + #define __P011 PAGE_COPY_X 189 + #define __P100 PAGE_READONLY 190 + #define __P101 PAGE_READONLY_X 191 + #define __P110 PAGE_COPY 192 + #define __P111 PAGE_COPY_X 193 + 194 + #define __S000 PAGE_NONE 195 + #define __S001 PAGE_READONLY_X 196 + #define __S010 PAGE_SHARED 197 + #define __S011 PAGE_SHARED_X 198 + #define __S100 PAGE_READONLY 199 + #define __S101 PAGE_READONLY_X 200 + #define __S110 PAGE_SHARED 201 + #define __S111 PAGE_SHARED_X 202 + 203 + /* zero page used for uninitialized stuff */ 204 + extern unsigned long empty_zero_page[2048]; 205 + #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) 206 + 207 + /* number of bits that fit into a memory pointer */ 208 + #define BITS_PER_PTR (8*sizeof(unsigned long)) 209 + 210 + /* to align the pointer to a pointer address */ 211 + #define PTR_MASK (~(sizeof(void *)-1)) 212 + 213 + /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */ 214 + /* 64-bit machines, beware! SRB. */ 215 + #define SIZEOF_PTR_LOG2 2 216 + 217 + /* to find an entry in a page-table */ 218 + #define PAGE_PTR(address) \ 219 + ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK) 220 + 221 + /* to set the page-dir */ 222 + #define SET_PAGE_DIR(tsk, pgdir) 223 + 224 + #define pte_none(x) (!pte_val(x)) 225 + #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) 226 + #define pte_clear(mm, addr, xp) do { pte_val(*(xp)) = 0; } while (0) 227 + 228 + #define pmd_none(x) (!pmd_val(x)) 229 + #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK)) != _KERNPG_TABLE) 230 + #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) 231 + #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while (0) 232 + 233 + /* 234 + * The following only work if pte_present() is true. 235 + * Undefined behaviour if not.. 236 + */ 237 + 238 + static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_READ; } 239 + static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } 240 + static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } 241 + static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } 242 + static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } 243 + static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } 244 + static inline int pte_special(pte_t pte) { return 0; } 245 + static inline pte_t pte_mkspecial(pte_t pte) { return pte; } 246 + 247 + static inline pte_t pte_wrprotect(pte_t pte) 248 + { 249 + pte_val(pte) &= ~(_PAGE_WRITE); 250 + return pte; 251 + } 252 + 253 + static inline pte_t pte_rdprotect(pte_t pte) 254 + { 255 + pte_val(pte) &= ~(_PAGE_READ); 256 + return pte; 257 + } 258 + 259 + static inline pte_t pte_exprotect(pte_t pte) 260 + { 261 + pte_val(pte) &= ~(_PAGE_EXEC); 262 + return pte; 263 + } 264 + 265 + static inline pte_t pte_mkclean(pte_t pte) 266 + { 267 + pte_val(pte) &= ~(_PAGE_DIRTY); 268 + return pte; 269 + } 270 + 271 + static inline pte_t pte_mkold(pte_t pte) 272 + { 273 + pte_val(pte) &= ~(_PAGE_ACCESSED); 274 + return pte; 275 + } 276 + 277 + static inline pte_t pte_mkwrite(pte_t pte) 278 + { 279 + pte_val(pte) |= _PAGE_WRITE; 280 + return pte; 281 + } 282 + 283 + static inline pte_t pte_mkread(pte_t pte) 284 + { 285 + pte_val(pte) |= _PAGE_READ; 286 + return pte; 287 + } 288 + 289 + static inline pte_t pte_mkexec(pte_t pte) 290 + { 291 + pte_val(pte) |= _PAGE_EXEC; 292 + return pte; 293 + } 294 + 295 + static inline pte_t pte_mkdirty(pte_t pte) 296 + { 297 + pte_val(pte) |= _PAGE_DIRTY; 298 + return pte; 299 + } 300 + 301 + static inline pte_t pte_mkyoung(pte_t pte) 302 + { 303 + pte_val(pte) |= _PAGE_ACCESSED; 304 + return pte; 305 + } 306 + 307 + /* 308 + * Conversion functions: convert a page and protection to a page entry, 309 + * and a page entry and page directory to the page they refer to. 310 + */ 311 + 312 + /* What actually goes as arguments to the various functions is less than 313 + * obvious, but a rule of thumb is that struct page's goes as struct page *, 314 + * really physical DRAM addresses are unsigned long's, and DRAM "virtual" 315 + * addresses (the 0xc0xxxxxx's) goes as void *'s. 316 + */ 317 + 318 + static inline pte_t __mk_pte(void *page, pgprot_t pgprot) 319 + { 320 + pte_t pte; 321 + /* the PTE needs a physical address */ 322 + pte_val(pte) = __pa(page) | pgprot_val(pgprot); 323 + return pte; 324 + } 325 + 326 + #define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot)) 327 + 328 + #define mk_pte_phys(physpage, pgprot) \ 329 + ({ \ 330 + pte_t __pte; \ 331 + \ 332 + pte_val(__pte) = (physpage) + pgprot_val(pgprot); \ 333 + __pte; \ 334 + }) 335 + 336 + static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 337 + { 338 + pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); 339 + return pte; 340 + } 341 + 342 + 343 + /* 344 + * pte_val refers to a page in the 0x0xxxxxxx physical DRAM interval 345 + * __pte_page(pte_val) refers to the "virtual" DRAM interval 346 + * pte_pagenr refers to the page-number counted starting from the virtual 347 + * DRAM start 348 + */ 349 + 350 + static inline unsigned long __pte_page(pte_t pte) 351 + { 352 + /* the PTE contains a physical address */ 353 + return (unsigned long)__va(pte_val(pte) & PAGE_MASK); 354 + } 355 + 356 + #define pte_pagenr(pte) ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT) 357 + 358 + /* permanent address of a page */ 359 + 360 + #define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT)) 361 + #define pte_page(pte) (mem_map+pte_pagenr(pte)) 362 + 363 + /* 364 + * only the pte's themselves need to point to physical DRAM (see above) 365 + * the pagetable links are purely handled within the kernel SW and thus 366 + * don't need the __pa and __va transformations. 367 + */ 368 + static inline void pmd_set(pmd_t *pmdp, pte_t *ptep) 369 + { 370 + pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep; 371 + } 372 + 373 + #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) 374 + #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) 375 + 376 + /* to find an entry in a page-table-directory. */ 377 + #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) 378 + 379 + #define __pgd_offset(address) pgd_index(address) 380 + 381 + #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) 382 + 383 + /* to find an entry in a kernel page-table-directory */ 384 + #define pgd_offset_k(address) pgd_offset(&init_mm, address) 385 + 386 + #define __pmd_offset(address) \ 387 + (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) 388 + 389 + /* 390 + * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] 391 + * 392 + * this macro returns the index of the entry in the pte page which would 393 + * control the given virtual address 394 + */ 395 + #define __pte_offset(address) \ 396 + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) 397 + #define pte_offset_kernel(dir, address) \ 398 + ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address)) 399 + #define pte_offset_map(dir, address) \ 400 + ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) 401 + #define pte_offset_map_nested(dir, address) \ 402 + pte_offset_map(dir, address) 403 + 404 + #define pte_unmap(pte) do { } while (0) 405 + #define pte_unmap_nested(pte) do { } while (0) 406 + #define pte_pfn(x) ((unsigned long)(((x).pte)) >> PAGE_SHIFT) 407 + #define pfn_pte(pfn, prot) __pte((((pfn) << PAGE_SHIFT)) | pgprot_val(prot)) 408 + 409 + #define pte_ERROR(e) \ 410 + printk(KERN_ERR "%s:%d: bad pte %p(%08lx).\n", \ 411 + __FILE__, __LINE__, &(e), pte_val(e)) 412 + #define pgd_ERROR(e) \ 413 + printk(KERN_ERR "%s:%d: bad pgd %p(%08lx).\n", \ 414 + __FILE__, __LINE__, &(e), pgd_val(e)) 415 + 416 + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */ 417 + 418 + /* 419 + * or32 doesn't have any external MMU info: the kernel page 420 + * tables contain all the necessary information. 421 + * 422 + * Actually I am not sure on what this could be used for. 423 + */ 424 + static inline void update_mmu_cache(struct vm_area_struct *vma, 425 + unsigned long address, pte_t *pte) 426 + { 427 + } 428 + 429 + /* __PHX__ FIXME, SWAP, this probably doesn't work */ 430 + 431 + /* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ 432 + /* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */ 433 + 434 + #define __swp_type(x) (((x).val >> 5) & 0x7f) 435 + #define __swp_offset(x) ((x).val >> 12) 436 + #define __swp_entry(type, offset) \ 437 + ((swp_entry_t) { ((type) << 5) | ((offset) << 12) }) 438 + #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 439 + #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 440 + 441 + /* Encode and decode a nonlinear file mapping entry */ 442 + 443 + #define PTE_FILE_MAX_BITS 26 444 + #define pte_to_pgoff(x) (pte_val(x) >> 6) 445 + #define pgoff_to_pte(x) __pte(((x) << 6) | _PAGE_FILE) 446 + 447 + #define kern_addr_valid(addr) (1) 448 + 449 + #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ 450 + remap_pfn_range(vma, vaddr, pfn, size, prot) 451 + 452 + #include <asm-generic/pgtable.h> 453 + 454 + /* 455 + * No page table caches to initialise 456 + */ 457 + #define pgtable_cache_init() do { } while (0) 458 + #define io_remap_page_range remap_page_range 459 + 460 + typedef pte_t *pte_addr_t; 461 + 462 + #endif /* __ASSEMBLY__ */ 463 + #endif /* __ASM_OPENRISC_PGTABLE_H */
+34
arch/openrisc/include/asm/tlb.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_TLB_H__ 20 + #define __ASM_OPENRISC_TLB_H__ 21 + 22 + /* 23 + * or32 doesn't need any special per-pte or 24 + * per-vma handling.. 25 + */ 26 + #define tlb_start_vma(tlb, vma) do { } while (0) 27 + #define tlb_end_vma(tlb, vma) do { } while (0) 28 + #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) 29 + 30 + #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) 31 + #include <linux/pagemap.h> 32 + #include <asm-generic/tlb.h> 33 + 34 + #endif /* __ASM_OPENRISC_TLB_H__ */
+55
arch/openrisc/include/asm/tlbflush.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_TLBFLUSH_H 20 + #define __ASM_OPENRISC_TLBFLUSH_H 21 + 22 + #include <linux/mm.h> 23 + #include <asm/processor.h> 24 + #include <asm/pgtable.h> 25 + #include <asm/pgalloc.h> 26 + #include <asm/current.h> 27 + #include <linux/sched.h> 28 + 29 + /* 30 + * - flush_tlb() flushes the current mm struct TLBs 31 + * - flush_tlb_all() flushes all processes TLBs 32 + * - flush_tlb_mm(mm) flushes the specified mm context TLB's 33 + * - flush_tlb_page(vma, vmaddr) flushes one page 34 + * - flush_tlb_range(mm, start, end) flushes a range of pages 35 + */ 36 + 37 + void flush_tlb_all(void); 38 + void flush_tlb_mm(struct mm_struct *mm); 39 + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); 40 + void flush_tlb_range(struct vm_area_struct *vma, 41 + unsigned long start, 42 + unsigned long end); 43 + 44 + static inline void flush_tlb(void) 45 + { 46 + flush_tlb_mm(current->mm); 47 + } 48 + 49 + static inline void flush_tlb_kernel_range(unsigned long start, 50 + unsigned long end) 51 + { 52 + flush_tlb_range(NULL, start, end); 53 + } 54 + 55 + #endif /* __ASM_OPENRISC_TLBFLUSH_H */
+355
arch/openrisc/include/asm/uaccess.h
··· 1 + /* 2 + * OpenRISC Linux 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * OpenRISC implementation: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * et al. 12 + * 13 + * This program is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + */ 18 + 19 + #ifndef __ASM_OPENRISC_UACCESS_H 20 + #define __ASM_OPENRISC_UACCESS_H 21 + 22 + /* 23 + * User space memory access functions 24 + */ 25 + #include <linux/errno.h> 26 + #include <linux/thread_info.h> 27 + #include <linux/prefetch.h> 28 + #include <linux/string.h> 29 + #include <linux/thread_info.h> 30 + #include <asm/page.h> 31 + 32 + #define VERIFY_READ 0 33 + #define VERIFY_WRITE 1 34 + 35 + /* 36 + * The fs value determines whether argument validity checking should be 37 + * performed or not. If get_fs() == USER_DS, checking is performed, with 38 + * get_fs() == KERNEL_DS, checking is bypassed. 39 + * 40 + * For historical reasons, these macros are grossly misnamed. 41 + */ 42 + 43 + /* addr_limit is the maximum accessible address for the task. we misuse 44 + * the KERNEL_DS and USER_DS values to both assign and compare the 45 + * addr_limit values through the equally misnamed get/set_fs macros. 46 + * (see above) 47 + */ 48 + 49 + #define KERNEL_DS (~0UL) 50 + #define get_ds() (KERNEL_DS) 51 + 52 + #define USER_DS (TASK_SIZE) 53 + #define get_fs() (current_thread_info()->addr_limit) 54 + #define set_fs(x) (current_thread_info()->addr_limit = (x)) 55 + 56 + #define segment_eq(a, b) ((a) == (b)) 57 + 58 + /* Ensure that the range from addr to addr+size is all within the process' 59 + * address space 60 + */ 61 + #define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs()-size)) 62 + 63 + /* Ensure that addr is below task's addr_limit */ 64 + #define __addr_ok(addr) ((unsigned long) addr < get_fs()) 65 + 66 + #define access_ok(type, addr, size) \ 67 + __range_ok((unsigned long)addr, (unsigned long)size) 68 + 69 + /* 70 + * The exception table consists of pairs of addresses: the first is the 71 + * address of an instruction that is allowed to fault, and the second is 72 + * the address at which the program should continue. No registers are 73 + * modified, so it is entirely up to the continuation code to figure out 74 + * what to do. 75 + * 76 + * All the routines below use bits of fixup code that are out of line 77 + * with the main instruction path. This means when everything is well, 78 + * we don't even have to jump over them. Further, they do not intrude 79 + * on our cache or tlb entries. 80 + */ 81 + 82 + struct exception_table_entry { 83 + unsigned long insn, fixup; 84 + }; 85 + 86 + /* Returns 0 if exception not found and fixup otherwise. */ 87 + extern unsigned long search_exception_table(unsigned long); 88 + extern void sort_exception_table(void); 89 + 90 + /* 91 + * These are the main single-value transfer routines. They automatically 92 + * use the right size if we just have the right pointer type. 93 + * 94 + * This gets kind of ugly. We want to return _two_ values in "get_user()" 95 + * and yet we don't want to do any pointers, because that is too much 96 + * of a performance impact. Thus we have a few rather ugly macros here, 97 + * and hide all the uglyness from the user. 98 + * 99 + * The "__xxx" versions of the user access functions are versions that 100 + * do not verify the address space, that must have been done previously 101 + * with a separate "access_ok()" call (this is used when we do multiple 102 + * accesses to the same area of user memory). 103 + * 104 + * As we use the same address space for kernel and user data on the 105 + * PowerPC, we can just do these as direct assignments. (Of course, the 106 + * exception handling means that it's no longer "just"...) 107 + */ 108 + #define get_user(x, ptr) \ 109 + __get_user_check((x), (ptr), sizeof(*(ptr))) 110 + #define put_user(x, ptr) \ 111 + __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) 112 + 113 + #define __get_user(x, ptr) \ 114 + __get_user_nocheck((x), (ptr), sizeof(*(ptr))) 115 + #define __put_user(x, ptr) \ 116 + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) 117 + 118 + extern long __put_user_bad(void); 119 + 120 + #define __put_user_nocheck(x, ptr, size) \ 121 + ({ \ 122 + long __pu_err; \ 123 + __put_user_size((x), (ptr), (size), __pu_err); \ 124 + __pu_err; \ 125 + }) 126 + 127 + #define __put_user_check(x, ptr, size) \ 128 + ({ \ 129 + long __pu_err = -EFAULT; \ 130 + __typeof__(*(ptr)) *__pu_addr = (ptr); \ 131 + if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ 132 + __put_user_size((x), __pu_addr, (size), __pu_err); \ 133 + __pu_err; \ 134 + }) 135 + 136 + #define __put_user_size(x, ptr, size, retval) \ 137 + do { \ 138 + retval = 0; \ 139 + switch (size) { \ 140 + case 1: __put_user_asm(x, ptr, retval, "l.sb"); break; \ 141 + case 2: __put_user_asm(x, ptr, retval, "l.sh"); break; \ 142 + case 4: __put_user_asm(x, ptr, retval, "l.sw"); break; \ 143 + case 8: __put_user_asm2(x, ptr, retval); break; \ 144 + default: __put_user_bad(); \ 145 + } \ 146 + } while (0) 147 + 148 + struct __large_struct { 149 + unsigned long buf[100]; 150 + }; 151 + #define __m(x) (*(struct __large_struct *)(x)) 152 + 153 + /* 154 + * We don't tell gcc that we are accessing memory, but this is OK 155 + * because we do not write to any memory gcc knows about, so there 156 + * are no aliasing issues. 157 + */ 158 + #define __put_user_asm(x, addr, err, op) \ 159 + __asm__ __volatile__( \ 160 + "1: "op" 0(%2),%1\n" \ 161 + "2:\n" \ 162 + ".section .fixup,\"ax\"\n" \ 163 + "3: l.addi %0,r0,%3\n" \ 164 + " l.j 2b\n" \ 165 + " l.nop\n" \ 166 + ".previous\n" \ 167 + ".section __ex_table,\"a\"\n" \ 168 + " .align 2\n" \ 169 + " .long 1b,3b\n" \ 170 + ".previous" \ 171 + : "=r"(err) \ 172 + : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)) 173 + 174 + #define __put_user_asm2(x, addr, err) \ 175 + __asm__ __volatile__( \ 176 + "1: l.sw 0(%2),%1\n" \ 177 + "2: l.sw 4(%2),%H1\n" \ 178 + "3:\n" \ 179 + ".section .fixup,\"ax\"\n" \ 180 + "4: l.addi %0,r0,%3\n" \ 181 + " l.j 3b\n" \ 182 + " l.nop\n" \ 183 + ".previous\n" \ 184 + ".section __ex_table,\"a\"\n" \ 185 + " .align 2\n" \ 186 + " .long 1b,4b\n" \ 187 + " .long 2b,4b\n" \ 188 + ".previous" \ 189 + : "=r"(err) \ 190 + : "r"(x), "r"(addr), "i"(-EFAULT), "0"(err)) 191 + 192 + #define __get_user_nocheck(x, ptr, size) \ 193 + ({ \ 194 + long __gu_err, __gu_val; \ 195 + __get_user_size(__gu_val, (ptr), (size), __gu_err); \ 196 + (x) = (__typeof__(*(ptr)))__gu_val; \ 197 + __gu_err; \ 198 + }) 199 + 200 + #define __get_user_check(x, ptr, size) \ 201 + ({ \ 202 + long __gu_err = -EFAULT, __gu_val = 0; \ 203 + const __typeof__(*(ptr)) * __gu_addr = (ptr); \ 204 + if (access_ok(VERIFY_READ, __gu_addr, size)) \ 205 + __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ 206 + (x) = (__typeof__(*(ptr)))__gu_val; \ 207 + __gu_err; \ 208 + }) 209 + 210 + extern long __get_user_bad(void); 211 + 212 + #define __get_user_size(x, ptr, size, retval) \ 213 + do { \ 214 + retval = 0; \ 215 + switch (size) { \ 216 + case 1: __get_user_asm(x, ptr, retval, "l.lbz"); break; \ 217 + case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break; \ 218 + case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break; \ 219 + case 8: __get_user_asm2(x, ptr, retval); \ 220 + default: (x) = __get_user_bad(); \ 221 + } \ 222 + } while (0) 223 + 224 + #define __get_user_asm(x, addr, err, op) \ 225 + __asm__ __volatile__( \ 226 + "1: "op" %1,0(%2)\n" \ 227 + "2:\n" \ 228 + ".section .fixup,\"ax\"\n" \ 229 + "3: l.addi %0,r0,%3\n" \ 230 + " l.addi %1,r0,0\n" \ 231 + " l.j 2b\n" \ 232 + " l.nop\n" \ 233 + ".previous\n" \ 234 + ".section __ex_table,\"a\"\n" \ 235 + " .align 2\n" \ 236 + " .long 1b,3b\n" \ 237 + ".previous" \ 238 + : "=r"(err), "=r"(x) \ 239 + : "r"(addr), "i"(-EFAULT), "0"(err)) 240 + 241 + #define __get_user_asm2(x, addr, err) \ 242 + __asm__ __volatile__( \ 243 + "1: l.lwz %1,0(%2)\n" \ 244 + "2: l.lwz %H1,4(%2)\n" \ 245 + "3:\n" \ 246 + ".section .fixup,\"ax\"\n" \ 247 + "4: l.addi %0,r0,%3\n" \ 248 + " l.addi %1,r0,0\n" \ 249 + " l.addi %H1,r0,0\n" \ 250 + " l.j 3b\n" \ 251 + " l.nop\n" \ 252 + ".previous\n" \ 253 + ".section __ex_table,\"a\"\n" \ 254 + " .align 2\n" \ 255 + " .long 1b,4b\n" \ 256 + " .long 2b,4b\n" \ 257 + ".previous" \ 258 + : "=r"(err), "=&r"(x) \ 259 + : "r"(addr), "i"(-EFAULT), "0"(err)) 260 + 261 + /* more complex routines */ 262 + 263 + extern unsigned long __must_check 264 + __copy_tofrom_user(void *to, const void *from, unsigned long size); 265 + 266 + #define __copy_from_user(to, from, size) \ 267 + __copy_tofrom_user(to, from, size) 268 + #define __copy_to_user(to, from, size) \ 269 + __copy_tofrom_user(to, from, size) 270 + 271 + #define __copy_to_user_inatomic __copy_to_user 272 + #define __copy_from_user_inatomic __copy_from_user 273 + 274 + static inline unsigned long 275 + copy_from_user(void *to, const void *from, unsigned long n) 276 + { 277 + unsigned long over; 278 + 279 + if (access_ok(VERIFY_READ, from, n)) 280 + return __copy_tofrom_user(to, from, n); 281 + if ((unsigned long)from < TASK_SIZE) { 282 + over = (unsigned long)from + n - TASK_SIZE; 283 + return __copy_tofrom_user(to, from, n - over) + over; 284 + } 285 + return n; 286 + } 287 + 288 + static inline unsigned long 289 + copy_to_user(void *to, const void *from, unsigned long n) 290 + { 291 + unsigned long over; 292 + 293 + if (access_ok(VERIFY_WRITE, to, n)) 294 + return __copy_tofrom_user(to, from, n); 295 + if ((unsigned long)to < TASK_SIZE) { 296 + over = (unsigned long)to + n - TASK_SIZE; 297 + return __copy_tofrom_user(to, from, n - over) + over; 298 + } 299 + return n; 300 + } 301 + 302 + extern unsigned long __clear_user(void *addr, unsigned long size); 303 + 304 + static inline __must_check unsigned long 305 + clear_user(void *addr, unsigned long size) 306 + { 307 + 308 + if (access_ok(VERIFY_WRITE, addr, size)) 309 + return __clear_user(addr, size); 310 + if ((unsigned long)addr < TASK_SIZE) { 311 + unsigned long over = (unsigned long)addr + size - TASK_SIZE; 312 + return __clear_user(addr, size - over) + over; 313 + } 314 + return size; 315 + } 316 + 317 + extern int __strncpy_from_user(char *dst, const char *src, long count); 318 + 319 + static inline long strncpy_from_user(char *dst, const char *src, long count) 320 + { 321 + if (access_ok(VERIFY_READ, src, 1)) 322 + return __strncpy_from_user(dst, src, count); 323 + return -EFAULT; 324 + } 325 + 326 + /* 327 + * Return the size of a string (including the ending 0) 328 + * 329 + * Return 0 for error 330 + */ 331 + 332 + extern int __strnlen_user(const char *str, long len, unsigned long top); 333 + 334 + /* 335 + * Returns the length of the string at str (including the null byte), 336 + * or 0 if we hit a page we can't access, 337 + * or something > len if we didn't find a null byte. 338 + * 339 + * The `top' parameter to __strnlen_user is to make sure that 340 + * we can never overflow from the user area into kernel space. 341 + */ 342 + static inline long strnlen_user(const char __user *str, long len) 343 + { 344 + unsigned long top = (unsigned long)get_fs(); 345 + unsigned long res = 0; 346 + 347 + if (__addr_ok(str)) 348 + res = __strnlen_user(str, len, top); 349 + 350 + return res; 351 + } 352 + 353 + #define strlen_user(str) strnlen_user(str, TASK_SIZE-1) 354 + 355 + #endif /* __ASM_OPENRISC_UACCESS_H */
+338
arch/openrisc/mm/fault.c
··· 1 + /* 2 + * OpenRISC fault.c 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * Modifications for the OpenRISC architecture: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 15 + * 2 of the License, or (at your option) any later version. 16 + */ 17 + 18 + #include <linux/mm.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/module.h> 21 + #include <linux/sched.h> 22 + 23 + #include <asm/uaccess.h> 24 + #include <asm/siginfo.h> 25 + #include <asm/signal.h> 26 + 27 + #define NUM_TLB_ENTRIES 64 28 + #define TLB_OFFSET(add) (((add) >> PAGE_SHIFT) & (NUM_TLB_ENTRIES-1)) 29 + 30 + unsigned long pte_misses; /* updated by do_page_fault() */ 31 + unsigned long pte_errors; /* updated by do_page_fault() */ 32 + 33 + /* __PHX__ :: - check the vmalloc_fault in do_page_fault() 34 + * - also look into include/asm-or32/mmu_context.h 35 + */ 36 + volatile pgd_t *current_pgd; 37 + 38 + extern void die(char *, struct pt_regs *, long); 39 + 40 + /* 41 + * This routine handles page faults. It determines the address, 42 + * and the problem, and then passes it off to one of the appropriate 43 + * routines. 44 + * 45 + * If this routine detects a bad access, it returns 1, otherwise it 46 + * returns 0. 47 + */ 48 + 49 + asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, 50 + unsigned long vector, int write_acc) 51 + { 52 + struct task_struct *tsk; 53 + struct mm_struct *mm; 54 + struct vm_area_struct *vma; 55 + siginfo_t info; 56 + int fault; 57 + 58 + tsk = current; 59 + 60 + /* 61 + * We fault-in kernel-space virtual memory on-demand. The 62 + * 'reference' page table is init_mm.pgd. 63 + * 64 + * NOTE! We MUST NOT take any locks for this case. We may 65 + * be in an interrupt or a critical region, and should 66 + * only copy the information from the master page table, 67 + * nothing more. 68 + * 69 + * NOTE2: This is done so that, when updating the vmalloc 70 + * mappings we don't have to walk all processes pgdirs and 71 + * add the high mappings all at once. Instead we do it as they 72 + * are used. However vmalloc'ed page entries have the PAGE_GLOBAL 73 + * bit set so sometimes the TLB can use a lingering entry. 74 + * 75 + * This verifies that the fault happens in kernel space 76 + * and that the fault was not a protection error. 77 + */ 78 + 79 + if (address >= VMALLOC_START && 80 + (vector != 0x300 && vector != 0x400) && 81 + !user_mode(regs)) 82 + goto vmalloc_fault; 83 + 84 + /* If exceptions were enabled, we can reenable them here */ 85 + if (user_mode(regs)) { 86 + /* Exception was in userspace: reenable interrupts */ 87 + local_irq_enable(); 88 + } else { 89 + /* If exception was in a syscall, then IRQ's may have 90 + * been enabled or disabled. If they were enabled, 91 + * reenable them. 92 + */ 93 + if (regs->sr && (SPR_SR_IEE | SPR_SR_TEE)) 94 + local_irq_enable(); 95 + } 96 + 97 + mm = tsk->mm; 98 + info.si_code = SEGV_MAPERR; 99 + 100 + /* 101 + * If we're in an interrupt or have no user 102 + * context, we must not take the fault.. 103 + */ 104 + 105 + if (in_interrupt() || !mm) 106 + goto no_context; 107 + 108 + down_read(&mm->mmap_sem); 109 + vma = find_vma(mm, address); 110 + 111 + if (!vma) 112 + goto bad_area; 113 + 114 + if (vma->vm_start <= address) 115 + goto good_area; 116 + 117 + if (!(vma->vm_flags & VM_GROWSDOWN)) 118 + goto bad_area; 119 + 120 + if (user_mode(regs)) { 121 + /* 122 + * accessing the stack below usp is always a bug. 123 + * we get page-aligned addresses so we can only check 124 + * if we're within a page from usp, but that might be 125 + * enough to catch brutal errors at least. 126 + */ 127 + if (address + PAGE_SIZE < regs->sp) 128 + goto bad_area; 129 + } 130 + if (expand_stack(vma, address)) 131 + goto bad_area; 132 + 133 + /* 134 + * Ok, we have a good vm_area for this memory access, so 135 + * we can handle it.. 136 + */ 137 + 138 + good_area: 139 + info.si_code = SEGV_ACCERR; 140 + 141 + /* first do some preliminary protection checks */ 142 + 143 + if (write_acc) { 144 + if (!(vma->vm_flags & VM_WRITE)) 145 + goto bad_area; 146 + } else { 147 + /* not present */ 148 + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 149 + goto bad_area; 150 + } 151 + 152 + /* are we trying to execute nonexecutable area */ 153 + if ((vector == 0x400) && !(vma->vm_page_prot.pgprot & _PAGE_EXEC)) 154 + goto bad_area; 155 + 156 + /* 157 + * If for any reason at all we couldn't handle the fault, 158 + * make sure we exit gracefully rather than endlessly redo 159 + * the fault. 160 + */ 161 + 162 + fault = handle_mm_fault(mm, vma, address, write_acc); 163 + if (unlikely(fault & VM_FAULT_ERROR)) { 164 + if (fault & VM_FAULT_OOM) 165 + goto out_of_memory; 166 + else if (fault & VM_FAULT_SIGBUS) 167 + goto do_sigbus; 168 + BUG(); 169 + } 170 + /*RGD modeled on Cris */ 171 + if (fault & VM_FAULT_MAJOR) 172 + tsk->maj_flt++; 173 + else 174 + tsk->min_flt++; 175 + 176 + up_read(&mm->mmap_sem); 177 + return; 178 + 179 + /* 180 + * Something tried to access memory that isn't in our memory map.. 181 + * Fix it, but check if it's kernel or user first.. 182 + */ 183 + 184 + bad_area: 185 + up_read(&mm->mmap_sem); 186 + 187 + bad_area_nosemaphore: 188 + 189 + /* User mode accesses just cause a SIGSEGV */ 190 + 191 + if (user_mode(regs)) { 192 + info.si_signo = SIGSEGV; 193 + info.si_errno = 0; 194 + /* info.si_code has been set above */ 195 + info.si_addr = (void *)address; 196 + force_sig_info(SIGSEGV, &info, tsk); 197 + return; 198 + } 199 + 200 + no_context: 201 + 202 + /* Are we prepared to handle this kernel fault? 203 + * 204 + * (The kernel has valid exception-points in the source 205 + * when it acesses user-memory. When it fails in one 206 + * of those points, we find it in a table and do a jump 207 + * to some fixup code that loads an appropriate error 208 + * code) 209 + */ 210 + 211 + { 212 + const struct exception_table_entry *entry; 213 + 214 + __asm__ __volatile__("l.nop 42"); 215 + 216 + if ((entry = search_exception_tables(regs->pc)) != NULL) { 217 + /* Adjust the instruction pointer in the stackframe */ 218 + regs->pc = entry->fixup; 219 + return; 220 + } 221 + } 222 + 223 + /* 224 + * Oops. The kernel tried to access some bad page. We'll have to 225 + * terminate things with extreme prejudice. 226 + */ 227 + 228 + if ((unsigned long)(address) < PAGE_SIZE) 229 + printk(KERN_ALERT 230 + "Unable to handle kernel NULL pointer dereference"); 231 + else 232 + printk(KERN_ALERT "Unable to handle kernel access"); 233 + printk(" at virtual address 0x%08lx\n", address); 234 + 235 + die("Oops", regs, write_acc); 236 + 237 + do_exit(SIGKILL); 238 + 239 + /* 240 + * We ran out of memory, or some other thing happened to us that made 241 + * us unable to handle the page fault gracefully. 242 + */ 243 + 244 + out_of_memory: 245 + __asm__ __volatile__("l.nop 42"); 246 + __asm__ __volatile__("l.nop 1"); 247 + 248 + up_read(&mm->mmap_sem); 249 + printk("VM: killing process %s\n", tsk->comm); 250 + if (user_mode(regs)) 251 + do_exit(SIGKILL); 252 + goto no_context; 253 + 254 + do_sigbus: 255 + up_read(&mm->mmap_sem); 256 + 257 + /* 258 + * Send a sigbus, regardless of whether we were in kernel 259 + * or user mode. 260 + */ 261 + info.si_signo = SIGBUS; 262 + info.si_errno = 0; 263 + info.si_code = BUS_ADRERR; 264 + info.si_addr = (void *)address; 265 + force_sig_info(SIGBUS, &info, tsk); 266 + 267 + /* Kernel mode? Handle exceptions or die */ 268 + if (!user_mode(regs)) 269 + goto no_context; 270 + return; 271 + 272 + vmalloc_fault: 273 + { 274 + /* 275 + * Synchronize this task's top level page-table 276 + * with the 'reference' page table. 277 + * 278 + * Use current_pgd instead of tsk->active_mm->pgd 279 + * since the latter might be unavailable if this 280 + * code is executed in a misfortunately run irq 281 + * (like inside schedule() between switch_mm and 282 + * switch_to...). 283 + */ 284 + 285 + int offset = pgd_index(address); 286 + pgd_t *pgd, *pgd_k; 287 + pud_t *pud, *pud_k; 288 + pmd_t *pmd, *pmd_k; 289 + pte_t *pte_k; 290 + 291 + /* 292 + phx_warn("do_page_fault(): vmalloc_fault will not work, " 293 + "since current_pgd assign a proper value somewhere\n" 294 + "anyhow we don't need this at the moment\n"); 295 + 296 + phx_mmu("vmalloc_fault"); 297 + */ 298 + pgd = (pgd_t *)current_pgd + offset; 299 + pgd_k = init_mm.pgd + offset; 300 + 301 + /* Since we're two-level, we don't need to do both 302 + * set_pgd and set_pmd (they do the same thing). If 303 + * we go three-level at some point, do the right thing 304 + * with pgd_present and set_pgd here. 305 + * 306 + * Also, since the vmalloc area is global, we don't 307 + * need to copy individual PTE's, it is enough to 308 + * copy the pgd pointer into the pte page of the 309 + * root task. If that is there, we'll find our pte if 310 + * it exists. 311 + */ 312 + 313 + pud = pud_offset(pgd, address); 314 + pud_k = pud_offset(pgd_k, address); 315 + if (!pud_present(*pud_k)) 316 + goto no_context; 317 + 318 + pmd = pmd_offset(pud, address); 319 + pmd_k = pmd_offset(pud_k, address); 320 + 321 + if (!pmd_present(*pmd_k)) 322 + goto bad_area_nosemaphore; 323 + 324 + set_pmd(pmd, *pmd_k); 325 + 326 + /* Make sure the actual PTE exists as well to 327 + * catch kernel vmalloc-area accesses to non-mapped 328 + * addresses. If we don't do this, this will just 329 + * silently loop forever. 330 + */ 331 + 332 + pte_k = pte_offset_kernel(pmd_k, address); 333 + if (!pte_present(*pte_k)) 334 + goto no_context; 335 + 336 + return; 337 + } 338 + }
+283
arch/openrisc/mm/init.c
··· 1 + /* 2 + * OpenRISC idle.c 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * Modifications for the OpenRISC architecture: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 15 + * 2 of the License, or (at your option) any later version. 16 + */ 17 + 18 + #include <linux/signal.h> 19 + #include <linux/sched.h> 20 + #include <linux/kernel.h> 21 + #include <linux/errno.h> 22 + #include <linux/string.h> 23 + #include <linux/types.h> 24 + #include <linux/ptrace.h> 25 + #include <linux/mman.h> 26 + #include <linux/mm.h> 27 + #include <linux/swap.h> 28 + #include <linux/smp.h> 29 + #include <linux/bootmem.h> 30 + #include <linux/init.h> 31 + #include <linux/delay.h> 32 + #include <linux/blkdev.h> /* for initrd_* */ 33 + #include <linux/pagemap.h> 34 + #include <linux/memblock.h> 35 + 36 + #include <asm/system.h> 37 + #include <asm/segment.h> 38 + #include <asm/pgalloc.h> 39 + #include <asm/pgtable.h> 40 + #include <asm/dma.h> 41 + #include <asm/io.h> 42 + #include <asm/tlb.h> 43 + #include <asm/mmu_context.h> 44 + #include <asm/kmap_types.h> 45 + #include <asm/fixmap.h> 46 + #include <asm/tlbflush.h> 47 + 48 + int mem_init_done; 49 + 50 + DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); 51 + 52 + static void __init zone_sizes_init(void) 53 + { 54 + unsigned long zones_size[MAX_NR_ZONES]; 55 + 56 + /* Clear the zone sizes */ 57 + memset(zones_size, 0, sizeof(zones_size)); 58 + 59 + /* 60 + * We use only ZONE_NORMAL 61 + */ 62 + zones_size[ZONE_NORMAL] = max_low_pfn; 63 + 64 + free_area_init(zones_size); 65 + } 66 + 67 + extern const char _s_kernel_ro[], _e_kernel_ro[]; 68 + 69 + /* 70 + * Map all physical memory into kernel's address space. 71 + * 72 + * This is explicitly coded for two-level page tables, so if you need 73 + * something else then this needs to change. 74 + */ 75 + static void __init map_ram(void) 76 + { 77 + unsigned long v, p, e; 78 + pgprot_t prot; 79 + pgd_t *pge; 80 + pud_t *pue; 81 + pmd_t *pme; 82 + pte_t *pte; 83 + /* These mark extents of read-only kernel pages... 84 + * ...from vmlinux.lds.S 85 + */ 86 + struct memblock_region *region; 87 + 88 + v = PAGE_OFFSET; 89 + 90 + for_each_memblock(memory, region) { 91 + p = (u32) region->base & PAGE_MASK; 92 + e = p + (u32) region->size; 93 + 94 + v = (u32) __va(p); 95 + pge = pgd_offset_k(v); 96 + 97 + while (p < e) { 98 + int j; 99 + pue = pud_offset(pge, v); 100 + pme = pmd_offset(pue, v); 101 + 102 + if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) { 103 + panic("%s: OR1K kernel hardcoded for " 104 + "two-level page tables", 105 + __func__); 106 + } 107 + 108 + /* Alloc one page for holding PTE's... */ 109 + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); 110 + set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte))); 111 + 112 + /* Fill the newly allocated page with PTE'S */ 113 + for (j = 0; p < e && j < PTRS_PER_PGD; 114 + v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) { 115 + if (v >= (u32) _e_kernel_ro || 116 + v < (u32) _s_kernel_ro) 117 + prot = PAGE_KERNEL; 118 + else 119 + prot = PAGE_KERNEL_RO; 120 + 121 + set_pte(pte, mk_pte_phys(p, prot)); 122 + } 123 + 124 + pge++; 125 + } 126 + 127 + printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__, 128 + region->base, region->base + region->size); 129 + } 130 + } 131 + 132 + void __init paging_init(void) 133 + { 134 + extern void tlb_init(void); 135 + 136 + unsigned long end; 137 + int i; 138 + 139 + printk(KERN_INFO "Setting up paging and PTEs.\n"); 140 + 141 + /* clear out the init_mm.pgd that will contain the kernel's mappings */ 142 + 143 + for (i = 0; i < PTRS_PER_PGD; i++) 144 + swapper_pg_dir[i] = __pgd(0); 145 + 146 + /* make sure the current pgd table points to something sane 147 + * (even if it is most probably not used until the next 148 + * switch_mm) 149 + */ 150 + current_pgd = init_mm.pgd; 151 + 152 + end = (unsigned long)__va(max_low_pfn * PAGE_SIZE); 153 + 154 + map_ram(); 155 + 156 + zone_sizes_init(); 157 + 158 + /* self modifying code ;) */ 159 + /* Since the old TLB miss handler has been running up until now, 160 + * the kernel pages are still all RW, so we can still modify the 161 + * text directly... after this change and a TLB flush, the kernel 162 + * pages will become RO. 163 + */ 164 + { 165 + extern unsigned long dtlb_miss_handler; 166 + extern unsigned long itlb_miss_handler; 167 + 168 + unsigned long *dtlb_vector = __va(0x900); 169 + unsigned long *itlb_vector = __va(0xa00); 170 + 171 + printk(KERN_INFO "dtlb_miss_handler %p\n", &dtlb_miss_handler); 172 + *dtlb_vector = ((unsigned long)&dtlb_miss_handler - 173 + (unsigned long)dtlb_vector) >> 2; 174 + 175 + printk(KERN_INFO "itlb_miss_handler %p\n", &itlb_miss_handler); 176 + *itlb_vector = ((unsigned long)&itlb_miss_handler - 177 + (unsigned long)itlb_vector) >> 2; 178 + } 179 + 180 + /* Invalidate instruction caches after code modification */ 181 + mtspr(SPR_ICBIR, 0x900); 182 + mtspr(SPR_ICBIR, 0xa00); 183 + 184 + /* New TLB miss handlers and kernel page tables are in now place. 185 + * Make sure that page flags get updated for all pages in TLB by 186 + * flushing the TLB and forcing all TLB entries to be recreated 187 + * from their page table flags. 188 + */ 189 + flush_tlb_all(); 190 + } 191 + 192 + /* References to section boundaries */ 193 + 194 + extern char _stext, _etext, _edata, __bss_start, _end; 195 + extern char __init_begin, __init_end; 196 + 197 + static int __init free_pages_init(void) 198 + { 199 + int reservedpages, pfn; 200 + 201 + /* this will put all low memory onto the freelists */ 202 + totalram_pages = free_all_bootmem(); 203 + 204 + reservedpages = 0; 205 + for (pfn = 0; pfn < max_low_pfn; pfn++) { 206 + /* 207 + * Only count reserved RAM pages 208 + */ 209 + if (PageReserved(mem_map + pfn)) 210 + reservedpages++; 211 + } 212 + 213 + return reservedpages; 214 + } 215 + 216 + static void __init set_max_mapnr_init(void) 217 + { 218 + max_mapnr = num_physpages = max_low_pfn; 219 + } 220 + 221 + void __init mem_init(void) 222 + { 223 + int codesize, reservedpages, datasize, initsize; 224 + 225 + if (!mem_map) 226 + BUG(); 227 + 228 + set_max_mapnr_init(); 229 + 230 + high_memory = (void *)__va(max_low_pfn * PAGE_SIZE); 231 + 232 + /* clear the zero-page */ 233 + memset((void *)empty_zero_page, 0, PAGE_SIZE); 234 + 235 + reservedpages = free_pages_init(); 236 + 237 + codesize = (unsigned long)&_etext - (unsigned long)&_stext; 238 + datasize = (unsigned long)&_edata - (unsigned long)&_etext; 239 + initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; 240 + 241 + printk(KERN_INFO 242 + "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n", 243 + (unsigned long)nr_free_pages() << (PAGE_SHIFT - 10), 244 + max_mapnr << (PAGE_SHIFT - 10), codesize >> 10, 245 + reservedpages << (PAGE_SHIFT - 10), datasize >> 10, 246 + initsize >> 10, (unsigned long)(0 << (PAGE_SHIFT - 10)) 247 + ); 248 + 249 + printk("mem_init_done ...........................................\n"); 250 + mem_init_done = 1; 251 + return; 252 + } 253 + 254 + #ifdef CONFIG_BLK_DEV_INITRD 255 + void free_initrd_mem(unsigned long start, unsigned long end) 256 + { 257 + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", 258 + (end - start) >> 10); 259 + 260 + for (; start < end; start += PAGE_SIZE) { 261 + ClearPageReserved(virt_to_page(start)); 262 + init_page_count(virt_to_page(start)); 263 + free_page(start); 264 + totalram_pages++; 265 + } 266 + } 267 + #endif 268 + 269 + void free_initmem(void) 270 + { 271 + unsigned long addr; 272 + 273 + addr = (unsigned long)(&__init_begin); 274 + for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { 275 + ClearPageReserved(virt_to_page(addr)); 276 + init_page_count(virt_to_page(addr)); 277 + free_page(addr); 278 + totalram_pages++; 279 + } 280 + printk(KERN_INFO "Freeing unused kernel memory: %luk freed\n", 281 + ((unsigned long)&__init_end - 282 + (unsigned long)&__init_begin) >> 10); 283 + }
+137
arch/openrisc/mm/ioremap.c
··· 1 + /* 2 + * OpenRISC ioremap.c 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * Modifications for the OpenRISC architecture: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 + * 12 + * This program is free software; you can redistribute it and/or 13 + * modify it under the terms of the GNU General Public License 14 + * as published by the Free Software Foundation; either version 15 + * 2 of the License, or (at your option) any later version. 16 + */ 17 + 18 + #include <linux/vmalloc.h> 19 + #include <linux/io.h> 20 + #include <asm/pgalloc.h> 21 + #include <asm/kmap_types.h> 22 + #include <asm/fixmap.h> 23 + #include <asm/bug.h> 24 + #include <asm/pgtable.h> 25 + #include <linux/sched.h> 26 + #include <asm/tlbflush.h> 27 + 28 + extern int mem_init_done; 29 + 30 + static unsigned int fixmaps_used __initdata; 31 + 32 + /* 33 + * Remap an arbitrary physical address space into the kernel virtual 34 + * address space. Needed when the kernel wants to access high addresses 35 + * directly. 36 + * 37 + * NOTE! We need to allow non-page-aligned mappings too: we will obviously 38 + * have to convert them into an offset in a page-aligned mapping, but the 39 + * caller shouldn't need to know that small detail. 40 + */ 41 + void __iomem *__init_refok 42 + __ioremap(phys_addr_t addr, unsigned long size, pgprot_t prot) 43 + { 44 + phys_addr_t p; 45 + unsigned long v; 46 + unsigned long offset, last_addr; 47 + struct vm_struct *area = NULL; 48 + 49 + /* Don't allow wraparound or zero size */ 50 + last_addr = addr + size - 1; 51 + if (!size || last_addr < addr) 52 + return NULL; 53 + 54 + /* 55 + * Mappings have to be page-aligned 56 + */ 57 + offset = addr & ~PAGE_MASK; 58 + p = addr & PAGE_MASK; 59 + size = PAGE_ALIGN(last_addr + 1) - p; 60 + 61 + if (likely(mem_init_done)) { 62 + area = get_vm_area(size, VM_IOREMAP); 63 + if (!area) 64 + return NULL; 65 + v = (unsigned long)area->addr; 66 + } else { 67 + if ((fixmaps_used + (size >> PAGE_SHIFT)) > FIX_N_IOREMAPS) 68 + return NULL; 69 + v = fix_to_virt(FIX_IOREMAP_BEGIN + fixmaps_used); 70 + fixmaps_used += (size >> PAGE_SHIFT); 71 + } 72 + 73 + if (ioremap_page_range(v, v + size, p, prot)) { 74 + if (likely(mem_init_done)) 75 + vfree(area->addr); 76 + else 77 + fixmaps_used -= (size >> PAGE_SHIFT); 78 + return NULL; 79 + } 80 + 81 + return (void __iomem *)(offset + (char *)v); 82 + } 83 + 84 + void iounmap(void *addr) 85 + { 86 + /* If the page is from the fixmap pool then we just clear out 87 + * the fixmap mapping. 88 + */ 89 + if (unlikely((unsigned long)addr > FIXADDR_START)) { 90 + /* This is a bit broken... we don't really know 91 + * how big the area is so it's difficult to know 92 + * how many fixed pages to invalidate... 93 + * just flush tlb and hope for the best... 94 + * consider this a FIXME 95 + * 96 + * Really we should be clearing out one or more page 97 + * table entries for these virtual addresses so that 98 + * future references cause a page fault... for now, we 99 + * rely on two things: 100 + * i) this code never gets called on known boards 101 + * ii) invalid accesses to the freed areas aren't made 102 + */ 103 + flush_tlb_all(); 104 + return; 105 + } 106 + 107 + return vfree((void *)(PAGE_MASK & (unsigned long)addr)); 108 + } 109 + 110 + /** 111 + * OK, this one's a bit tricky... ioremap can get called before memory is 112 + * initialized (early serial console does this) and will want to alloc a page 113 + * for its mapping. No userspace pages will ever get allocated before memory 114 + * is initialized so this applies only to kernel pages. In the event that 115 + * this is called before memory is initialized we allocate the page using 116 + * the memblock infrastructure. 117 + */ 118 + 119 + pte_t __init_refok *pte_alloc_one_kernel(struct mm_struct *mm, 120 + unsigned long address) 121 + { 122 + pte_t *pte; 123 + 124 + if (likely(mem_init_done)) { 125 + pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT); 126 + } else { 127 + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); 128 + #if 0 129 + /* FIXME: use memblock... */ 130 + pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); 131 + #endif 132 + } 133 + 134 + if (pte) 135 + clear_page(pte); 136 + return pte; 137 + }
+193
arch/openrisc/mm/tlb.c
··· 1 + /* 2 + * OpenRISC tlb.c 3 + * 4 + * Linux architectural port borrowing liberally from similar works of 5 + * others. All original copyrights apply as per the original source 6 + * declaration. 7 + * 8 + * Modifications for the OpenRISC architecture: 9 + * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 + * Copyright (C) 2010-2011 Julius Baxter <julius.baxter@orsoc.se> 11 + * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 12 + * 13 + * This program is free software; you can redistribute it and/or 14 + * modify it under the terms of the GNU General Public License 15 + * as published by the Free Software Foundation; either version 16 + * 2 of the License, or (at your option) any later version. 17 + */ 18 + 19 + #include <linux/sched.h> 20 + #include <linux/kernel.h> 21 + #include <linux/errno.h> 22 + #include <linux/string.h> 23 + #include <linux/types.h> 24 + #include <linux/ptrace.h> 25 + #include <linux/mman.h> 26 + #include <linux/mm.h> 27 + #include <linux/init.h> 28 + 29 + #include <asm/system.h> 30 + #include <asm/segment.h> 31 + #include <asm/tlbflush.h> 32 + #include <asm/pgtable.h> 33 + #include <asm/mmu_context.h> 34 + #include <asm/spr_defs.h> 35 + 36 + #define NO_CONTEXT -1 37 + 38 + #define NUM_DTLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \ 39 + SPR_DMMUCFGR_NTS_OFF)) 40 + #define NUM_ITLB_SETS (1 << ((mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_NTS) >> \ 41 + SPR_IMMUCFGR_NTS_OFF)) 42 + #define DTLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_DTLB_SETS-1)) 43 + #define ITLB_OFFSET(addr) (((addr) >> PAGE_SHIFT) & (NUM_ITLB_SETS-1)) 44 + /* 45 + * Invalidate all TLB entries. 46 + * 47 + * This comes down to setting the 'valid' bit for all xTLBMR registers to 0. 48 + * Easiest way to accomplish this is to just zero out the xTLBMR register 49 + * completely. 50 + * 51 + */ 52 + 53 + void flush_tlb_all(void) 54 + { 55 + int i; 56 + unsigned long num_tlb_sets; 57 + 58 + /* Determine number of sets for IMMU. */ 59 + /* FIXME: Assumption is I & D nsets equal. */ 60 + num_tlb_sets = NUM_ITLB_SETS; 61 + 62 + for (i = 0; i < num_tlb_sets; i++) { 63 + mtspr_off(SPR_DTLBMR_BASE(0), i, 0); 64 + mtspr_off(SPR_ITLBMR_BASE(0), i, 0); 65 + } 66 + } 67 + 68 + #define have_dtlbeir (mfspr(SPR_DMMUCFGR) & SPR_DMMUCFGR_TEIRI) 69 + #define have_itlbeir (mfspr(SPR_IMMUCFGR) & SPR_IMMUCFGR_TEIRI) 70 + 71 + /* 72 + * Invalidate a single page. This is what the xTLBEIR register is for. 73 + * 74 + * There's no point in checking the vma for PAGE_EXEC to determine whether it's 75 + * the data or instruction TLB that should be flushed... that would take more 76 + * than the few instructions that the following compiles down to! 77 + * 78 + * The case where we don't have the xTLBEIR register really only works for 79 + * MMU's with a single way and is hard-coded that way. 80 + */ 81 + 82 + #define flush_dtlb_page_eir(addr) mtspr(SPR_DTLBEIR, addr) 83 + #define flush_dtlb_page_no_eir(addr) \ 84 + mtspr_off(SPR_DTLBMR_BASE(0), DTLB_OFFSET(addr), 0); 85 + 86 + #define flush_itlb_page_eir(addr) mtspr(SPR_ITLBEIR, addr) 87 + #define flush_itlb_page_no_eir(addr) \ 88 + mtspr_off(SPR_ITLBMR_BASE(0), ITLB_OFFSET(addr), 0); 89 + 90 + void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) 91 + { 92 + if (have_dtlbeir) 93 + flush_dtlb_page_eir(addr); 94 + else 95 + flush_dtlb_page_no_eir(addr); 96 + 97 + if (have_itlbeir) 98 + flush_itlb_page_eir(addr); 99 + else 100 + flush_itlb_page_no_eir(addr); 101 + } 102 + 103 + void flush_tlb_range(struct vm_area_struct *vma, 104 + unsigned long start, unsigned long end) 105 + { 106 + int addr; 107 + bool dtlbeir; 108 + bool itlbeir; 109 + 110 + dtlbeir = have_dtlbeir; 111 + itlbeir = have_itlbeir; 112 + 113 + for (addr = start; addr < end; addr += PAGE_SIZE) { 114 + if (dtlbeir) 115 + flush_dtlb_page_eir(addr); 116 + else 117 + flush_dtlb_page_no_eir(addr); 118 + 119 + if (itlbeir) 120 + flush_itlb_page_eir(addr); 121 + else 122 + flush_itlb_page_no_eir(addr); 123 + } 124 + } 125 + 126 + /* 127 + * Invalidate the selected mm context only. 128 + * 129 + * FIXME: Due to some bug here, we're flushing everything for now. 130 + * This should be changed to loop over over mm and call flush_tlb_range. 131 + */ 132 + 133 + void flush_tlb_mm(struct mm_struct *mm) 134 + { 135 + 136 + /* Was seeing bugs with the mm struct passed to us. Scrapped most of 137 + this function. */ 138 + /* Several architctures do this */ 139 + flush_tlb_all(); 140 + } 141 + 142 + /* called in schedule() just before actually doing the switch_to */ 143 + 144 + void switch_mm(struct mm_struct *prev, struct mm_struct *next, 145 + struct task_struct *next_tsk) 146 + { 147 + /* remember the pgd for the fault handlers 148 + * this is similar to the pgd register in some other CPU's. 149 + * we need our own copy of it because current and active_mm 150 + * might be invalid at points where we still need to derefer 151 + * the pgd. 152 + */ 153 + current_pgd = next->pgd; 154 + 155 + /* We don't have context support implemented, so flush all 156 + * entries belonging to previous map 157 + */ 158 + 159 + if (prev != next) 160 + flush_tlb_mm(prev); 161 + 162 + } 163 + 164 + /* 165 + * Initialize the context related info for a new mm_struct 166 + * instance. 167 + */ 168 + 169 + int init_new_context(struct task_struct *tsk, struct mm_struct *mm) 170 + { 171 + mm->context = NO_CONTEXT; 172 + return 0; 173 + } 174 + 175 + /* called by __exit_mm to destroy the used MMU context if any before 176 + * destroying the mm itself. this is only called when the last user of the mm 177 + * drops it. 178 + */ 179 + 180 + void destroy_context(struct mm_struct *mm) 181 + { 182 + flush_tlb_mm(mm); 183 + 184 + } 185 + 186 + /* called once during VM initialization, from init.c */ 187 + 188 + void __init tlb_init(void) 189 + { 190 + /* Do nothing... */ 191 + /* invalidate the entire TLB */ 192 + /* flush_tlb_all(); */ 193 + }