1 /* $OpenBSD: locore.S,v 1.18 1998/09/15 10:58:53 pefo Exp $ */
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Digital Equipment Corporation and Ralph Campbell.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
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.
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)
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
54 * Contains code that is the first executed at boot time plus
55 * assembly language support routines.
58 #include "opt_cputype.h"
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>
68 #if defined(ISA_MIPS32)
70 #elif defined(ISA_MIPS64)
71 #define WITH_64BIT_CP0
72 #elif defined(ISA_MIPS3)
73 #define WITH_64BIT_CP0
75 #error "Please write the code for this ISA"
83 #define WIRED_SHIFT 34
93 .set noreorder # Noreorder is default style!
94 #if defined(ISA_MIPS32)
96 #elif defined(ISA_MIPS64)
98 #elif defined(ISA_MIPS3)
102 #define ITLBNOPFIX nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
105 * FREEBSD_DEVELOPERS_FIXME
106 * Some MIPS CPU may need delays using nops between executing CP0 Instructions
108 #define MIPS_CPU_NOP_DELAY nop;nop;nop;nop;
110 /*--------------------------------------------------------------------------
112 * Mips_TLBWriteIndexed(unsigned index, tlb *tlb);
114 * Write the given entry into the TLB at the given index.
122 *--------------------------------------------------------------------------
124 LEAF(Mips_TLBWriteIndexed)
125 mfc0 v1, COP_0_STATUS_REG # Save the status register.
126 mtc0 zero, COP_0_STATUS_REG # Disable interrupts
130 _MFC0 t0, COP_0_TLB_HI # Save the current PID.
132 _MTC0 a2, COP_0_TLB_LO0 # Set up entry low0.
133 _MTC0 a3, COP_0_TLB_LO1 # Set up entry low1.
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.
140 tlbwi # Write the TLB
143 _MTC0 t0, COP_0_TLB_HI # Restore the PID.
145 _MTC0 zero, COP_0_TLB_PG_MASK # Default mask value.
146 mtc0 v1, COP_0_STATUS_REG # Restore the status register
150 END(Mips_TLBWriteIndexed)
152 /*--------------------------------------------------------------------------
154 * Mips_SetPID(int pid);
156 * Write the given pid into the TLB pid reg.
162 * PID set in the entry hi register.
164 *--------------------------------------------------------------------------
167 _MTC0 a0, COP_0_TLB_HI # Write the hi reg value
168 nop # required for QED5230
169 nop # required for QED5230
174 /*--------------------------------------------------------------------------
176 * Mips_SetWIRED(int wired);
178 * Write the given value into the TLB wired reg.
184 * WIRED set in the wired register.
186 *--------------------------------------------------------------------------
189 mtc0 a0, COP_0_TLB_WIRED
194 /*--------------------------------------------------------------------------
196 * Mips_GetWIRED(void);
198 * Get the value from the TLB wired reg.
201 * Value of wired reg.
206 *--------------------------------------------------------------------------
209 mfc0 v0, COP_0_TLB_WIRED
214 /*--------------------------------------------------------------------------
216 * Mips_TLBFlush(tlbsize);
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.
226 * The TLB is flushed.
228 *--------------------------------------------------------------------------
231 mfc0 v1, COP_0_STATUS_REG # Save the status register.
232 mtc0 zero, COP_0_STATUS_REG # Disable interrupts
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
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.
243 * Align the starting value (t1) and the upper bound (a0).
246 mtc0 t1, COP_0_TLB_INDEX # Set the index register.
248 _MTC0 t0, COP_0_TLB_HI # Restore the PID
249 addu t1, t1, 1 # Increment index.
250 addu t0, t0, 8 * 1024
252 tlbwi # Write the TLB entry.
257 _MTC0 t0, COP_0_TLB_HI # Restore the PID
258 mtc0 v1, COP_0_STATUS_REG # Restore the status register
265 /*--------------------------------------------------------------------------
267 * Mips_TLBFlushAddr(unsigned TLBhi);
269 * Flush any TLB entries for the given address and TLB PID.
275 * The process's page is flushed from the TLB.
277 *--------------------------------------------------------------------------
279 LEAF(Mips_TLBFlushAddr)
280 mfc0 v1, COP_0_STATUS_REG # Save the status register.
281 mtc0 zero, COP_0_STATUS_REG # Disable interrupts
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
289 tlbp # Probe for the entry.
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
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
301 _MTC0 t1, COP_0_TLB_HI # Mark entry high as invalid
303 _MTC0 zero, COP_0_TLB_LO0 # Zero out low entry.
304 _MTC0 zero, COP_0_TLB_LO1 # Zero out low entry.
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
315 END(Mips_TLBFlushAddr)
317 /*--------------------------------------------------------------------------
319 * Mips_TLBUpdate(unsigned virpageadr, lowregx);
321 * Update the TLB if highreg is found; otherwise, enter the data.
324 * < 0 if loaded >= 0 if updated.
329 *--------------------------------------------------------------------------
332 mfc0 v1, COP_0_STATUS_REG # Save the status register.
333 mtc0 zero, COP_0_STATUS_REG # Disable interrupts
335 and t1, a0, 0x1000 # t1 = Even/Odd flag
336 li v0, (PTE_HVPN | PTE_ASID)
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
342 tlbp # Probe for the entry.
343 _SLL a1, a1, WIRED_SHIFT
344 _SRL a1, a1, WIRED_SHIFT
346 mfc0 v0, COP_0_TLB_INDEX # See what we got
347 bne t1, zero, 2f # Decide even odd
350 bltz v0, 1f # index < 0 => !found
353 tlbr # update, read entry first
355 _MTC0 a1, COP_0_TLB_LO0 # init low reg0.
357 tlbwi # update slot found
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.
366 tlbwr # enter into a random slot
373 bltz v0, 3f # index < 0 => !found
376 tlbr # read the entry first
378 _MTC0 a1, COP_0_TLB_LO1 # init low reg1.
380 tlbwi # update slot found
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.
390 tlbwr # enter into a random slot
392 4: # Make shure pipeline
394 _MTC0 t0, COP_0_TLB_HI # restore PID
395 mtc0 v1, COP_0_STATUS_REG # Restore the status register
401 /*--------------------------------------------------------------------------
403 * Mips_TLBRead(unsigned entry, struct tlb *tlb);
405 * Read the TLB entry.
411 * tlb will contain the TLB entry found.
413 *--------------------------------------------------------------------------
416 mfc0 v1, COP_0_STATUS_REG # Save the status register.
417 mtc0 zero, COP_0_STATUS_REG # Disable interrupts
419 _MFC0 t0, COP_0_TLB_HI # Get current PID
421 mtc0 a0, COP_0_TLB_INDEX # Set the index register
423 tlbr # Read from the TLB
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
431 mtc0 v1, COP_0_STATUS_REG # Restore the status register
440 /*--------------------------------------------------------------------------
442 * Mips_TLBGetPID(void);
445 * Returns the current TLB pid reg.
450 *--------------------------------------------------------------------------
453 _MFC0 v0, COP_0_TLB_HI # get PID
455 and v0, v0, VMTLB_PID # mask off PID
460 /*--------------------------------------------------------------------------
462 * void mips_TBIAP(int sizeofTLB);
464 * Invalidate TLB entries belong to per process user spaces while
465 * leaving entries for kernel space marked global intact.
467 *--------------------------------------------------------------------------
470 mfc0 v1, COP_0_STATUS_REG # save status register
471 mtc0 zero, COP_0_STATUS_REG # disable interrupts
473 _MFC0 t4, COP_0_TLB_HI # Get current PID
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
479 # do {} while (t1 < t2)
481 mtc0 t1, COP_0_TLB_INDEX # set index
483 tlbr # obtain an entry
485 _MFC0 a0, COP_0_TLB_LO1
486 and a0, a0, PTE_G # check to see it has G bit
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
495 tlbwi # invalidate the TLB entry
498 addu v0, 1 << (PAGE_SHIFT + 1)
502 _MTC0 t4, COP_0_TLB_HI # restore PID
503 mtc0 t3, COP_0_TLB_PG_MASK # restore pgMask
505 mtc0 v1, COP_0_STATUS_REG # restore status register
506 j ra # new ASID will be set soon