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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [mips/] [mm/] [tlb-r3k.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * r2300.c: R2000 and R3000 specific mmu/cache code.
3
 *
4
 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
5
 *
6
 * with a lot of changes to make this thing work for R3000s
7
 * Tx39XX R4k style caches added. HK
8
 * Copyright (C) 1998, 1999, 2000 Harald Koerfgen
9
 * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
10
 * Copyright (C) 2002  Ralf Baechle
11
 * Copyright (C) 2002  Maciej W. Rozycki
12
 */
13
#include <linux/init.h>
14
#include <linux/kernel.h>
15
#include <linux/sched.h>
16
#include <linux/mm.h>
17
 
18
#include <asm/page.h>
19
#include <asm/pgtable.h>
20
#include <asm/mmu_context.h>
21
#include <asm/system.h>
22
#include <asm/isadep.h>
23
#include <asm/io.h>
24
#include <asm/bootinfo.h>
25
#include <asm/cpu.h>
26
 
27
#undef DEBUG_TLB
28
 
29
extern void build_tlb_refill_handler(void);
30
 
31
/* CP0 hazard avoidance. */
32
#define BARRIER                         \
33
        __asm__ __volatile__(           \
34
                ".set   push\n\t"       \
35
                ".set   noreorder\n\t"  \
36
                "nop\n\t"               \
37
                ".set   pop\n\t")
38
 
39
int r3k_have_wired_reg;         /* should be in cpu_data? */
40
 
41
/* TLB operations. */
42
void local_flush_tlb_all(void)
43
{
44
        unsigned long flags;
45
        unsigned long old_ctx;
46
        int entry;
47
 
48
#ifdef DEBUG_TLB
49
        printk("[tlball]");
50
#endif
51
 
52
        local_irq_save(flags);
53
        old_ctx = read_c0_entryhi() & ASID_MASK;
54
        write_c0_entrylo0(0);
55
        entry = r3k_have_wired_reg ? read_c0_wired() : 8;
56
        for (; entry < current_cpu_data.tlbsize; entry++) {
57
                write_c0_index(entry << 8);
58
                write_c0_entryhi((entry | 0x80000) << 12);
59
                BARRIER;
60
                tlb_write_indexed();
61
        }
62
        write_c0_entryhi(old_ctx);
63
        local_irq_restore(flags);
64
}
65
 
66
void local_flush_tlb_mm(struct mm_struct *mm)
67
{
68
        int cpu = smp_processor_id();
69
 
70
        if (cpu_context(cpu, mm) != 0) {
71
#ifdef DEBUG_TLB
72
                printk("[tlbmm<%lu>]", (unsigned long)cpu_context(cpu, mm));
73
#endif
74
                drop_mmu_context(mm, cpu);
75
        }
76
}
77
 
78
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
79
                           unsigned long end)
80
{
81
        struct mm_struct *mm = vma->vm_mm;
82
        int cpu = smp_processor_id();
83
 
84
        if (cpu_context(cpu, mm) != 0) {
85
                unsigned long flags;
86
                int size;
87
 
88
#ifdef DEBUG_TLB
89
                printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",
90
                        cpu_context(cpu, mm) & ASID_MASK, start, end);
91
#endif
92
                local_irq_save(flags);
93
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
94
                if (size <= current_cpu_data.tlbsize) {
95
                        int oldpid = read_c0_entryhi() & ASID_MASK;
96
                        int newpid = cpu_context(cpu, mm) & ASID_MASK;
97
 
98
                        start &= PAGE_MASK;
99
                        end += PAGE_SIZE - 1;
100
                        end &= PAGE_MASK;
101
                        while (start < end) {
102
                                int idx;
103
 
104
                                write_c0_entryhi(start | newpid);
105
                                start += PAGE_SIZE;     /* BARRIER */
106
                                tlb_probe();
107
                                idx = read_c0_index();
108
                                write_c0_entrylo0(0);
109
                                write_c0_entryhi(KSEG0);
110
                                if (idx < 0)             /* BARRIER */
111
                                        continue;
112
                                tlb_write_indexed();
113
                        }
114
                        write_c0_entryhi(oldpid);
115
                } else {
116
                        drop_mmu_context(mm, cpu);
117
                }
118
                local_irq_restore(flags);
119
        }
120
}
121
 
122
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
123
{
124
        unsigned long flags;
125
        int size;
126
 
127
#ifdef DEBUG_TLB
128
        printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", start, end);
129
#endif
130
        local_irq_save(flags);
131
        size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
132
        if (size <= current_cpu_data.tlbsize) {
133
                int pid = read_c0_entryhi();
134
 
135
                start &= PAGE_MASK;
136
                end += PAGE_SIZE - 1;
137
                end &= PAGE_MASK;
138
 
139
                while (start < end) {
140
                        int idx;
141
 
142
                        write_c0_entryhi(start);
143
                        start += PAGE_SIZE;             /* BARRIER */
144
                        tlb_probe();
145
                        idx = read_c0_index();
146
                        write_c0_entrylo0(0);
147
                        write_c0_entryhi(KSEG0);
148
                        if (idx < 0)                     /* BARRIER */
149
                                continue;
150
                        tlb_write_indexed();
151
                }
152
                write_c0_entryhi(pid);
153
        } else {
154
                local_flush_tlb_all();
155
        }
156
        local_irq_restore(flags);
157
}
158
 
159
void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
160
{
161
        int cpu = smp_processor_id();
162
 
163
        if (!vma || cpu_context(cpu, vma->vm_mm) != 0) {
164
                unsigned long flags;
165
                int oldpid, newpid, idx;
166
 
167
#ifdef DEBUG_TLB
168
                printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page);
169
#endif
170
                newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK;
171
                page &= PAGE_MASK;
172
                local_irq_save(flags);
173
                oldpid = read_c0_entryhi() & ASID_MASK;
174
                write_c0_entryhi(page | newpid);
175
                BARRIER;
176
                tlb_probe();
177
                idx = read_c0_index();
178
                write_c0_entrylo0(0);
179
                write_c0_entryhi(KSEG0);
180
                if (idx < 0)                             /* BARRIER */
181
                        goto finish;
182
                tlb_write_indexed();
183
 
184
finish:
185
                write_c0_entryhi(oldpid);
186
                local_irq_restore(flags);
187
        }
188
}
189
 
190
void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
191
{
192
        unsigned long flags;
193
        int idx, pid;
194
 
195
        /*
196
         * Handle debugger faulting in for debugee.
197
         */
198
        if (current->active_mm != vma->vm_mm)
199
                return;
200
 
201
        pid = read_c0_entryhi() & ASID_MASK;
202
 
203
#ifdef DEBUG_TLB
204
        if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) {
205
                printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",
206
                       (cpu_context(cpu, vma->vm_mm)), pid);
207
        }
208
#endif
209
 
210
        local_irq_save(flags);
211
        address &= PAGE_MASK;
212
        write_c0_entryhi(address | pid);
213
        BARRIER;
214
        tlb_probe();
215
        idx = read_c0_index();
216
        write_c0_entrylo0(pte_val(pte));
217
        write_c0_entryhi(address | pid);
218
        if (idx < 0) {                                   /* BARRIER */
219
                tlb_write_random();
220
        } else {
221
                tlb_write_indexed();
222
        }
223
        write_c0_entryhi(pid);
224
        local_irq_restore(flags);
225
}
226
 
227
void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
228
                            unsigned long entryhi, unsigned long pagemask)
229
{
230
        unsigned long flags;
231
        unsigned long old_ctx;
232
        static unsigned long wired = 0;
233
 
234
        if (r3k_have_wired_reg) {                       /* TX39XX */
235
                unsigned long old_pagemask;
236
                unsigned long w;
237
 
238
#ifdef DEBUG_TLB
239
                printk("[tlbwired<entry lo0 %8x, hi %8x\n, pagemask %8x>]\n",
240
                       entrylo0, entryhi, pagemask);
241
#endif
242
 
243
                local_irq_save(flags);
244
                /* Save old context and create impossible VPN2 value */
245
                old_ctx = read_c0_entryhi() & ASID_MASK;
246
                old_pagemask = read_c0_pagemask();
247
                w = read_c0_wired();
248
                write_c0_wired(w + 1);
249
                if (read_c0_wired() != w + 1) {
250
                        printk("[tlbwired] No WIRED reg?\n");
251
                        return;
252
                }
253
                write_c0_index(w << 8);
254
                write_c0_pagemask(pagemask);
255
                write_c0_entryhi(entryhi);
256
                write_c0_entrylo0(entrylo0);
257
                BARRIER;
258
                tlb_write_indexed();
259
 
260
                write_c0_entryhi(old_ctx);
261
                write_c0_pagemask(old_pagemask);
262
                local_flush_tlb_all();
263
                local_irq_restore(flags);
264
 
265
        } else if (wired < 8) {
266
#ifdef DEBUG_TLB
267
                printk("[tlbwired<entry lo0 %8x, hi %8x\n>]\n",
268
                       entrylo0, entryhi);
269
#endif
270
 
271
                local_irq_save(flags);
272
                old_ctx = read_c0_entryhi() & ASID_MASK;
273
                write_c0_entrylo0(entrylo0);
274
                write_c0_entryhi(entryhi);
275
                write_c0_index(wired);
276
                wired++;                                /* BARRIER */
277
                tlb_write_indexed();
278
                write_c0_entryhi(old_ctx);
279
                local_flush_tlb_all();
280
                local_irq_restore(flags);
281
        }
282
}
283
 
284
void __init tlb_init(void)
285
{
286
        local_flush_tlb_all();
287
 
288
        build_tlb_refill_handler();
289
}

powered by: WebSVN 2.1.0

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