xlr_machdep.c revision 211812
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 211812 2010-08-25 12:10:20Z 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> 69#include <mips/rmi/rmi_mips_exts.h> 70 71#include <mips/rmi/iomap.h> 72#include <mips/rmi/clock.h> 73#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> 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 281static void 282xlr_pic_init(void) 283{ 284 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_PIC_OFFSET); 285 int i, level, irq; 286 287 mtx_init(&xlr_pic_lock, "pic", NULL, MTX_SPIN); 288 xlr_write_reg(mmio, PIC_CTRL, 0); 289 for (i = 0; i < PIC_NUM_IRTS; i++) { 290 irq = PIC_INTR_TO_IRQ(i); 291 level = PIC_IRQ_IS_EDGE_TRIGGERED(irq); 292 293 /* Bind all PIC irqs to cpu 0 */ 294 xlr_write_reg(mmio, PIC_IRT_0(i), 0x01); 295 296 /* 297 * Use local scheduling and high polarity for all IRTs 298 * Invalidate all IRTs, by default 299 */ 300 xlr_write_reg(mmio, PIC_IRT_1(i), (level << 30) | (1 << 6) | 301 irq); 302 } 303} 304 305static void 306xlr_mem_init(void) 307{ 308 struct xlr_boot1_mem_map *boot_map; 309 vm_size_t physsz = 0; 310 int i, j; 311 312 /* get physical memory info from boot loader */ 313 boot_map = (struct xlr_boot1_mem_map *) 314 (unsigned long)xlr_boot1_info.psb_mem_map; 315 for (i = 0, j = 0; i < boot_map->num_entries; i++, j += 2) { 316 if (boot_map->physmem_map[i].type == BOOT1_MEM_RAM) { 317 if (j == 14) { 318 printf("*** ERROR *** memory map too large ***\n"); 319 break; 320 } 321 if (j == 0) { 322 /* TODO FIXME */ 323 /* start after kernel end */ 324 phys_avail[0] = (vm_paddr_t) 325 MIPS_KSEG0_TO_PHYS(&_end) + 0x20000; 326 /* boot loader start */ 327 /* HACK to Use bootloaders memory region */ 328 /* TODO FIXME */ 329 if (boot_map->physmem_map[0].size == 0x0c000000) { 330 boot_map->physmem_map[0].size = 0x0ff00000; 331 } 332 phys_avail[1] = boot_map->physmem_map[0].addr + 333 boot_map->physmem_map[0].size; 334 printf("First segment: addr:%p -> %p \n", 335 (void *)phys_avail[0], 336 (void *)phys_avail[1]); 337 338 } else { 339/* 340 * Can't use this code yet, because most of the fixed allocations happen from 341 * the biggest physical area. If we have more than 512M memory the kernel will try 342 * to map from the second are which is not in KSEG0 and not mapped 343 */ 344 phys_avail[j] = (vm_paddr_t) 345 boot_map->physmem_map[i].addr; 346 phys_avail[j + 1] = phys_avail[j] + 347 boot_map->physmem_map[i].size; 348 if (phys_avail[j + 1] < phys_avail[j] ) { 349 /* Houston we have an issue. Memory is 350 * larger than possible. Its probably in 351 * 64 bit > 4Gig and we are in 32 bit mode. 352 */ 353 phys_avail[j + 1] = 0xfffff000; 354 printf("boot map size was %jx\n", 355 (intmax_t)boot_map->physmem_map[i].size); 356 boot_map->physmem_map[i].size = phys_avail[j + 1] 357 - phys_avail[j]; 358 printf("reduced to %jx\n", 359 (intmax_t)boot_map->physmem_map[i].size); 360 } 361 printf("Next segment : addr:%p -> %p \n", 362 (void *)phys_avail[j], 363 (void *)phys_avail[j+1]); 364 } 365 physsz += boot_map->physmem_map[i].size; 366 } 367 } 368 369 /* FIXME XLR TODO */ 370 phys_avail[j] = phys_avail[j + 1] = 0; 371 realmem = physmem = btoc(physsz); 372} 373 374void 375platform_start(__register_t a0 __unused, 376 __register_t a1 __unused, 377 __register_t a2 __unused, 378 __register_t a3 __unused) 379{ 380 int i; 381#ifdef SMP 382 uint32_t tmp; 383 void (*wakeup) (void *, void *, unsigned int); 384#endif 385 386 /* XXX FIXME the code below is not 64 bit clean */ 387 /* Save boot loader and other stuff from scratch regs */ 388 xlr_boot1_info = *(struct boot1_info *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 0); 389 cpu_mask_info = read_c0_register64(MIPS_COP_0_OSSCRATCH, 1); 390 xlr_online_cpumask = read_c0_register32(MIPS_COP_0_OSSCRATCH, 2); 391 xlr_run_mode = read_c0_register32(MIPS_COP_0_OSSCRATCH, 3); 392 xlr_argc = read_c0_register32(MIPS_COP_0_OSSCRATCH, 4); 393 /* 394 * argv and envp are passed in array of 32bit pointers 395 */ 396 xlr_argv = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 5); 397 xlr_envp = (int32_t *)(intptr_t)(int)read_c0_register32(MIPS_COP_0_OSSCRATCH, 6); 398 399 /* TODO: Verify the magic number here */ 400 /* FIXMELATER: xlr_boot1_info.magic_number */ 401 402 /* Initialize pcpu stuff */ 403 mips_pcpu0_init(); 404 405 /* initialize console so that we have printf */ 406 boothowto |= (RB_SERIAL | RB_MULTIPLE); /* Use multiple consoles */ 407 408 /* clockrate used by delay, so initialize it here */ 409 cpu_clock = xlr_boot1_info.cpu_frequency / 1000000; 410 411 /* 412 * Note the time counter on CPU0 runs not at system clock speed, but 413 * at PIC time counter speed (which is returned by 414 * platform_get_frequency(). Thus we do not use 415 * xlr_boot1_info.cpu_frequency here. 416 */ 417 mips_timer_early_init(xlr_boot1_info.cpu_frequency); 418 419 /* Init console please */ 420 cninit(); 421 init_static_kenv(boot1_env, sizeof(boot1_env)); 422 printf("Environment (from %d args):\n", xlr_argc - 1); 423 if (xlr_argc == 1) 424 printf("\tNone\n"); 425 for (i = 1; i < xlr_argc; i++) { 426 char *n, *arg; 427 428 arg = (char *)(intptr_t)xlr_argv[i]; 429 printf("\t%s\n", arg); 430 n = strsep(&arg, "="); 431 if (arg == NULL) 432 setenv(n, "1"); 433 else 434 setenv(n, arg); 435 } 436 437 xlr_set_boot_flags(); 438 xlr_parse_mmu_options(); 439 440 xlr_mem_init(); 441 /* Set up hz, among others. */ 442 mips_init(); 443 444#ifdef SMP 445 /* 446 * If thread 0 of any core is not available then mark whole core as 447 * not available 448 */ 449 tmp = xlr_boot1_info.cpu_online_map; 450 for (i = 4; i < MAXCPU; i += 4) { 451 if ((tmp & (0xf << i)) && !(tmp & (0x1 << i))) { 452 /* 453 * Oops.. thread 0 is not available. Disable whole 454 * core 455 */ 456 tmp = tmp & ~(0xf << i); 457 printf("WARNING: Core %d is disabled because thread 0" 458 " of this core is not enabled.\n", i / 4); 459 } 460 } 461 xlr_boot1_info.cpu_online_map = tmp; 462 463 /* Wakeup Other cpus, and put them in bsd park code. */ 464 wakeup = ((void (*) (void *, void *, unsigned int)) 465 (unsigned long)(xlr_boot1_info.wakeup)); 466 printf("Waking up CPUs 0x%jx.\n", 467 (intmax_t)xlr_boot1_info.cpu_online_map & ~(0x1U)); 468 if (xlr_boot1_info.cpu_online_map & ~(0x1U)) 469 wakeup(mpwait, 0, 470 (unsigned int)xlr_boot1_info.cpu_online_map); 471#endif 472 473 /* xlr specific post initialization */ 474 /* initialize other on chip stuff */ 475 xlr_board_info_setup(); 476 xlr_msgring_config(); 477 xlr_pic_init(); 478 xlr_msgring_cpu_init(); 479 480 mips_timer_init_params(xlr_boot1_info.cpu_frequency, 0); 481 482 printf("Platform specific startup now completes\n"); 483} 484 485void 486platform_cpu_init() 487{ 488} 489 490void 491platform_identify(void) 492{ 493 494 printf("Board [%d:%d], processor 0x%08x\n", (int)xlr_boot1_info.board_major_version, 495 (int)xlr_boot1_info.board_minor_version, mips_rd_prid()); 496} 497 498/* 499 * XXX Maybe return the state of the watchdog in enter, and pass it to 500 * exit? Like spl(). 501 */ 502void 503platform_trap_enter(void) 504{ 505} 506 507void 508platform_reset(void) 509{ 510 xlr_reg_t *mmio = xlr_io_mmio(XLR_IO_GPIO_OFFSET); 511 512 /* write 1 to GPIO software reset register */ 513 xlr_write_reg(mmio, 8, 1); 514} 515 516void 517platform_trap_exit(void) 518{ 519} 520 521#ifdef SMP 522int xlr_ap_release[MAXCPU]; 523 524int 525platform_start_ap(int cpuid) 526{ 527 int hwid = xlr_cpuid_to_hwtid[cpuid]; 528 529 if (xlr_boot1_info.cpu_online_map & (1<<hwid)) { 530 /* 531 * other cpus are enabled by the boot loader and they will be 532 * already looping in mpwait, release them 533 */ 534 atomic_store_rel_int(&xlr_ap_release[hwid], 1); 535 return (0); 536 } else 537 return (-1); 538} 539 540void 541platform_init_ap(int cpuid) 542{ 543 uint32_t stat; 544 545 /* The first thread has to setup the core MMU split */ 546 if (xlr_thr_id() == 0) 547 xlr_setup_mmu_split(); 548 549 /* Setup interrupts for secondary CPUs here */ 550 stat = mips_rd_status(); 551 KASSERT((stat & MIPS_SR_INT_IE) == 0, 552 ("Interrupts enabled in %s!", __func__)); 553 stat |= MIPS_SR_COP_2_BIT | MIPS_SR_COP_0_BIT; 554 mips_wr_status(stat); 555 556 xlr_unmask_hard_irq((void *)IRQ_IPI); 557 xlr_unmask_hard_irq((void *)IRQ_TIMER); 558 if (xlr_thr_id() == 0) { 559 xlr_msgring_cpu_init(); 560 xlr_unmask_hard_irq((void *)IRQ_MSGRING); 561 } 562 563 return; 564} 565 566int 567platform_ipi_intrnum(void) 568{ 569 570 return (IRQ_IPI); 571} 572 573void 574platform_ipi_send(int cpuid) 575{ 576 577 pic_send_ipi(xlr_cpuid_to_hwtid[cpuid], platform_ipi_intrnum()); 578 579} 580 581void 582platform_ipi_clear(void) 583{ 584} 585 586int 587platform_processor_id(void) 588{ 589 590 return (xlr_hwtid_to_cpuid[xlr_cpu_id()]); 591} 592 593int 594platform_num_processors(void) 595{ 596 597 return (xlr_ncores * xlr_threads_per_core); 598} 599 600struct cpu_group * 601platform_smp_topo() 602{ 603 604 return (smp_topo_2level(CG_SHARE_L2, xlr_ncores, CG_SHARE_L1, 605 xlr_threads_per_core, CG_FLAG_THREAD)); 606} 607#endif 608