====== TLB Assemble Example 1 ======
Reference: {{:mywiki:hw:mips:mips_tlb.pdf|{{:mywiki:hw:mips:mips_tlb.pdf|}}}}
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: releng/8.1/sys/mips/mips/tlb.S 178172 2008-04-13 07:27:37Z imp $
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
61 #include
62 #include
63 #include
64 #include
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)
====== TLB example 2 ======
/*
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
* The President and Fellows of Harvard College.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include
#include
/*
* TLB handling for mips-1 (r2000/r3000)
*/
.text
.set noreorder
/*
* tlb_random: use the "tlbwr" instruction to write a TLB entry
* into a (very pseudo-) random slot in the TLB.
*
* Pipeline hazard: must wait between setting entryhi/lo and
* doing the tlbwr. Use two cycles; some processors may vary.
*/
.globl tlb_random
.type tlb_random,@function
.ent tlb_random
tlb_random:
mtc0 a0, c0_entryhi /* store the passed entry into the */
mtc0 a1, c0_entrylo /* tlb entry registers */
nop /* wait for pipeline hazard */
nop
tlbwr /* do it */
j ra
nop
.end tlb_random
/*
* tlb_write: use the "tlbwi" instruction to write a TLB entry
* into a selected slot in the TLB.
*
* Pipeline hazard: must wait between setting entryhi/lo and
* doing the tlbwi. Use two cycles; some processors may vary.
*/
.text
.globl tlb_write
.type tlb_write,@function
.ent tlb_write
tlb_write:
mtc0 a0, c0_entryhi /* store the passed entry into the */
mtc0 a1, c0_entrylo /* tlb entry registers */
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
mtc0 t0, c0_index /* store the shifted index into the index register */
nop /* wait for pipeline hazard */
nop
tlbwi /* do it */
j ra
nop
.end tlb_write
/*
* tlb_read: use the "tlbr" instruction to read a TLB entry
* from a selected slot in the TLB.
*
* Pipeline hazard: must wait between setting c0_index and
* doing the tlbr. Use two cycles; some processors may vary.
* Similarly, three more cycles before reading c0_entryhi/lo.
*/
.text
.globl tlb_read
.type tlb_read,@function
.ent tlb_read
tlb_read:
sll t0, a2, CIN_INDEXSHIFT /* shift the passed index into place */
mtc0 t0, c0_index /* store the shifted index into the index register */
nop /* wait for pipeline hazard */
nop
tlbr /* do it */
nop /* wait for pipeline hazard */
nop
nop
mfc0 t0, c0_entryhi /* get the tlb entry out of the */
mfc0 t1, c0_entrylo /* tlb entry registers */
sw t0, 0(a0) /* store through the passed pointer */
j ra
sw t1, 0(a1) /* store (in delay slot) */
.end tlb_read
/*
* tlb_probe: use the "tlbp" instruction to find the index in the
* TLB of a TLB entry matching the relevant parts of the one supplied.
*
* Pipeline hazard: must wait between setting c0_entryhi/lo and
* doing the tlbp. Use two cycles; some processors may vary.
* Similarly, two more cycles before reading c0_index.
*/
.text
.globl tlb_probe
.type tlb_probe,@function
.ent tlb_probe
tlb_probe:
mtc0 a0, c0_entryhi /* store the passed entry into the */
mtc0 a1, c0_entrylo /* tlb entry registers */
nop /* wait for pipeline hazard */
nop
tlbp /* do it */
nop /* wait for pipeline hazard */
nop
mfc0 t0, c0_index /* fetch the index back in t0 */
/*
* If the high bit (CIN_P) of c0_index is set, the probe failed.
* The high bit is not set <--> c0_index (now in t0) >= 0.
*/
bgez t0, 1f /* did probe succeed? if so, skip forward */
nop /* delay slot */
addi v0, z0, -1 /* set return value to -1 to indicate failure */
j ra /* done */
nop /* delay slot */
1:
/* succeeded - get the index field from the index register value */
andi t1, t0, CIN_INDEX /* mask off the field */
j ra /* done */
sra v0, t1, CIN_INDEXSHIFT /* shift it (in delay slot) */
.end tlb_probe
/*
* tlb_reset
*
* Initialize the TLB. At processor startup, the TLB state is completely
* undefined. So be sure to avoid creating any duplicates. Also make sure
* that the initialization entries don't duplicate the INVALID entries
* defined in tlb.h. (This way you can write the invalid entries in
* without having to use tlbp to find out if they're going to cause dups.)
*
* This function is not defined in tlb.h because it's only called from
* start.S.
*
* Pipeline hazards are as above.
*/
.text
.globl tlb_reset
.type tlb_reset,@function
.ent tlb_reset
tlb_reset:
li t0, 0 /* t0 <- tlb index number (shifted) */
li t1, 0x81000000 /* t1 <- tlb reset vaddr */
1:
mtc0 $0, c0_entrylo /* set up proposed tlb entry for reset */
mtc0 t1, c0_entryhi
nop /* wait for pipeline hazard */
nop
tlbp /* check if it already exists */
nop /* wait for pipeline hazard */
nop
mfc0 t2, c0_index
bgez t2, 1b /* if it does, loop back */
addiu t1, t1, 0x1000 /* next vaddr (in delay slot) */
mtc0 t0, c0_index /* doesn't exist, set index to write to */
/* nop */ /* don't wait for pipeline hazard */
/* nop */ /* (have enough other instructions) */
addiu t0, t0, 0x100 /* next tlb index (shifted) */
bne t0, 0x4000, 1b /* if it's not the last tlb index, loop */
tlbwi /* write tlb entry (in delay slot) */
j ra /* done */
nop /* delay slot */
.end tlb_reset
====== Shao Guohua TLB ASM test ======
##probe failure
#define TLB_INDEX_P_OFFSET 31
#define TLB_INDEX_P_MAKS 0x80000000
#define TLB_INDEX_INDEX_OFFSET 0
#define TLB_INDEX_INDEX_MASK 0x3F
#define TLB_ENTRYLO_R_OFFSET 30
#define TLB_ENTRYLO_R_MASK 0xC0000000
#define TLB_ENTRYLO_PFN_OFFSET 6
#define TLB_ENTRYLO_PFN_MASK 0x3FFFFC0
##cache coherency
##3 WB Cacheable, noncoherent, write-back, write allocate
##4 CWBE Cacheable, write-back, write-allocate, coherent, read misses request Exclusive
##5 CWB Cacheable, write-back, write-allocate, coherent, read misses request Shared
##6 - Reserved
##7 UCA Uncached Accelerated
##
#define TLB_ENTRYLO_C_OFFSET 3
#define TLB_ENTRYLO_C_MASK 0x38
##dirt or writable
#define TLB_ENTRYLO_D_OFFSET 2
#define TLB_ENTRYLO_D_MASK 0x4
##valid bit
#define TLB_ENTRYLO_V_OFFSET 1
#define TLB_ENTRYLO_V_MASK 0x2
##global
#define TLB_ENTRYLO_G_OFFSET 0
#define TLB_ENTRYLO_G_MASK 0x1
#define TLB_ENTRYHI_VPN2_OFFSET 13
#define TLB_ENTRYHI_VPN2_MASK 0xFFFFE000
#define TLB_ENTRYHI_EHINV_OFFSET 10
#define TLB_ENTRYHI_EHINV_MASK 0x400
#define TLB_ENTRYHI_ASID_OFFSET 0
#define TLB_ENTRYHI_ASI_MASK 0xFF
##entry_lo0.reg.field.d = 1;
##entry_lo0.reg.field.v = 1;
##entry_lo0.reg.field.g = 1;
##entry_lo0.reg.field.c = 5;
##entry_lo1.reg.field.d = 1;
##entry_lo1.reg.field.v = 1;
##entry_lo1.reg.field.g = 1;
##entry_lo1.reg.field.c = 5;
##entry_hi.reg.field.asid = 0x1f;
##pagemask = 0x0;
##
##entry_hi.reg.field.vpn2 = (v_addr + (0x2000 * i)) >> 13;
##entry_lo0.reg.field.pfn = (phy_addr +(0x2000 * i)) >> 12;
##entry_lo1.reg.field.pfn = (phy_addr +(0x2000 * i)+0x1000) >> 12;
##tlb->tlb[i].pagemask = pagemask;
##tlb->tlb[i].entryhi = entry_hi.reg.all;
##tlb->tlb[i].entrylo0 = entry_lo0.reg.all;
##if ((i == (pages -1)) && !last_odd_page_vld ) ##last odd page not valid
##{
## tlb->tlb[i].entrylo1 = 0;
## entry_lo1.reg.field.v = 0;
##}
##else
## tlb->tlb[i].entrylo1 = entry_lo1.reg.all;
.data
str_index: .asciiz "index: "
str_entryhi: .asciiz "enryhi: "
str_entrylo0: .asciiz "enrylo0: "
str_entrylo1: .asciiz "enrylo1: "
str_pagemask: .asciiz "pagemask: "
str_newline: .asciiz "\n"
str_size: .asciiz "size:"
#define MAP_TLB_BASE 0xC0000000
#define TLB_4K_PAGE_OFFSET 12
#define ENTRYHI_DEFAULT 0x0
#define TLB_ENTRYLO_DEFAULT_G ( (5<< TLB_ENTRYLO_C_OFFSET) | (1<< TLB_ENTRYLO_D_OFFSET) | (1<< TLB_ENTRYLO_V_OFFSET) | (1<< TLB_ENTRYLO_G_OFFSET))
#define TLB_ENTRYLO_DEFAULT_P ( (5<< TLB_ENTRYLO_C_OFFSET) | (1<< TLB_ENTRYLO_D_OFFSET) | (1<< TLB_ENTRYLO_V_OFFSET) )
.text
.globl __start # declaration of main as a global variable
__start:
li $t6, 0x20060000
li $t0, 154333
_set_tlb_global:
#EntryHi:
#---------------------------------
#| 31 13| 12 8 | 7 0 |
#| VPN2 | 0 0 | ASID |
#---------------------------------
#Entrylo0/1
#---------------------------------
#| 31 6| 5 3 | 2 | 1 | 0 |
#| PFN | C | D | V | G |
#---------------------------------
#Mask
#---------------------------------
#| 31 29| 28 13| 12 0 |
#| 0 0| Mask | 0 0 |
#---------------------------------
#t0 -- MPE shared code/data size need to map
#t1 -- Index
#t2-- entryhi
#t3 -- entrylo
#t4 -- asid
#t5 -- pagemask
#t6 -- physical address, virtual address is harded coded here, ie, 0xc000 0000
#V0 -- tmp register
#prepare $t1 for Index
li $t1, 0
#prepare $t2 for entryhi
li $t2, 0xC0000000
#prepare $t3 for entrylo
add $t3, $t6, 0 #PHYsical base
srl $t3, $t3, 12 #TLB_4K_PAGE_OFFSET
sll $t3, $t3, 6 #TLB_ENTRYLO_PFN_OFFSET
addi $t3, $t3, 0x2f #TLB_ENTRYLO_DEFAULT_G
#$t4 for asid
li $t4, 0
#$t5 for pagemask
li $t5, 0
tlb_g_loop:
ble $t0, 0, _set_tlb_global_done
nop
#print size
li $v0, 4
la $a0, str_size
syscall
li $v0, 1
addi $a0, $t0, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#write even index
li $v0, 4
la $a0, str_index
syscall
li $v0, 1
addi $a0, $t1, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#write even entryhi
li $v0, 4
la $a0, str_entryhi
syscall
li $v0, 1
addi $a0, $t2, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#write even entrylo0
li $v0, 4
la $a0, str_entrylo0
syscall
li $v0, 1
addi $a0, $t3, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#write even pagemask
li $v0, 4
la $a0, str_pagemask
syscall
li $v0, 1
addi $a0, $t5, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#wlbwt
#update odd page
addi $t3, $t3, 0x40
#write entrylo1
li $v0, 4
la $a0, str_entrylo1
syscall
li $v0, 1
addi $a0, $t3, 0
syscall
li $v0, 4
la $a0, str_newline
syscall
#wlbwt
#prepare next tlb index--
#update size $t0 reduce 2 * 4K since one tlb support 2 pages
li $v0, 0x2000
sub $t0, $t0, $v0
#update index $t1
li $v0, 1
add $t1, $t1, $v0
#update entryhi $t2
addi $t2, $t2, 0x2000 #(2<