Origin 350でのセカンダリプロセッサ起動テスト/Secondary processor launch test on Origin 350

前にも書いた通り、cpu0,cpu1,cpu2の3つを認識させ、cpu1を無効なまま放置してcpu2を起動するのがファーストステップである。

As I mentioned before, detect cpu0, cpu1, cpu2 and leave cpu1 disabled and launch cpu2 is the first step.

Index: sgi/sgi/ip27_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/sgi/sgi/ip27_machdep.c,v
retrieving revision 1.49
diff -r1.49 ip27_machdep.c
284a285,286
> 	ncpusfound = 3;
> 

よって、cpu数は3。

Therefore number of cpus set to 3.

291a294,296
> #define IP27_MAXCPUS 3
> //static int ip27_cpu_exists(int);
> 
299a305,307
> #ifdef MULTIPROCESSOR
> 	int cpuid;
> #endif
312a321,340
> 
> #ifdef MULTIPROCESSOR
> 	for (cpuid = 1; cpuid < IP27_MAXCPUS; cpuid++) {
> //		if (ip27_cpu_exists(cpuid)) {
> /*
> 			struct cpu_hwinfo hw;
> 			bcopy(&bootcpu_hwinfo, &hw, sizeof(struct cpu_hwinfo));
> 			hw.c0prid = 
> 		           *(volatile uint32_t *)(mpconf + MPCONF_PRID(cpuid));
> 			hw.type = (hw.c0prid >> 8) & 0xff;
> 			hw.l2size = 1 << *(volatile uint32_t *)
> 			    (mpconf + MPCONF_SCACHESZ(cpuid));
> 			u.caa.caa_hw = &hw;
> */
> 			u.caa.caa_hw = &bootcpu_hwinfo;
> 			config_found(parent, &u, ip27_print);
> //		}
> 	}
> #endif
> 

config_found()でcpu1, cpu2をattachする。

Attach cpu1, cpu2 on config_found().

916a947,1042
> 
> #ifdef MULTIPROCESSOR
> #define IP27PROM_LAUNCHSLAVE	PHYS_TO_CKSEG1(0x1fc00038)
> #define LAUNCH_SLAVE	(*(void (*)(int nasid, int cpu, \
> 				    void *call_addr, \
> 				    uint64_t call_parm, \
> 				    void *stack_addr, \
> 				    void *gp_addr)) \
> 			 IP27PROM_LAUNCHSLAVE)

Linux, IRIXのヘッダを見ると、IP27PROMへN64ABIで関数コールを行なう事でセカンダリプロセッサをする事が出来る事がわかる。
これにアクセスする為のマクロを定義。

We can see on Linux and IRIX headers that secondary processor can launch by calling function to IP27PROM, using N64ABI.
Then define the macro to access it.

> void
> hw_cpu_boot_secondary(struct cpu_info *ci)
> {
> 	int cpuid =  ci->ci_cpuid;
> 	vaddr_t kstack;
> 
> #ifdef DEBUG
> #endif
> 	kstack = smp_malloc(USPACE);
> 	if (kstack == NULL)
> 		panic("unable to allocate idle stack\n");
> 	bzero((char *)kstack, USPACE);
> 	ci->ci_curprocpaddr = (void *)kstack;
> 
> 	LAUNCH_SLAVE(0, cpuid, (void *)hw_cpu_spinup_trampoline, (uint64_t)ci, 
> 		(void *)(kstack + USPACE), (void *)0);
> 
> 	while (!cpuset_isset(&cpus_running, ci))
> 		;
> }
> 

hw_cpu_boot_secondary()からLAUNCH_SLAVEマクロを叩いてセカンダリプロセッサを起動。
取り敢えず1ノードなのでnasidは0固定。

Bootup secondary processor to call LAUNCH_SLAVE macro on hw_cpu_boot_secondary().
nasid set to 0 because this time we test with single node configuration for now.

> void
> hw_cpu_hatch(struct cpu_info *ci)
> {
> 	int s;
> 
> 	/*
> 	 * Make sure we can access the extended address space.
> 	 * Note that r10k and later do not allow XUSEG accesses
> 	 * from kernel mode unless SR_UX is set.
> 	 */
> 	setsr(getsr() | SR_KX | SR_UX);
> 
> 	tlb_set_page_mask(TLB_PAGE_MASK);
> 	tlb_set_wired(0);
> 	tlb_flush(64);
> 	tlb_set_wired(UPAGES / 2);
> 
> 	tlb_set_pid(0);
> 
> 	/*
> 	 * Turn off bootstrap exception vectors.
> 	 */
> 	setsr(getsr() & ~SR_BOOT_EXC_VEC);
> 
> 	/*
> 	 * Clear out the I and D caches.
> 	 */
> 	Mips10k_ConfigCache(ci);
> 	Mips_SyncCache(ci);
> 
> 	while(1)
> 		printf("cpu2 launched\n");
> 
> 	cpu_startclock(ci);
> 
> 	ncpus++;
> 	cpuset_add(&cpus_running, ci);
> 
> 	mips64_ipi_init();
> //	xheart_setintrmask(0);
> 
> 	spl0();
> 	(void)updateimask(0);
> 
> 	SCHED_LOCK(s);
> 	cpu_switchto(NULL, sched_chooseproc());
> }
> 
> int
> hw_ipi_intr_establish(int (*func)(void *), u_long cpuid)
> {
> 	return 0;
> };
> 
> void
> hw_ipi_intr_set(u_long cpuid)
> {
> }
> 
> void
> hw_ipi_intr_clear(u_long cpuid)
> {
> }
> 
> #endif

セカンダリプロセッサの起動コードは取り敢えずprintfを入れた。
結果、このコードでprintfの出力が得られる事が確認出来た。

Put debug print on boot code for secondary processor for testing propose.
In the result, I could get debug print output with the code.