~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-ia64/mmu_context.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _ASM_IA64_MMU_CONTEXT_H
  2 #define _ASM_IA64_MMU_CONTEXT_H
  3 
  4 /*
  5  * Copyright (C) 1998-2000 Hewlett-Packard Co
  6  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  7  */
  8 
  9 #include <linux/sched.h>
 10 #include <linux/spinlock.h>
 11 
 12 #include <asm/processor.h>
 13 
 14 /*
 15  * Routines to manage the allocation of task context numbers.  Task
 16  * context numbers are used to reduce or eliminate the need to perform
 17  * TLB flushes due to context switches.  Context numbers are
 18  * implemented using ia-64 region ids.  Since ia-64 TLBs do not
 19  * guarantee that the region number is checked when performing a TLB
 20  * lookup, we need to assign a unique region id to each region in a
 21  * process.  We use the least significant three bits in a region id
 22  * for this purpose.  On processors where the region number is checked
 23  * in TLB lookups, we can get back those two bits by defining
 24  * CONFIG_IA64_TLB_CHECKS_REGION_NUMBER.  The macro
 25  * IA64_REGION_ID_BITS gives the number of bits in a region id.  The
 26  * architecture manual guarantees this number to be in the range
 27  * 18-24.
 28  *
 29  * Copyright (C) 1998 David Mosberger-Tang <davidm@hpl.hp.com>
 30  */
 31 
 32 #define IA64_REGION_ID_KERNEL   0 /* the kernel's region id (tlb.c depends on this being 0) */
 33 
 34 struct ia64_ctx {
 35         spinlock_t lock;
 36         unsigned int next;      /* next context number to use */
 37         unsigned int limit;     /* next >= limit => must call wrap_mmu_context() */
 38         unsigned int max_ctx;   /* max. context value supported by all CPUs */
 39 };
 40 
 41 extern struct ia64_ctx ia64_ctx;
 42 
 43 extern void wrap_mmu_context (struct mm_struct *mm);
 44 
 45 static inline void
 46 enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
 47 {
 48 }
 49 
 50 static inline unsigned long
 51 ia64_rid (unsigned long context, unsigned long region_addr)
 52 {
 53         return context << 3 | (region_addr >> 61);
 54 }
 55 
 56 static inline void
 57 get_new_mmu_context (struct mm_struct *mm)
 58 {
 59         spin_lock(&ia64_ctx.lock);
 60         {
 61                 if (ia64_ctx.next >= ia64_ctx.limit)
 62                         wrap_mmu_context(mm);
 63                 mm->context = ia64_ctx.next++;
 64         }
 65         spin_unlock(&ia64_ctx.lock);
 66 
 67 }
 68 
 69 static inline void
 70 get_mmu_context (struct mm_struct *mm)
 71 {
 72         /* check if our ASN is of an older generation and thus invalid: */
 73         if (mm->context == 0)
 74                 get_new_mmu_context(mm);
 75 }
 76 
 77 static inline int
 78 init_new_context (struct task_struct *p, struct mm_struct *mm)
 79 {
 80         mm->context = 0;
 81         return 0;
 82 }
 83 
 84 static inline void
 85 destroy_context (struct mm_struct *mm)
 86 {
 87         /* Nothing to do.  */
 88 }
 89 
 90 static inline void
 91 reload_context (struct mm_struct *mm)
 92 {
 93         unsigned long rid;
 94         unsigned long rid_incr = 0;
 95         unsigned long rr0, rr1, rr2, rr3, rr4;
 96 
 97         rid = mm->context << 3; /* make space for encoding the region number */
 98         rid_incr = 1 << 8;
 99 
100         /* encode the region id, preferred page size, and VHPT enable bit: */
101         rr0 = (rid << 8) | (PAGE_SHIFT << 2) | 1;
102         rr1 = rr0 + 1*rid_incr;
103         rr2 = rr0 + 2*rid_incr;
104         rr3 = rr0 + 3*rid_incr;
105         rr4 = rr0 + 4*rid_incr;
106         ia64_set_rr(0x0000000000000000, rr0);
107         ia64_set_rr(0x2000000000000000, rr1);
108         ia64_set_rr(0x4000000000000000, rr2);
109         ia64_set_rr(0x6000000000000000, rr3);
110         ia64_set_rr(0x8000000000000000, rr4);
111         ia64_insn_group_barrier();
112         ia64_srlz_i();                  /* srlz.i implies srlz.d */
113         ia64_insn_group_barrier();
114 }
115 
116 /*
117  * Switch from address space PREV to address space NEXT.
118  */
119 static inline void
120 activate_mm (struct mm_struct *prev, struct mm_struct *next)
121 {
122         /*
123          * We may get interrupts here, but that's OK because interrupt
124          * handlers cannot touch user-space.
125          */
126         __asm__ __volatile__ ("mov ar.k7=%0" :: "r"(__pa(next->pgd)));
127         get_mmu_context(next);
128         reload_context(next);
129 }
130 
131 #define switch_mm(prev_mm,next_mm,next_task,cpu)        activate_mm(prev_mm, next_mm)
132 
133 #endif /* _ASM_IA64_MMU_CONTEXT_H */
134 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.