OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-ia64/] [mmu_context.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
#ifndef _ASM_IA64_MMU_CONTEXT_H
2
#define _ASM_IA64_MMU_CONTEXT_H
3
 
4
/*
5
 * Copyright (C) 1998-2002 Hewlett-Packard Co
6
 *      David Mosberger-Tang <davidm@hpl.hp.com>
7
 */
8
 
9
/*
10
 * Routines to manage the allocation of task context numbers.  Task context numbers are
11
 * used to reduce or eliminate the need to perform TLB flushes due to context switches.
12
 * Context numbers are implemented using ia-64 region ids.  Since the IA-64 TLB does not
13
 * consider the region number when performing a TLB lookup, we need to assign a unique
14
 * region id to each region in a process.  We use the least significant three bits in a
15
 * region id for this purpose.
16
 */
17
 
18
#define IA64_REGION_ID_KERNEL   0 /* the kernel's region id (tlb.c depends on this being 0) */
19
 
20
#define ia64_rid(ctx,addr)      (((ctx) << 3) | (addr >> 61))
21
 
22
# ifndef __ASSEMBLY__
23
 
24
#include <linux/sched.h>
25
#include <linux/spinlock.h>
26
 
27
#include <asm/processor.h>
28
 
29
struct ia64_ctx {
30
        spinlock_t lock;
31
        unsigned int next;      /* next context number to use */
32
        unsigned int limit;     /* next >= limit => must call wrap_mmu_context() */
33
        unsigned int max_ctx;   /* max. context value supported by all CPUs */
34
};
35
 
36
extern struct ia64_ctx ia64_ctx;
37
 
38
extern void wrap_mmu_context (struct mm_struct *mm);
39
 
40
static inline void
41
enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
42
{
43
}
44
 
45
/*
46
 * When the context counter wraps around all TLBs need to be flushed because an old
47
 * context number might have been reused. This is signalled by the ia64_need_tlb_flush
48
 * per-CPU variable, which is checked in the routine below. Called by activate_mm().
49
 * <efocht@ess.nec.de>
50
 */
51
static inline void
52
delayed_tlb_flush (void)
53
{
54
        extern void local_flush_tlb_all (void);
55
 
56
        if (unlikely(local_cpu_data->need_tlb_flush)) {
57
                local_flush_tlb_all();
58
                local_cpu_data->need_tlb_flush = 0;
59
        }
60
}
61
 
62
static inline mm_context_t
63
get_mmu_context (struct mm_struct *mm)
64
{
65
        unsigned long flags;
66
        mm_context_t context = mm->context;
67
 
68
        if (context)
69
                return context;
70
 
71
        spin_lock_irqsave(&ia64_ctx.lock, flags);
72
        {
73
                /* re-check, now that we've got the lock: */
74
                context = mm->context;
75
                if (context == 0) {
76
                        if (ia64_ctx.next >= ia64_ctx.limit)
77
                                wrap_mmu_context(mm);
78
                        mm->context = context = ia64_ctx.next++;
79
                }
80
        }
81
        spin_unlock_irqrestore(&ia64_ctx.lock, flags);
82
        return context;
83
}
84
 
85
/*
86
 * Initialize context number to some sane value.  MM is guaranteed to be a brand-new
87
 * address-space, so no TLB flushing is needed, ever.
88
 */
89
static inline int
90
init_new_context (struct task_struct *p, struct mm_struct *mm)
91
{
92
        mm->context = 0;
93
        return 0;
94
}
95
 
96
static inline void
97
destroy_context (struct mm_struct *mm)
98
{
99
        /* Nothing to do.  */
100
}
101
 
102
static inline void
103
reload_context (mm_context_t context)
104
{
105
        unsigned long rid;
106
        unsigned long rid_incr = 0;
107
        unsigned long rr0, rr1, rr2, rr3, rr4;
108
 
109
        rid = context << 3;     /* make space for encoding the region number */
110
        rid_incr = 1 << 8;
111
 
112
        /* encode the region id, preferred page size, and VHPT enable bit: */
113
        rr0 = (rid << 8) | (PAGE_SHIFT << 2) | 1;
114
        rr1 = rr0 + 1*rid_incr;
115
        rr2 = rr0 + 2*rid_incr;
116
        rr3 = rr0 + 3*rid_incr;
117
        rr4 = rr0 + 4*rid_incr;
118
#ifdef  CONFIG_HUGETLB_PAGE
119
        rr4 = (rr4 & (~(0xfcUL))) | (HPAGE_SHIFT << 2);
120
#endif
121
 
122
        ia64_set_rr(0x0000000000000000, rr0);
123
        ia64_set_rr(0x2000000000000000, rr1);
124
        ia64_set_rr(0x4000000000000000, rr2);
125
        ia64_set_rr(0x6000000000000000, rr3);
126
        ia64_set_rr(0x8000000000000000, rr4);
127
        ia64_insn_group_barrier();
128
        ia64_srlz_i();                  /* srlz.i implies srlz.d */
129
        ia64_insn_group_barrier();
130
}
131
 
132
static inline void
133
activate_context (struct mm_struct *mm)
134
{
135
        mm_context_t context;
136
 
137
        do {
138
                context = get_mmu_context(mm);
139
                reload_context(context);
140
                /* in the unlikely event of a TLB-flush by another thread, redo the load: */
141
        } while (unlikely(context != mm->context));
142
}
143
 
144
/*
145
 * Switch from address space PREV to address space NEXT.
146
 */
147
static inline void
148
activate_mm (struct mm_struct *prev, struct mm_struct *next)
149
{
150
        delayed_tlb_flush();
151
 
152
        /*
153
         * We may get interrupts here, but that's OK because interrupt handlers cannot
154
         * touch user-space.
155
         */
156
        ia64_set_kr(IA64_KR_PT_BASE, __pa(next->pgd));
157
        activate_context(next);
158
}
159
 
160
#define switch_mm(prev_mm,next_mm,next_task,cpu)        activate_mm(prev_mm, next_mm)
161
 
162
# endif /* ! __ASSEMBLY__ */
163
#endif /* _ASM_IA64_MMU_CONTEXT_H */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.