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>
|
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
|