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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.