Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | /* $Id: mmu_context.h,v 1.3 1999/01/04 16:09:23 ralf Exp $ * * Switch a MMU context. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1996, 1997, 1998 by Ralf Baechle */ #ifndef __ASM_MIPS_MMU_CONTEXT_H #define __ASM_MIPS_MMU_CONTEXT_H /* Fuck. The f-word is here so you can grep for it :-) */ extern unsigned long asid_cache; /* I patch, therefore I am ... */ #define ASID_INC(asid) \ ({ unsigned long __asid = asid; \ __asm__("1:\taddiu\t%0,0\t\t\t\t# patched\n\t" \ ".section\t__asid_inc,\"a\"\n\t" \ ".word\t1b\n\t" \ ".previous" \ :"=r" (__asid) \ :"0" (__asid)); \ __asid; }) #define ASID_MASK(asid) \ ({ unsigned long __asid = asid; \ __asm__("1:\tandi\t%0,%1,0\t\t\t# patched\n\t" \ ".section\t__asid_mask,\"a\"\n\t" \ ".word\t1b\n\t" \ ".previous" \ :"=r" (__asid) \ :"r" (__asid)); \ __asid; }) #define ASID_VERSION_MASK \ ({ unsigned long __asid; \ __asm__("1:\tli\t%0,0\t\t\t\t# patched\n\t" \ ".section\t__asid_version_mask,\"a\"\n\t" \ ".word\t1b\n\t" \ ".previous" \ :"=r" (__asid)); \ __asid; }) #define ASID_FIRST_VERSION \ ({ unsigned long __asid = asid; \ __asm__("1:\tli\t%0,0\t\t\t\t# patched\n\t" \ ".section\t__asid_first_version,\"a\"\n\t" \ ".word\t1b\n\t" \ ".previous" \ :"=r" (__asid)); \ __asid; }) #define ASID_FIRST_VERSION_R3000 0x1000 #define ASID_FIRST_VERSION_R4000 0x100 extern inline void get_new_mmu_context(struct mm_struct *mm, unsigned long asid) { if (!ASID_MASK((asid = ASID_INC(asid)))) { flush_tlb_all(); /* start new asid cycle */ if (!asid) /* fix version if needed */ asid = ASID_FIRST_VERSION; } mm->context = asid_cache = asid; } extern inline void get_mmu_context(struct task_struct *p) { struct mm_struct *mm = p->mm; if (mm) { unsigned long asid = asid_cache; /* Check if our ASID is of an older version and thus invalid */ if ((mm->context ^ asid) & ASID_VERSION_MASK) get_new_mmu_context(mm, asid); } } /* * Initialize the context related info for a new mm_struct * instance. */ extern inline void init_new_context(struct mm_struct *mm) { mm->context = 0; } /* * Destroy context related info for an mm_struct that is about * to be put to rest. */ extern inline void destroy_context(struct mm_struct *mm) { mm->context = 0; } /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. */ extern inline void activate_context(struct task_struct *tsk) { get_mmu_context(tsk); set_entryhi(tsk->mm->context); } extern void __asid_setup(unsigned int inc, unsigned int mask, unsigned int version_mask, unsigned int first_version); extern inline void r3000_asid_setup(void) { __asid_setup(0x40, 0xfc0, 0xf000, ASID_FIRST_VERSION_R3000); } extern inline void r6000_asid_setup(void) { panic("r6000_asid_setup: implement me"); /* No idea ... */ } extern inline void tfp_asid_setup(void) { panic("tfp_asid_setup: implement me"); /* No idea ... */ } extern inline void r4xx0_asid_setup(void) { __asid_setup(1, 0xff, 0xff00, ASID_FIRST_VERSION_R4000); } /* R10000 has the same ASID mechanism as the R4000. */ #define andes_asid_setup r4xx0_asid_setup #endif /* __ASM_MIPS_MMU_CONTEXT_H */ |