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