]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/mips/mips/tlb.S
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / mips / mips / tlb.S
1 /*      $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $        */
2 /*-
3  * Copyright (c) 1992, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Digital Equipment Corporation and Ralph Campbell.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Copyright (C) 1989 Digital Equipment Corporation.
34  * Permission to use, copy, modify, and distribute this software and
35  * its documentation for any purpose and without fee is hereby granted,
36  * provided that the above copyright notice appears in all copies.
37  * Digital Equipment Corporation makes no representations about the
38  * suitability of this software for any purpose.  It is provided "as is"
39  * without express or implied warranty.
40  *
41  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
42  *      v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
43  * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
44  *      v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
45  * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
46  *      v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
47  *
48  *      from: @(#)locore.s      8.5 (Berkeley) 1/4/94
49  *      JNPR: tlb.S,v 1.1.4.2 2007/09/10 09:02:05 girish
50  * $FreeBSD$
51  */
52
53 /*
54  *      Contains code that is the first executed at boot time plus
55  *      assembly language support routines.
56  */
57
58 #include "opt_cputype.h"
59
60 #include <machine/asm.h>
61 #include <machine/cpu.h>
62 #include <machine/cpuregs.h>
63 #include <machine/regnum.h>
64 #include <machine/pte.h>
65
66 #include "assym.s"
67
68 #if defined(ISA_MIPS32)
69 #undef WITH_64BIT_CP0
70 #elif defined(ISA_MIPS64)
71 #define WITH_64BIT_CP0
72 #elif defined(ISA_MIPS3)
73 #define WITH_64BIT_CP0
74 #else
75 #error "Please write the code for this ISA"
76 #endif
77
78 #ifdef WITH_64BIT_CP0
79 #define _SLL    dsll
80 #define _SRL    dsrl
81 #define _MFC0   dmfc0
82 #define _MTC0   dmtc0
83 #define WIRED_SHIFT 34
84 #define PAGE_SHIFT 34
85 #else
86 #define _SLL    sll
87 #define _SRL    srl
88 #define _MFC0   mfc0
89 #define _MTC0   mtc0
90 #define WIRED_SHIFT 2
91 #define PAGE_SHIFT 2
92 #endif
93         .set    noreorder                       # Noreorder is default style!
94 #if defined(ISA_MIPS32)
95         .set    mips32
96 #elif defined(ISA_MIPS64)
97         .set    mips64
98 #elif defined(ISA_MIPS3)
99         .set    mips3
100 #endif
101
102 #define ITLBNOPFIX      nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
103
104 /*
105  * FREEBSD_DEVELOPERS_FIXME
106  * Some MIPS CPU may need delays using nops between executing CP0 Instructions
107  */
108 #define MIPS_CPU_NOP_DELAY      nop;nop;nop;nop;
109
110 /*--------------------------------------------------------------------------
111  *
112  * Mips_TLBWriteIndexed(unsigned index, tlb *tlb);
113  *
114  *      Write the given entry into the TLB at the given index.
115  *
116  * Results:
117  *      None.
118  *
119  * Side effects:
120  *      TLB entry set.
121  *
122  *--------------------------------------------------------------------------
123  */
124 LEAF(Mips_TLBWriteIndexed)
125         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
126         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
127         ITLBNOPFIX
128         lw      a2, 8(a1)
129         lw      a3, 12(a1)
130         _MFC0   t0, COP_0_TLB_HI                # Save the current PID.
131
132         _MTC0   a2, COP_0_TLB_LO0               # Set up entry low0.
133         _MTC0   a3, COP_0_TLB_LO1               # Set up entry low1.
134         lw      a2, 0(a1)
135         lw      a3, 4(a1)
136         mtc0    a0, COP_0_TLB_INDEX             # Set the index.
137         _MTC0   a2, COP_0_TLB_PG_MASK           # Set up entry mask.
138         _MTC0   a3, COP_0_TLB_HI                # Set up entry high.
139         MIPS_CPU_NOP_DELAY
140         tlbwi                                   # Write the TLB
141         MIPS_CPU_NOP_DELAY
142
143         _MTC0   t0, COP_0_TLB_HI                # Restore the PID.
144         nop
145         _MTC0   zero, COP_0_TLB_PG_MASK         # Default mask value.
146         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
147         ITLBNOPFIX
148         j       ra
149         nop
150 END(Mips_TLBWriteIndexed)
151
152 /*--------------------------------------------------------------------------
153  *
154  * Mips_SetPID(int pid);
155  *
156  *      Write the given pid into the TLB pid reg.
157  *
158  * Results:
159  *      None.
160  *
161  * Side effects:
162  *      PID set in the entry hi register.
163  *
164  *--------------------------------------------------------------------------
165  */
166 LEAF(Mips_SetPID)
167         _MTC0   a0, COP_0_TLB_HI                # Write the hi reg value
168         nop                                     # required for QED5230
169         nop                                     # required for QED5230
170         j       ra
171         nop
172 END(Mips_SetPID)
173
174 /*--------------------------------------------------------------------------
175  *
176  * Mips_SetWIRED(int wired);
177  *
178  *      Write the given value into the TLB wired reg.
179  *
180  * Results:
181  *      None.
182  *
183  * Side effects:
184  *      WIRED set in the wired register.
185  *
186  *--------------------------------------------------------------------------
187  */
188 LEAF(Mips_SetWIRED)
189         mtc0    a0, COP_0_TLB_WIRED
190         j       ra
191         nop
192 END(Mips_SetWIRED)
193
194 /*--------------------------------------------------------------------------
195  *
196  * Mips_GetWIRED(void);
197  *
198  *      Get the value from the TLB wired reg.
199  *
200  * Results:
201  *      Value of wired reg.
202  *
203  * Side effects:
204  *      None.
205  *
206  *--------------------------------------------------------------------------
207  */
208 LEAF(Mips_GetWIRED)
209         mfc0    v0, COP_0_TLB_WIRED
210         j       ra
211         nop
212 END(Mips_GetWIRED)
213
214 /*--------------------------------------------------------------------------
215  *
216  * Mips_TLBFlush(tlbsize);
217  *
218  *      Flush the "random" entries from the TLB.
219  *      Uses "wired" register to determine what register to start with.
220  *      Arg "tlbsize" is the number of entries to flush.
221  *
222  * Results:
223  *      None.
224  *
225  * Side effects:
226  *      The TLB is flushed.
227  *
228  *--------------------------------------------------------------------------
229  */
230 LEAF(Mips_TLBFlush)
231         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
232         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
233         ITLBNOPFIX
234         mfc0    t1, COP_0_TLB_WIRED
235         li      v0, MIPS_KSEG3_START + 0x0fff0000 # invalid address
236         _MFC0   t0, COP_0_TLB_HI                # Save the PID
237
238         _MTC0   v0, COP_0_TLB_HI                # Mark entry high as invalid
239         _MTC0   zero, COP_0_TLB_LO0             # Zero out low entry0.
240         _MTC0   zero, COP_0_TLB_LO1             # Zero out low entry1.
241         mtc0    zero, COP_0_TLB_PG_MASK         # Zero out mask entry.
242 /*
243  * Align the starting value (t1) and the upper bound (a0).
244  */
245 1:
246         mtc0    t1, COP_0_TLB_INDEX             # Set the index register.
247         ITLBNOPFIX
248         _MTC0   t0, COP_0_TLB_HI                # Restore the PID
249         addu    t1, t1, 1                       # Increment index.
250         addu    t0, t0, 8 * 1024
251         MIPS_CPU_NOP_DELAY
252         tlbwi                                   # Write the TLB entry.
253         MIPS_CPU_NOP_DELAY
254         bne     t1, a0, 1b
255         nop
256
257         _MTC0   t0, COP_0_TLB_HI                # Restore the PID
258         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
259         ITLBNOPFIX
260         j       ra
261         nop
262 END(Mips_TLBFlush)
263
264
265 /*--------------------------------------------------------------------------
266  *
267  * Mips_TLBFlushAddr(unsigned TLBhi);
268  *
269  *      Flush any TLB entries for the given address and TLB PID.
270  *
271  * Results:
272  *      None.
273  *
274  * Side effects:
275  *      The process's page is flushed from the TLB.
276  *
277  *--------------------------------------------------------------------------
278  */
279 LEAF(Mips_TLBFlushAddr)
280         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
281         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
282         ITLBNOPFIX
283         li      v0, (PTE_HVPN | PTE_ASID)
284         and     a0, a0, v0                      # Make shure valid hi value.
285         _MFC0   t0, COP_0_TLB_HI                # Get current PID
286         mfc0    t3, COP_0_TLB_PG_MASK           # Save current pgMask
287         _MTC0   a0, COP_0_TLB_HI                # look for addr & PID
288         MIPS_CPU_NOP_DELAY
289         tlbp                                    # Probe for the entry.
290         MIPS_CPU_NOP_DELAY
291         mfc0    v0, COP_0_TLB_INDEX             # See what we got
292         li      t1, MIPS_KSEG0_START + 0x0fff0000
293         bltz    v0, 1f                          # index < 0 => !found
294         nop
295         # Load invalid entry, each TLB entry should have it's own bogus 
296         # address calculated by following expression:
297         # MIPS_KSEG0_START + 0x0fff0000 + 2 * i * PAGE_SIZE;
298         # One bogus value for every TLB entry might cause MCHECK exception
299         sll     v0, PAGE_SHIFT + 1
300         addu    t1, v0
301         _MTC0   t1, COP_0_TLB_HI                # Mark entry high as invalid
302
303         _MTC0   zero, COP_0_TLB_LO0             # Zero out low entry.
304         _MTC0   zero, COP_0_TLB_LO1             # Zero out low entry.
305         MIPS_CPU_NOP_DELAY
306         tlbwi
307         MIPS_CPU_NOP_DELAY
308 1:
309         _MTC0   t0, COP_0_TLB_HI                # restore PID
310         mtc0    t3, COP_0_TLB_PG_MASK           # Restore pgMask
311         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
312         ITLBNOPFIX
313         j       ra
314         nop
315 END(Mips_TLBFlushAddr)
316
317 /*--------------------------------------------------------------------------
318  *
319  * Mips_TLBUpdate(unsigned virpageadr, lowregx);
320  *
321  *      Update the TLB if highreg is found; otherwise, enter the data.
322  *
323  * Results:
324  *      < 0 if loaded >= 0 if updated.
325  *
326  * Side effects:
327  *      None.
328  *
329  *--------------------------------------------------------------------------
330  */
331 LEAF(Mips_TLBUpdate)
332         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
333         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
334         ITLBNOPFIX
335         and     t1, a0, 0x1000                  # t1 = Even/Odd flag
336         li      v0, (PTE_HVPN | PTE_ASID)
337         and     a0, a0, v0
338         _MFC0   t0, COP_0_TLB_HI                # Save current PID
339         _MTC0   a0, COP_0_TLB_HI                # Init high reg
340         and     a2, a1, PTE_G                   # Copy global bit
341         MIPS_CPU_NOP_DELAY
342         tlbp                                    # Probe for the entry.
343         _SLL    a1, a1, WIRED_SHIFT
344         _SRL    a1, a1, WIRED_SHIFT
345         nop
346         mfc0    v0, COP_0_TLB_INDEX             # See what we got
347         bne     t1, zero, 2f                    # Decide even odd
348 # EVEN
349         nop
350         bltz    v0, 1f                          # index < 0 => !found
351         MIPS_CPU_NOP_DELAY
352
353         tlbr                                    # update, read entry first
354         MIPS_CPU_NOP_DELAY
355         _MTC0   a1, COP_0_TLB_LO0               # init low reg0.
356         MIPS_CPU_NOP_DELAY
357         tlbwi                                   # update slot found
358         b       4f
359         nop
360 1:
361         mtc0    zero, COP_0_TLB_PG_MASK         # init mask.
362         _MTC0   a0, COP_0_TLB_HI                # init high reg.
363         _MTC0   a1, COP_0_TLB_LO0               # init low reg0.
364         _MTC0   a2, COP_0_TLB_LO1               # init low reg1.
365         MIPS_CPU_NOP_DELAY
366         tlbwr                                   # enter into a random slot
367         MIPS_CPU_NOP_DELAY
368         b       4f
369         nop
370 # ODD
371 2:
372         nop
373         bltz    v0, 3f                          # index < 0 => !found
374         MIPS_CPU_NOP_DELAY
375
376         tlbr                                    # read the entry first
377         MIPS_CPU_NOP_DELAY
378         _MTC0   a1, COP_0_TLB_LO1               # init low reg1.
379         MIPS_CPU_NOP_DELAY
380         tlbwi                                   # update slot found
381         MIPS_CPU_NOP_DELAY
382         b       4f
383         nop
384 3:
385         mtc0    zero, COP_0_TLB_PG_MASK         # init mask.
386         _MTC0   a0, COP_0_TLB_HI                # init high reg.
387         _MTC0   a2, COP_0_TLB_LO0               # init low reg0.
388         _MTC0   a1, COP_0_TLB_LO1               # init low reg1.
389         MIPS_CPU_NOP_DELAY
390         tlbwr                                   # enter into a random slot
391
392 4:                                              # Make shure pipeline
393         MIPS_CPU_NOP_DELAY
394         _MTC0   t0, COP_0_TLB_HI                # restore PID
395         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
396         ITLBNOPFIX
397         j       ra
398         nop
399 END(Mips_TLBUpdate)
400
401 /*--------------------------------------------------------------------------
402  *
403  * Mips_TLBRead(unsigned entry, struct tlb *tlb);
404  *
405  *      Read the TLB entry.
406  *
407  * Results:
408  *      None.
409  *
410  * Side effects:
411  *      tlb will contain the TLB entry found.
412  *
413  *--------------------------------------------------------------------------
414  */
415 LEAF(Mips_TLBRead)
416         mfc0    v1, COP_0_STATUS_REG            # Save the status register.
417         mtc0    zero, COP_0_STATUS_REG          # Disable interrupts
418         ITLBNOPFIX
419         _MFC0   t0, COP_0_TLB_HI                # Get current PID
420
421         mtc0    a0, COP_0_TLB_INDEX             # Set the index register
422         MIPS_CPU_NOP_DELAY
423         tlbr                                    # Read from the TLB
424         MIPS_CPU_NOP_DELAY
425         mfc0    t2, COP_0_TLB_PG_MASK           # fetch the hi entry
426         _MFC0   t3, COP_0_TLB_HI                # fetch the hi entry
427         _MFC0   t4, COP_0_TLB_LO0               # See what we got
428         _MFC0   t5, COP_0_TLB_LO1               # See what we got
429         _MTC0   t0, COP_0_TLB_HI                # restore PID
430         MIPS_CPU_NOP_DELAY
431         mtc0    v1, COP_0_STATUS_REG            # Restore the status register
432         ITLBNOPFIX
433         sw      t2, 0(a1)
434         sw      t3, 4(a1)
435         sw      t4, 8(a1)
436         j       ra
437         sw      t5, 12(a1)
438 END(Mips_TLBRead)
439
440 /*--------------------------------------------------------------------------
441  *
442  * Mips_TLBGetPID(void);
443  *
444  * Results:
445  *      Returns the current TLB pid reg.
446  *
447  * Side effects:
448  *      None.
449  *
450  *--------------------------------------------------------------------------
451  */
452 LEAF(Mips_TLBGetPID)
453         _MFC0   v0, COP_0_TLB_HI                # get PID
454         j       ra
455         and     v0, v0, VMTLB_PID               # mask off PID
456 END(Mips_TLBGetPID)
457
458
459
460 /*--------------------------------------------------------------------------
461  *
462  * void mips_TBIAP(int sizeofTLB);
463  *
464  * Invalidate TLB entries belong to per process user spaces while
465  * leaving entries for kernel space marked global intact.
466  *
467  *--------------------------------------------------------------------------
468  */
469 LEAF(mips_TBIAP)
470         mfc0    v1, COP_0_STATUS_REG            # save status register
471         mtc0    zero, COP_0_STATUS_REG          # disable interrupts
472
473         _MFC0   t4, COP_0_TLB_HI                # Get current PID
474         move    t2, a0
475         mfc0    t1, COP_0_TLB_WIRED
476         li      v0, MIPS_KSEG0_START + 0x0fff0000       # invalid address
477         mfc0    t3, COP_0_TLB_PG_MASK           # save current pgMask
478
479         # do {} while (t1 < t2)
480 1:
481         mtc0    t1, COP_0_TLB_INDEX             # set index
482         MIPS_CPU_NOP_DELAY
483         tlbr                                    # obtain an entry
484         MIPS_CPU_NOP_DELAY
485         _MFC0   a0, COP_0_TLB_LO1
486         and     a0, a0, PTE_G                   # check to see it has G bit
487         bnez    a0, 2f
488         nop
489
490         _MTC0   v0, COP_0_TLB_HI                # make entryHi invalid
491         _MTC0   zero, COP_0_TLB_LO0             # zero out entryLo0
492         _MTC0   zero, COP_0_TLB_LO1             # zero out entryLo1
493         mtc0    zero, COP_0_TLB_PG_MASK         # zero out mask entry
494         MIPS_CPU_NOP_DELAY
495         tlbwi                                   # invalidate the TLB entry
496 2:
497         addu    t1, t1, 1
498         addu    v0, 1 << (PAGE_SHIFT + 1)
499         bne     t1, t2, 1b
500         nop
501
502         _MTC0   t4, COP_0_TLB_HI                # restore PID
503         mtc0    t3, COP_0_TLB_PG_MASK           # restore pgMask
504         MIPS_CPU_NOP_DELAY
505         mtc0    v1, COP_0_STATUS_REG            # restore status register
506         j       ra                              # new ASID will be set soon
507         nop
508         .set    mips2
509 END(mips_TBIAP)