Deleted Added
full compact
xlr_machdep.c (211893) xlr_machdep.c (211994)
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>
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: head/sys/mips/rmi/xlr_machdep.c 211893 2010-08-27 19:53:57Z jchandra $");
29__FBSDID("$FreeBSD: head/sys/mips/rmi/xlr_machdep.c 211994 2010-08-30 13:05:21Z jchandra $");
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>
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#include <mips/rmi/rmi_mips_exts.h>
70
71#include <mips/rmi/iomap.h>
69
70#include <mips/rmi/iomap.h>
72#include <mips/rmi/clock.h>
73#include <mips/rmi/msgring.h>
71#include <mips/rmi/msgring.h>
74#include <mips/rmi/xlrconfig.h>
75#include <mips/rmi/interrupt.h>
76#include <mips/rmi/pic.h>
77#include <mips/rmi/board.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>
78
79void mpwait(void);
80unsigned long xlr_io_base = (unsigned long)(DEFAULT_XLR_IO_BASE);
81
82/* 4KB static data aread to keep a copy of the bootload env until
83 the dynamic kenv is setup */
84char boot1_env[4096];
85int rmi_spin_mutex_safe=0;
86struct mtx xlr_pic_lock;
87
88/*
89 * Parameters from boot loader
90 */
91struct boot1_info xlr_boot1_info;
92int xlr_run_mode;
93int xlr_argc;
94int32_t *xlr_argv, *xlr_envp;
95uint64_t cpu_mask_info;
96uint32_t xlr_online_cpumask;
97uint32_t xlr_core_cpu_mask = 0x1; /* Core 0 thread 0 is always there */
98
99int xlr_shtlb_enabled;
100int xlr_ncores;
101int xlr_threads_per_core;
102uint32_t xlr_hw_thread_mask;
103int xlr_cpuid_to_hwtid[MAXCPU];
104int xlr_hwtid_to_cpuid[MAXCPU];
105
106static void
107xlr_setup_mmu_split(void)
108{
109 int mmu_setup;
110 int val = 0;
111
112 if (xlr_threads_per_core == 4 && xlr_shtlb_enabled == 0)
113 return; /* no change from boot setup */
114
115 switch (xlr_threads_per_core) {
116 case 1:
117 val = 0; break;
118 case 2:
119 val = 2; break;
120 case 4:
121 val = 3; break;
122 }
123
124 mmu_setup = read_32bit_phnx_ctrl_reg(4, 0);
125 mmu_setup = mmu_setup & ~0x06;
126 mmu_setup |= (val << 1);
127
128 /* turn on global mode */
129 if (xlr_shtlb_enabled)
130 mmu_setup |= 0x01;
131
132 write_32bit_phnx_ctrl_reg(4, 0, mmu_setup);
133}
134
135static void
136xlr_parse_mmu_options(void)
137{
138#ifdef notyet
139 char *hw_env, *start, *end;
140#endif
141 uint32_t cpu_map;
142 uint8_t core0_thr_mask, core_thr_mask;
143 int i, j, k;
144
145 /* First check for the shared TLB setup */
146 xlr_shtlb_enabled = 0;
147#ifdef notyet
148 /*
149 * We don't support sharing TLB per core - TODO
150 */
151 xlr_shtlb_enabled = 0;
152 if ((hw_env = getenv("xlr.shtlb")) != NULL) {
153 start = hw_env;
154 tmp = strtoul(start, &end, 0);
155 if (start != end)
156 xlr_shtlb_enabled = (tmp != 0);
157 else
158 printf("Bad value for xlr.shtlb [%s]\n", hw_env);
159 freeenv(hw_env);
160 }
161#endif
162 /*
163 * XLR supports splitting the 64 TLB entries across one, two or four
164 * threads (split mode). XLR also allows the 64 TLB entries to be shared
165 * across all threads in the core using a global flag (shared TLB mode).
166 * We will support 1/2/4 threads in split mode or shared mode.
167 *
168 */
169 xlr_ncores = 1;
170 cpu_map = xlr_boot1_info.cpu_online_map;
171 core0_thr_mask = cpu_map & 0xf;
172 switch (core0_thr_mask) {
173 case 1:
174 xlr_threads_per_core = 1; break;
175 case 3:
176 xlr_threads_per_core = 2; break;
177 case 0xf:
178 xlr_threads_per_core = 4; break;
179 default:
180 goto unsupp;
181 }
182
183 /* Verify other cores CPU masks */
184 for (i = 1; i < XLR_MAX_CORES; i++) {
185 core_thr_mask = (cpu_map >> (i*4)) & 0xf;
186 if (core_thr_mask) {
187 if (core_thr_mask != core0_thr_mask)
188 goto unsupp;
189 xlr_ncores++;
190 }
191 }
192
193 /* setup hardware processor id to cpu id mapping */
194 xlr_hw_thread_mask = xlr_boot1_info.cpu_online_map;
195 for (i = 0; i< MAXCPU; i++)
196 xlr_cpuid_to_hwtid[i] =
197 xlr_hwtid_to_cpuid [i] = -1;
198 for (i = 0, k = 0; i < XLR_MAX_CORES; i++) {
199 if (((cpu_map >> (i*4)) & 0xf) == 0)
200 continue;
201 for (j = 0; j < xlr_threads_per_core; j++) {
202 xlr_cpuid_to_hwtid[k] = i*4 + j;
203 xlr_hwtid_to_cpuid[i*4 + j] = k;
204 k++;
205 }
206 }
207
208 /* setup for the startup core */
209 xlr_setup_mmu_split();
210 return;
211
212unsupp:
213 printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n"
214 "\tcore0 thread mask [%lx], boot cpu mask [%lx]\n"
215 "\tUsing default, 16 TLB entries per CPU, split mode\n",
216 (u_long)core0_thr_mask, (u_long)cpu_map);
217 panic("Invalid CPU mask - halting.\n");
218 return;
219}
220
221static void
222xlr_set_boot_flags(void)
223{
224 char *p;
225
226 p = getenv("bootflags");
227 if (p == NULL)
228 p = getenv("boot_flags"); /* old style */
229 if (p == NULL)
230 return;
231
232 for (; p && *p != '\0'; p++) {
233 switch (*p) {
234 case 'd':
235 case 'D':
236 boothowto |= RB_KDB;
237 break;
238 case 'g':
239 case 'G':
240 boothowto |= RB_GDB;
241 break;
242 case 'v':
243 case 'V':
244 boothowto |= RB_VERBOSE;
245 break;
246
247 case 's': /* single-user (default, supported for sanity) */
248 case 'S':
249 boothowto |= RB_SINGLE;
250 break;
251
252 default:
253 printf("Unrecognized boot flag '%c'.\n", *p);
254 break;
255 }
256 }
257
258 freeenv(p);
259 return;
260}
261extern uint32_t _end;
262
263static void
264mips_init(void)
265{
266 init_param1();
267 init_param2(physmem);
268
269 mips_cpu_init();
270 pmap_bootstrap();
271#ifdef DDB
272 kdb_init();
273 if (boothowto & RB_KDB) {
274 kdb_enter("Boot flags requested debugger", NULL);
275 }
276#endif
277 mips_proc0_init();
278 mutex_init();
279}
280
281u_int
282platform_get_timecount(struct timecounter *tc __unused)
283{
284
285 return (0xffffffffU - pic_timer_count32(PIC_CLOCK_TIMER));
286}
287
288static void
289xlr_pic_init(void)
290{
291 struct timecounter pic_timecounter = {
292 platform_get_timecount, /* get_timecount */
293 0, /* no poll_pps */
294 ~0U, /* counter_mask */
295 PIC_TIMER_HZ, /* frequency */
296 "XLRPIC", /* name */
297 2000, /* quality (adjusted in code) */
298 };
299 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
300 int i, level, irq;
301
302 mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
303 xlr_write_reg(mmio, PIC_CTRL, 0);
304
305 /* Initialize all IRT entries */
306 for (i = 0; i < PIC_NUM_IRTS; i++) {
307 irq = PIC_INTR_TO_IRQ(i);
308 level = PIC_IS_EDGE_TRIGGERED(i);
309
310 /* Bind all PIC irqs to cpu 0 */
311 xlr_write_reg(mmio, PIC_IRT_0(i), 0x01);
312
313 /*
314 * Use local scheduling and high polarity for all IRTs
315 * Invalidate all IRTs, by default
316 */
317 xlr_write_reg(mmio, PIC_IRT_1(i), (level << 30) | (1 << 6) |
318 irq);
319 }
320
321 /* Setup timer 7 of PIC as a timestamp, no interrupts */
322 pic_init_timer(PIC_CLOCK_TIMER);
323 pic_set_timer(PIC_CLOCK_TIMER, ~UINT64_C(0));
324 platform_timecounter = &pic_timecounter;
325}
326
327static void
328xlr_mem_init(void)
329{
330 struct xlr_boot1_mem_map *boot_map;
331 vm_size_t physsz = 0;
332 int i, j;
333
334 /* get physical memory info from boot loader */
335 boot_map = (struct xlr_boot1_mem_map *)
336 (unsigned long)xlr_boot1_info.psb_mem_map;
337 for (i = 0, j = 0; i < boot_map->num_entries; i++, j += 2) {
338 if (boot_map->physmem_map[i].type == BOOT1_MEM_RAM) {
339 if (j == 14) {
340 printf("*** ERROR *** memory map too large ***\n");
341 break;
342 }
343 if (j == 0) {
344 /* TODO FIXME */
345 /* start after kernel end */
346 phys_avail[0] = (vm_paddr_t)
347 MIPS_KSEG0_TO_PHYS(&_end) + 0x20000;
348 /* boot loader start */
349 /* HACK to Use bootloaders memory region */
350 /* TODO FIXME */
351 if (boot_map->physmem_map[0].size == 0x0c000000) {
352 boot_map->physmem_map[0].size = 0x0ff00000;
353 }
354 phys_avail[1] = boot_map->physmem_map[0].addr +
355 boot_map->physmem_map[0].size;
356 printf("First segment: addr:%p -> %p \n",
357 (void *)phys_avail[0],
358 (void *)phys_avail[1]);
359
360 } else {
361/*
362 * Can't use this code yet, because most of the fixed allocations happen from
363 * the biggest physical area. If we have more than 512M memory the kernel will try
364 * to map from the second are which is not in KSEG0 and not mapped
365 */
366 phys_avail[j] = (vm_paddr_t)
367 boot_map->physmem_map[i].addr;
368 phys_avail[j + 1] = phys_avail[j] +
369 boot_map->physmem_map[i].size;
370 if (phys_avail[j + 1] < phys_avail[j] ) {
371 /* Houston we have an issue. Memory is
372 * larger than possible. Its probably in
373 * 64 bit > 4Gig and we are in 32 bit mode.
374 */
375 phys_avail[j + 1] = 0xfffff000;
376 printf("boot map size was %jx\n",
377 (intmax_t)boot_map->physmem_map[i].size);
378 boot_map->physmem_map[i].size = phys_avail[j + 1]
379 - phys_avail[j];
380 printf("reduced to %jx\n",
381 (intmax_t)boot_map->physmem_map[i].size);
382 }
383 printf("Next segment : addr:%p -> %p \n",
384 (void *)phys_avail[j],
385 (void *)phys_avail[j+1]);
386 }
387 physsz += boot_map->physmem_map[i].size;
388 }
389 }
390
391 /* FIXME XLR TODO */
392 phys_avail[j] = phys_avail[j + 1] = 0;
393 realmem = physmem = btoc(physsz);
394}
395
396void
397platform_start(__register_t a0 __unused,
398 __register_t a1 __unused,
399 __register_t a2 __unused,
400 __register_t a3 __unused)
401{
402 int i;
403#ifdef SMP
404 uint32_t tmp;
405 void (*wakeup) (void *, void *, unsigned int);
406#endif
407
408 /* XXX FIXME the code below is not 64 bit clean */
409 /* Save boot loader and other stuff from scratch regs */
410 xlr_boot1_info = *(struct boot1_info *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 0);
411 cpu_mask_info = read_c0_register64(MIPS_COP_0_OSSCRATCH, 1);
412 xlr_online_cpumask = read_c0_register32(MIPS_COP_0_OSSCRATCH, 2);
413 xlr_run_mode = read_c0_register32(MIPS_COP_0_OSSCRATCH, 3);
414 xlr_argc = read_c0_register32(MIPS_COP_0_OSSCRATCH, 4);
415 /*
416 * argv and envp are passed in array of 32bit pointers
417 */
418 xlr_argv = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 5);
419 xlr_envp = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 6);
420
421 /* TODO: Verify the magic number here */
422 /* FIXMELATER: xlr_boot1_info.magic_number */
423
424 /* Initialize pcpu stuff */
425 mips_pcpu0_init();
426
427 /* initialize console so that we have printf */
428 boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
429
430 /* clockrate used by delay, so initialize it here */
431 cpu_clock = xlr_boot1_info.cpu_frequency / 1000000;
432
433 /*
434 * Note the time counter on CPU0 runs not at system clock speed, but
435 * at PIC time counter speed (which is returned by
436 * platform_get_frequency(). Thus we do not use
437 * xlr_boot1_info.cpu_frequency here.
438 */
439 mips_timer_early_init(xlr_boot1_info.cpu_frequency);
440
441 /* Init console please */
442 cninit();
443 init_static_kenv(boot1_env, sizeof(boot1_env));
444 printf("Environment (from %d args):\n", xlr_argc - 1);
445 if (xlr_argc == 1)
446 printf("\tNone\n");
447 for (i = 1; i < xlr_argc; i++) {
448 char *n, *arg;
449
450 arg = (char *)(intptr_t)xlr_argv[i];
451 printf("\t%s\n", arg);
452 n = strsep(&arg, "=");
453 if (arg == NULL)
454 setenv(n, "1");
455 else
456 setenv(n, arg);
457 }
458
459 xlr_set_boot_flags();
460 xlr_parse_mmu_options();
461
462 xlr_mem_init();
463 /* Set up hz, among others. */
464 mips_init();
465
466#ifdef SMP
467 /*
468 * If thread 0 of any core is not available then mark whole core as
469 * not available
470 */
471 tmp = xlr_boot1_info.cpu_online_map;
472 for (i = 4; i < MAXCPU; i += 4) {
473 if ((tmp & (0xf << i)) && !(tmp & (0x1 << i))) {
474 /*
475 * Oops.. thread 0 is not available. Disable whole
476 * core
477 */
478 tmp = tmp & ~(0xf << i);
479 printf("WARNING: Core %d is disabled because thread 0"
480 " of this core is not enabled.\n", i / 4);
481 }
482 }
483 xlr_boot1_info.cpu_online_map = tmp;
484
485 /* Wakeup Other cpus, and put them in bsd park code. */
486 wakeup = ((void (*) (void *, void *, unsigned int))
487 (unsigned long)(xlr_boot1_info.wakeup));
488 printf("Waking up CPUs 0x%jx.\n",
489 (intmax_t)xlr_boot1_info.cpu_online_map & ~(0x1U));
490 if (xlr_boot1_info.cpu_online_map & ~(0x1U))
491 wakeup(mpwait, 0,
492 (unsigned int)xlr_boot1_info.cpu_online_map);
493#endif
494
495 /* xlr specific post initialization */
496 /* initialize other on chip stuff */
497 xlr_board_info_setup();
498 xlr_msgring_config();
499 xlr_pic_init();
500 xlr_msgring_cpu_init();
501
502 mips_timer_init_params(xlr_boot1_info.cpu_frequency, 0);
503
504 printf("Platform specific startup now completes\n");
505}
506
507void
508platform_cpu_init()
509{
510}
511
512void
513platform_identify(void)
514{
515
516 printf("Board [%d:%d], processor 0x%08x\n", (int)xlr_boot1_info.board_major_version,
517 (int)xlr_boot1_info.board_minor_version, mips_rd_prid());
518}
519
520/*
521 * XXX Maybe return the state of the watchdog in enter, and pass it to
522 * exit? Like spl().
523 */
524void
525platform_trap_enter(void)
526{
527}
528
529void
530platform_reset(void)
531{
532 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
533
534 /* write 1 to GPIO software reset register */
535 xlr_write_reg(mmio, 8, 1);
536}
537
538void
539platform_trap_exit(void)
540{
541}
542
543#ifdef SMP
544int xlr_ap_release[MAXCPU];
545
546int
547platform_start_ap(int cpuid)
548{
549 int hwid = xlr_cpuid_to_hwtid[cpuid];
550
551 if (xlr_boot1_info.cpu_online_map & (1<<hwid)) {
552 /*
553 * other cpus are enabled by the boot loader and they will be
554 * already looping in mpwait, release them
555 */
556 atomic_store_rel_int(&xlr_ap_release[hwid], 1);
557 return (0);
558 } else
559 return (-1);
560}
561
562void
563platform_init_ap(int cpuid)
564{
565 uint32_t stat;
566
567 /* The first thread has to setup the core MMU split */
568 if (xlr_thr_id() == 0)
569 xlr_setup_mmu_split();
570
571 /* Setup interrupts for secondary CPUs here */
572 stat = mips_rd_status();
573 KASSERT((stat & MIPS_SR_INT_IE) == 0,
574 ("Interrupts enabled in %s!", __func__));
575 stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT;
576 mips_wr_status(stat);
577
578 xlr_enable_irq(IRQ_IPI);
579 xlr_enable_irq(IRQ_TIMER);
580 if (xlr_thr_id() == 0) {
581 xlr_msgring_cpu_init();
582 xlr_enable_irq(IRQ_MSGRING);
583 }
584
585 return;
586}
587
588int
589platform_ipi_intrnum(void)
590{
591
592 return (IRQ_IPI);
593}
594
595void
596platform_ipi_send(int cpuid)
597{
598
599 pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum());
600
601}
602
603void
604platform_ipi_clear(void)
605{
606}
607
608int
609platform_processor_id(void)
610{
611
612 return (xlr_hwtid_to_cpuid[xlr_cpu_id()]);
613}
614
615int
616platform_num_processors(void)
617{
618
619 return (xlr_ncores * xlr_threads_per_core);
620}
621
622struct cpu_group *
623platform_smp_topo()
624{
625
626 return (smp_topo_2level(CG_SHARE_L2, xlr_ncores, CG_SHARE_L1,
627 xlr_threads_per_core, CG_FLAG_THREAD));
628}
629#endif
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 int 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_32bit_phnx_ctrl_reg(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_32bit_phnx_ctrl_reg(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 = 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 core0_thr_mask = cpu_map & 0xf;
171 switch (core0_thr_mask) {
172 case 1:
173 xlr_threads_per_core = 1; break;
174 case 3:
175 xlr_threads_per_core = 2; break;
176 case 0xf:
177 xlr_threads_per_core = 4; break;
178 default:
179 goto unsupp;
180 }
181
182 /* Verify other cores CPU masks */
183 for (i = 1; i < XLR_MAX_CORES; i++) {
184 core_thr_mask = (cpu_map >> (i*4)) & 0xf;
185 if (core_thr_mask) {
186 if (core_thr_mask != core0_thr_mask)
187 goto unsupp;
188 xlr_ncores++;
189 }
190 }
191
192 /* setup hardware processor id to cpu id mapping */
193 xlr_hw_thread_mask = xlr_boot1_info.cpu_online_map;
194 for (i = 0; i< MAXCPU; i++)
195 xlr_cpuid_to_hwtid[i] =
196 xlr_hwtid_to_cpuid [i] = -1;
197 for (i = 0, k = 0; i < XLR_MAX_CORES; i++) {
198 if (((cpu_map >> (i*4)) & 0xf) == 0)
199 continue;
200 for (j = 0; j < xlr_threads_per_core; j++) {
201 xlr_cpuid_to_hwtid[k] = i*4 + j;
202 xlr_hwtid_to_cpuid[i*4 + j] = k;
203 k++;
204 }
205 }
206
207 /* setup for the startup core */
208 xlr_setup_mmu_split();
209 return;
210
211unsupp:
212 printf("ERROR : Unsupported CPU mask [use 1,2 or 4 threads per core].\n"
213 "\tcore0 thread mask [%lx], boot cpu mask [%lx]\n"
214 "\tUsing default, 16 TLB entries per CPU, split mode\n",
215 (u_long)core0_thr_mask, (u_long)cpu_map);
216 panic("Invalid CPU mask - halting.\n");
217 return;
218}
219
220static void
221xlr_set_boot_flags(void)
222{
223 char *p;
224
225 p = getenv("bootflags");
226 if (p == NULL)
227 p = getenv("boot_flags"); /* old style */
228 if (p == NULL)
229 return;
230
231 for (; p && *p != '\0'; p++) {
232 switch (*p) {
233 case 'd':
234 case 'D':
235 boothowto |= RB_KDB;
236 break;
237 case 'g':
238 case 'G':
239 boothowto |= RB_GDB;
240 break;
241 case 'v':
242 case 'V':
243 boothowto |= RB_VERBOSE;
244 break;
245
246 case 's': /* single-user (default, supported for sanity) */
247 case 'S':
248 boothowto |= RB_SINGLE;
249 break;
250
251 default:
252 printf("Unrecognized boot flag '%c'.\n", *p);
253 break;
254 }
255 }
256
257 freeenv(p);
258 return;
259}
260extern uint32_t _end;
261
262static void
263mips_init(void)
264{
265 init_param1();
266 init_param2(physmem);
267
268 mips_cpu_init();
269 pmap_bootstrap();
270#ifdef DDB
271 kdb_init();
272 if (boothowto & RB_KDB) {
273 kdb_enter("Boot flags requested debugger", NULL);
274 }
275#endif
276 mips_proc0_init();
277 mutex_init();
278}
279
280u_int
281platform_get_timecount(struct timecounter *tc __unused)
282{
283
284 return (0xffffffffU - pic_timer_count32(PIC_CLOCK_TIMER));
285}
286
287static void
288xlr_pic_init(void)
289{
290 struct timecounter pic_timecounter = {
291 platform_get_timecount, /* get_timecount */
292 0, /* no poll_pps */
293 ~0U, /* counter_mask */
294 PIC_TIMER_HZ, /* frequency */
295 "XLRPIC", /* name */
296 2000, /* quality (adjusted in code) */
297 };
298 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET);
299 int i, level, irq;
300
301 mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN);
302 xlr_write_reg(mmio, PIC_CTRL, 0);
303
304 /* Initialize all IRT entries */
305 for (i = 0; i < PIC_NUM_IRTS; i++) {
306 irq = PIC_INTR_TO_IRQ(i);
307 level = PIC_IS_EDGE_TRIGGERED(i);
308
309 /* Bind all PIC irqs to cpu 0 */
310 xlr_write_reg(mmio, PIC_IRT_0(i), 0x01);
311
312 /*
313 * Use local scheduling and high polarity for all IRTs
314 * Invalidate all IRTs, by default
315 */
316 xlr_write_reg(mmio, PIC_IRT_1(i), (level << 30) | (1 << 6) |
317 irq);
318 }
319
320 /* Setup timer 7 of PIC as a timestamp, no interrupts */
321 pic_init_timer(PIC_CLOCK_TIMER);
322 pic_set_timer(PIC_CLOCK_TIMER, ~UINT64_C(0));
323 platform_timecounter = &pic_timecounter;
324}
325
326static void
327xlr_mem_init(void)
328{
329 struct xlr_boot1_mem_map *boot_map;
330 vm_size_t physsz = 0;
331 int i, j;
332
333 /* get physical memory info from boot loader */
334 boot_map = (struct xlr_boot1_mem_map *)
335 (unsigned long)xlr_boot1_info.psb_mem_map;
336 for (i = 0, j = 0; i < boot_map->num_entries; i++, j += 2) {
337 if (boot_map->physmem_map[i].type == BOOT1_MEM_RAM) {
338 if (j == 14) {
339 printf("*** ERROR *** memory map too large ***\n");
340 break;
341 }
342 if (j == 0) {
343 /* TODO FIXME */
344 /* start after kernel end */
345 phys_avail[0] = (vm_paddr_t)
346 MIPS_KSEG0_TO_PHYS(&_end) + 0x20000;
347 /* boot loader start */
348 /* HACK to Use bootloaders memory region */
349 /* TODO FIXME */
350 if (boot_map->physmem_map[0].size == 0x0c000000) {
351 boot_map->physmem_map[0].size = 0x0ff00000;
352 }
353 phys_avail[1] = boot_map->physmem_map[0].addr +
354 boot_map->physmem_map[0].size;
355 printf("First segment: addr:%p -> %p \n",
356 (void *)phys_avail[0],
357 (void *)phys_avail[1]);
358
359 } else {
360/*
361 * Can't use this code yet, because most of the fixed allocations happen from
362 * the biggest physical area. If we have more than 512M memory the kernel will try
363 * to map from the second are which is not in KSEG0 and not mapped
364 */
365 phys_avail[j] = (vm_paddr_t)
366 boot_map->physmem_map[i].addr;
367 phys_avail[j + 1] = phys_avail[j] +
368 boot_map->physmem_map[i].size;
369 if (phys_avail[j + 1] < phys_avail[j] ) {
370 /* Houston we have an issue. Memory is
371 * larger than possible. Its probably in
372 * 64 bit > 4Gig and we are in 32 bit mode.
373 */
374 phys_avail[j + 1] = 0xfffff000;
375 printf("boot map size was %jx\n",
376 (intmax_t)boot_map->physmem_map[i].size);
377 boot_map->physmem_map[i].size = phys_avail[j + 1]
378 - phys_avail[j];
379 printf("reduced to %jx\n",
380 (intmax_t)boot_map->physmem_map[i].size);
381 }
382 printf("Next segment : addr:%p -> %p \n",
383 (void *)phys_avail[j],
384 (void *)phys_avail[j+1]);
385 }
386 physsz += boot_map->physmem_map[i].size;
387 }
388 }
389
390 /* FIXME XLR TODO */
391 phys_avail[j] = phys_avail[j + 1] = 0;
392 realmem = physmem = btoc(physsz);
393}
394
395void
396platform_start(__register_t a0 __unused,
397 __register_t a1 __unused,
398 __register_t a2 __unused,
399 __register_t a3 __unused)
400{
401 int i;
402#ifdef SMP
403 uint32_t tmp;
404 void (*wakeup) (void *, void *, unsigned int);
405#endif
406
407 /* XXX FIXME the code below is not 64 bit clean */
408 /* Save boot loader and other stuff from scratch regs */
409 xlr_boot1_info = *(struct boot1_info *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 0);
410 cpu_mask_info = read_c0_register64(MIPS_COP_0_OSSCRATCH, 1);
411 xlr_online_cpumask = read_c0_register32(MIPS_COP_0_OSSCRATCH, 2);
412 xlr_run_mode = read_c0_register32(MIPS_COP_0_OSSCRATCH, 3);
413 xlr_argc = read_c0_register32(MIPS_COP_0_OSSCRATCH, 4);
414 /*
415 * argv and envp are passed in array of 32bit pointers
416 */
417 xlr_argv = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 5);
418 xlr_envp = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 6);
419
420 /* TODO: Verify the magic number here */
421 /* FIXMELATER: xlr_boot1_info.magic_number */
422
423 /* Initialize pcpu stuff */
424 mips_pcpu0_init();
425
426 /* initialize console so that we have printf */
427 boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */
428
429 /* clockrate used by delay, so initialize it here */
430 cpu_clock = xlr_boot1_info.cpu_frequency / 1000000;
431
432 /*
433 * Note the time counter on CPU0 runs not at system clock speed, but
434 * at PIC time counter speed (which is returned by
435 * platform_get_frequency(). Thus we do not use
436 * xlr_boot1_info.cpu_frequency here.
437 */
438 mips_timer_early_init(xlr_boot1_info.cpu_frequency);
439
440 /* Init console please */
441 cninit();
442 init_static_kenv(boot1_env, sizeof(boot1_env));
443 printf("Environment (from %d args):\n", xlr_argc - 1);
444 if (xlr_argc == 1)
445 printf("\tNone\n");
446 for (i = 1; i < xlr_argc; i++) {
447 char *n, *arg;
448
449 arg = (char *)(intptr_t)xlr_argv[i];
450 printf("\t%s\n", arg);
451 n = strsep(&arg, "=");
452 if (arg == NULL)
453 setenv(n, "1");
454 else
455 setenv(n, arg);
456 }
457
458 xlr_set_boot_flags();
459 xlr_parse_mmu_options();
460
461 xlr_mem_init();
462 /* Set up hz, among others. */
463 mips_init();
464
465#ifdef SMP
466 /*
467 * If thread 0 of any core is not available then mark whole core as
468 * not available
469 */
470 tmp = xlr_boot1_info.cpu_online_map;
471 for (i = 4; i < MAXCPU; i += 4) {
472 if ((tmp & (0xf << i)) && !(tmp & (0x1 << i))) {
473 /*
474 * Oops.. thread 0 is not available. Disable whole
475 * core
476 */
477 tmp = tmp & ~(0xf << i);
478 printf("WARNING: Core %d is disabled because thread 0"
479 " of this core is not enabled.\n", i / 4);
480 }
481 }
482 xlr_boot1_info.cpu_online_map = tmp;
483
484 /* Wakeup Other cpus, and put them in bsd park code. */
485 wakeup = ((void (*) (void *, void *, unsigned int))
486 (unsigned long)(xlr_boot1_info.wakeup));
487 printf("Waking up CPUs 0x%jx.\n",
488 (intmax_t)xlr_boot1_info.cpu_online_map & ~(0x1U));
489 if (xlr_boot1_info.cpu_online_map & ~(0x1U))
490 wakeup(mpwait, 0,
491 (unsigned int)xlr_boot1_info.cpu_online_map);
492#endif
493
494 /* xlr specific post initialization */
495 /* initialize other on chip stuff */
496 xlr_board_info_setup();
497 xlr_msgring_config();
498 xlr_pic_init();
499 xlr_msgring_cpu_init();
500
501 mips_timer_init_params(xlr_boot1_info.cpu_frequency, 0);
502
503 printf("Platform specific startup now completes\n");
504}
505
506void
507platform_cpu_init()
508{
509}
510
511void
512platform_identify(void)
513{
514
515 printf("Board [%d:%d], processor 0x%08x\n", (int)xlr_boot1_info.board_major_version,
516 (int)xlr_boot1_info.board_minor_version, mips_rd_prid());
517}
518
519/*
520 * XXX Maybe return the state of the watchdog in enter, and pass it to
521 * exit? Like spl().
522 */
523void
524platform_trap_enter(void)
525{
526}
527
528void
529platform_reset(void)
530{
531 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
532
533 /* write 1 to GPIO software reset register */
534 xlr_write_reg(mmio, 8, 1);
535}
536
537void
538platform_trap_exit(void)
539{
540}
541
542#ifdef SMP
543int xlr_ap_release[MAXCPU];
544
545int
546platform_start_ap(int cpuid)
547{
548 int hwid = xlr_cpuid_to_hwtid[cpuid];
549
550 if (xlr_boot1_info.cpu_online_map & (1<<hwid)) {
551 /*
552 * other cpus are enabled by the boot loader and they will be
553 * already looping in mpwait, release them
554 */
555 atomic_store_rel_int(&xlr_ap_release[hwid], 1);
556 return (0);
557 } else
558 return (-1);
559}
560
561void
562platform_init_ap(int cpuid)
563{
564 uint32_t stat;
565
566 /* The first thread has to setup the core MMU split */
567 if (xlr_thr_id() == 0)
568 xlr_setup_mmu_split();
569
570 /* Setup interrupts for secondary CPUs here */
571 stat = mips_rd_status();
572 KASSERT((stat & MIPS_SR_INT_IE) == 0,
573 ("Interrupts enabled in %s!", __func__));
574 stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT;
575 mips_wr_status(stat);
576
577 xlr_enable_irq(IRQ_IPI);
578 xlr_enable_irq(IRQ_TIMER);
579 if (xlr_thr_id() == 0) {
580 xlr_msgring_cpu_init();
581 xlr_enable_irq(IRQ_MSGRING);
582 }
583
584 return;
585}
586
587int
588platform_ipi_intrnum(void)
589{
590
591 return (IRQ_IPI);
592}
593
594void
595platform_ipi_send(int cpuid)
596{
597
598 pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum());
599
600}
601
602void
603platform_ipi_clear(void)
604{
605}
606
607int
608platform_processor_id(void)
609{
610
611 return (xlr_hwtid_to_cpuid[xlr_cpu_id()]);
612}
613
614int
615platform_num_processors(void)
616{
617
618 return (xlr_ncores * xlr_threads_per_core);
619}
620
621struct cpu_group *
622platform_smp_topo()
623{
624
625 return (smp_topo_2level(CG_SHARE_L2, xlr_ncores, CG_SHARE_L1,
626 xlr_threads_per_core, CG_FLAG_THREAD));
627}
628#endif