sb_machdep.c revision 203697
1195333Simp/*- 2195333Simp * Copyright (c) 2007 Bruce M. Simpson. 3195333Simp * All rights reserved. 4195333Simp * 5195333Simp * Redistribution and use in source and binary forms, with or without 6195333Simp * modification, are permitted provided that the following conditions 7195333Simp * are met: 8195333Simp * 1. Redistributions of source code must retain the above copyright 9195333Simp * notice, this list of conditions and the following disclaimer. 10195333Simp * 2. Redistributions in binary form must reproduce the above copyright 11195333Simp * notice, this list of conditions and the following disclaimer in the 12195333Simp * documentation and/or other materials provided with the distribution. 13195333Simp * 14195333Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15195333Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16195333Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17195333Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18195333Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19195333Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20195333Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21195333Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22195333Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23195333Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24195333Simp * SUCH DAMAGE. 25195333Simp */ 26195333Simp 27195333Simp#include <sys/cdefs.h> 28195333Simp__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_machdep.c 203697 2010-02-09 06:24:43Z neel $"); 29195333Simp 30195333Simp#include <sys/param.h> 31195333Simp#include <machine/cpuregs.h> 32195333Simp 33195333Simp#include "opt_ddb.h" 34195333Simp#include "opt_kdb.h" 35195333Simp 36195333Simp#include <sys/param.h> 37195333Simp#include <sys/conf.h> 38195333Simp#include <sys/kernel.h> 39195333Simp#include <sys/systm.h> 40195333Simp#include <sys/imgact.h> 41195333Simp#include <sys/bio.h> 42195333Simp#include <sys/buf.h> 43195333Simp#include <sys/bus.h> 44195333Simp#include <sys/cpu.h> 45195333Simp#include <sys/cons.h> 46195333Simp#include <sys/exec.h> 47195333Simp#include <sys/ucontext.h> 48195333Simp#include <sys/proc.h> 49195333Simp#include <sys/kdb.h> 50195333Simp#include <sys/ptrace.h> 51195333Simp#include <sys/reboot.h> 52195333Simp#include <sys/signalvar.h> 53195333Simp#include <sys/sysent.h> 54195333Simp#include <sys/sysproto.h> 55195333Simp#include <sys/user.h> 56195333Simp 57195333Simp#include <vm/vm.h> 58195333Simp#include <vm/vm_object.h> 59195333Simp#include <vm/vm_page.h> 60195333Simp#include <vm/vm_pager.h> 61195333Simp 62195333Simp#include <machine/cache.h> 63195333Simp#include <machine/clock.h> 64195333Simp#include <machine/cpu.h> 65195333Simp#include <machine/cpuinfo.h> 66195333Simp#include <machine/cpufunc.h> 67195333Simp#include <machine/cpuregs.h> 68195333Simp#include <machine/hwfunc.h> 69195333Simp#include <machine/intr_machdep.h> 70195333Simp#include <machine/locore.h> 71195333Simp#include <machine/md_var.h> 72195333Simp#include <machine/pte.h> 73195333Simp#include <machine/sigframe.h> 74195333Simp#include <machine/trap.h> 75195333Simp#include <machine/vmparam.h> 76195333Simp 77203697Sneel#ifdef SMP 78203697Sneel#include <machine/smp.h> 79203697Sneel#endif 80203697Sneel 81195333Simp#ifdef CFE 82195333Simp#include <dev/cfe/cfe_api.h> 83195333Simp#endif 84195333Simp 85195333Simp#include "sb_scd.h" 86195333Simp 87195333Simp#ifdef DDB 88195333Simp#ifndef KDB 89195333Simp#error KDB must be enabled in order for DDB to work! 90195333Simp#endif 91195333Simp#endif 92195333Simp 93195333Simp#ifdef CFE_ENV 94195333Simpextern void cfe_env_init(void); 95195333Simp#endif 96195333Simp 97195333Simpextern int *edata; 98195333Simpextern int *end; 99195333Simp 100203000Sneelextern char MipsTLBMiss[], MipsTLBMissEnd[]; 101203000Sneel 102198669Srrsvoid 103198669Srrsplatform_cpu_init() 104198669Srrs{ 105198669Srrs /* Nothing special */ 106198669Srrs} 107198669Srrs 108195333Simpstatic void 109203510Sneelsb_intr_init(int cpuid) 110203510Sneel{ 111203510Sneel int intrnum, intsrc; 112203510Sneel 113203510Sneel /* 114203510Sneel * Disable all sources to the interrupt mapper and setup the mapping 115203510Sneel * between an interrupt source and the mips hard interrupt number. 116203510Sneel */ 117203510Sneel for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) { 118203510Sneel intrnum = sb_route_intsrc(intsrc); 119203510Sneel sb_disable_intsrc(cpuid, intsrc); 120203510Sneel sb_write_intmap(cpuid, intsrc, intrnum); 121203697Sneel#ifdef SMP 122203697Sneel /* 123203697Sneel * Set up the mailbox interrupt mapping. 124203697Sneel * 125203697Sneel * The mailbox interrupt is "special" in that it is not shared 126203697Sneel * with any other interrupt source. 127203697Sneel */ 128203697Sneel if (intsrc == INTSRC_MAILBOX3) { 129203697Sneel intrnum = platform_ipi_intrnum(); 130203697Sneel sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum); 131203697Sneel sb_enable_intsrc(cpuid, INTSRC_MAILBOX3); 132203697Sneel } 133203697Sneel#endif 134203510Sneel } 135203510Sneel} 136203510Sneel 137203510Sneelstatic void 138195333Simpmips_init(void) 139195333Simp{ 140195333Simp int i, cfe_mem_idx, tmp; 141195333Simp uint64_t maxmem; 142195333Simp 143195333Simp#ifdef CFE_ENV 144195333Simp cfe_env_init(); 145195333Simp#endif 146195333Simp 147195333Simp TUNABLE_INT_FETCH("boothowto", &boothowto); 148195333Simp 149195333Simp if (boothowto & RB_VERBOSE) 150195333Simp bootverbose++; 151195333Simp 152195333Simp#ifdef MAXMEM 153195333Simp tmp = MAXMEM; 154195333Simp#else 155195333Simp tmp = 0; 156195333Simp#endif 157195333Simp TUNABLE_INT_FETCH("hw.physmem", &tmp); 158195333Simp maxmem = (uint64_t)tmp * 1024; 159195333Simp 160195333Simp#ifdef CFE 161195333Simp /* 162195333Simp * Query DRAM memory map from CFE. 163195333Simp */ 164195333Simp physmem = 0; 165195333Simp cfe_mem_idx = 0; 166195333Simp for (i = 0; i < 10; i += 2) { 167195333Simp int result; 168195333Simp uint64_t addr, len, type; 169195333Simp 170195333Simp result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type); 171195333Simp if (result < 0) { 172195333Simp phys_avail[i] = phys_avail[i + 1] = 0; 173195333Simp break; 174195333Simp } 175195333Simp 176195333Simp KASSERT(type == CFE_MI_AVAILABLE, 177195333Simp ("CFE DRAM region is not available?")); 178195333Simp 179195333Simp if (bootverbose) 180195333Simp printf("cfe_enummem: 0x%016jx/%llu.\n", addr, len); 181195333Simp 182195333Simp if (maxmem != 0) { 183195333Simp if (addr >= maxmem) { 184195333Simp printf("Ignoring %llu bytes of memory at 0x%jx " 185195333Simp "that is above maxmem %dMB\n", 186195333Simp len, addr, 187195333Simp (int)(maxmem / (1024 * 1024))); 188195333Simp continue; 189195333Simp } 190195333Simp 191195333Simp if (addr + len > maxmem) { 192195333Simp printf("Ignoring %llu bytes of memory " 193195333Simp "that is above maxmem %dMB\n", 194195333Simp (addr + len) - maxmem, 195195333Simp (int)(maxmem / (1024 * 1024))); 196195333Simp len = maxmem - addr; 197195333Simp } 198195333Simp } 199195333Simp 200195333Simp phys_avail[i] = addr; 201195333Simp if (i == 0 && addr == 0) { 202195333Simp /* 203195333Simp * If this is the first physical memory segment probed 204195333Simp * from CFE, omit the region at the start of physical 205195333Simp * memory where the kernel has been loaded. 206195333Simp */ 207202954Sgonzo phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 208195333Simp } 209195333Simp phys_avail[i + 1] = addr + len; 210195333Simp physmem += len; 211195333Simp } 212195333Simp 213195333Simp realmem = btoc(physmem); 214195333Simp#endif 215195333Simp 216195333Simp physmem = realmem; 217195333Simp 218195333Simp init_param1(); 219195333Simp init_param2(physmem); 220195333Simp mips_cpu_init(); 221203000Sneel 222203000Sneel /* 223203000Sneel * XXX 224203000Sneel * The kernel is running in 32-bit mode but the CFE is running in 225203000Sneel * 64-bit mode. So the SR_KX bit in the status register is turned 226203000Sneel * on by the CFE every time we call into it - for e.g. CFE_CONSOLE. 227203000Sneel * 228203000Sneel * This means that if get a TLB miss for any address above 0xc0000000 229203000Sneel * and the SR_KX bit is set then we will end up in the XTLB exception 230203000Sneel * vector. 231203000Sneel * 232203000Sneel * For now work around this by copying the TLB exception handling 233203000Sneel * code to the XTLB exception vector. 234203000Sneel */ 235203000Sneel { 236203000Sneel bcopy(MipsTLBMiss, (void *)XTLB_MISS_EXC_VEC, 237203000Sneel MipsTLBMissEnd - MipsTLBMiss); 238203000Sneel 239203000Sneel mips_icache_sync_all(); 240203000Sneel mips_dcache_wbinv_all(); 241203000Sneel } 242203000Sneel 243195333Simp pmap_bootstrap(); 244195333Simp mips_proc0_init(); 245195333Simp mutex_init(); 246195333Simp 247195333Simp kdb_init(); 248195333Simp#ifdef KDB 249195333Simp if (boothowto & RB_KDB) 250195333Simp kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 251195333Simp#endif 252195333Simp} 253195333Simp 254195333Simpvoid 255195333Simpplatform_halt(void) 256195333Simp{ 257195333Simp 258195333Simp} 259195333Simp 260195333Simp 261195333Simpvoid 262195333Simpplatform_identify(void) 263195333Simp{ 264195333Simp 265195333Simp} 266195333Simp 267195333Simpvoid 268195333Simpplatform_reset(void) 269195333Simp{ 270195333Simp 271195333Simp /* 272195333Simp * XXX SMP 273195333Simp * XXX flush data caches 274195333Simp */ 275195333Simp sb_system_reset(); 276195333Simp} 277195333Simp 278195333Simpvoid 279195333Simpplatform_trap_enter(void) 280195333Simp{ 281195333Simp 282195333Simp} 283195333Simp 284195333Simpvoid 285195333Simpplatform_trap_exit(void) 286195333Simp{ 287195333Simp 288195333Simp} 289195333Simp 290202864Sneelstatic void 291202864Sneelkseg0_map_coherent(void) 292202864Sneel{ 293202864Sneel uint32_t config; 294202864Sneel const int CFG_K0_COHERENT = 5; 295202864Sneel 296202864Sneel config = mips_rd_config(); 297202864Sneel config &= ~CFG_K0_MASK; 298202864Sneel config |= CFG_K0_COHERENT; 299202864Sneel mips_wr_config(config); 300202864Sneel} 301202864Sneel 302203697Sneel#ifdef SMP 303195333Simpvoid 304203697Sneelplatform_ipi_send(int cpuid) 305203697Sneel{ 306203697Sneel KASSERT(cpuid == 0 || cpuid == 1, 307203697Sneel ("platform_ipi_send: invalid cpuid %d", cpuid)); 308203697Sneel 309203697Sneel sb_set_mailbox(cpuid, 1ULL); 310203697Sneel} 311203697Sneel 312203697Sneelvoid 313203697Sneelplatform_ipi_clear(void) 314203697Sneel{ 315203697Sneel int cpuid; 316203697Sneel 317203697Sneel cpuid = PCPU_GET(cpuid); 318203697Sneel sb_clear_mailbox(cpuid, 1ULL); 319203697Sneel} 320203697Sneel 321203697Sneelint 322203697Sneelplatform_ipi_intrnum(void) 323203697Sneel{ 324203697Sneel 325203697Sneel return (4); 326203697Sneel} 327203697Sneel 328203697Sneelvoid 329203697Sneelplatform_init_ap(int cpuid) 330203697Sneel{ 331203697Sneel 332203697Sneel KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid)); 333203697Sneel 334203697Sneel /* 335203697Sneel * Make sure that kseg0 is mapped cacheable-coherent 336203697Sneel */ 337203697Sneel kseg0_map_coherent(); 338203697Sneel 339203697Sneel sb_intr_init(cpuid); 340203697Sneel} 341203697Sneel 342203697Sneelint 343203697Sneelplatform_start_ap(int cpuid) 344203697Sneel{ 345203697Sneel#ifdef CFE 346203697Sneel int error; 347203697Sneel 348203697Sneel if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) { 349203697Sneel printf("cfe_cpu_start error: %d\n", error); 350203697Sneel return (-1); 351203697Sneel } else { 352203697Sneel return (0); 353203697Sneel } 354203697Sneel#else 355203697Sneel return (-1); 356203697Sneel#endif /* CFE */ 357203697Sneel} 358203697Sneel#endif /* SMP */ 359203697Sneel 360203697Sneelvoid 361201631Sneelplatform_start(__register_t a0, __register_t a1, __register_t a2, 362201631Sneel __register_t a3) 363195333Simp{ 364202864Sneel /* 365202864Sneel * Make sure that kseg0 is mapped cacheable-coherent 366202864Sneel */ 367202864Sneel kseg0_map_coherent(); 368202864Sneel 369195333Simp /* clear the BSS and SBSS segments */ 370195333Simp memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata); 371202954Sgonzo mips_postboot_fixup(); 372195333Simp 373203510Sneel sb_intr_init(0); 374203510Sneel 375201845Simp /* Initialize pcpu stuff */ 376201881Simp mips_pcpu0_init(); 377201845Simp 378195333Simp#ifdef CFE 379195333Simp /* 380195333Simp * Initialize CFE firmware trampolines before 381195333Simp * we initialize the low-level console. 382201631Sneel * 383201631Sneel * CFE passes the following values in registers: 384201631Sneel * a0: firmware handle 385201631Sneel * a2: firmware entry point 386201631Sneel * a3: entry point seal 387195333Simp */ 388201631Sneel if (a3 == CFE_EPTSEAL) 389201631Sneel cfe_init(a0, a2); 390195333Simp#endif 391195333Simp cninit(); 392195333Simp 393195333Simp mips_init(); 394195333Simp 395195333Simp mips_timer_init_params(sb_cpu_speed(), 0); 396195333Simp} 397