xref: /netbsd/sys/arch/mips/mips/locore_mips3.S (revision 487e496d)
1/*	$NetBSD: locore_mips3.S,v 1.116 2023/02/23 14:56:00 riastradh 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. Neither the name of the University nor the names of its contributors
51 *    may be used to endorse or promote products derived from this software
52 *    without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * Copyright (C) 1989 Digital Equipment Corporation.
67 * Permission to use, copy, modify, and distribute this software and
68 * its documentation for any purpose and without fee is hereby granted,
69 * provided that the above copyright notice appears in all copies.
70 * Digital Equipment Corporation makes no representations about the
71 * suitability of this software for any purpose.  It is provided "as is"
72 * without express or implied warranty.
73 *
74 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/loMem.s,
75 *	v 1.1 89/07/11 17:55:04 nelson Exp  SPRITE (DECWRL)
76 * from: Header: /sprite/src/kernel/mach/ds3100.md/RCS/machAsm.s,
77 *	v 9.2 90/01/29 18:00:39 shirriff Exp  SPRITE (DECWRL)
78 * from: Header: /sprite/src/kernel/vm/ds3100.md/vmPmaxAsm.s,
79 *	v 1.1 89/07/10 14:27:41 nelson Exp  SPRITE (DECWRL)
80 *
81 *	@(#)locore.s	8.5 (Berkeley) 1/4/94
82 */
83#include "opt_cputype.h"
84#include "opt_ddb.h"
85#include "opt_lockdebug.h"
86#include "opt_multiprocessor.h"
87#include "opt_kgdb.h"
88
89#include <sys/cdefs.h>
90#include <sys/endian.h>
91
92#include <mips/asm.h>
93#include <mips/cpuregs.h>
94
95RCSID("$NetBSD: locore_mips3.S,v 1.116 2023/02/23 14:56:00 riastradh Exp $")
96
97#include "assym.h"
98
99/*
100 * XXX We need a cleaner way of handling the instruction hazards of
101 * the various processors.  Here are the relevant rules for the QED 52XX:
102 *	tlbw[ri]	-- two integer ops beforehand
103 *	tlbr		-- two integer ops beforehand
104 *	tlbp		-- two integer ops beforehand
105 *	mtc0	[PageMask,EntryHi,Cp0] -- two integer ops afterwards
106 *	changing JTLB	-- two integer ops afterwards
107 *	mtc0	[EPC,ErrorEPC,Status] -- two int ops afterwards before eret
108 *	config.k0	-- five int ops before kseg0, ckseg0 memref
109 *
110 * For the IDT R4000, some hazards are:
111 *	mtc0/mfc0	one integer op before and after
112 *	tlbp		-- one integer op afterwards
113 * Obvious solution is to take least common denominator.
114 */
115
116/*
117 *============================================================================
118 *
119 *  MIPS III ISA support, part 1: locore exception vectors.
120 *  The following code is copied to the vector locations to which
121 *  the CPU jumps in response to an exception or a TLB miss.
122 *
123 *============================================================================
124 */
125	.set	noreorder
126#if (__mips < 3) || __mips_o32
127	.set	mips3
128#endif
129
130#ifdef _LP64
131#define	_MFC0	dmfc0
132#define	_MTC0	dmtc0
133#else
134#define	_MFC0	mfc0
135#define	_MTC0	mtc0
136#endif
137
138	.text
139
140/*----------------------------------------------------------------------------
141 *
142 * mips3_wbflush --
143 *
144 *	Return when the write buffer is empty.
145 *
146 *	Common for all MIPS3 and greater ISAs
147 *
148 * Results:
149 *	None.
150 *
151 * Side effects:
152 *	None.
153 *
154 *----------------------------------------------------------------------------
155 */
156LEAF(mips3_wbflush)
157XLEAF(loongson2_wbflush)
158XLEAF(mips32_wbflush)
159XLEAF(mips32r2_wbflush)
160XLEAF(mips64_wbflush)
161XLEAF(mips64r2_wbflush)
162	nop
163	sync
164	jr	ra
165	 nop
166END(mips3_wbflush)
167
168
169/*
170 * mips_wait_idle:
171 *
172 *	When no processes are on the runq, cpu_idle branches to
173 *	mips_wait_idle to save power.
174 */
175LEAF(mips_wait_idle)
176	mfc0	v0, MIPS_COP_0_STATUS
177	andi	v1, v0, MIPS_SR_INT_IE
178#if __mips >= 32
179	teqi	v1, 0
180#else
181	beqz	v1, 1f
182	 nop
183#endif
184	andi	v1, v0, MIPS_INT_MASK
185#if __mips >= 32
186	teqi	v1, 0
187#else
188	bnez	v1, 2f
189	 nop
1901:
191	move	a1, v0
192	PANIC("mips_wait_idle: interrupts disabled status=%#x")
193#endif
194
1952:	wait
196	nop
197	nop
198	nop
199	mfc0	v0, MIPS_COP_0_STATUS
200	andi	v1, v0, MIPS_SR_INT_IE
201#if __mips >= 32
202	teqi	v1, 0
203#else
204	beqz	v1, 1b
205	 nop
206#endif
207	andi	v1, v0, MIPS_INT_MASK
208#if __mips >= 32
209	teqi	v1, 0
210#else
211	beqz	v1, 1b
212	 nop
213#endif
214	jr	ra
215	 nop
216END(mips_wait_idle)
217
218/*
219 * uint32_t mips3_cp0_compare_read(void)
220 *
221 *	Return the current value of the CP0 Compare register.
222 */
223LEAF(mips3_cp0_compare_read)
224	mfc0	v0, MIPS_COP_0_COMPARE
225	jr	ra
226	 nop
227END(mips3_cp0_compare_read)
228
229/*
230 * void mips3_cp0_compare_write(uint32_t)
231 *
232 *	Set the value of the CP0 Compare register.
233 */
234LEAF(mips3_cp0_compare_write)
235	mtc0	a0, MIPS_COP_0_COMPARE
236	JR_HB_RA
237END(mips3_cp0_compare_write)
238
239/*
240 * uint32_t mips3_cp0_config_read(void)
241 *
242 *	Return the current value of the CP0 Config register.
243 */
244LEAF(mips3_cp0_config_read)
245	mfc0	v0, MIPS_COP_0_CONFIG
246	jr	ra
247	 nop
248END(mips3_cp0_config_read)
249
250/*
251 * void mips3_cp0_config_write(uint32_t)
252 *
253 *	Set the value of the CP0 Config register.
254 */
255LEAF(mips3_cp0_config_write)
256	mtc0	a0, MIPS_COP_0_CONFIG
257	JR_HB_RA
258END(mips3_cp0_config_write)
259
260#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
261	.set push
262#ifdef __mips_o32
263	.set mips32
264#else
265	.set mips64
266#endif
267/*
268 * uint32_t mipsNN_cp0_config1_read(void)
269 *
270 *	Return the current value of the CP0 Config (Select 1) register.
271 */
272LEAF(mipsNN_cp0_config1_read)
273	mfc0	v0, MIPS_COP_0_CONFIG, 1
274	jr	ra
275	 nop
276END(mipsNN_cp0_config1_read)
277
278/*
279 * uint32_t mipsNN_cp0_config1_write(uint32_t)
280 *
281 *	Set the current value of the CP0 Config (Select 1) register.
282 */
283LEAF(mipsNN_cp0_config1_write)
284	mtc0	v0, MIPS_COP_0_CONFIG, 1
285	JR_HB_RA
286END(mipsNN_cp0_config1_write)
287
288/*
289 * uint32_t mipsNN_cp0_config2_read(void)
290 *
291 *	Return the current value of the CP0 Config (Select 2) register.
292 */
293LEAF(mipsNN_cp0_config2_read)
294	mfc0	v0, MIPS_COP_0_CONFIG, 2
295	jr	ra
296	 nop
297END(mipsNN_cp0_config2_read)
298
299/*
300 * uint32_t mipsNN_cp0_config3_read(void)
301 *
302 *	Return the current value of the CP0 Config (Select 3) register.
303 */
304LEAF(mipsNN_cp0_config3_read)
305	mfc0	v0, MIPS_COP_0_CONFIG, 3
306	jr	ra
307	 nop
308END(mipsNN_cp0_config3_read)
309
310/*
311 * uint32_t mipsNN_cp0_config4_read(void)
312 *
313 *	Return the current value of the CP0 Config (Select 4) register.
314 */
315LEAF(mipsNN_cp0_config4_read)
316	mfc0	v0, MIPS_COP_0_CONFIG, 4
317	jr	ra
318	 nop
319END(mipsNN_cp0_config4_read)
320
321/*
322 * uint32_t mipsNN_cp0_config5_read(void)
323 *
324 *	Return the current value of the CP0 Config (Select 5) register.
325 */
326LEAF(mipsNN_cp0_config5_read)
327	mfc0	v0, MIPS_COP_0_CONFIG, 5
328	jr	ra
329	 nop
330END(mipsNN_cp0_config5_read)
331
332/*
333 * uint32_t mipsNN_cp0_config6_read(void)
334 *
335 *	Return the current value of the CP0 Config (Select 6) register.
336 */
337LEAF(mipsNN_cp0_config6_read)
338	mfc0	v0, MIPS_COP_0_CONFIG, 6
339	jr	ra
340	 nop
341END(mipsNN_cp0_config6_read)
342
343/*
344 * uint32_t mipsNN_cp0_config7_read(void)
345 *
346 *	Return the current value of the CP0 Config (Select 7) register.
347 */
348LEAF(mipsNN_cp0_config7_read)
349	mfc0	v0, MIPS_COP_0_CONFIG, 7
350	jr	ra
351	 nop
352END(mipsNN_cp0_config7_read)
353
354/*
355 * uintptr_t mipsNN_cp0_watchlo_read(u_int sel)
356 *
357 *	Return the current value of the selected CP0 Watchlo register.
358 */
359LEAF(mipsNN_cp0_watchlo_read)
360	sll	a0, 2
361	PTR_LA	t9, 1f
362	PTR_ADDU t9, a0
363	jr	t9
364	 nop
3651:
366	jr	ra
367	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 0
368	jr	ra
369	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 1
370	jr	ra
371	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 2
372	jr	ra
373	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 3
374	jr	ra
375	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 4
376	jr	ra
377	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 5
378	jr	ra
379	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 6
380	jr	ra
381	 _MFC0	v0, MIPS_COP_0_WATCH_LO, 7
382END(mipsNN_cp0_watchlo_read)
383
384/*
385 * void mipsNN_cp0_watchlo_write(u_int sel, uintptr_t val)
386 *
387 *	Set the current value of the selected CP0 WatchLo register.
388 */
389LEAF(mipsNN_cp0_watchlo_write)
390	sll	a0, 2
391	PTR_LA	t9, 1f
392	PTR_ADDU t9, a0
393	jr	t9
394	 nop
3951:
396	jr	ra
397	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 0
398	jr	ra
399	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 1
400	jr	ra
401	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 2
402	jr	ra
403	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 3
404	jr	ra
405	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 4
406	jr	ra
407	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 5
408	jr	ra
409	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 6
410	jr	ra
411	 _MTC0	a1, MIPS_COP_0_WATCH_LO, 7
412END(mipsNN_cp0_watchlo_write)
413
414/*
415 * uint32_t mipsNN_cp0_watchhi_read(u_int sel)
416 *
417 *	Return the current value of the selected CP0 WatchHi register.
418 */
419LEAF(mipsNN_cp0_watchhi_read)
420	sll	a0, 2
421	PTR_LA	t9, 1f
422	PTR_ADDU t9, a0
423	jr	t9
424	 nop
4251:
426	jr	ra
427	 mfc0	v0, MIPS_COP_0_WATCH_HI, 0
428	jr	ra
429	 mfc0	v0, MIPS_COP_0_WATCH_HI, 1
430	jr	ra
431	 mfc0	v0, MIPS_COP_0_WATCH_HI, 2
432	jr	ra
433	 mfc0	v0, MIPS_COP_0_WATCH_HI, 3
434	jr	ra
435	 mfc0	v0, MIPS_COP_0_WATCH_HI, 4
436	jr	ra
437	 mfc0	v0, MIPS_COP_0_WATCH_HI, 5
438	jr	ra
439	 mfc0	v0, MIPS_COP_0_WATCH_HI, 6
440	jr	ra
441	 mfc0	v0, MIPS_COP_0_WATCH_HI, 7
442END(mipsNN_cp0_watchhi_read)
443
444/*
445 * void mipsNN_cp0_watchhi_write(u_int sel, uint32_t val)
446 *
447 *	Set the current value of the selected CP0 WatchHi register.
448 */
449LEAF(mipsNN_cp0_watchhi_write)
450	sll	a0, 2
451	PTR_LA	t9, 1f
452	PTR_ADDU t9, a0
453	jr	t9
454	 nop
4551:
456	jr	ra
457	 mtc0	a1, MIPS_COP_0_WATCH_HI, 0
458	jr	ra
459	 mtc0	a1, MIPS_COP_0_WATCH_HI, 1
460	jr	ra
461	 mtc0	a1, MIPS_COP_0_WATCH_HI, 2
462	jr	ra
463	 mtc0	a1, MIPS_COP_0_WATCH_HI, 3
464	jr	ra
465	 mtc0	a1, MIPS_COP_0_WATCH_HI, 4
466	jr	ra
467	 mtc0	a1, MIPS_COP_0_WATCH_HI, 5
468	jr	ra
469	 mtc0	a1, MIPS_COP_0_WATCH_HI, 6
470	jr	ra
471	 mtc0	a1, MIPS_COP_0_WATCH_HI, 7
472END(mipsNN_cp0_watchhi_write)
473
474/*
475 * void mipsNN_cp0_ebase_read(void *);
476 *	Get the value of the CP0 EBASE (PRID, select 1) register.
477 */
478LEAF(mipsNN_cp0_ebase_read)
479	jr	ra
480	 mfc0	v0, MIPS_COP_0_EBASE
481END(mipsNN_cp0_ebase_read)
482
483/*
484 * void mipsNN_cp0_ebase_write(void *);
485 *	Set the value of the CP0 EBASE (PRID, select 1) register.
486 */
487LEAF(mipsNN_cp0_ebase_write)
488	and	v0, v0, 0x1ff
489	xor	v0, v0, a0
490	jr	ra
491	 mtc0	v0, MIPS_COP_0_EBASE
492END(mipsNN_cp0_ebase_write)
493
494#if (MIPS32R2 + MIPS64R2) > 0
495/*
496 * uint32_t mipsNN_cp0_rdhwr_cpunum(void);
497 *	Set the value of the CP0 HWRENA register.
498 */
499LEAF(mipsNN_cp0_rdhwr_cpunum)
500	.set push
501#ifdef __mips_o32
502	.set mips32r2
503#else
504	.set mips64r2
505#endif
506	jr	ra
507	 rdhwr	v0, MIPS_HWR_CPUNUM
508	.set pop
509END(mipsNN_cp0_rdhwr_cpunum)
510
511/*
512 * void mipsNN_cp0_hwrena_write(void *);
513 *	Set the value of the CP0 HWRENA register.
514 */
515LEAF(mipsNN_cp0_hwrena_write)
516	jr	ra
517	 mtc0	a0, MIPS_COP_0_HWRENA
518END(mipsNN_cp0_hwrena_write)
519
520/*
521 * void mipsNN_cp0_userlocal_write(void *);
522 *	Set the value of the CP0 USERLOCAL (TLB_CONTEXT, select 2) register.
523 */
524LEAF(mipsNN_cp0_userlocal_write)
525	jr	ra
526	 _MTC0	a0, MIPS_COP_0_USERLOCAL
527END(mipsNN_cp0_userlocal_write)
528#endif /* (MIPS32R2 + MIPS64R2) > 0 */
529	.set	pop
530#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
531
532/*
533 * uint32_t mips3_cp0_count_read(void)
534 *
535 *	Return the current value of the CP0 Count register.
536 */
537LEAF(mips3_cp0_count_read)
538	mfc0	v0, MIPS_COP_0_COUNT
539	jr	ra
540	 nop
541END(mips3_cp0_count_read)
542WEAK_ALIAS(cpu_counter32, mips3_cp0_count_read)
543
544/*
545 * void mips3_cp0_count_write(uint32_t)
546 *
547 *	Set the value of the CP0 Count register.
548 */
549LEAF(mips3_cp0_count_write)
550	mtc0	a0, MIPS_COP_0_COUNT
551	JR_HB_RA
552END(mips3_cp0_count_write)
553
554/*
555 * uint32_t mips3_cp0_wired_read(void)
556 *
557 *	Return the current value of the CP0 Wired register.
558 */
559LEAF(mips3_cp0_wired_read)
560	mfc0	v0, MIPS_COP_0_TLB_WIRED
561	jr	ra
562	 nop
563END(mips3_cp0_wired_read)
564
565/*
566 * void mips3_cp0_wired_write(uint32_t)
567 *
568 *	Set the value of the CP0 Wired register.
569 */
570LEAF(mips3_cp0_wired_write)
571	mtc0	a0, MIPS_COP_0_TLB_WIRED
572	JR_HB_RA
573END(mips3_cp0_wired_write)
574
575/*
576 * void mips3_cp0_pg_mask_write(uint32_t)
577 *
578 *	Set the value of the CP0 PG_MASK register.
579 */
580LEAF(mips3_cp0_pg_mask_write)
581	mtc0	a0, MIPS_COP_0_TLB_PG_MASK
582	JR_HB_RA
583END(mips3_cp0_pg_mask_write)
584
585#if __mips != 32
586LEAF(mips3_ld)
587#if defined(__mips_o32)
588#if (MIPS64R2) > 0
589	di	t0
590#else
591	mfc0	t0, MIPS_COP_0_STATUS		# turn off interrupts
592	and	t1, t0, ~(MIPS_SR_INT_IE)
593	mtc0	t1, MIPS_COP_0_STATUS
594#endif
595	COP0_SYNC
596
597	ld	v0, 0(a0)
598#if _BYTE_ORDER == _BIG_ENDIAN
599	dsll	v1, v0, 32
600	dsra	v1, v1, 32			# low word in v1
601#else
602	dsra	v1, v0, 32			# high word in v1
603	dsll	v0, v0, 32
604#endif
605	dsra	v0, v0, 32			# low word in v0
606
607	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
608	JR_HB_RA
609#else /* !__mips_o32 */
610	jr	ra
611	 ld	v0, 0(a0)
612#endif /* !__mips_o32 */
613END(mips3_ld)
614
615LEAF(mips3_sd)
616#if defined(__mips_o32)
617#if (MIPS64R2) > 0
618	di	t0
619#else
620	mfc0	t0, MIPS_COP_0_STATUS		# turn off interrupts
621	and	t1, t0, ~(MIPS_SR_INT_IE)
622	mtc0	t1, MIPS_COP_0_STATUS
623#endif
624	COP0_SYNC
625
626	dsll	a2, a2, 32			# high word in a2
627#if _BYTE_ORDER == _BIG_ENDIAN
628	dsll	a3, a3, 32			# low word in a3
629	dsrl	a3, a3, 32
630#else
631	dsrl	a2, a2, 32
632	dsll	a3, a3, 32			# high word in a3
633#endif
634	or	a1, a2, a3
635	sd	a1, 0(a0)
636
637	mtc0	t0, MIPS_COP_0_STATUS		# restore intr status.
638	JR_HB_RA
639#else /* !__mips_o32 */
640	jr	ra
641	 sd	a1, 0(a0)
642#endif /* !__mips_o32 */
643END(mips3_sd)
644
645/*
646 * int badaddr64(uint64_t addr, int len)
647 * See if access to addr with a len type instruction causes a machine check.
648 * len is length of access in bytes (can be 1, 2, 4, or 8).
649 */
650LEAF(badaddr64)
651	PTR_L	v1, L_PCB(MIPS_CURLWP)
652	PTR_LA	v0, _C_LABEL(baderr64)
653
654#ifdef __mips_o32
655	/* Enable KX */
656	mfc0	t0, MIPS_COP_0_STATUS
657	or	t1, t0, MIPS3_SR_KX
658	and	t2, t0, MIPS_SR_INT_IE	# disable interrupts
659	xor	t1, t2
660	mtc0	t1, MIPS_COP_0_STATUS
661	COP0_SYNC
662
663#ifdef __MIPSEB__
664	dsll	a0, a0, 32	# MSW
665	dsll	a1, a1, 32	# LSW
666	dsrl	a1, a1, 32
667#else
668	dsll	a1, a1, 32	# MSW
669	dsll	a0, a0, 32	# LSW
670	dsrl	a0, a0, 32
671#endif
672	or	a0, a1		# combine
673	move	a1, a2		# move up length argument
674#endif /* __mips_o32 */
675
676	bne	a1, 1, 2f
677	 PTR_S	v0, PCB_ONFAULT(v1)
678	b	9f
679	 lbu	v0, (a0)
6802:
681	bne	a1, 2, 4f
682	 nop
683	b	9f
684	 lhu	v0, (a0)
6854:
686	bne	a1, 4, 8f
687	 nop
688	b	9f
689	 INT_L	v0, (a0)
6908:
691	REG_L	v0, (a0)
6929:
693	sync
694#ifdef __mips_o32
695	mtc0	t0, MIPS_COP_0_STATUS           # Restore KX
696	COP0_SYNC
697#endif
698	PTR_S	zero, PCB_ONFAULT(v1)
699	jr	ra
700	 move	v0, zero			# made it w/o errors
701END(badaddr64)
702
703LEAF(baderr64)
704#ifdef __mips_o32
705	mtc0	t0, MIPS_COP_0_STATUS		# Restore KX
706	COP0_SYNC
707#endif
708	PTR_S	zero, PCB_ONFAULT(v1)
709	jr	ra
710	 li	v0, -1
711END(baderr64)
712
713/*
714 * uint64_t mips3_cp0_tlb_entry_hi_probe(void);
715 *
716 * Write 1s to the VPN and ASID fields of Entry_Hi0 to see how many VA bits
717 * and ASID bits are implemented.  Assumes that interrupts are disabled.
718 */
719LEAF(mips3_cp0_tlb_entry_hi_probe)
720	dmfc0	t0, MIPS_COP_0_TLB_HI
721	li	v0, -1		/* all 1s */
722#if defined(__mips_isa_rev) && __mips_isa_rev >= 2
723	dinsu	v0, zero, 62, 2
724#else
725	dsll	v0, v0, 2	/* except the top 2 */
726	dsrl	v0, v0, 2
727#endif
728	dmtc0	v0, MIPS_COP_0_TLB_HI
729	COP0_SYNC
730	dmfc0	v0, MIPS_COP_0_TLB_HI
731	dmtc0	t0, MIPS_COP_0_TLB_HI
732	COP0_SYNC
733	nop
734#ifdef __mips_o32
735	nop
736#if BYTE_ORDER == BIG_ENDIAN
737	srl	v1, v0, 0
738	dsra	v0, v0, 32
739#endif
740#if BYTE_ORDER == LITTLE_ENDIAN
741	dsra	v1, v0, 32
742	srl	v0, v0, 0
743#endif
744#endif /* __mips_o32 */
745	jr	ra
746	 nop
747END(mips3_cp0_tlb_entry_hi_probe)
748#endif /* __mips != 32 */
749
750/*
751 * uint64_t mips3_cp0_tlb_entry_lo_probe(void);
752 *
753 * Write 1s to the PFN field of Entry_Lo0 to see how many
754 * PA bits are implemented.  Assumes that interrupts are disabled.
755 */
756LEAF(mips3_cp0_tlb_entry_lo_probe)
757	dmfc0	t0, MIPS_COP_0_TLB_LO0
758	li	v0, -64		/* all 1s except low 6 bits */
759	dmtc0	v0, MIPS_COP_0_TLB_LO0
760	COP0_SYNC
761	dmfc0	v0, MIPS_COP_0_TLB_LO0
762	dmtc0	t0, MIPS_COP_0_TLB_LO0
763	COP0_SYNC
764#ifdef __mips_o32
765#if BYTE_ORDER == BIG_ENDIAN
766	srl	v1, v0, 0
767	dsra	v0, v0, 32
768#endif
769#if BYTE_ORDER == LITTLE_ENDIAN
770	dsra	v1, v0, 32
771	srl	v0, v0, 0
772#endif
773#endif /* __mips_o32 */
774	jr	ra
775	 nop
776END(mips3_cp0_tlb_entry_lo_probe)
777
778/*
779 * uint32_t mips3_cp0_tlb_page_mask_probe(void);
780 *
781 * Write 1s to the RPN field of Entry_Lo0 to see how many PA bits are implemented.
782 * Assumes that interrupts are disabled.
783 */
784LEAF(mips3_cp0_tlb_page_mask_probe)
785	mfc0	t0, MIPS_COP_0_TLB_PG_MASK
786	lui	v0, 0xffff
787	srl	v0, v0, 3
788	mtc0	v0, MIPS_COP_0_TLB_PG_MASK
789	COP0_SYNC
790	mfc0	v0, MIPS_COP_0_TLB_PG_MASK
791	mtc0	t0, MIPS_COP_0_TLB_PG_MASK
792	JR_HB_RA
793END(mips3_cp0_tlb_page_mask_probe)
794
795#ifdef MULTIPROCESSOR
796/*
797 * MD code calls/jumps to this with the pointer to this CPU's cpu_info in a1,
798 * sp set to ci->ci_data.cpu_idlelwp->l_md.md_utf.  gp will be overridden so
799 * 0 can be supplied if needed.  (This happens to match what CFE wants)
800 */
801NESTED_NOPROFILE(cpu_trampoline, 0, ra)
802	/*
803	 * We act as the idle lwp so make it CURLWP.  When know
804	 * that the cpu_info is a KSEG0 address.
805	 */
806	move	a0, a1
807	// Loop until idlelwp is filled in.
8081:	PTR_L	MIPS_CURLWP, CPU_INFO_IDLELWP(a0)
809	nop
810	beqz	MIPS_CURLWP, 1b
811	 nop
812	/*
813	 * No membar needed because we're not switching from a
814	 * previous lwp, and the idle lwp we're switching to can't be
815	 * holding locks already; see cpu_switchto.
816	 */
817	PTR_S	MIPS_CURLWP, CPU_INFO_CURLWP(a0)
818
819#ifdef _LP64
820	li	v0, MIPS_SR_KX | MIPS_SR_UX	# allow 64bit addressing
821#elif defined(__mips_n32)
822	li	v0, MIPS_SR_KX			# allow 64bit kernel addressing
823#else
824	li	v0, 0
825#endif
826	mtc0	v0, MIPS_COP_0_STATUS		# reset to known state
827	COP0_SYNC
828
829	PTR_L	sp, L_MD_UTF(MIPS_CURLWP)	# fetch KSP
830
831	/*
832	 * Indicate that no one has called us.
833	 */
834	move	ra, zero
835	REG_S	ra, CALLFRAME_RA(sp)
836
837#ifdef __GP_SUPPORT__
838	/*
839	 * New execution constant needs GP to be loaded.
840	 */
841	PTR_LA	gp, _C_LABEL(_gp)
842#endif
843
844#if 0
845	LONG_L	t0, CPU_INFO_FLAGS(a0)
846	or	t0, t0, CPUF_PRESENT
847	LONG_S	t0, CPU_INFO_FLAGS(a0)
848	sync
849#endif
850
851	/*
852	 * and off we go.
853	 */
854	j	_C_LABEL(cpu_hatch)		# does everything
855	 nop
856END(cpu_trampoline)
857#endif /* MULTIPROCESSOR */
858