Module Name:    src
Committed By:   cliff
Date:           Sun Mar 21 21:23:54 UTC 2010

Modified Files:
        src/sys/arch/mips/rmi [matt-nb5-mips64]: rmixl_cpu.c

Log Message:
- use different wakeup trampolines depending on firmware type
so far only RMI formware with callback wakeup method is tested.
- add a (chip-specific) softc structure, and cross link it
with struct cpu_info
- remove exception vectors mem allocation, it is now provided
by cpu_attach_common
- remove common cpu_info initialization, now provided
by cpu_attach_common
- use per-CPU bit in 'cpus_hatched' as handshake with the CPU
we just hatched
- call rmixl_intr_init_cpu for per-CPU interrupt initialization
- call cpu_attach_common() for common mips stuff
- cpu_rmixl_attach_once() groups together chip-specific initializations
that are only to be one once, i.e. by CPU#0
- cpu_rmixl_hatch() provides chip-specific hatch code called from
(mips-common) cpu_hatch() via lsw_cpu_init
- cpu_setup_trampoline_callback() provides method to wake up
subordinate CPUs using RMI firmware callback.
- rmixl_cpuinfo_print() can be called for debugging e.g. from DDB
should maybe evolve into DDB 'mach cpu <n>' ?


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.5 -r1.1.2.6 src/sys/arch/mips/rmi/rmixl_cpu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/rmi/rmixl_cpu.c
diff -u src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.5 src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.6
--- src/sys/arch/mips/rmi/rmixl_cpu.c:1.1.2.5	Tue Feb 23 20:33:48 2010
+++ src/sys/arch/mips/rmi/rmixl_cpu.c	Sun Mar 21 21:23:54 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rmixl_cpu.c,v 1.1.2.5 2010/02/23 20:33:48 matt Exp $	*/
+/*	$NetBSD: rmixl_cpu.c,v 1.1.2.6 2010/03/21 21:23:54 cliff Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -38,29 +38,55 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.1.2.5 2010/02/23 20:33:48 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.1.2.6 2010/03/21 21:23:54 cliff Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
 #include <sys/systm.h>
 #include <sys/cpu.h>
 #include <sys/lock.h>
+#include <sys/lwp.h>
+#include <sys/cpu.h>
+#include <sys/user.h>
+#include <sys/malloc.h>
 #include <uvm/uvm_pglist.h>
 #include <uvm/uvm_extern.h>
+#include <mips/regnum.h>
+#include <mips/asm.h> 
 #include <mips/pmap.h>
 #include <mips/rmi/rmixlreg.h>
 #include <mips/rmi/rmixlvar.h>
 #include <mips/rmi/rmixl_cpucorevar.h>
+#include <mips/rmi/rmixl_cpuvar.h>
+#include <mips/rmi/rmixl_intr.h>
+#include <mips/rmi/rmixl_fmnvar.h>
+
 
 static int	cpu_rmixl_match(device_t, cfdata_t, void *);
 static void	cpu_rmixl_attach(device_t, device_t, void *);
+static void	cpu_rmixl_attach_once(struct rmixl_cpu_softc * const);
+#ifdef NOTYET
+static int	cpu_fmn_intr(void *, rmixl_fmn_rxmsg_t *);
+#endif
 
 #ifdef MULTIPROCESSOR
-void		cpu_trampoline_park(void);
-static void	cpu_setup_trampoline(struct device *, struct cpu_info *);
+void		cpu_rmixl_hatch(struct cpu_info *);
+#if 0
+static void	cpu_setup_trampoline_ipi(struct device *, struct cpu_info *);
 #endif
+static void	cpu_setup_trampoline_callback(struct device *, struct cpu_info *);
+static void	cpu_setup_trampoline_fmn(struct device *, struct cpu_info *);
+#ifdef DEBUG
+void		rmixl_cpu_data_print(struct cpu_data *);
+struct cpu_info *
+		rmixl_cpuinfo_print(cpuid_t);
+#endif	/* DEBUG */
+#endif	/* MULTIPROCESSOR */
 
-CFATTACH_DECL_NEW(cpu_rmixl, 0, cpu_rmixl_match, cpu_rmixl_attach, NULL, NULL);
+CFATTACH_DECL_NEW(cpu_rmixl, sizeof(struct rmixl_cpu_softc),
+	cpu_rmixl_match, cpu_rmixl_attach, NULL, NULL); 
+
+static struct rmixl_cpu_trampoline_args rmixl_cpu_trampoline_args;
 
 static int
 cpu_rmixl_match(device_t parent, cfdata_t cf, void *aux)
@@ -84,69 +110,145 @@
 static void
 cpu_rmixl_attach(device_t parent, device_t self, void *aux)
 {
+	struct rmixl_cpu_softc * const sc = device_private(self);
 	struct cpucore_attach_args *ca = aux;
+	struct cpu_info *ci = NULL;
 
 	if (ca->ca_thread == 0 && ca->ca_core == 0) {
-		struct cpu_info * const ci = curcpu();
-		ci->ci_dev = self;
-		self->dv_private = ci;
+		ci = curcpu();
+		sc->sc_dev = self;
+		sc->sc_ci = ci;
+		ci->ci_softc = (void *)sc;
+
+		cpu_rmixl_attach_once(sc);
+
 #ifdef MULTIPROCESSOR
+		mips_locoresw.lsw_cpu_init = cpu_rmixl_hatch;
 	} else {
 		struct cpucore_softc * const ccsc = device_private(parent);
 		rmixlfw_psb_type_t psb_type = rmixl_configuration.rc_psb_type;
-		struct pglist pglist;
-		int error;
+		cpuid_t cpuid;
+		int s;
+
+		s = splhigh();
+
+		KASSERT(ca->ca_core < 8);
+		KASSERT(ca->ca_thread < 4);
+		cpuid = (ca->ca_core << 2) | ca->ca_thread;
+		ci = cpu_info_alloc(ccsc->sc_tlbinfo, cpuid);
+		KASSERT(ci != NULL);
+		sc->sc_dev = self;
+		sc->sc_ci = ci;
+		ci->ci_softc = (void *)sc;
 
 		switch (psb_type) {
 		case PSB_TYPE_RMI:
+			cpu_setup_trampoline_callback(self, ci);
 			break;
 		case PSB_TYPE_DELL:
-			/* FALLTHROUGH */
+			cpu_setup_trampoline_fmn(self, ci);
+			break;
 		default:
 			aprint_error(": psb type=%s cpu_wakeup unsupported\n",
 				rmixlfw_psb_type_name(psb_type));
 			return;
 		}
- 
-		/*
-		 * Grab a page from the first 256MB to use to store
-		 * exception vectors and cpu_info for this cpu.
-		 */
-		error = uvm_pglistalloc(PAGE_SIZE,
-		    0, 0x10000000,
-		    PAGE_SIZE, PAGE_SIZE, &pglist, 1, false);
-		if (error) {
-			aprint_error(": failed to allocte exception vectors\n");
+
+		const u_long cpu_mask = 1L << cpu_index(ci);
+		for (size_t i=0; i < 10000; i++) {
+			if ((cpus_hatched & cpu_mask) != 0)
+				 break;
+			DELAY(100);
+		}
+		if ((cpus_hatched & cpu_mask) == 0) {
+			aprint_error(": failed to hatch\n");
 			return;
 		}
 
-		const paddr_t pa = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist));
-		const vaddr_t va = MIPS_PHYS_TO_KSEG0(pa);
-		struct cpu_info * const ci = (void *) (va + 0x400);
-		memset((void *)va, 0, PAGE_SIZE);
-		ci->ci_dev = self;
-		KASSERT(ca->ca_core < 8);
-		KASSERT(ca->ca_thread < 4);
-		ci->ci_cpuid = (ca->ca_core << 2) | ca->ca_thread;
-		pmap_tlb_info_attach(ccsc->sc_tlbinfo, ci);
-		self->dv_private = ci;
+		splx(s);
 
-		cpu_setup_trampoline(self, ci);
+#endif	/* MULTIPROCESSOR */
+	}
+
+	/*
+	 * do per-cpu interrupt initialization
+	 */
+	rmixl_intr_init_cpu(ci);
+
+	aprint_normal("\n");
+
+        cpu_attach_common(self, ci);
+}
+
+static void
+cpu_rmixl_attach_once(struct rmixl_cpu_softc * const sc)
+{
+	static bool once = false;
+
+	KASSERT("once != true");
+	if (once == true)
+		return;
+	once = true;
+
+	rmixl_fmn_init();
 
+	sc->sc_ih_clk = rmixl_intr_init_clk();
+#ifdef MULTIPROCESSOR
+	sc->sc_ih_ipi = rmixl_intr_init_ipi();
 #endif
+
+#ifdef NOTYET
+	void *ih = rmixl_fmn_intr_establish(RMIXL_FMN_STID_CORE0,
+		cpu_fmn_intr, ci);
+	if (ih == NULL)
+		panic("%s: rmixl_fmn_intr_establish failed",
+			__func__);
+	sc->sc_ih_fmn = ih;
+#endif
+
+}
+
+#ifdef NOTYET
+static int
+cpu_fmn_intr(void *arg, rmixl_fmn_rxmsg_t *rxmsg)
+{
+	if (cpu_number() == 0) {
+		printf("%s: cpu %ld: rxsid=%#x, code=%d, size=%d\n",
+			__func__, cpu_number(),
+			rxmsg->rxsid, rxmsg->code, rxmsg->size);
+		for (int i=0; i < rxmsg->size; i++)
+			printf("\t%#"PRIx64"\n", rxmsg->msg.data[i]);
 	}
-	aprint_normal("\n");
+
+	return 1;
 }
+#endif
 
 #ifdef MULTIPROCESSOR
+/*
+ * cpu_rmixl_hatch
+ *
+ * - chip-specific hatch code called from cpu_hatch via lsw_cpu_init
+ */
 void
-cpu_trampoline_park(void)
+cpu_rmixl_hatch(struct cpu_info *ci)
 {
+	(void)splhigh();
+
+#ifdef DEBUG
+	uint32_t ebase;
+	asm volatile("dmfc0 %0, $15, 1;" : "=r"(ebase));
+	KASSERT((ebase & __BITS(9,0)) == ci->ci_cpuid);
+	KASSERT(curcpu() == ci);
+#endif
+
+	if (RMIXL_CPU_THREAD(ci->ci_cpuid) == 0)
+		rmixl_fmn_init_core();
 }
 
-#if 0
+#ifdef NOTYET
 static void
-cpu_setup_trampoline(struct device *self, struct cpu_info *ci)
+cpu_setup_trampoline_ipi(struct device *self, struct cpu_info *ci)
 {
 	volatile struct rmixlfw_cpu_wakeup_info *wip;
 	u_int cpu, core, thread;
@@ -158,7 +260,7 @@
 	volatile uint32_t *maskp;
 	__cpu_simple_lock_t *llk;
 	volatile uint32_t *xflag;			/* ??? */
-	extern void cpu_wakeup_trampoline(void);
+	extern void rmixl_cpu_trampoline(void *);
 
 	cpu = ci->ci_cpuid;
 	core = cpu >> 2;
@@ -182,7 +284,7 @@
 
 	/* entry addr must be uncached, use KSEG1 */
 	addr = (int32_t)MIPS_PHYS_TO_KSEG1(
-			MIPS_KSEG0_TO_PHYS(cpu_wakeup_trampoline));
+			MIPS_KSEG0_TO_PHYS(rmixl_cpu_trampoline));
 printf("%s: addr %#x\n", __func__, addr);
 
 	__asm__ volatile("move	%0, $gp\n" : "=r"(gp));
@@ -220,19 +322,155 @@
 
 	Debugger();
 }
-#else
-static uint64_t argv[4] = { 0x1234,  0x2345, 0x3456, 0x4567 };
+#endif	/* NOTYET */
+
+static uint64_t argv[4] = { 0x1234,  0x2345, 0x3456, 0x4567 };	/* XXX TMP */
+
 static void
-cpu_setup_trampoline(struct device *self, struct cpu_info *ci)
+cpu_setup_trampoline_callback(struct device *self, struct cpu_info *ci)
 {
 	void (*wakeup_cpu)(void *, void *, unsigned int);
-	extern void cpu_wakeup_trampoline(void);
+	extern void rmixl_cpu_trampoline(void *);
 	extern void rmixlfw_wakeup_cpu(void *, void *, u_int64_t, void *);
+	struct lwp *l = ci->ci_data.cpu_idlelwp;
+	struct rmixl_cpu_trampoline_args *ta = &rmixl_cpu_trampoline_args;
+	uintptr_t stacktop;
+ 
+	/*
+	 * Ensure 'ta' is a KSEG0 address for trampoline args
+	 * to avoid TLB fault in trampoline when loading args.
+	 *
+	 * Note:
+	 *   RMI firmware only passes the lower half of 'ta'
+	 *   to rmixl_cpu_trampoline (the upper half is clear)
+	 *   so rmixl_cpu_trampoline must reconstruct the missing upper half
+	 *   rmixl_cpu_trampoline "knows" to use MIPS_KSEG0_START
+	 *   to reconstruct upper half of 'ta'.
+	 */
+	KASSERT(MIPS_KSEG0_P(ta));
+
+	/*
+	 * marshall args for rmixl_cpu_trampoline,
+	 */
+	stacktop = (uintptr_t)l->l_addr + USPACE
+			 - sizeof(struct trapframe) - CALLFRAME_SIZ;
+	ta->ta_sp = (uint64_t)(uintptr_t)stacktop;
+	ta->ta_lwp = (uint64_t)(uintptr_t)l;
+	ta->ta_cpuinfo = (uint64_t)(uintptr_t)ci;
 
+#if _LP64
 	wakeup_cpu = (void *)rmixl_configuration.rc_psb_info.wakeup;
+#else
+	wakeup_cpu = (void *)(intptr_t)
+		(rmixl_configuration.rc_psb_info.wakeup & 0xffffffff);
+#endif
 
-	rmixlfw_wakeup_cpu(cpu_wakeup_trampoline, argv,
+	rmixlfw_wakeup_cpu(rmixl_cpu_trampoline, (void *)ta,
 		1 << ci->ci_cpuid, wakeup_cpu);
 }
-#endif	/* 0 */
+
+static void
+cpu_setup_trampoline_fmn(struct device *self, struct cpu_info *ci)
+{
+	rmixl_fmn_msg_t msg;
+	intptr_t sp;
+	extern void rmixl_cpu_trampoline(void *);
+
+	sp = (intptr_t)malloc(4096, M_DEVBUF, M_NOWAIT);
+	if (sp == 0)
+		panic("%s: cannot malloc size 4096", __func__);
+
+	msg.data[0] = (uint64_t)sp + 4096 - 32;
+	msg.data[1] = (uint64_t)sp;
+	msg.data[2] = (uint64_t)rmixl_cpu_trampoline;
+	msg.data[3] = (uint64_t)argv;		/* XXX TMP DEBUG */
+
+	msg.data[0] |= 0xffffffff00000000ULL;
+	msg.data[1] |= 0xffffffff00000000ULL;
+	msg.data[2] |= 0xffffffff00000000ULL;
+	msg.data[3] |= 0xffffffff00000000ULL;
+
+	rmixl_fmn_msg_send(4, RMIXL_FMN_CODE_PSB_WAKEUP,
+		RMIXL_FMN_CORE_DESTID(ci->ci_cpuid, 0), &msg);	/* XXX FIXME */
+}
+
+#ifdef DEBUG
+void
+rmixl_cpu_data_print(struct cpu_data *dp)
+{
+	printf("cpu_biglock_wanted %p\n", dp->cpu_biglock_wanted);
+	printf("cpu_callout %p\n", dp->cpu_callout);
+	printf("cpu_unused1 %p\n", dp->cpu_unused1);
+	printf("cpu_unused2 %d\n", dp->cpu_unused2);
+	printf("&cpu_schedstate %p\n", &dp->cpu_schedstate);	/* TBD */
+	printf("&cpu_xcall %p\n", &dp->cpu_xcall);		/* TBD */
+	printf("cpu_xcall_pending %d\n", dp->cpu_xcall_pending);
+	printf("cpu_onproc %p\n", dp->cpu_onproc);
+	printf("&cpu_qchain %p\n", &dp->cpu_qchain);		/* TBD */
+	printf("cpu_idlelwp %p\n", dp->cpu_idlelwp);
+	printf("cpu_lockstat %p\n", dp->cpu_lockstat);
+	printf("cpu_index %d\n", dp->cpu_index);
+	printf("cpu_biglock_count %d\n", dp->cpu_biglock_count);
+	printf("cpu_spin_locks %d\n", dp->cpu_spin_locks);
+	printf("cpu_simple_locks %d\n", dp->cpu_simple_locks);
+	printf("cpu_spin_locks2 %d\n", dp->cpu_spin_locks2);
+	printf("cpu_lkdebug_recurse %d\n", dp->cpu_lkdebug_recurse);
+	printf("cpu_softints %d\n", dp->cpu_softints);
+	printf("cpu_nsyscall %d\n", dp->cpu_nsyscall);
+	printf("cpu_ntrap %d\n", dp->cpu_ntrap);
+	printf("cpu_nswtch %d\n", dp->cpu_nswtch);
+	printf("cpu_uvm %p\n", dp->cpu_uvm);
+	printf("cpu_softcpu %p\n", dp->cpu_softcpu);
+	printf("&cpu_biodone %p\n", &dp->cpu_biodone);		/* TBD */
+	printf("&cpu_percpu %p\n", &dp->cpu_percpu);		/* TBD */
+	printf("cpu_selcpu %p\n", dp->cpu_selcpu);
+	printf("cpu_nch %p\n", dp->cpu_nch);
+	printf("&cpu_ld_locks %p\n", &dp->cpu_ld_locks);	/* TBD */
+	printf("&cpu_ld_lock %p\n", &dp->cpu_ld_lock);		/* TBD */
+	printf("cpu_cc_freq %#"PRIx64"\n", dp->cpu_cc_freq);
+	printf("cpu_cc_skew %#"PRIx64"\n", dp->cpu_cc_skew);
+}
+
+struct cpu_info *
+rmixl_cpuinfo_print(cpuid_t cpuid)
+{
+	struct cpu_info * const ci = cpu_lookup(cpuid);
+
+	if (ci != NULL) {
+		rmixl_cpu_data_print(&ci->ci_data);
+		printf("ci_dev %p\n", ci->ci_dev);
+		printf("ci_cpuid %ld\n", ci->ci_cpuid);
+		printf("ci_cctr_freq %ld\n", ci->ci_cctr_freq);
+		printf("ci_cpu_freq %ld\n", ci->ci_cpu_freq);
+		printf("ci_cycles_per_hz %ld\n", ci->ci_cycles_per_hz);
+		printf("ci_divisor_delay %ld\n", ci->ci_divisor_delay);
+		printf("ci_divisor_recip %ld\n", ci->ci_divisor_recip);
+		printf("ci_curlwp %p\n", ci->ci_curlwp);
+		printf("ci_want_resched %d\n", ci->ci_want_resched);
+		printf("ci_mtx_count %d\n", ci->ci_mtx_count);
+		printf("ci_mtx_oldspl %d\n", ci->ci_mtx_oldspl);
+		printf("ci_idepth %d\n", ci->ci_idepth);
+		printf("ci_cpl %d\n", ci->ci_cpl);
+		printf("&ci_cpl %p\n", &ci->ci_cpl);	/* XXX */
+		printf("ci_next_cp0_clk_intr %#x\n", ci->ci_next_cp0_clk_intr);
+		for (int i=0; i < SOFTINT_COUNT; i++)
+			printf("ci_softlwps[%d] %p\n", i, ci->ci_softlwps[i]);
+		printf("ci_tlb_slot %d\n", ci->ci_tlb_slot);
+		printf("ci_tlb_info %p\n", ci->ci_tlb_info);
+		printf("ci_pmap_segbase %p\n", ci->ci_pmap_segbase);
+		printf("ci_pmap_srcbase %#"PRIxVADDR"\n", ci->ci_pmap_srcbase);
+		printf("ci_pmap_dstbase %#"PRIxVADDR"\n", ci->ci_pmap_dstbase);
+#ifdef MULTIPROCESSOR
+		printf("ci_flags %#lx\n", ci->ci_flags);
+		printf("ci_request_ipis %#"PRIx64"\n", ci->ci_request_ipis);
+		printf("ci_active_ipis %#"PRIx64"\n", ci->ci_active_ipis);
+		printf("ci_ksp_tlb_slot %d\n", ci->ci_ksp_tlb_slot);
+		printf("ci_fpsave_si %p\n", ci->ci_fpsave_si);
+#endif
+	}
+
+	return ci;
+}
+
+#endif	/* DEBUG */
 #endif	/* MULTIPROCESSOR */

Reply via email to