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

microblaze_mmu_v2: Context handling - mmu_context.c/h

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

+238 -21
+5 -21
arch/microblaze/include/asm/mmu_context.h
··· 1 - /* 2 - * Copyright (C) 2006 Atmark Techno, Inc. 3 - * 4 - * This file is subject to the terms and conditions of the GNU General Public 5 - * License. See the file "COPYING" in the main directory of this archive 6 - * for more details. 7 - */ 8 - 9 - #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H 10 - #define _ASM_MICROBLAZE_MMU_CONTEXT_H 11 - 12 - # define init_new_context(tsk, mm) ({ 0; }) 13 - 14 - # define enter_lazy_tlb(mm, tsk) do {} while (0) 15 - # define change_mm_context(old, ctx, _pml4) do {} while (0) 16 - # define destroy_context(mm) do {} while (0) 17 - # define deactivate_mm(tsk, mm) do {} while (0) 18 - # define switch_mm(prev, next, tsk) do {} while (0) 19 - # define activate_mm(prev, next) do {} while (0) 20 - 21 - #endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */ 1 + #ifdef CONFIG_MMU 2 + # include "mmu_context_mm.h" 3 + #else 4 + # include "mmu_context_no.h" 5 + #endif
+140
arch/microblaze/include/asm/mmu_context_mm.h
··· 1 + /* 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 4 + * Copyright (C) 2006 Atmark Techno, Inc. 5 + * 6 + * This file is subject to the terms and conditions of the GNU General Public 7 + * License. See the file "COPYING" in the main directory of this archive 8 + * for more details. 9 + */ 10 + 11 + #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H 12 + #define _ASM_MICROBLAZE_MMU_CONTEXT_H 13 + 14 + #include <asm/atomic.h> 15 + #include <asm/bitops.h> 16 + #include <asm/mmu.h> 17 + #include <asm-generic/mm_hooks.h> 18 + 19 + # ifdef __KERNEL__ 20 + /* 21 + * This function defines the mapping from contexts to VSIDs (virtual 22 + * segment IDs). We use a skew on both the context and the high 4 bits 23 + * of the 32-bit virtual address (the "effective segment ID") in order 24 + * to spread out the entries in the MMU hash table. 25 + */ 26 + # define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \ 27 + & 0xffffff) 28 + 29 + /* 30 + MicroBlaze has 256 contexts, so we can just rotate through these 31 + as a way of "switching" contexts. If the TID of the TLB is zero, 32 + the PID/TID comparison is disabled, so we can use a TID of zero 33 + to represent all kernel pages as shared among all contexts. 34 + */ 35 + 36 + static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) 37 + { 38 + } 39 + 40 + # define NO_CONTEXT 256 41 + # define LAST_CONTEXT 255 42 + # define FIRST_CONTEXT 1 43 + 44 + /* 45 + * Set the current MMU context. 46 + * This is done byloading up the segment registers for the user part of the 47 + * address space. 48 + * 49 + * Since the PGD is immediately available, it is much faster to simply 50 + * pass this along as a second parameter, which is required for 8xx and 51 + * can be used for debugging on all processors (if you happen to have 52 + * an Abatron). 53 + */ 54 + extern void set_context(mm_context_t context, pgd_t *pgd); 55 + 56 + /* 57 + * Bitmap of contexts in use. 58 + * The size of this bitmap is LAST_CONTEXT + 1 bits. 59 + */ 60 + extern unsigned long context_map[]; 61 + 62 + /* 63 + * This caches the next context number that we expect to be free. 64 + * Its use is an optimization only, we can't rely on this context 65 + * number to be free, but it usually will be. 66 + */ 67 + extern mm_context_t next_mmu_context; 68 + 69 + /* 70 + * Since we don't have sufficient contexts to give one to every task 71 + * that could be in the system, we need to be able to steal contexts. 72 + * These variables support that. 73 + */ 74 + extern atomic_t nr_free_contexts; 75 + extern struct mm_struct *context_mm[LAST_CONTEXT+1]; 76 + extern void steal_context(void); 77 + 78 + /* 79 + * Get a new mmu context for the address space described by `mm'. 80 + */ 81 + static inline void get_mmu_context(struct mm_struct *mm) 82 + { 83 + mm_context_t ctx; 84 + 85 + if (mm->context != NO_CONTEXT) 86 + return; 87 + while (atomic_dec_if_positive(&nr_free_contexts) < 0) 88 + steal_context(); 89 + ctx = next_mmu_context; 90 + while (test_and_set_bit(ctx, context_map)) { 91 + ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx); 92 + if (ctx > LAST_CONTEXT) 93 + ctx = 0; 94 + } 95 + next_mmu_context = (ctx + 1) & LAST_CONTEXT; 96 + mm->context = ctx; 97 + context_mm[ctx] = mm; 98 + } 99 + 100 + /* 101 + * Set up the context for a new address space. 102 + */ 103 + # define init_new_context(tsk, mm) (((mm)->context = NO_CONTEXT), 0) 104 + 105 + /* 106 + * We're finished using the context for an address space. 107 + */ 108 + static inline void destroy_context(struct mm_struct *mm) 109 + { 110 + if (mm->context != NO_CONTEXT) { 111 + clear_bit(mm->context, context_map); 112 + mm->context = NO_CONTEXT; 113 + atomic_inc(&nr_free_contexts); 114 + } 115 + } 116 + 117 + static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 118 + struct task_struct *tsk) 119 + { 120 + tsk->thread.pgdir = next->pgd; 121 + get_mmu_context(next); 122 + set_context(next->context, next->pgd); 123 + } 124 + 125 + /* 126 + * After we have set current->mm to a new value, this activates 127 + * the context for the new mm so we see the new mappings. 128 + */ 129 + static inline void activate_mm(struct mm_struct *active_mm, 130 + struct mm_struct *mm) 131 + { 132 + current->thread.pgdir = mm->pgd; 133 + get_mmu_context(mm); 134 + set_context(mm->context, mm->pgd); 135 + } 136 + 137 + extern void mmu_context_init(void); 138 + 139 + # endif /* __KERNEL__ */ 140 + #endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
+23
arch/microblaze/include/asm/mmu_context_no.h
··· 1 + /* 2 + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> 3 + * Copyright (C) 2008-2009 PetaLogix 4 + * Copyright (C) 2006 Atmark Techno, Inc. 5 + * 6 + * This file is subject to the terms and conditions of the GNU General Public 7 + * License. See the file "COPYING" in the main directory of this archive 8 + * for more details. 9 + */ 10 + 11 + #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H 12 + #define _ASM_MICROBLAZE_MMU_CONTEXT_H 13 + 14 + # define init_new_context(tsk, mm) ({ 0; }) 15 + 16 + # define enter_lazy_tlb(mm, tsk) do {} while (0) 17 + # define change_mm_context(old, ctx, _pml4) do {} while (0) 18 + # define destroy_context(mm) do {} while (0) 19 + # define deactivate_mm(tsk, mm) do {} while (0) 20 + # define switch_mm(prev, next, tsk) do {} while (0) 21 + # define activate_mm(prev, next) do {} while (0) 22 + 23 + #endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
+70
arch/microblaze/mm/mmu_context.c
··· 1 + /* 2 + * This file contains the routines for handling the MMU. 3 + * 4 + * Copyright (C) 2007 Xilinx, Inc. All rights reserved. 5 + * 6 + * Derived from arch/ppc/mm/4xx_mmu.c: 7 + * -- paulus 8 + * 9 + * Derived from arch/ppc/mm/init.c: 10 + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 11 + * 12 + * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) 13 + * and Cort Dougan (PReP) (cort@cs.nmt.edu) 14 + * Copyright (C) 1996 Paul Mackerras 15 + * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). 16 + * 17 + * Derived from "arch/i386/mm/init.c" 18 + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 19 + * 20 + * This program is free software; you can redistribute it and/or 21 + * modify it under the terms of the GNU General Public License 22 + * as published by the Free Software Foundation; either version 23 + * 2 of the License, or (at your option) any later version. 24 + * 25 + */ 26 + 27 + #include <linux/mm.h> 28 + #include <linux/init.h> 29 + 30 + #include <asm/tlbflush.h> 31 + #include <asm/mmu_context.h> 32 + 33 + mm_context_t next_mmu_context; 34 + unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; 35 + atomic_t nr_free_contexts; 36 + struct mm_struct *context_mm[LAST_CONTEXT+1]; 37 + 38 + /* 39 + * Initialize the context management stuff. 40 + */ 41 + void __init mmu_context_init(void) 42 + { 43 + /* 44 + * The use of context zero is reserved for the kernel. 45 + * This code assumes FIRST_CONTEXT < 32. 46 + */ 47 + context_map[0] = (1 << FIRST_CONTEXT) - 1; 48 + next_mmu_context = FIRST_CONTEXT; 49 + atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1); 50 + } 51 + 52 + /* 53 + * Steal a context from a task that has one at the moment. 54 + * 55 + * This isn't an LRU system, it just frees up each context in 56 + * turn (sort-of pseudo-random replacement :). This would be the 57 + * place to implement an LRU scheme if anyone were motivated to do it. 58 + */ 59 + void steal_context(void) 60 + { 61 + struct mm_struct *mm; 62 + 63 + /* free up context `next_mmu_context' */ 64 + /* if we shouldn't free context 0, don't... */ 65 + if (next_mmu_context < FIRST_CONTEXT) 66 + next_mmu_context = FIRST_CONTEXT; 67 + mm = context_mm[next_mmu_context]; 68 + flush_tlb_mm(mm); 69 + destroy_context(mm); 70 + }