xlr_machdep.c revision 331722
1/*-
2 * Copyright (c) 2006-2009 RMI Corporation
3 * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: stable/11/sys/mips/rmi/xlr_machdep.c 331722 2018-03-29 02:50:57Z eadler $");
30
31#include "opt_ddb.h"
32
33#include <sys/param.h>
34#include <sys/bus.h>
35#include <sys/conf.h>
36#include <sys/rtprio.h>
37#include <sys/systm.h>
38#include <sys/interrupt.h>
39#include <sys/limits.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/mutex.h>
43#include <sys/random.h>
44
45#include <sys/cons.h>		/* cinit() */
46#include <sys/kdb.h>
47#include <sys/reboot.h>
48#include <sys/queue.h>
49#include <sys/smp.h>
50#include <sys/timetc.h>
51
52#include <vm/vm.h>
53#include <vm/vm_page.h>
54
55#include <machine/cpu.h>
56#include <machine/cpufunc.h>
57#include <machine/cpuinfo.h>
58#include <machine/cpuregs.h>
59#include <machine/frame.h>
60#include <machine/hwfunc.h>
61#include <machine/md_var.h>
62#include <machine/asm.h>
63#include <machine/pmap.h>
64#include <machine/trap.h>
65#include <machine/clock.h>
66#include <machine/fls64.h>
67#include <machine/intr_machdep.h>
68#include <machine/smp.h>
69
70#include <mips/rmi/iomap.h>
71#include <mips/rmi/msgring.h>
72#include <mips/rmi/interrupt.h>
73#include <mips/rmi/pic.h>
74#include <mips/rmi/board.h>
75#include <mips/rmi/rmi_mips_exts.h>
76#include <mips/rmi/rmi_boot_info.h>
77
78void mpwait(void);
79unsigned long xlr_io_base = (unsigned long)(DEFAULT_XLR_IO_BASE);
80
81/* 4KB static data aread to keep a copy of the bootload env until
82   the dynamic kenv is setup */
83char boot1_env[4096];
84int rmi_spin_mutex_safe=0;
85struct mtx xlr_pic_lock;
86
87/*
88 * Parameters from boot loader
89 */
90struct boot1_info xlr_boot1_info;
91int xlr_run_mode;
92int xlr_argc;
93int32_t *xlr_argv, *xlr_envp;
94uint64_t cpu_mask_info;
95uint32_t xlr_online_cpumask;
96uint32_t xlr_core_cpu_mask = 0x1;	/* Core 0 thread 0 is always there */
97
98int xlr_shtlb_enabled;
99int xlr_ncores;
100int xlr_threads_per_core;
101uint32_t xlr_hw_thread_mask;
102int xlr_cpuid_to_hwtid[MAXCPU];
103int xlr_hwtid_to_cpuid[MAXCPU];
104
105static void
106xlr_setup_mmu_split(void)
107{
108	uint64_t mmu_setup;
109	int val = 0;
110
111	if (xlr_threads_per_core == 4 && xlr_shtlb_enabled == 0)
112		return;   /* no change from boot setup */
113
114	switch (xlr_threads_per_core) {
115	case 1:
116		val = 0; break;
117	case 2:
118		val = 2; break;
119	case 4:
120		val = 3; break;
121	}
122
123	mmu_setup = read_xlr_ctrl_register(4, 0);
124	mmu_setup = mmu_setup & ~0x06;
125	mmu_setup |= (val << 1);
126
127	/* turn on global mode */
128	if (xlr_shtlb_enabled)
129		mmu_setup |= 0x01;
130
131	write_xlr_ctrl_register(4, 0, mmu_setup);
132}
133
134static void
135xlr_parse_mmu_options(void)
136{
137#ifdef notyet
138	char *hw_env, *start, *end;
139#endif
140	uint32_t cpu_map;
141	uint8_t core0_thr_mask, core_thr_mask;
142	int i, j, k;
143
144	/* First check for the shared TLB setup */
145	xlr_shtlb_enabled = 0;
146#ifdef notyet
147	/*
148	 * We don't support sharing TLB per core - TODO
149	 */
150	xlr_shtlb_enabled = 0;
151	if ((hw_env = kern_getenv("xlr.shtlb")) != NULL) {
152		start = hw_env;
153		tmp = strtoul(start, &end, 0);
154		if (start != end)
155			xlr_shtlb_enabled = (tmp != 0);
156		else
157			printf("Bad value for xlr.shtlb [%s]\n", hw_env);
158		freeenv(hw_env);
159	}
160#endif
161	/*
162	 * XLR supports splitting the 64 TLB entries across one, two or four
163	 * threads (split mode).  XLR also allows the 64 TLB entries to be shared
164         * across all threads in the core using a global flag (shared TLB mode).
165         * We will support 1/2/4 threads in split mode or shared mode.
166	 *
167	 */
168	xlr_ncores = 1;
169	cpu_map = xlr_boot1_info.cpu_online_map;
170
171#ifndef SMP /* Uniprocessor! */
172	if (cpu_map != 0x1) {
173		printf("WARNING: Starting uniprocessor kernel on cpumask [0x%lx]!\n"
174		   "WARNING: Other CPUs will be unused.\n", (u_long)cpu_map);
175		cpu_map = 0x1;
176	}
177#endif
178	core0_thr_mask = cpu_map & 0xf;
179	switch (core0_thr_mask) {
180	case 1:
181		xlr_threads_per_core = 1; break;
182	case 3:
183		xlr_threads_per_core = 2; break;
184	case 0xf:
185		xlr_threads_per_core = 4; break;
186	default:
187		goto unsupp;
188	}
189
190	/* Verify other cores CPU masks */
191	for (i = 1; i < XLR_MAX_CORES; i++) {
192		core_thr_mask = (cpu_map >> (i*4)) & 0xf;
193		if (core_thr_mask) {
194			if (core_thr_mask != core0_thr_mask)
195				goto unsupp;
196			xlr_ncores++;
197		}
198	}
199	xlr_hw_thread_mask = cpu_map;
200
201	/* setup hardware processor id to cpu id mapping */
202	for (i = 0; i< MAXCPU; i++)
203		xlr_cpuid_to_hwtid[i] =
204		    xlr_hwtid_to_cpuid [i] = -1;
205	for (i = 0, k = 0; i < XLR_MAX_CORES; i++) {
206		if (((cpu_map >> (i*4)) & 0xf) == 0)
207			continue;
208		for (j = 0; j < xlr_threads_per_core; j++) {
209			xlr_cpuid_to_hwtid[k] = i*4 + j;
210			xlr_hwtid_to_cpuid[i*4 + j] = k;
211			k++;
212		}
213	}
214
215	/* setup for the startup core */
216	xlr_setup_mmu_split();
217	return;
218
219unsupp:
220	printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n"
221	    "\tcore0 thread mask [%lx], boot cpu mask [%lx]\n"
222	    "\tUsing default, 16 TLB entries per CPU, split mode\n",
223	    (u_long)core0_thr_mask, (u_long)cpu_map);
224	panic("Invalid CPU mask - halting.\n");
225	return;
226}
227
228static void
229xlr_set_boot_flags(void)
230{
231	char *p;
232
233	p = kern_getenv("bootflags");
234	if (p == NULL)
235		p = kern_getenv("boot_flags");  /* old style */
236	if (p == NULL)
237		return;
238
239	for (; p && *p != '\0'; p++) {
240		switch (*p) {
241		case 'd':
242		case 'D':
243			boothowto |= RB_KDB;
244			break;
245		case 'g':
246		case 'G':
247			boothowto |= RB_GDB;
248			break;
249		case 'v':
250		case 'V':
251			boothowto |= RB_VERBOSE;
252			break;
253
254		case 's':	/* single-user (default, supported for sanity) */
255		case 'S':
256			boothowto |= RB_SINGLE;
257			break;
258
259		default:
260			printf("Unrecognized boot flag '%c'.\n", *p);
261			break;
262		}
263	}
264
265	freeenv(p);
266	return;
267}
268extern uint32_t _end;
269
270static void
271mips_init(void)
272{
273	init_param1();
274	init_param2(physmem);
275
276	mips_cpu_init();
277	cpuinfo.cache_coherent_dma = TRUE;
278	pmap_bootstrap();
279#ifdef DDB
280	kdb_init();
281	if (boothowto & RB_KDB) {
282		kdb_enter("Boot flags requested debugger", NULL);
283	}
284#endif
285	mips_proc0_init();
286	mutex_init();
287}
288
289u_int
290platform_get_timecount(struct timecounter *tc __unused)
291{
292
293	return (0xffffffffU - pic_timer_count32(PIC_CLOCK_TIMER));
294}
295
296static void
297xlr_pic_init(void)
298{
299	struct timecounter pic_timecounter = {
300		platform_get_timecount, /* get_timecount */
301		0,                      /* no poll_pps */
302		~0U,                    /* counter_mask */
303		PIC_TIMER_HZ,           /* frequency */
304		"XLRPIC",               /* name */
305		2000,                   /* quality (adjusted in code) */
306	};
307	xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
308	int i, irq;
309
310	write_c0_eimr64(0ULL);
311	mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
312	xlr_write_reg(mmio, PIC_CTRL, 0);
313
314	/* Initialize all IRT entries */
315	for (i = 0; i < PIC_NUM_IRTS; i++) {
316		irq = PIC_INTR_TO_IRQ(i);
317
318		/*
319		 * Disable all IRTs. Set defaults (local scheduling, high
320		 * polarity, level * triggered, and CPU irq)
321		 */
322		xlr_write_reg(mmio, PIC_IRT_1(i), (1 << 30) | (1 << 6) | irq);
323		/* Bind all PIC irqs to cpu 0 */
324		xlr_write_reg(mmio, PIC_IRT_0(i), 0x01);
325	}
326
327	/* Setup timer 7 of PIC as a timestamp, no interrupts */
328	pic_init_timer(PIC_CLOCK_TIMER);
329	pic_set_timer(PIC_CLOCK_TIMER, ~UINT64_C(0));
330	platform_timecounter = &pic_timecounter;
331}
332
333static void
334xlr_mem_init(void)
335{
336	struct xlr_boot1_mem_map *boot_map;
337	vm_size_t physsz = 0;
338	int i, j;
339
340	/* get physical memory info from boot loader */
341	boot_map = (struct xlr_boot1_mem_map *)
342	    (unsigned long)xlr_boot1_info.psb_mem_map;
343	for (i = 0, j = 0; i < boot_map->num_entries; i++, j += 2) {
344		if (boot_map->physmem_map[i].type != BOOT1_MEM_RAM)
345			continue;
346		if (j == 14) {
347			printf("*** ERROR *** memory map too large ***\n");
348			break;
349		}
350		if (j == 0) {
351			/* start after kernel end */
352			phys_avail[0] = (vm_paddr_t)
353			    MIPS_KSEG0_TO_PHYS(&_end) + 0x20000;
354			/* boot loader start */
355			/* HACK to Use bootloaders memory region */
356			if (boot_map->physmem_map[0].size == 0x0c000000) {
357				boot_map->physmem_map[0].size = 0x0ff00000;
358			}
359			phys_avail[1] = boot_map->physmem_map[0].addr +
360			    boot_map->physmem_map[0].size;
361			printf("First segment: addr:%#jx -> %#jx \n",
362			       (uintmax_t)phys_avail[0],
363			       (uintmax_t)phys_avail[1]);
364
365			dump_avail[0] = phys_avail[0];
366			dump_avail[1] = phys_avail[1];
367		} else {
368#if !defined(__mips_n64) && !defined(__mips_n32) /* !PHYSADDR_64_BIT */
369			/*
370			 * In 32 bit physical address mode we cannot use
371			 * mem > 0xffffffff
372			 */
373			if (boot_map->physmem_map[i].addr > 0xfffff000U) {
374				printf("Memory: start %#jx size %#jx ignored"
375				    "(>4GB)\n",
376				    (intmax_t)boot_map->physmem_map[i].addr,
377				    (intmax_t)boot_map->physmem_map[i].size);
378				continue;
379			}
380			if (boot_map->physmem_map[i].addr +
381			    boot_map->physmem_map[i].size > 0xfffff000U) {
382				boot_map->physmem_map[i].size = 0xfffff000U -
383				    boot_map->physmem_map[i].addr;
384				printf("Memory: start %#jx limited to 4GB\n",
385				    (intmax_t)boot_map->physmem_map[i].addr);
386			}
387#endif /* !PHYSADDR_64_BIT */
388			phys_avail[j] = (vm_paddr_t)
389			    boot_map->physmem_map[i].addr;
390			phys_avail[j + 1] = phys_avail[j] +
391			    boot_map->physmem_map[i].size;
392			printf("Next segment : addr:%#jx -> %#jx\n",
393			       (uintmax_t)phys_avail[j],
394			       (uintmax_t)phys_avail[j+1]);
395		}
396
397		dump_avail[j] = phys_avail[j];
398		dump_avail[j+1] = phys_avail[j+1];
399
400		physsz += boot_map->physmem_map[i].size;
401	}
402
403	phys_avail[j] = phys_avail[j + 1] = 0;
404	realmem = physmem = btoc(physsz);
405}
406
407void
408platform_start(__register_t a0 __unused,
409    __register_t a1 __unused,
410    __register_t a2 __unused,
411    __register_t a3 __unused)
412{
413	int i;
414#ifdef SMP
415	uint32_t tmp;
416	void (*wakeup) (void *, void *, unsigned int);
417#endif
418
419	/* Save boot loader and other stuff from scratch regs */
420	xlr_boot1_info = *(struct boot1_info *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 0);
421	cpu_mask_info = read_c0_register64(MIPS_COP_0_OSSCRATCH, 1);
422	xlr_online_cpumask = read_c0_register32(MIPS_COP_0_OSSCRATCH, 2);
423	xlr_run_mode = read_c0_register32(MIPS_COP_0_OSSCRATCH, 3);
424	xlr_argc = read_c0_register32(MIPS_COP_0_OSSCRATCH, 4);
425	/*
426	 * argv and envp are passed in array of 32bit pointers
427	 */
428	xlr_argv = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 5);
429	xlr_envp = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 6);
430
431	/* Initialize pcpu stuff */
432	mips_pcpu0_init();
433
434	/* initialize console so that we have printf */
435	boothowto |= (RB_SERIAL | RB_MULTIPLE);	/* Use multiple consoles */
436
437	/* clockrate used by delay, so initialize it here */
438	cpu_clock = xlr_boot1_info.cpu_frequency / 1000000;
439
440	/*
441	 * Note the time counter on CPU0 runs not at system clock speed, but
442	 * at PIC time counter speed (which is returned by
443	 * platform_get_frequency(). Thus we do not use
444	 * xlr_boot1_info.cpu_frequency here.
445	 */
446	mips_timer_early_init(xlr_boot1_info.cpu_frequency);
447
448	/* Init console please */
449	cninit();
450	init_static_kenv(boot1_env, sizeof(boot1_env));
451	printf("Environment (from %d args):\n", xlr_argc - 1);
452	if (xlr_argc == 1)
453		printf("\tNone\n");
454	for (i = 1; i < xlr_argc; i++) {
455		char *n, *arg;
456
457		arg = (char *)(intptr_t)xlr_argv[i];
458		printf("\t%s\n", arg);
459		n = strsep(&arg, "=");
460		if (arg == NULL)
461			kern_setenv(n, "1");
462		else
463			kern_setenv(n, arg);
464	}
465
466	xlr_set_boot_flags();
467	xlr_parse_mmu_options();
468
469	xlr_mem_init();
470	/* Set up hz, among others. */
471	mips_init();
472
473#ifdef SMP
474	/*
475	 * If thread 0 of any core is not available then mark whole core as
476	 * not available
477	 */
478	tmp = xlr_boot1_info.cpu_online_map;
479	for (i = 4; i < MAXCPU; i += 4) {
480		if ((tmp & (0xf << i)) && !(tmp & (0x1 << i))) {
481			/*
482			 * Oops.. thread 0 is not available. Disable whole
483			 * core
484			 */
485			tmp = tmp & ~(0xf << i);
486			printf("WARNING: Core %d is disabled because thread 0"
487			    " of this core is not enabled.\n", i / 4);
488		}
489	}
490	xlr_boot1_info.cpu_online_map = tmp;
491
492	/* Wakeup Other cpus, and put them in bsd park code. */
493	wakeup = ((void (*) (void *, void *, unsigned int))
494	    (unsigned long)(xlr_boot1_info.wakeup));
495	printf("Waking up CPUs 0x%jx.\n",
496	    (intmax_t)xlr_boot1_info.cpu_online_map & ~(0x1U));
497	if (xlr_boot1_info.cpu_online_map & ~(0x1U))
498		wakeup(mpwait, 0,
499		    (unsigned int)xlr_boot1_info.cpu_online_map);
500#endif
501
502	/* xlr specific post initialization */
503	/* initialize other on chip stuff */
504	xlr_board_info_setup();
505	xlr_msgring_config();
506	xlr_pic_init();
507	xlr_msgring_cpu_init();
508
509	mips_timer_init_params(xlr_boot1_info.cpu_frequency, 0);
510
511	printf("Platform specific startup now completes\n");
512}
513
514void
515platform_cpu_init()
516{
517}
518
519void
520platform_reset(void)
521{
522	xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
523
524	/* write 1 to GPIO software reset register */
525	xlr_write_reg(mmio, 8, 1);
526}
527
528#ifdef SMP
529int xlr_ap_release[MAXCPU];
530
531int
532platform_start_ap(int cpuid)
533{
534	int hwid = xlr_cpuid_to_hwtid[cpuid];
535
536	if (xlr_boot1_info.cpu_online_map & (1<<hwid)) {
537		/*
538		 * other cpus are enabled by the boot loader and they will be
539		 * already looping in mpwait, release them
540		 */
541		atomic_store_rel_int(&xlr_ap_release[hwid], 1);
542		return (0);
543	} else
544		return (-1);
545}
546
547void
548platform_init_ap(int cpuid)
549{
550	uint32_t stat;
551
552	/* The first thread has to setup the core MMU split  */
553	if (xlr_thr_id() == 0)
554		xlr_setup_mmu_split();
555
556	/* Setup interrupts for secondary CPUs here */
557	stat = mips_rd_status();
558	KASSERT((stat & MIPS_SR_INT_IE) == 0,
559	    ("Interrupts enabled in %s!", __func__));
560	stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT;
561	mips_wr_status(stat);
562
563	write_c0_eimr64(0ULL);
564	xlr_enable_irq(IRQ_IPI);
565	xlr_enable_irq(IRQ_TIMER);
566	if (xlr_thr_id() == 0)
567		xlr_msgring_cpu_init();
568	 xlr_enable_irq(IRQ_MSGRING);
569
570	return;
571}
572
573int
574platform_ipi_intrnum(void)
575{
576
577	return (IRQ_IPI);
578}
579
580void
581platform_ipi_send(int cpuid)
582{
583
584	pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum());
585}
586
587void
588platform_ipi_clear(void)
589{
590}
591
592int
593platform_processor_id(void)
594{
595
596	return (xlr_hwtid_to_cpuid[xlr_cpu_id()]);
597}
598
599void
600platform_cpu_mask(cpuset_t *mask)
601{
602	int i, s;
603
604	CPU_ZERO(mask);
605	s = xlr_ncores * xlr_threads_per_core;
606	for (i = 0; i < s; i++)
607		CPU_SET(i, mask);
608}
609
610struct cpu_group *
611platform_smp_topo()
612{
613
614	return (smp_topo_2level(CG_SHARE_L2, xlr_ncores, CG_SHARE_L1,
615		xlr_threads_per_core, CG_FLAG_THREAD));
616}
617#endif
618