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