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