sb_machdep.c revision 210910
1/*- 2 * Copyright (c) 2007 Bruce M. Simpson. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_machdep.c 210910 2010-08-06 05:24:41Z neel $"); 29 30#include <sys/param.h> 31 32#include "opt_ddb.h" 33#include "opt_kdb.h" 34 35#include <sys/param.h> 36#include <sys/conf.h> 37#include <sys/kernel.h> 38#include <sys/systm.h> 39#include <sys/imgact.h> 40#include <sys/bio.h> 41#include <sys/buf.h> 42#include <sys/bus.h> 43#include <sys/cpu.h> 44#include <sys/cons.h> 45#include <sys/exec.h> 46#include <sys/ucontext.h> 47#include <sys/proc.h> 48#include <sys/kdb.h> 49#include <sys/ptrace.h> 50#include <sys/reboot.h> 51#include <sys/signalvar.h> 52#include <sys/sysent.h> 53#include <sys/sysproto.h> 54#include <sys/user.h> 55#include <sys/timetc.h> 56 57#include <vm/vm.h> 58#include <vm/vm_object.h> 59#include <vm/vm_page.h> 60#include <vm/vm_pager.h> 61 62#include <machine/cache.h> 63#include <machine/clock.h> 64#include <machine/cpu.h> 65#include <machine/cpuinfo.h> 66#include <machine/cpufunc.h> 67#include <machine/cpuregs.h> 68#include <machine/hwfunc.h> 69#include <machine/intr_machdep.h> 70#include <machine/locore.h> 71#include <machine/md_var.h> 72#include <machine/pte.h> 73#include <machine/sigframe.h> 74#include <machine/trap.h> 75#include <machine/vmparam.h> 76 77#ifdef SMP 78#include <sys/smp.h> 79#include <machine/smp.h> 80#endif 81 82#ifdef CFE 83#include <dev/cfe/cfe_api.h> 84#endif 85 86#include "sb_scd.h" 87 88#ifdef DDB 89#ifndef KDB 90#error KDB must be enabled in order for DDB to work! 91#endif 92#endif 93 94#ifdef CFE_ENV 95extern void cfe_env_init(void); 96#endif 97 98extern int *edata; 99extern int *end; 100 101extern char MipsTLBMiss[], MipsTLBMissEnd[]; 102 103void 104platform_cpu_init() 105{ 106 /* Nothing special */ 107} 108 109static void 110sb_intr_init(int cpuid) 111{ 112 int intrnum, intsrc; 113 114 /* 115 * Disable all sources to the interrupt mapper and setup the mapping 116 * between an interrupt source and the mips hard interrupt number. 117 */ 118 for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) { 119 intrnum = sb_route_intsrc(intsrc); 120 sb_disable_intsrc(cpuid, intsrc); 121 sb_write_intmap(cpuid, intsrc, intrnum); 122#ifdef SMP 123 /* 124 * Set up the mailbox interrupt mapping. 125 * 126 * The mailbox interrupt is "special" in that it is not shared 127 * with any other interrupt source. 128 */ 129 if (intsrc == INTSRC_MAILBOX3) { 130 intrnum = platform_ipi_intrnum(); 131 sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum); 132 sb_enable_intsrc(cpuid, INTSRC_MAILBOX3); 133 } 134#endif 135 } 136} 137 138static void 139mips_init(void) 140{ 141 int i, cfe_mem_idx, tmp; 142 uint64_t maxmem; 143 144#ifdef CFE_ENV 145 cfe_env_init(); 146#endif 147 148 TUNABLE_INT_FETCH("boothowto", &boothowto); 149 150 if (boothowto & RB_VERBOSE) 151 bootverbose++; 152 153#ifdef MAXMEM 154 tmp = MAXMEM; 155#else 156 tmp = 0; 157#endif 158 TUNABLE_INT_FETCH("hw.physmem", &tmp); 159 maxmem = (uint64_t)tmp * 1024; 160 161 /* 162 * XXX 163 * If we used vm_paddr_t consistently in pmap, etc., we could 164 * use 64-bit page numbers on !n64 systems, too, like i386 165 * does with PAE. 166 */ 167#if !defined(__mips_n64) 168 if (maxmem == 0 || maxmem > 0xffffffff) 169 maxmem = 0xffffffff; 170#endif 171 172#ifdef CFE 173 /* 174 * Query DRAM memory map from CFE. 175 */ 176 physmem = 0; 177 cfe_mem_idx = 0; 178 for (i = 0; i < 10; i += 2) { 179 int result; 180 uint64_t addr, len, type; 181 182 result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type); 183 if (result < 0) { 184 phys_avail[i] = phys_avail[i + 1] = 0; 185 break; 186 } 187 188 KASSERT(type == CFE_MI_AVAILABLE, 189 ("CFE DRAM region is not available?")); 190 191 if (bootverbose) 192 printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len); 193 194 if (maxmem != 0) { 195 if (addr >= maxmem) { 196 printf("Ignoring %ju bytes of memory at 0x%jx " 197 "that is above maxmem %dMB\n", 198 len, addr, 199 (int)(maxmem / (1024 * 1024))); 200 continue; 201 } 202 203 if (addr + len > maxmem) { 204 printf("Ignoring %ju bytes of memory " 205 "that is above maxmem %dMB\n", 206 (addr + len) - maxmem, 207 (int)(maxmem / (1024 * 1024))); 208 len = maxmem - addr; 209 } 210 } 211 212 phys_avail[i] = addr; 213 if (i == 0 && addr == 0) { 214 /* 215 * If this is the first physical memory segment probed 216 * from CFE, omit the region at the start of physical 217 * memory where the kernel has been loaded. 218 */ 219 phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 220 } 221 phys_avail[i + 1] = addr + len; 222 physmem += len; 223 } 224 225 realmem = btoc(physmem); 226#endif 227 228 physmem = realmem; 229 230 init_param1(); 231 init_param2(physmem); 232 mips_cpu_init(); 233 234 /* 235 * Sibyte has a L1 data cache coherent with DMA. This includes 236 * on-chip network interfaces as well as PCI/HyperTransport bus 237 * masters. 238 */ 239 cpuinfo.cache_coherent_dma = TRUE; 240 241 /* 242 * XXX 243 * The kernel is running in 32-bit mode but the CFE is running in 244 * 64-bit mode. So the SR_KX bit in the status register is turned 245 * on by the CFE every time we call into it - for e.g. CFE_CONSOLE. 246 * 247 * This means that if get a TLB miss for any address above 0xc0000000 248 * and the SR_KX bit is set then we will end up in the XTLB exception 249 * vector. 250 * 251 * For now work around this by copying the TLB exception handling 252 * code to the XTLB exception vector. 253 */ 254 { 255 bcopy(MipsTLBMiss, (void *)MIPS3_XTLB_MISS_EXC_VEC, 256 MipsTLBMissEnd - MipsTLBMiss); 257 258 mips_icache_sync_all(); 259 mips_dcache_wbinv_all(); 260 } 261 262 pmap_bootstrap(); 263 mips_proc0_init(); 264 mutex_init(); 265 266 kdb_init(); 267#ifdef KDB 268 if (boothowto & RB_KDB) 269 kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 270#endif 271} 272 273void 274platform_halt(void) 275{ 276 277} 278 279 280void 281platform_identify(void) 282{ 283 284} 285 286void 287platform_reset(void) 288{ 289 290 /* 291 * XXX SMP 292 * XXX flush data caches 293 */ 294 sb_system_reset(); 295} 296 297void 298platform_trap_enter(void) 299{ 300 301} 302 303void 304platform_trap_exit(void) 305{ 306 307} 308 309static void 310kseg0_map_coherent(void) 311{ 312 uint32_t config; 313 const int CFG_K0_COHERENT = 5; 314 315 config = mips_rd_config(); 316 config &= ~MIPS3_CONFIG_K0_MASK; 317 config |= CFG_K0_COHERENT; 318 mips_wr_config(config); 319} 320 321#ifdef SMP 322void 323platform_ipi_send(int cpuid) 324{ 325 KASSERT(cpuid == 0 || cpuid == 1, 326 ("platform_ipi_send: invalid cpuid %d", cpuid)); 327 328 sb_set_mailbox(cpuid, 1ULL); 329} 330 331void 332platform_ipi_clear(void) 333{ 334 int cpuid; 335 336 cpuid = PCPU_GET(cpuid); 337 sb_clear_mailbox(cpuid, 1ULL); 338} 339 340int 341platform_ipi_intrnum(void) 342{ 343 344 return (4); 345} 346 347struct cpu_group * 348platform_smp_topo(void) 349{ 350 351 return (smp_topo_none()); 352} 353 354void 355platform_init_ap(int cpuid) 356{ 357 int ipi_int_mask, clock_int_mask; 358 359 KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid)); 360 361 /* 362 * Make sure that kseg0 is mapped cacheable-coherent 363 */ 364 kseg0_map_coherent(); 365 366 sb_intr_init(cpuid); 367 368 /* 369 * Unmask the clock and ipi interrupts. 370 */ 371 clock_int_mask = hard_int_mask(5); 372 ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); 373 set_intr_mask(MIPS_SR_INT_MASK & ~(ipi_int_mask | clock_int_mask)); 374} 375 376int 377platform_start_ap(int cpuid) 378{ 379#ifdef CFE 380 int error; 381 382 if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) { 383 printf("cfe_cpu_start error: %d\n", error); 384 return (-1); 385 } else { 386 return (0); 387 } 388#else 389 return (-1); 390#endif /* CFE */ 391} 392#endif /* SMP */ 393 394static u_int 395sb_get_timecount(struct timecounter *tc) 396{ 397 398 return ((u_int)sb_zbbus_cycle_count()); 399} 400 401static void 402sb_timecounter_init(void) 403{ 404 static struct timecounter sb_timecounter = { 405 sb_get_timecount, 406 NULL, 407 ~0u, 408 0, 409 "sibyte_zbbus_counter", 410 2000 411 }; 412 413 /* 414 * The ZBbus cycle counter runs at half the cpu frequency. 415 */ 416 sb_timecounter.tc_frequency = sb_cpu_speed() / 2; 417 platform_timecounter = &sb_timecounter; 418} 419 420void 421platform_start(__register_t a0, __register_t a1, __register_t a2, 422 __register_t a3) 423{ 424 /* 425 * Make sure that kseg0 is mapped cacheable-coherent 426 */ 427 kseg0_map_coherent(); 428 429 /* clear the BSS and SBSS segments */ 430 memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata); 431 mips_postboot_fixup(); 432 433 sb_intr_init(0); 434 sb_timecounter_init(); 435 436 /* Initialize pcpu stuff */ 437 mips_pcpu0_init(); 438 439#ifdef CFE 440 /* 441 * Initialize CFE firmware trampolines before 442 * we initialize the low-level console. 443 * 444 * CFE passes the following values in registers: 445 * a0: firmware handle 446 * a2: firmware entry point 447 * a3: entry point seal 448 */ 449 if (a3 == CFE_EPTSEAL) 450 cfe_init(a0, a2); 451#endif 452 cninit(); 453 454 mips_init(); 455 456 mips_timer_init_params(sb_cpu_speed(), 0); 457} 458