sb_machdep.c revision 216318
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 216318 2010-12-09 07:01:03Z gonzo $"); 29195333Simp 30195333Simp#include <sys/param.h> 31195333Simp 32195333Simp#include "opt_ddb.h" 33195333Simp#include "opt_kdb.h" 34195333Simp 35195333Simp#include <sys/param.h> 36195333Simp#include <sys/conf.h> 37195333Simp#include <sys/kernel.h> 38195333Simp#include <sys/systm.h> 39195333Simp#include <sys/imgact.h> 40195333Simp#include <sys/bio.h> 41195333Simp#include <sys/buf.h> 42195333Simp#include <sys/bus.h> 43195333Simp#include <sys/cpu.h> 44195333Simp#include <sys/cons.h> 45195333Simp#include <sys/exec.h> 46195333Simp#include <sys/ucontext.h> 47195333Simp#include <sys/proc.h> 48195333Simp#include <sys/kdb.h> 49195333Simp#include <sys/ptrace.h> 50195333Simp#include <sys/reboot.h> 51195333Simp#include <sys/signalvar.h> 52195333Simp#include <sys/sysent.h> 53195333Simp#include <sys/sysproto.h> 54195333Simp#include <sys/user.h> 55205364Sneel#include <sys/timetc.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 78208253Sneel#include <sys/smp.h> 79203697Sneel#include <machine/smp.h> 80203697Sneel#endif 81203697Sneel 82195333Simp#ifdef CFE 83195333Simp#include <dev/cfe/cfe_api.h> 84195333Simp#endif 85195333Simp 86195333Simp#include "sb_scd.h" 87195333Simp 88195333Simp#ifdef DDB 89195333Simp#ifndef KDB 90195333Simp#error KDB must be enabled in order for DDB to work! 91195333Simp#endif 92195333Simp#endif 93195333Simp 94195333Simp#ifdef CFE_ENV 95195333Simpextern void cfe_env_init(void); 96195333Simp#endif 97195333Simp 98195333Simpextern int *edata; 99195333Simpextern int *end; 100195333Simp 101203000Sneelextern char MipsTLBMiss[], MipsTLBMissEnd[]; 102203000Sneel 103198669Srrsvoid 104198669Srrsplatform_cpu_init() 105198669Srrs{ 106198669Srrs /* Nothing special */ 107198669Srrs} 108198669Srrs 109195333Simpstatic void 110203510Sneelsb_intr_init(int cpuid) 111203510Sneel{ 112203510Sneel int intrnum, intsrc; 113203510Sneel 114203510Sneel /* 115203510Sneel * Disable all sources to the interrupt mapper and setup the mapping 116203510Sneel * between an interrupt source and the mips hard interrupt number. 117203510Sneel */ 118203510Sneel for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) { 119203510Sneel intrnum = sb_route_intsrc(intsrc); 120203510Sneel sb_disable_intsrc(cpuid, intsrc); 121203510Sneel sb_write_intmap(cpuid, intsrc, intrnum); 122203697Sneel#ifdef SMP 123203697Sneel /* 124203697Sneel * Set up the mailbox interrupt mapping. 125203697Sneel * 126203697Sneel * The mailbox interrupt is "special" in that it is not shared 127203697Sneel * with any other interrupt source. 128203697Sneel */ 129203697Sneel if (intsrc == INTSRC_MAILBOX3) { 130203697Sneel intrnum = platform_ipi_intrnum(); 131203697Sneel sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum); 132203697Sneel sb_enable_intsrc(cpuid, INTSRC_MAILBOX3); 133203697Sneel } 134203697Sneel#endif 135203510Sneel } 136203510Sneel} 137203510Sneel 138203510Sneelstatic void 139195333Simpmips_init(void) 140195333Simp{ 141216318Sgonzo int i, j, cfe_mem_idx, tmp; 142195333Simp uint64_t maxmem; 143195333Simp 144195333Simp#ifdef CFE_ENV 145195333Simp cfe_env_init(); 146195333Simp#endif 147195333Simp 148195333Simp TUNABLE_INT_FETCH("boothowto", &boothowto); 149195333Simp 150195333Simp if (boothowto & RB_VERBOSE) 151195333Simp bootverbose++; 152195333Simp 153195333Simp#ifdef MAXMEM 154195333Simp tmp = MAXMEM; 155195333Simp#else 156195333Simp tmp = 0; 157195333Simp#endif 158195333Simp TUNABLE_INT_FETCH("hw.physmem", &tmp); 159195333Simp maxmem = (uint64_t)tmp * 1024; 160195333Simp 161207131Sjmallett /* 162207131Sjmallett * XXX 163207131Sjmallett * If we used vm_paddr_t consistently in pmap, etc., we could 164207131Sjmallett * use 64-bit page numbers on !n64 systems, too, like i386 165207131Sjmallett * does with PAE. 166207131Sjmallett */ 167207131Sjmallett#if !defined(__mips_n64) 168207131Sjmallett if (maxmem == 0 || maxmem > 0xffffffff) 169207131Sjmallett maxmem = 0xffffffff; 170207131Sjmallett#endif 171207131Sjmallett 172195333Simp#ifdef CFE 173195333Simp /* 174195333Simp * Query DRAM memory map from CFE. 175195333Simp */ 176195333Simp physmem = 0; 177195333Simp cfe_mem_idx = 0; 178195333Simp for (i = 0; i < 10; i += 2) { 179195333Simp int result; 180195333Simp uint64_t addr, len, type; 181195333Simp 182195333Simp result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type); 183195333Simp if (result < 0) { 184195333Simp phys_avail[i] = phys_avail[i + 1] = 0; 185195333Simp break; 186195333Simp } 187195333Simp 188195333Simp KASSERT(type == CFE_MI_AVAILABLE, 189195333Simp ("CFE DRAM region is not available?")); 190195333Simp 191195333Simp if (bootverbose) 192210910Sneel printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len); 193195333Simp 194195333Simp if (maxmem != 0) { 195195333Simp if (addr >= maxmem) { 196210910Sneel printf("Ignoring %ju bytes of memory at 0x%jx " 197195333Simp "that is above maxmem %dMB\n", 198195333Simp len, addr, 199195333Simp (int)(maxmem / (1024 * 1024))); 200195333Simp continue; 201195333Simp } 202195333Simp 203195333Simp if (addr + len > maxmem) { 204210910Sneel printf("Ignoring %ju bytes of memory " 205195333Simp "that is above maxmem %dMB\n", 206195333Simp (addr + len) - maxmem, 207195333Simp (int)(maxmem / (1024 * 1024))); 208195333Simp len = maxmem - addr; 209195333Simp } 210195333Simp } 211195333Simp 212195333Simp phys_avail[i] = addr; 213195333Simp if (i == 0 && addr == 0) { 214195333Simp /* 215195333Simp * If this is the first physical memory segment probed 216195333Simp * from CFE, omit the region at the start of physical 217195333Simp * memory where the kernel has been loaded. 218195333Simp */ 219202954Sgonzo phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 220195333Simp } 221195333Simp phys_avail[i + 1] = addr + len; 222195333Simp physmem += len; 223195333Simp } 224195333Simp 225195333Simp realmem = btoc(physmem); 226195333Simp#endif 227195333Simp 228216318Sgonzo for (j = 0; j < i; j += 2) { 229216318Sgonzo dump_avail[j] = phys_avail[j]; 230216318Sgonzo dump_avail[j+1] = phys_avail[j+1] - phys_avail[j]; 231216318Sgonzo } 232216318Sgonzo 233195333Simp physmem = realmem; 234195333Simp 235195333Simp init_param1(); 236195333Simp init_param2(physmem); 237195333Simp mips_cpu_init(); 238203000Sneel 239203000Sneel /* 240204689Sneel * Sibyte has a L1 data cache coherent with DMA. This includes 241204689Sneel * on-chip network interfaces as well as PCI/HyperTransport bus 242204689Sneel * masters. 243204689Sneel */ 244204689Sneel cpuinfo.cache_coherent_dma = TRUE; 245204689Sneel 246204689Sneel /* 247203000Sneel * XXX 248203000Sneel * The kernel is running in 32-bit mode but the CFE is running in 249203000Sneel * 64-bit mode. So the SR_KX bit in the status register is turned 250203000Sneel * on by the CFE every time we call into it - for e.g. CFE_CONSOLE. 251203000Sneel * 252203000Sneel * This means that if get a TLB miss for any address above 0xc0000000 253203000Sneel * and the SR_KX bit is set then we will end up in the XTLB exception 254203000Sneel * vector. 255203000Sneel * 256203000Sneel * For now work around this by copying the TLB exception handling 257203000Sneel * code to the XTLB exception vector. 258203000Sneel */ 259203000Sneel { 260210027Simp bcopy(MipsTLBMiss, (void *)MIPS3_XTLB_MISS_EXC_VEC, 261203000Sneel MipsTLBMissEnd - MipsTLBMiss); 262203000Sneel 263203000Sneel mips_icache_sync_all(); 264203000Sneel mips_dcache_wbinv_all(); 265203000Sneel } 266203000Sneel 267195333Simp pmap_bootstrap(); 268195333Simp mips_proc0_init(); 269195333Simp mutex_init(); 270195333Simp 271195333Simp kdb_init(); 272195333Simp#ifdef KDB 273195333Simp if (boothowto & RB_KDB) 274195333Simp kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 275195333Simp#endif 276195333Simp} 277195333Simp 278195333Simpvoid 279195333Simpplatform_halt(void) 280195333Simp{ 281195333Simp 282195333Simp} 283195333Simp 284195333Simp 285195333Simpvoid 286195333Simpplatform_identify(void) 287195333Simp{ 288195333Simp 289195333Simp} 290195333Simp 291195333Simpvoid 292195333Simpplatform_reset(void) 293195333Simp{ 294195333Simp 295195333Simp /* 296195333Simp * XXX SMP 297195333Simp * XXX flush data caches 298195333Simp */ 299195333Simp sb_system_reset(); 300195333Simp} 301195333Simp 302195333Simpvoid 303195333Simpplatform_trap_enter(void) 304195333Simp{ 305195333Simp 306195333Simp} 307195333Simp 308195333Simpvoid 309195333Simpplatform_trap_exit(void) 310195333Simp{ 311195333Simp 312195333Simp} 313195333Simp 314202864Sneelstatic void 315202864Sneelkseg0_map_coherent(void) 316202864Sneel{ 317202864Sneel uint32_t config; 318202864Sneel const int CFG_K0_COHERENT = 5; 319202864Sneel 320202864Sneel config = mips_rd_config(); 321210027Simp config &= ~MIPS3_CONFIG_K0_MASK; 322202864Sneel config |= CFG_K0_COHERENT; 323202864Sneel mips_wr_config(config); 324202864Sneel} 325202864Sneel 326203697Sneel#ifdef SMP 327195333Simpvoid 328203697Sneelplatform_ipi_send(int cpuid) 329203697Sneel{ 330203697Sneel KASSERT(cpuid == 0 || cpuid == 1, 331203697Sneel ("platform_ipi_send: invalid cpuid %d", cpuid)); 332203697Sneel 333203697Sneel sb_set_mailbox(cpuid, 1ULL); 334203697Sneel} 335203697Sneel 336203697Sneelvoid 337203697Sneelplatform_ipi_clear(void) 338203697Sneel{ 339203697Sneel int cpuid; 340203697Sneel 341203697Sneel cpuid = PCPU_GET(cpuid); 342203697Sneel sb_clear_mailbox(cpuid, 1ULL); 343203697Sneel} 344203697Sneel 345203697Sneelint 346203697Sneelplatform_ipi_intrnum(void) 347203697Sneel{ 348203697Sneel 349203697Sneel return (4); 350203697Sneel} 351203697Sneel 352208249Srrsstruct cpu_group * 353208249Srrsplatform_smp_topo(void) 354208249Srrs{ 355208253Sneel 356208249Srrs return (smp_topo_none()); 357208249Srrs} 358208249Srrs 359203697Sneelvoid 360203697Sneelplatform_init_ap(int cpuid) 361203697Sneel{ 362208249Srrs int ipi_int_mask, clock_int_mask; 363203697Sneel 364203697Sneel KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid)); 365203697Sneel 366203697Sneel /* 367203697Sneel * Make sure that kseg0 is mapped cacheable-coherent 368203697Sneel */ 369203697Sneel kseg0_map_coherent(); 370203697Sneel 371203697Sneel sb_intr_init(cpuid); 372208249Srrs 373208249Srrs /* 374208249Srrs * Unmask the clock and ipi interrupts. 375208249Srrs */ 376208249Srrs clock_int_mask = hard_int_mask(5); 377208249Srrs ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); 378212632Sneel set_intr_mask(ipi_int_mask | clock_int_mask); 379203697Sneel} 380203697Sneel 381203697Sneelint 382203697Sneelplatform_start_ap(int cpuid) 383203697Sneel{ 384203697Sneel#ifdef CFE 385203697Sneel int error; 386203697Sneel 387203697Sneel if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) { 388203697Sneel printf("cfe_cpu_start error: %d\n", error); 389203697Sneel return (-1); 390203697Sneel } else { 391203697Sneel return (0); 392203697Sneel } 393203697Sneel#else 394203697Sneel return (-1); 395203697Sneel#endif /* CFE */ 396203697Sneel} 397203697Sneel#endif /* SMP */ 398203697Sneel 399205364Sneelstatic u_int 400205364Sneelsb_get_timecount(struct timecounter *tc) 401205364Sneel{ 402205364Sneel 403205364Sneel return ((u_int)sb_zbbus_cycle_count()); 404205364Sneel} 405205364Sneel 406205364Sneelstatic void 407205364Sneelsb_timecounter_init(void) 408205364Sneel{ 409205364Sneel static struct timecounter sb_timecounter = { 410205364Sneel sb_get_timecount, 411205364Sneel NULL, 412205364Sneel ~0u, 413205364Sneel 0, 414205364Sneel "sibyte_zbbus_counter", 415205364Sneel 2000 416205364Sneel }; 417205364Sneel 418205364Sneel /* 419205364Sneel * The ZBbus cycle counter runs at half the cpu frequency. 420205364Sneel */ 421205364Sneel sb_timecounter.tc_frequency = sb_cpu_speed() / 2; 422205364Sneel platform_timecounter = &sb_timecounter; 423205364Sneel} 424205364Sneel 425203697Sneelvoid 426201631Sneelplatform_start(__register_t a0, __register_t a1, __register_t a2, 427201631Sneel __register_t a3) 428195333Simp{ 429202864Sneel /* 430202864Sneel * Make sure that kseg0 is mapped cacheable-coherent 431202864Sneel */ 432202864Sneel kseg0_map_coherent(); 433202864Sneel 434195333Simp /* clear the BSS and SBSS segments */ 435195333Simp memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata); 436202954Sgonzo mips_postboot_fixup(); 437195333Simp 438203510Sneel sb_intr_init(0); 439205364Sneel sb_timecounter_init(); 440203510Sneel 441201845Simp /* Initialize pcpu stuff */ 442201881Simp mips_pcpu0_init(); 443201845Simp 444195333Simp#ifdef CFE 445195333Simp /* 446195333Simp * Initialize CFE firmware trampolines before 447195333Simp * we initialize the low-level console. 448201631Sneel * 449201631Sneel * CFE passes the following values in registers: 450201631Sneel * a0: firmware handle 451201631Sneel * a2: firmware entry point 452201631Sneel * a3: entry point seal 453195333Simp */ 454201631Sneel if (a3 == CFE_EPTSEAL) 455201631Sneel cfe_init(a0, a2); 456195333Simp#endif 457195333Simp cninit(); 458195333Simp 459195333Simp mips_init(); 460195333Simp 461195333Simp mips_timer_init_params(sb_cpu_speed(), 0); 462195333Simp} 463