xref: /netbsd/sys/arch/sgimips/sgimips/cpu.c (revision 6550d01e)
1 /*	$NetBSD: cpu.c,v 1.25 2011/01/28 10:20:28 tsutsui Exp $	*/
2 
3 /*
4  * Copyright (c) 2000 Soren S. Jorvang
5  * Copyright (c) 2001 Jason R. Thorpe.
6  * Copyright (c) 2004 Christopher SEKIYA
7  * All rights reserved.
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  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *          This product includes software developed for the
20  *          NetBSD Project.  See http://www.NetBSD.org/ for
21  *          information about NetBSD.
22  * 4. The name of the author may not be used to endorse or promote products
23  *    derived from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.25 2011/01/28 10:20:28 tsutsui Exp $");
39 
40 #include <sys/param.h>
41 #include <sys/device.h>
42 #include <sys/systm.h>
43 #include <sys/cpu.h>
44 
45 #include <uvm/uvm_extern.h>
46 
47 #include <machine/locore.h>
48 #include <machine/psl.h>
49 #include <machine/autoconf.h>
50 #include <machine/machtype.h>
51 #include <machine/sysconf.h>
52 
53 #include <dev/arcbios/arcbios.h>
54 #include <dev/arcbios/arcbiosvar.h>
55 
56 static int	cpu_match(device_t, cfdata_t, void *);
57 static void	cpu_attach(device_t, device_t, void *);
58 void		cpu_intr(uint32_t, uint32_t, vaddr_t, uint32_t);
59 void *cpu_intr_establish(int, int, int (*func)(void *), void *);
60 void		mips1_fpu_intr(u_int32_t, u_int32_t, u_int32_t, u_int32_t);
61 
62 extern void	MachFPInterrupt(u_int32_t, u_int32_t, u_int32_t, struct frame *);
63 
64 static struct evcnt mips_int0_evcnt =
65 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 0");
66 
67 static struct evcnt mips_int1_evcnt =
68 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 1");
69 
70 static struct evcnt mips_int2_evcnt =
71 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 2");
72 
73 static struct evcnt mips_int3_evcnt =
74 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 3");
75 
76 static struct evcnt mips_int4_evcnt =
77 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 4");
78 
79 static struct evcnt mips_int5_evcnt =
80 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "int 5");
81 
82 static struct evcnt mips_spurint_evcnt =
83 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "mips", "spurious interrupts");
84 
85 CFATTACH_DECL_NEW(cpu, 0,
86     cpu_match, cpu_attach, NULL, NULL);
87 
88 static int
89 cpu_match(device_t parent, cfdata_t cf, void *aux)
90 {
91 	return 1;
92 }
93 
94 static void
95 cpu_attach(device_t parent, device_t self, void *aux)
96 {
97 	printf(": ");
98 	cpu_identify();
99 }
100 
101 /*
102  * NB: Do not re-enable interrupts here -- reentrancy here can cause all
103  * sorts of Bad Things(tm) to happen, including kernel stack overflows.
104  */
105 void
106 cpu_intr(uint32_t status, uint32_t cause, vaddr_t pc, uint32_t ipending)
107 {
108 	struct cpu_info *ci;
109 
110 	ci = curcpu();
111 	ci->ci_idepth++;
112 	ci->ci_data.cpu_nintr++;
113 
114 	(void)(*platform.watchdog_reset)();
115 
116 	if (ipending & MIPS_HARD_INT_MASK) {
117         	if (ipending & MIPS_INT_MASK_5) {
118                		(void)(*platform.intr5)(status, cause, pc, ipending);
119 			mips_int5_evcnt.ev_count++;
120 			cause &= ~MIPS_INT_MASK_5;
121         	}
122 
123 		if (ipending & MIPS_INT_MASK_4) {
124 			(void)(*platform.intr4)(status, cause, pc, ipending);
125 			mips_int4_evcnt.ev_count++;
126 			cause &= ~MIPS_INT_MASK_4;
127 		}
128 
129 		if (ipending & MIPS_INT_MASK_3) {
130 			(void)(*platform.intr3)(status, cause, pc, ipending);
131 			mips_int3_evcnt.ev_count++;
132 			cause &= ~MIPS_INT_MASK_3;
133 		}
134 
135 	        if (ipending & MIPS_INT_MASK_2) {
136 			(void)(*platform.intr2)(status, cause, pc, ipending);
137 			mips_int2_evcnt.ev_count++;
138 			cause &= ~MIPS_INT_MASK_2;
139 		}
140 
141 		if (ipending & MIPS_INT_MASK_1) {
142 			(void)(*platform.intr1)(status, cause, pc, ipending);
143 			mips_int1_evcnt.ev_count++;
144 			cause &= ~MIPS_INT_MASK_1;
145 		}
146 
147 		if (ipending & MIPS_INT_MASK_0) {
148 			(void)(*platform.intr0)(status, cause, pc, ipending);
149 			mips_int0_evcnt.ev_count++;
150 			cause &= ~MIPS_INT_MASK_0;
151 		}
152 
153 		if (cause & status & MIPS_HARD_INT_MASK)
154 			mips_spurint_evcnt.ev_count++;
155 	}
156 	ci->ci_idepth--;
157 
158 #ifdef __HAVE_FAST_SOFTINTS
159 	/* software interrupt */
160 	ipending &= (MIPS_SOFT_INT_MASK_1|MIPS_SOFT_INT_MASK_0);
161 	if (ipending == 0)
162 		return;
163 	_clrsoftintr(ipending);
164 	softintr_dispatch(ipending);
165 #endif
166 }
167 
168 void *
169 cpu_intr_establish(int level, int ipl, int (*func)(void *), void *arg)
170 {
171 	(*platform.intr_establish)(level, ipl, func, arg);
172 	return (void *) -1;
173 }
174 
175 void
176 mips1_fpu_intr(u_int32_t status, u_int32_t cause, u_int32_t pc,
177     u_int32_t ipending)
178 {
179 
180 	if (!USERMODE(status))
181 		panic("kernel used FPU: PC 0x%08x, CR 0x%08x, SR 0x%08x",
182 		    pc, cause, status);
183 
184 #if !defined(NOFPU) && !defined(SOFTFLOAT)
185 	MachFPInterrupt(status, cause, pc, curlwp->l_md.md_regs);
186 #endif
187 }
188