···22#define __ASM_POWERPC_MMU_CONTEXT_H33#ifdef __KERNEL__4455+#include <asm/mmu.h> 66+#include <asm/cputable.h>77+#include <asm-generic/mm_hooks.h>88+59#ifndef CONFIG_PPC6466-#include <asm-ppc/mmu_context.h>1010+#include <asm/atomic.h>1111+#include <asm/bitops.h>1212+1313+/*1414+ * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs1515+ * (virtual segment identifiers) for each context. Although the1616+ * hardware supports 24-bit VSIDs, and thus >1 million contexts,1717+ * we only use 32,768 of them. That is ample, since there can be1818+ * at most around 30,000 tasks in the system anyway, and it means1919+ * that we can use a bitmap to indicate which contexts are in use.2020+ * Using a bitmap means that we entirely avoid all of the problems2121+ * that we used to have when the context number overflowed,2222+ * particularly on SMP systems.2323+ * -- paulus.2424+ */2525+2626+/*2727+ * This function defines the mapping from contexts to VSIDs (virtual2828+ * segment IDs). We use a skew on both the context and the high 4 bits2929+ * of the 32-bit virtual address (the "effective segment ID") in order3030+ * to spread out the entries in the MMU hash table. Note, if this3131+ * function is changed then arch/ppc/mm/hashtable.S will have to be3232+ * changed to correspond.3333+ */3434+#define CTX_TO_VSID(ctx, va) (((ctx) * (897 * 16) + ((va) >> 28) * 0x111) \3535+ & 0xffffff)3636+3737+/*3838+ The MPC8xx has only 16 contexts. We rotate through them on each3939+ task switch. A better way would be to keep track of tasks that4040+ own contexts, and implement an LRU usage. That way very active4141+ tasks don't always have to pay the TLB reload overhead. The4242+ kernel pages are mapped shared, so the kernel can run on behalf4343+ of any task that makes a kernel entry. Shared does not mean they4444+ are not protected, just that the ASID comparison is not performed.4545+ -- Dan4646+4747+ The IBM4xx has 256 contexts, so we can just rotate through these4848+ as a way of "switching" contexts. If the TID of the TLB is zero,4949+ the PID/TID comparison is disabled, so we can use a TID of zero5050+ to represent all kernel pages as shared among all contexts.5151+ -- Dan5252+ */5353+5454+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)5555+{5656+}5757+5858+#ifdef CONFIG_8xx5959+#define NO_CONTEXT 166060+#define LAST_CONTEXT 156161+#define FIRST_CONTEXT 06262+6363+#elif defined(CONFIG_4xx)6464+#define NO_CONTEXT 2566565+#define LAST_CONTEXT 2556666+#define FIRST_CONTEXT 16767+6868+#elif defined(CONFIG_E200) || defined(CONFIG_E500)6969+#define NO_CONTEXT 2567070+#define LAST_CONTEXT 2557171+#define FIRST_CONTEXT 17272+7373+#else7474+7575+/* PPC 6xx, 7xx CPUs */7676+#define NO_CONTEXT ((unsigned long) -1)7777+#define LAST_CONTEXT 327677878+#define FIRST_CONTEXT 17979+#endif8080+8181+/*8282+ * Set the current MMU context.8383+ * On 32-bit PowerPCs (other than the 8xx embedded chips), this is done by8484+ * loading up the segment registers for the user part of the address space.8585+ *8686+ * Since the PGD is immediately available, it is much faster to simply8787+ * pass this along as a second parameter, which is required for 8xx and8888+ * can be used for debugging on all processors (if you happen to have8989+ * an Abatron).9090+ */9191+extern void set_context(unsigned long contextid, pgd_t *pgd);9292+9393+/*9494+ * Bitmap of contexts in use.9595+ * The size of this bitmap is LAST_CONTEXT + 1 bits.9696+ */9797+extern unsigned long context_map[];9898+9999+/*100100+ * This caches the next context number that we expect to be free.101101+ * Its use is an optimization only, we can't rely on this context102102+ * number to be free, but it usually will be.103103+ */104104+extern unsigned long next_mmu_context;105105+106106+/*107107+ * If we don't have sufficient contexts to give one to every task108108+ * that could be in the system, we need to be able to steal contexts.109109+ * These variables support that.110110+ */111111+#if LAST_CONTEXT < 30000112112+#define FEW_CONTEXTS 1113113+extern atomic_t nr_free_contexts;114114+extern struct mm_struct *context_mm[LAST_CONTEXT+1];115115+extern void steal_context(void);116116+#endif117117+118118+/*119119+ * Get a new mmu context for the address space described by `mm'.120120+ */121121+static inline void get_mmu_context(struct mm_struct *mm)122122+{123123+ unsigned long ctx;124124+125125+ if (mm->context.id != NO_CONTEXT)126126+ return;127127+#ifdef FEW_CONTEXTS128128+ while (atomic_dec_if_positive(&nr_free_contexts) < 0)129129+ steal_context();130130+#endif131131+ ctx = next_mmu_context;132132+ while (test_and_set_bit(ctx, context_map)) {133133+ ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);134134+ if (ctx > LAST_CONTEXT)135135+ ctx = 0;136136+ }137137+ next_mmu_context = (ctx + 1) & LAST_CONTEXT;138138+ mm->context.id = ctx;139139+#ifdef FEW_CONTEXTS140140+ context_mm[ctx] = mm;141141+#endif142142+}143143+144144+/*145145+ * Set up the context for a new address space.146146+ */147147+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)148148+{149149+ mm->context.id = NO_CONTEXT;150150+ mm->context.vdso_base = 0;151151+ return 0;152152+}153153+154154+/*155155+ * We're finished using the context for an address space.156156+ */157157+static inline void destroy_context(struct mm_struct *mm)158158+{159159+ preempt_disable();160160+ if (mm->context.id != NO_CONTEXT) {161161+ clear_bit(mm->context.id, context_map);162162+ mm->context.id = NO_CONTEXT;163163+#ifdef FEW_CONTEXTS164164+ atomic_inc(&nr_free_contexts);165165+#endif166166+ }167167+ preempt_enable();168168+}169169+170170+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,171171+ struct task_struct *tsk)172172+{173173+#ifdef CONFIG_ALTIVEC174174+ if (cpu_has_feature(CPU_FTR_ALTIVEC))175175+ asm volatile ("dssall;\n"176176+#ifndef CONFIG_POWER4177177+ "sync;\n" /* G4 needs a sync here, G5 apparently not */178178+#endif179179+ : : );180180+#endif /* CONFIG_ALTIVEC */181181+182182+ tsk->thread.pgdir = next->pgd;183183+184184+ /* No need to flush userspace segments if the mm doesnt change */185185+ if (prev == next)186186+ return;187187+188188+ /* Setup new userspace context */189189+ get_mmu_context(next);190190+ set_context(next->context.id, next->pgd);191191+}192192+193193+#define deactivate_mm(tsk,mm) do { } while (0)194194+195195+/*196196+ * After we have set current->mm to a new value, this activates197197+ * the context for the new mm so we see the new mappings.198198+ */199199+#define activate_mm(active_mm, mm) switch_mm(active_mm, mm, current)200200+201201+extern void mmu_context_init(void);202202+203203+7204#else82059206#include <linux/kernel.h> 10207#include <linux/mm.h> 11208#include <linux/sched.h>1212-#include <asm/mmu.h> 1313-#include <asm/cputable.h>1414-#include <asm-generic/mm_hooks.h>1520916210/*17211 * Copyright (C) 2001 PPC 64 Team, IBM Corp