xref: /netbsd/sys/arch/mips/mips/locore_mips3.S (revision c4a72b64)
1/*	$NetBSD: locore_mips3.S,v 1.84 2002/11/08 00:49:32 simonb Exp $	*/
2
3/*
4 * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by Jonathan R. Stone for
18 *      the NetBSD Project.
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35/*
36 * Copyright (c) 1992, 1993
37 *	The Regents of the University of California.  All rights reserved.
38 *
39 * This code is derived from software contributed to Berkeley by
40 * Digital Equipment Corporation and Ralph Campbell.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 *    must display the following acknowledgement:
52 *	This product includes software developed by the University of
53 *	California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors
55 *    may be used to endorse or promote products derived from this software
56 *    without specific prior written permission.
57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE.
69 *
70 * Copyright (C) 1989 Digital Equipment Corporation.
71 * Permission to use, copy, modify, and distribute this software and
72 * its documentation for any purpose and without fee is hereby granted,
73 * provided that the above copyright notice appears in all copies.
74 * Digital Equipment Corporation makes no representations about the
75 * suitability of this software for any purpose.  It is provided "as is"
76 * without express or implied warranty.
77 *
78 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
79 *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
80 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
81 *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
82 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
83 *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
84 *
85 *	@(#)locore.s	8.5 (Berkeley) 1/4/94
86 */
87#include "opt_cputype.h"
88#include "opt_ddb.h"
89#include "opt_lockdebug.h"
90#include "opt_kgdb.h"
91
92#include <sys/cdefs.h>
93
94#include <mips/asm.h>
95#include <mips/cpuregs.h>
96#include <machine/param.h>
97#include <machine/endian.h>
98
99#include "assym.h"
100
101/*
102 * XXX We need a cleaner way of handling the instruction hazards of
103 * the various processors.  Here are the relevant rules for the QED 52XX:
104 *	tlbw[ri]	-- two integer ops beforehand
105 *	tlbr		-- two integer ops beforehand
106 *	tlbp		-- two integer ops beforehand
107 *	mtc0	[PageMask,EntryHi,Cp0] -- two integer ops afterwards
108 *	changing JTLB	-- two integer ops afterwards
109 *	mtc0	[EPC,ErrorEPC,Status] -- two int ops afterwards before eret
110 *	config.k0	-- five int ops before kseg0, ckseg0 memref
111 *
112 * For the IDT R4000, some hazards are:
113 *	mtc0/mfc0	one integer op before and after
114 *	tlbp		-- one integer op afterwards
115 * Obvious solution is to take least common denominator.
116 *
117 * For the Toshiba R5900, TX79:
118 *	mtc0		following sync.p
119 *	tlbw[ri], tlbp	following sync.p or eret
120 * for those CPU, define COP0_SYNC as sync.p
121 */
122
123/*
124 *============================================================================
125 *
126 *  MIPS III ISA support, part 1: locore exception vectors.
127 *  The following code is copied to the vector locations to which
128 *  the CPU jumps in response to an exception or a TLB miss.
129 *
130 *============================================================================
131 */
132	.set	noreorder
133	.set	mips3
134
135	.text
136
137/*----------------------------------------------------------------------------
138 *
139 * mips3_wbflush --
140 *
141 *	Return when the write buffer is empty.
142 *
143 *	Common for all MIPS3 and greater ISAs
144 *
145 * Results:
146 *	None.
147 *
148 * Side effects:
149 *	None.
150 *
151 *----------------------------------------------------------------------------
152 */
153LEAF(mips3_wbflush)
154XLEAF(mips5900_wbflush)
155XLEAF(mips32_wbflush)
156XLEAF(mips64_wbflush)
157	nop
158	sync
159	j	ra
160	nop
161END(mips3_wbflush)
162
163
164/* XXX simonb: ugg, another ugly #ifdef check... */
165#if (defined(MIPS3) && !defined(MIPS3_5900)) || defined(MIPS32) || defined(MIPS64)
166/*
167 * mips_wait_idle:
168 *
169 *	When no processes are on the runq, cpu_switch branches to
170 *	idle to wait for something to come ready.
171 *
172 *	NOTE: This is really part of cpu_switch(), but defined here
173 *	for kernel profiling.
174 *
175 *	This version takes advantage of power-saving features on
176 *	the QED RM52xx family of CPUs, and MIPS32 & MIPS64 CPUs.
177 */
178LEAF(mips_wait_idle)
179	sw	zero, _C_LABEL(curproc)		# set curproc NULL for stats
180#if defined(LOCKDEBUG)
181	jal	_C_LABEL(sched_unlock_idle)	# release sched_lock
182	nop
183#endif
184	li	t0, (MIPS_INT_MASK | MIPS_SR_INT_IE)
185	DYNAMIC_STATUS_MASK(t0,t1)		# machine dependent masking
186	mtc0	t0, MIPS_COP_0_STATUS		# enable all interrupts
187	COP0_SYNC
188	nop
189
190	/* Try to zero some free pages. */
191	lw	t0, _C_LABEL(uvm) + UVM_PAGE_IDLE_ZERO
192	nop
193	beq	t0, zero, 1f
194	nop
195	jal	_C_LABEL(uvm_pageidlezero)
196	nop
1971:
198#ifdef MIPS_DYNAMIC_STATUS_MASK
199	# Do this again since the mask may have changed.
200	li	t3, (MIPS_INT_MASK | MIPS_SR_INT_IE)
201	DYNAMIC_STATUS_MASK(t3,t1)		# machine dependent masking
202	mtc0	t3, MIPS_COP_0_STATUS		# enable all interrupts
203	COP0_SYNC
204	nop
205#endif
206	lw	t0, _C_LABEL(sched_whichqs)	# look for non-empty queue
207	bne	t0, zero, 1f
208	nop
209	wait
210	nop
211	nop
212	nop
213	b	1b
214	nop
2151:
216#if defined(LOCKDEBUG)
217	mtc0	zero, MIPS_COP_0_STATUS		# disable all interrupts
218	COP0_SYNC
219	nop
220	nop
221	nop
222	nop
223	jal	_C_LABEL(sched_lock_idle)	# acquire sched_lock
224	nop
225	la	ra, cpu_switch_queuescan
226	j	ra
227	nop
228#else
229	mtc0	zero, MIPS_COP_0_STATUS		# disable all interrupts
230	COP0_SYNC
231	nop
232	nop
233	nop
234	la	ra, cpu_switch_queuescan
235	j	ra
236	nop
237#endif
238END(mips_wait_idle)
239#endif /* (MIPS3 && !MIPS3_5900) || MIPS32 || MIPS64 */
240
241/*
242 * u_int32_t mips3_cp0_compare_read(void)
243 *
244 *	Return the current value of the CP0 Compare register.
245 */
246LEAF(mips3_cp0_compare_read)
247	mfc0	v0, MIPS_COP_0_COMPARE
248	j	ra
249	nop
250END(mips3_cp0_compare_read)
251
252/*
253 * void mips3_cp0_compare_write(u_int32_t)
254 *
255 *	Set the value of the CP0 Compare register.
256 */
257LEAF(mips3_cp0_compare_write)
258	mtc0	a0, MIPS_COP_0_COMPARE
259	COP0_SYNC
260	nop
261	nop
262	j	ra
263	nop
264END(mips3_cp0_compare_write)
265
266/*
267 * u_int32_t mips3_cp0_config_read(void)
268 *
269 *	Return the current value of the CP0 Config register.
270 */
271LEAF(mips3_cp0_config_read)
272	mfc0	v0, MIPS_COP_0_CONFIG
273	j	ra
274	nop
275END(mips3_cp0_config_read)
276
277/*
278 * void mips3_cp0_config_write(u_int32_t)
279 *
280 *	Set the value of the CP0 Config register.
281 */
282LEAF(mips3_cp0_config_write)
283	mtc0	a0, MIPS_COP_0_CONFIG
284	COP0_SYNC
285	nop
286	nop
287	j	ra
288	nop
289END(mips3_cp0_config_write)
290
291#if defined(MIPS32) || defined(MIPS64)
292/*
293 * u_int32_t mipsNN_cp0_config1_read(void)
294 *
295 *	Return the current value of the CP0 Config (Select 1) register.
296 */
297LEAF(mipsNN_cp0_config1_read)
298	.set push
299	.set mips32
300	mfc0	v0, MIPS_COP_0_CONFIG, 1
301	j	ra
302	nop
303	.set pop
304END(mipsNN_cp0_config1_read)
305
306/*
307 * u_int32_t mipsNN_cp0_config1_write(u_int32_t)
308 *
309 *	Return the current value of the CP0 Config (Select 1) register.
310 */
311LEAF(mipsNN_cp0_config1_write)
312	.set push
313	.set mips32
314	mtc0	v0, MIPS_COP_0_CONFIG, 1
315	nop
316	j	ra
317	nop
318	.set pop
319END(mipsNN_cp0_config1_write)
320
321/*
322 * u_int32_t mipsNN_cp0_config2_read(void)
323 *
324 *	Return the current value of the CP0 Config (Select 2) register.
325 */
326LEAF(mipsNN_cp0_config2_read)
327	.set push
328	.set mips32
329	mfc0	v0, MIPS_COP_0_CONFIG, 2
330	j	ra
331	nop
332	.set pop
333END(mipsNN_cp0_config2_read)
334
335/*
336 * u_int32_t mipsNN_cp0_config3_read(void)
337 *
338 *	Return the current value of the CP0 Config (Select 3) register.
339 */
340LEAF(mipsNN_cp0_config3_read)
341	.set push
342	.set mips32
343	mfc0	v0, MIPS_COP_0_CONFIG, 3
344	j	ra
345	nop
346	.set pop
347END(mipsNN_cp0_config3_read)
348#endif /* MIPS32 || MIPS64 */
349
350/*
351 * u_int32_t mips3_cp0_count_read(void)
352 *
353 *	Return the current value of the CP0 Count register.
354 */
355LEAF(mips3_cp0_count_read)
356	mfc0	v0, MIPS_COP_0_COUNT
357	j	ra
358	nop
359END(mips3_cp0_count_read)
360
361/*
362 * void mips3_cp0_count_write(u_int32_t)
363 *
364 *	Set the value of the CP0 Count register.
365 */
366LEAF(mips3_cp0_count_write)
367	mtc0	a0, MIPS_COP_0_COUNT
368	COP0_SYNC
369	nop
370	nop
371	j	ra
372	nop
373END(mips3_cp0_count_write)
374
375/*
376 * u_int32_t mips3_cp0_wired_read(void)
377 *
378 *	Return the current value of the CP0 Wired register.
379 */
380LEAF(mips3_cp0_wired_read)
381	mfc0	v0, MIPS_COP_0_TLB_WIRED
382	j	ra
383	nop
384END(mips3_cp0_wired_read)
385
386/*
387 * void mips3_cp0_wired_write(u_int32_t)
388 *
389 *	Set the value of the CP0 Wired register.
390 */
391LEAF(mips3_cp0_wired_write)
392	mtc0	a0, MIPS_COP_0_TLB_WIRED
393	COP0_SYNC
394	nop
395	nop
396	j	ra
397	nop
398END(mips3_cp0_wired_write)
399
400#if defined(_MIPS_BSD_API) && \
401    (_MIPS_BSD_API == _MIPS_BSD_API_N32 || _MIPS_BSD_API == _MIPS_BSD_API_LP64)
402#error mips3_ld and mips3_sd should be adjusted for N32 or LP64
403#endif
404
405LEAF(mips3_ld)
406#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
407	mfc0	t0, MIPS_COP_0_STATUS		# turn of interrupts
408	and	t1, t0, ~(MIPS_SR_INT_IE)
409	mtc0	t1, MIPS_COP_0_STATUS
410	COP0_SYNC
411	nop
412	nop
413	nop
414#endif
415
416	ld	v0, 0(a0)
417#if _BYTE_ORDER == _BIG_ENDIAN
418	dsll	v1, v0, 32
419	dsra	v1, v1, 32			# low word in v1
420	dsra	v0, v0, 32			# high word in v0
421#else
422	dsra	v1, v0, 32			# high word in v1
423	dsll	v0, v0, 32
424	dsra	v0, v0, 32			# low word in v0
425#endif
426
427#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
428	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
429	COP0_SYNC
430	nop
431#endif
432
433	jr	ra
434	nop
435END(mips3_ld)
436
437LEAF(mips3_sd)
438#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
439	mfc0	t0, MIPS_COP_0_STATUS		# turn of interrupts
440	and	t1, t0, ~(MIPS_SR_INT_IE)
441	mtc0	t1, MIPS_COP_0_STATUS
442	COP0_SYNC
443	nop
444	nop
445	nop
446#endif
447
448	# NOTE: a1 is padding!
449
450#if _BYTE_ORDER == _BIG_ENDIAN
451	dsll	a2, a2, 32			# high word in a2
452	dsll	a3, a3, 32			# low word in a3
453	dsrl	a3, a3, 32
454#else
455	dsll	a2, a2, 32			# low word in a2
456	dsrl	a2, a2, 32
457	dsll	a3, a3, 32			# high word in a3
458#endif
459	or	a1, a2, a3
460	sd	a1, 0(a0)
461
462#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
463	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
464	COP0_SYNC
465	nop
466#endif
467
468	jr	ra
469	nop
470END(mips3_sd)
471
472/*
473 * int badaddr64(uint64_t addr, int len)
474 * See if access to addr with a len type instruction causes a machine check.
475 * len is length of access in bytes (can be 1, 2, 4, or 8).
476 */
477#if defined(_MIPS_BSD_API) && _MIPS_BSD_API != _MIPS_BSD_API_LP32
478LEAF(badaddr64)
479	lw	v1, _C_LABEL(curpcb)
480	la	v0, _C_LABEL(baderr64)
481
482	/* Enable KX */
483	mfc0	t0, MIPS_COP_0_STATUS
484	or	t1, t0, MIPS3_SR_KX
485	mtc0	t1, MIPS_COP_0_STATUS
486	COP0_SYNC
487
488#if _BYTE_ORDER == _BIG_ENDIAN
489	dsll	a0, a0, 32			# high word in a0
490	dsll	a1, a1, 32			# low word in a1
491	dsrl	a1, a1, 32
492#else
493	dsll	a0, a0, 32			# low word in a2
494	dsrl	a0, a0, 32
495	dsll	a1, a1, 32			# high word in a3
496#endif
497	or	a0, a0, a1
498
499	bne	a2, 1, 2f
500	sw	v0, U_PCB_ONFAULT(v1)
501	b	9f
502	lbu	v0, (a0)
5032:
504	bne	a2, 2, 4f
505	nop
506	b	9f
507	lhu	v0, (a0)
5084:
509	bne	a2, 4, 8f
510	nop
511	b	9f
512	lw	v0, (a0)
5138:
514	ld	v0, (a0)
5159:
516	mtc0	t0, MIPS_COP_0_STATUS           # Restore KX
517	COP0_SYNC
518	sw	zero, U_PCB_ONFAULT(v1)
519	j	ra
520	move	v0, zero			# made it w/o errors
521END(badaddr64)
522
523LEAF(baderr64)
524	mtc0	t0, MIPS_COP_0_STATUS		# Restore KX
525	COP0_SYNC
526	sw	zero, U_PCB_ONFAULT(v1)
527	j	ra
528	li	v0, -1
529END(baderr64)
530#endif
531