Viewing file: mmu_context.h (2.82 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * 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, 1999 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ #ifndef _ASM_MMU_CONTEXT_H #define _ASM_MMU_CONTEXT_H
#include <linux/config.h> #include <linux/slab.h> #include <asm/pgalloc.h>
/* Fuck. The f-word is here so you can grep for it :-) */ extern unsigned long asid_cache; extern pgd_t *current_pgd[];
#if defined(CONFIG_CPU_R3000)
#define ASID_INC 0x40 #define ASID_MASK 0xfc0
#else /* FIXME: not correct for R6000, R8000 */
#define ASID_INC 0x1 #define ASID_MASK 0xff
#endif
static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu) { }
/* * All unused by hardware upper bits will be considered * as a software asid extension. */ #define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1))) #define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
extern inline void get_new_mmu_context(struct mm_struct *mm, unsigned long asid) { if (! ((asid += ASID_INC) & ASID_MASK) ) { flush_tlb_all(); /* start new asid cycle */ if (!asid) /* fix version if needed */ asid = ASID_FIRST_VERSION; } mm->context = asid_cache = asid; }
/* * Initialize the context related info for a new mm_struct * instance. */ extern inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { #ifndef CONFIG_SMP mm->context = 0; #else mm->context = (unsigned long)kmalloc(smp_num_cpus * sizeof(unsigned long), GFP_KERNEL); /* * Init the "context" values so that a tlbpid allocation * happens on the first switch. */ if (mm->context == 0) return -ENOMEM; memset((void *)mm->context, 0, smp_num_cpus * sizeof(unsigned long)); #endif return 0; }
extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu) { unsigned long asid = asid_cache;
/* Check if our ASID is of an older version and thus invalid */ if ((next->context ^ asid) & ASID_VERSION_MASK) get_new_mmu_context(next, asid);
current_pgd[cpu] = next->pgd; set_entryhi(next->context); }
/* * 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) { /* Nothing to do. */ }
/* * 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_mm(struct mm_struct *prev, struct mm_struct *next) { /* Unconditionally get a new ASID. */ get_new_mmu_context(next, asid_cache);
current_pgd[smp_processor_id()] = next->pgd; set_entryhi(next->context); }
#endif /* _ASM_MMU_CONTEXT_H */
|