Annotation of src/sys/arch/mips/rmi/rmixl_cpu.c, Revision 1.1.2.14
1.1.2.14! matt 1: /* $NetBSD: rmixl_cpu.c,v 1.1.2.13 2010/08/16 18:01:13 matt Exp $ */
1.1.2.1 cliff 2:
3: /*
4: * Copyright 2002 Wasabi Systems, Inc.
5: * All rights reserved.
6: *
7: * Written by Simon Burge for Wasabi Systems, Inc.
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 NetBSD Project by
20: * Wasabi Systems, Inc.
21: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35: * POSSIBILITY OF SUCH DAMAGE.
36: */
37:
38: #include "locators.h"
39:
40: #include <sys/cdefs.h>
1.1.2.14! matt 41: __KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.1.2.13 2010/08/16 18:01:13 matt Exp $");
1.1.2.1 cliff 42:
43: #include <sys/param.h>
44: #include <sys/device.h>
45: #include <sys/systm.h>
46: #include <sys/cpu.h>
1.1.2.3 cliff 47: #include <sys/lock.h>
1.1.2.6 cliff 48: #include <sys/lwp.h>
49: #include <sys/cpu.h>
50: #include <sys/user.h>
51: #include <sys/malloc.h>
1.1.2.3 cliff 52: #include <uvm/uvm_pglist.h>
53: #include <uvm/uvm_extern.h>
1.1.2.6 cliff 54: #include <mips/regnum.h>
55: #include <mips/asm.h>
1.1.2.5 matt 56: #include <mips/pmap.h>
1.1.2.3 cliff 57: #include <mips/rmi/rmixlreg.h>
1.1.2.2 matt 58: #include <mips/rmi/rmixlvar.h>
1.1.2.1 cliff 59: #include <mips/rmi/rmixl_cpucorevar.h>
1.1.2.6 cliff 60: #include <mips/rmi/rmixl_cpuvar.h>
61: #include <mips/rmi/rmixl_intr.h>
62: #include <mips/rmi/rmixl_fmnvar.h>
63:
1.1.2.1 cliff 64:
1.1.2.2 matt 65: static int cpu_rmixl_match(device_t, cfdata_t, void *);
66: static void cpu_rmixl_attach(device_t, device_t, void *);
1.1.2.6 cliff 67: static void cpu_rmixl_attach_once(struct rmixl_cpu_softc * const);
68: #ifdef NOTYET
69: static int cpu_fmn_intr(void *, rmixl_fmn_rxmsg_t *);
70: #endif
1.1.2.1 cliff 71:
1.1.2.3 cliff 72: #ifdef MULTIPROCESSOR
1.1.2.6 cliff 73: void cpu_rmixl_hatch(struct cpu_info *);
74: #if 0
75: static void cpu_setup_trampoline_ipi(struct device *, struct cpu_info *);
1.1.2.3 cliff 76: #endif
1.1.2.10 cliff 77: static int cpu_setup_trampoline_common(struct cpu_info *, struct rmixl_cpu_trampoline_args *);
78: static void cpu_setup_trampoline_callback(struct cpu_info *);
1.1.2.6 cliff 79: #ifdef DEBUG
80: void rmixl_cpu_data_print(struct cpu_data *);
81: struct cpu_info *
82: rmixl_cpuinfo_print(cpuid_t);
83: #endif /* DEBUG */
84: #endif /* MULTIPROCESSOR */
1.1.2.3 cliff 85:
1.1.2.6 cliff 86: CFATTACH_DECL_NEW(cpu_rmixl, sizeof(struct rmixl_cpu_softc),
87: cpu_rmixl_match, cpu_rmixl_attach, NULL, NULL);
88:
1.1.2.7 cliff 89: #ifdef MULTIPROCESSOR
1.1.2.6 cliff 90: static struct rmixl_cpu_trampoline_args rmixl_cpu_trampoline_args;
1.1.2.7 cliff 91: #endif
1.1.2.1 cliff 92:
1.1.2.12 cliff 93: /*
94: * cpu_xls616_erratum
95: *
96: * on the XLS616, COUNT/COMPARE clock regs seem to interact between
97: * threads on a core
98: *
99: * the symptom of the error is retarded clock interrupts
100: * and very slow apparent system performance
101: *
102: * other XLS chips may have the same problem.
103: * we may need to add other PID checks.
104: */
105: static inline bool
106: cpu_xls616_erratum(device_t parent, struct cpucore_attach_args *ca)
107: {
108: if (mips_options.mips_cpu->cpu_pid == MIPS_XLS616) {
109: if (ca->ca_thread > 0) {
110: aprint_error_dev(parent, "XLS616 CLOCK ERRATUM: "
111: "deconfigure cpu%d\n", ca->ca_thread);
112: return true;
113: }
114: }
115: return false;
116: }
117:
118: static bool
119: cpu_rmixl_erratum(device_t parent, struct cpucore_attach_args *ca)
120: {
121: return cpu_xls616_erratum(parent, ca);
122: }
123:
1.1.2.1 cliff 124: static int
1.1.2.2 matt 125: cpu_rmixl_match(device_t parent, cfdata_t cf, void *aux)
1.1.2.1 cliff 126: {
127: struct cpucore_attach_args *ca = aux;
128: int thread = cf->cf_loc[CPUCORECF_THREAD];
129:
1.1.2.2 matt 130: if (!cpu_rmixl(mips_options.mips_cpu))
131: return 0;
132:
1.1.2.1 cliff 133: if (strncmp(ca->ca_name, cf->cf_name, strlen(cf->cf_name)) == 0
134: #ifndef MULTIPROCESSOR
135: && ca->ca_thread == 0
136: #endif
1.1.2.12 cliff 137: && (thread == CPUCORECF_THREAD_DEFAULT || thread == ca->ca_thread)
138: && (!cpu_rmixl_erratum(parent, ca)))
1.1.2.1 cliff 139: return 1;
140:
141: return 0;
142: }
143:
144: static void
1.1.2.2 matt 145: cpu_rmixl_attach(device_t parent, device_t self, void *aux)
1.1.2.1 cliff 146: {
1.1.2.6 cliff 147: struct rmixl_cpu_softc * const sc = device_private(self);
1.1.2.1 cliff 148: struct cpucore_attach_args *ca = aux;
1.1.2.6 cliff 149: struct cpu_info *ci = NULL;
1.1.2.12 cliff 150: extern void rmixl_spl_init_cpu(void);
1.1.2.3 cliff 151:
1.1.2.1 cliff 152: if (ca->ca_thread == 0 && ca->ca_core == 0) {
1.1.2.6 cliff 153: ci = curcpu();
154: sc->sc_dev = self;
155: sc->sc_ci = ci;
156: ci->ci_softc = (void *)sc;
157:
1.1.2.12 cliff 158: rmixl_spl_init_cpu(); /* spl initialization for CPU#0 */
1.1.2.6 cliff 159: cpu_rmixl_attach_once(sc);
160:
1.1.2.1 cliff 161: #ifdef MULTIPROCESSOR
1.1.2.6 cliff 162: mips_locoresw.lsw_cpu_init = cpu_rmixl_hatch;
1.1.2.1 cliff 163: } else {
1.1.2.5 matt 164: struct cpucore_softc * const ccsc = device_private(parent);
1.1.2.4 cliff 165: rmixlfw_psb_type_t psb_type = rmixl_configuration.rc_psb_type;
1.1.2.6 cliff 166: cpuid_t cpuid;
167:
168: KASSERT(ca->ca_core < 8);
169: KASSERT(ca->ca_thread < 4);
170: cpuid = (ca->ca_core << 2) | ca->ca_thread;
1.1.2.14! matt 171: ci = cpu_info_alloc(ccsc->sc_tlbinfo, cpuid,
! 172: /* XXX */ 0, ca->ca_core, ca->ca_thread);
1.1.2.6 cliff 173: KASSERT(ci != NULL);
174: sc->sc_dev = self;
175: sc->sc_ci = ci;
176: ci->ci_softc = (void *)sc;
1.1.2.1 cliff 177:
1.1.2.4 cliff 178: switch (psb_type) {
179: case PSB_TYPE_RMI:
180: case PSB_TYPE_DELL:
1.1.2.10 cliff 181: cpu_setup_trampoline_callback(ci);
1.1.2.6 cliff 182: break;
1.1.2.4 cliff 183: default:
184: aprint_error(": psb type=%s cpu_wakeup unsupported\n",
185: rmixlfw_psb_type_name(psb_type));
186: return;
187: }
1.1.2.6 cliff 188:
189: const u_long cpu_mask = 1L << cpu_index(ci);
190: for (size_t i=0; i < 10000; i++) {
191: if ((cpus_hatched & cpu_mask) != 0)
192: break;
193: DELAY(100);
194: }
195: if ((cpus_hatched & cpu_mask) == 0) {
196: aprint_error(": failed to hatch\n");
1.1.2.1 cliff 197: return;
198: }
1.1.2.6 cliff 199: #endif /* MULTIPROCESSOR */
200: }
201:
202: /*
203: * do per-cpu interrupt initialization
204: */
205: rmixl_intr_init_cpu(ci);
206:
207: aprint_normal("\n");
208:
209: cpu_attach_common(self, ci);
210: }
211:
212: static void
213: cpu_rmixl_attach_once(struct rmixl_cpu_softc * const sc)
214: {
215: static bool once = false;
216:
217: KASSERT("once != true");
218: if (once == true)
219: return;
220: once = true;
221:
222: rmixl_fmn_init();
1.1.2.3 cliff 223:
1.1.2.6 cliff 224: sc->sc_ih_clk = rmixl_intr_init_clk();
225: #ifdef MULTIPROCESSOR
226: sc->sc_ih_ipi = rmixl_intr_init_ipi();
1.1.2.1 cliff 227: #endif
1.1.2.6 cliff 228:
229: #ifdef NOTYET
230: void *ih = rmixl_fmn_intr_establish(RMIXL_FMN_STID_CORE0,
231: cpu_fmn_intr, ci);
232: if (ih == NULL)
233: panic("%s: rmixl_fmn_intr_establish failed",
234: __func__);
235: sc->sc_ih_fmn = ih;
236: #endif
237:
238: }
239:
240: #ifdef NOTYET
241: static int
242: cpu_fmn_intr(void *arg, rmixl_fmn_rxmsg_t *rxmsg)
243: {
244: if (cpu_number() == 0) {
245: printf("%s: cpu %ld: rxsid=%#x, code=%d, size=%d\n",
246: __func__, cpu_number(),
247: rxmsg->rxsid, rxmsg->code, rxmsg->size);
248: for (int i=0; i < rxmsg->size; i++)
249: printf("\t%#"PRIx64"\n", rxmsg->msg.data[i]);
1.1.2.1 cliff 250: }
1.1.2.6 cliff 251:
252: return 1;
1.1.2.1 cliff 253: }
1.1.2.6 cliff 254: #endif
1.1.2.3 cliff 255:
256: #ifdef MULTIPROCESSOR
1.1.2.6 cliff 257: /*
258: * cpu_rmixl_hatch
259: *
260: * - chip-specific hatch code called from cpu_hatch via lsw_cpu_init
261: */
1.1.2.3 cliff 262: void
1.1.2.6 cliff 263: cpu_rmixl_hatch(struct cpu_info *ci)
1.1.2.3 cliff 264: {
1.1.2.12 cliff 265: extern void rmixl_spl_init_cpu(void);
266:
267: rmixl_spl_init_cpu(); /* spl initialization for this CPU */
268:
1.1.2.6 cliff 269: (void)splhigh();
270:
271: #ifdef DEBUG
272: uint32_t ebase;
273: asm volatile("dmfc0 %0, $15, 1;" : "=r"(ebase));
274: KASSERT((ebase & __BITS(9,0)) == ci->ci_cpuid);
275: KASSERT(curcpu() == ci);
276: #endif
277:
278: if (RMIXL_CPU_THREAD(ci->ci_cpuid) == 0)
279: rmixl_fmn_init_core();
1.1.2.3 cliff 280: }
281:
1.1.2.10 cliff 282: static int
283: cpu_setup_trampoline_common(struct cpu_info *ci, struct rmixl_cpu_trampoline_args *ta)
1.1.2.3 cliff 284: {
1.1.2.6 cliff 285: struct lwp *l = ci->ci_data.cpu_idlelwp;
286: uintptr_t stacktop;
287:
1.1.2.8 cliff 288: #ifdef DIAGNOSTIC
289: /* Ensure our current stack can be used by the firmware */
290: uint64_t sp;
291: __asm__ volatile("move %0, $sp\n" : "=r"(sp));
292: #ifdef _LP64
293: /* can be made into a KSEG0 addr */
294: KASSERT(MIPS_XKPHYS_P(sp));
295: KASSERT((MIPS_XKPHYS_TO_PHYS(sp) >> 32) == 0);
296: #else
297: /* is a KSEG0 addr */
298: KASSERT(MIPS_KSEG0_P(sp));
299: #endif /* _LP64 */
300: #endif /* DIAGNOSTIC */
301:
302: #ifndef _LP64
303: /*
304: * Ensure 'ci' is a KSEG0 address for trampoline args
305: * to avoid TLB fault in cpu_trampoline() when loading ci_idlelwp
306: */
307: KASSERT(MIPS_KSEG0_P(ci));
308: #endif
309:
1.1.2.6 cliff 310: /*
311: * Ensure 'ta' is a KSEG0 address for trampoline args
312: * to avoid TLB fault in trampoline when loading args.
313: *
314: * Note:
1.1.2.10 cliff 315: * RMI firmware only passes the lower 32-bit half of 'ta'
1.1.2.6 cliff 316: * to rmixl_cpu_trampoline (the upper half is clear)
317: * so rmixl_cpu_trampoline must reconstruct the missing upper half
318: * rmixl_cpu_trampoline "knows" to use MIPS_KSEG0_START
319: * to reconstruct upper half of 'ta'.
320: */
321: KASSERT(MIPS_KSEG0_P(ta));
322:
323: /*
1.1.2.10 cliff 324: * marshal args for rmixl_cpu_trampoline;
1.1.2.8 cliff 325: * note for non-LP64 kernel, use of intptr_t
326: * forces sign extension of 32 bit pointers
1.1.2.6 cliff 327: */
328: stacktop = (uintptr_t)l->l_addr + USPACE
329: - sizeof(struct trapframe) - CALLFRAME_SIZ;
1.1.2.8 cliff 330: ta->ta_sp = (uint64_t)(intptr_t)stacktop;
331: ta->ta_lwp = (uint64_t)(intptr_t)l;
332: ta->ta_cpuinfo = (uint64_t)(intptr_t)ci;
1.1.2.3 cliff 333:
1.1.2.10 cliff 334: return 0;
1.1.2.3 cliff 335: }
1.1.2.6 cliff 336:
337: static void
1.1.2.10 cliff 338: cpu_setup_trampoline_callback(struct cpu_info *ci)
1.1.2.6 cliff 339: {
1.1.2.10 cliff 340: void (*wakeup_cpu)(void *, void *, unsigned int);
341: struct rmixl_cpu_trampoline_args *ta = &rmixl_cpu_trampoline_args;
1.1.2.6 cliff 342: extern void rmixl_cpu_trampoline(void *);
1.1.2.10 cliff 343: extern void rmixlfw_wakeup_cpu(void *, void *, u_int64_t, void *);
344:
345: cpu_setup_trampoline_common(ci, ta);
1.1.2.6 cliff 346:
1.1.2.10 cliff 347: #if _LP64
348: wakeup_cpu = (void *)rmixl_configuration.rc_psb_info.wakeup;
349: #else
350: wakeup_cpu = (void *)(intptr_t)
351: (rmixl_configuration.rc_psb_info.wakeup & 0xffffffff);
352: #endif
1.1.2.6 cliff 353:
1.1.2.10 cliff 354: rmixlfw_wakeup_cpu(rmixl_cpu_trampoline, (void *)ta,
355: (uint64_t)1 << ci->ci_cpuid, wakeup_cpu);
1.1.2.6 cliff 356: }
357:
1.1.2.10 cliff 358:
1.1.2.6 cliff 359: #ifdef DEBUG
360: void
361: rmixl_cpu_data_print(struct cpu_data *dp)
362: {
363: printf("cpu_biglock_wanted %p\n", dp->cpu_biglock_wanted);
364: printf("cpu_callout %p\n", dp->cpu_callout);
365: printf("cpu_unused1 %p\n", dp->cpu_unused1);
366: printf("cpu_unused2 %d\n", dp->cpu_unused2);
367: printf("&cpu_schedstate %p\n", &dp->cpu_schedstate); /* TBD */
368: printf("&cpu_xcall %p\n", &dp->cpu_xcall); /* TBD */
369: printf("cpu_xcall_pending %d\n", dp->cpu_xcall_pending);
370: printf("cpu_onproc %p\n", dp->cpu_onproc);
371: printf("&cpu_qchain %p\n", &dp->cpu_qchain); /* TBD */
372: printf("cpu_idlelwp %p\n", dp->cpu_idlelwp);
373: printf("cpu_lockstat %p\n", dp->cpu_lockstat);
374: printf("cpu_index %d\n", dp->cpu_index);
375: printf("cpu_biglock_count %d\n", dp->cpu_biglock_count);
376: printf("cpu_spin_locks %d\n", dp->cpu_spin_locks);
377: printf("cpu_simple_locks %d\n", dp->cpu_simple_locks);
378: printf("cpu_spin_locks2 %d\n", dp->cpu_spin_locks2);
379: printf("cpu_lkdebug_recurse %d\n", dp->cpu_lkdebug_recurse);
380: printf("cpu_softints %d\n", dp->cpu_softints);
381: printf("cpu_nsyscall %d\n", dp->cpu_nsyscall);
382: printf("cpu_ntrap %d\n", dp->cpu_ntrap);
383: printf("cpu_nswtch %d\n", dp->cpu_nswtch);
384: printf("cpu_uvm %p\n", dp->cpu_uvm);
385: printf("cpu_softcpu %p\n", dp->cpu_softcpu);
386: printf("&cpu_biodone %p\n", &dp->cpu_biodone); /* TBD */
387: printf("&cpu_percpu %p\n", &dp->cpu_percpu); /* TBD */
388: printf("cpu_selcpu %p\n", dp->cpu_selcpu);
389: printf("cpu_nch %p\n", dp->cpu_nch);
390: printf("&cpu_ld_locks %p\n", &dp->cpu_ld_locks); /* TBD */
391: printf("&cpu_ld_lock %p\n", &dp->cpu_ld_lock); /* TBD */
392: printf("cpu_cc_freq %#"PRIx64"\n", dp->cpu_cc_freq);
393: printf("cpu_cc_skew %#"PRIx64"\n", dp->cpu_cc_skew);
394: }
395:
396: struct cpu_info *
397: rmixl_cpuinfo_print(cpuid_t cpuid)
398: {
399: struct cpu_info * const ci = cpu_lookup(cpuid);
400:
401: if (ci != NULL) {
402: rmixl_cpu_data_print(&ci->ci_data);
403: printf("ci_dev %p\n", ci->ci_dev);
404: printf("ci_cpuid %ld\n", ci->ci_cpuid);
405: printf("ci_cctr_freq %ld\n", ci->ci_cctr_freq);
406: printf("ci_cpu_freq %ld\n", ci->ci_cpu_freq);
407: printf("ci_cycles_per_hz %ld\n", ci->ci_cycles_per_hz);
408: printf("ci_divisor_delay %ld\n", ci->ci_divisor_delay);
409: printf("ci_divisor_recip %ld\n", ci->ci_divisor_recip);
410: printf("ci_curlwp %p\n", ci->ci_curlwp);
411: printf("ci_want_resched %d\n", ci->ci_want_resched);
412: printf("ci_mtx_count %d\n", ci->ci_mtx_count);
413: printf("ci_mtx_oldspl %d\n", ci->ci_mtx_oldspl);
414: printf("ci_idepth %d\n", ci->ci_idepth);
415: printf("ci_cpl %d\n", ci->ci_cpl);
416: printf("&ci_cpl %p\n", &ci->ci_cpl); /* XXX */
417: printf("ci_next_cp0_clk_intr %#x\n", ci->ci_next_cp0_clk_intr);
418: for (int i=0; i < SOFTINT_COUNT; i++)
419: printf("ci_softlwps[%d] %p\n", i, ci->ci_softlwps[i]);
420: printf("ci_tlb_slot %d\n", ci->ci_tlb_slot);
421: printf("ci_tlb_info %p\n", ci->ci_tlb_info);
1.1.2.13 matt 422: printf("ci_pmap_seg0tab %p\n", ci->ci_pmap_seg0tab);
423: #ifdef _LP64
424: printf("ci_pmap_segtab %p\n", ci->ci_pmap_segtab);
425: #else
1.1.2.6 cliff 426: printf("ci_pmap_srcbase %#"PRIxVADDR"\n", ci->ci_pmap_srcbase);
427: printf("ci_pmap_dstbase %#"PRIxVADDR"\n", ci->ci_pmap_dstbase);
1.1.2.13 matt 428: #endif
1.1.2.6 cliff 429: #ifdef MULTIPROCESSOR
430: printf("ci_flags %#lx\n", ci->ci_flags);
431: printf("ci_request_ipis %#"PRIx64"\n", ci->ci_request_ipis);
432: printf("ci_active_ipis %#"PRIx64"\n", ci->ci_active_ipis);
433: printf("ci_ksp_tlb_slot %d\n", ci->ci_ksp_tlb_slot);
434: printf("ci_fpsave_si %p\n", ci->ci_fpsave_si);
435: #endif
436: }
437:
438: return ci;
439: }
440:
441: #endif /* DEBUG */
1.1.2.3 cliff 442: #endif /* MULTIPROCESSOR */
CVSweb <webmaster@jp.NetBSD.org>