sb_machdep.c revision 247297
1181641Skmacy/*- 2181641Skmacy * Copyright (c) 2007 Bruce M. Simpson. 3181641Skmacy * All rights reserved. 4181641Skmacy * 5181641Skmacy * Redistribution and use in source and binary forms, with or without 6181641Skmacy * modification, are permitted provided that the following conditions 7181641Skmacy * are met: 8181641Skmacy * 1. Redistributions of source code must retain the above copyright 9181641Skmacy * notice, this list of conditions and the following disclaimer. 10181641Skmacy * 2. Redistributions in binary form must reproduce the above copyright 11181641Skmacy * notice, this list of conditions and the following disclaimer in the 12181641Skmacy * documentation and/or other materials provided with the distribution. 13181641Skmacy * 14181641Skmacy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15181641Skmacy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16181641Skmacy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17181641Skmacy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18181641Skmacy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19181641Skmacy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20181641Skmacy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21181641Skmacy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22181641Skmacy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23181641Skmacy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24181641Skmacy * SUCH DAMAGE. 25181641Skmacy */ 26181641Skmacy 27181641Skmacy#include <sys/cdefs.h> 28181641Skmacy__FBSDID("$FreeBSD: head/sys/mips/sibyte/sb_machdep.c 247297 2013-02-26 01:00:11Z attilio $"); 29181641Skmacy 30181641Skmacy#include "opt_ddb.h" 31181641Skmacy#include "opt_kdb.h" 32181641Skmacy 33181641Skmacy#include <sys/param.h> 34181641Skmacy#include <sys/conf.h> 35181641Skmacy#include <sys/kernel.h> 36181641Skmacy#include <sys/systm.h> 37181641Skmacy#include <sys/imgact.h> 38181641Skmacy#include <sys/bio.h> 39181641Skmacy#include <sys/buf.h> 40181641Skmacy#include <sys/bus.h> 41181641Skmacy#include <sys/cpu.h> 42181641Skmacy#include <sys/cons.h> 43181641Skmacy#include <sys/exec.h> 44181641Skmacy#include <sys/ucontext.h> 45181641Skmacy#include <sys/proc.h> 46181641Skmacy#include <sys/kdb.h> 47181641Skmacy#include <sys/ptrace.h> 48181641Skmacy#include <sys/reboot.h> 49181641Skmacy#include <sys/signalvar.h> 50181641Skmacy#include <sys/sysent.h> 51181641Skmacy#include <sys/sysproto.h> 52181641Skmacy#include <sys/user.h> 53181641Skmacy#include <sys/timetc.h> 54181641Skmacy 55181641Skmacy#include <vm/vm.h> 56181641Skmacy#include <vm/vm_object.h> 57181641Skmacy#include <vm/vm_page.h> 58181641Skmacy 59181641Skmacy#include <machine/cache.h> 60181641Skmacy#include <machine/clock.h> 61181641Skmacy#include <machine/cpu.h> 62181641Skmacy#include <machine/cpuinfo.h> 63181641Skmacy#include <machine/cpufunc.h> 64181641Skmacy#include <machine/cpuregs.h> 65181641Skmacy#include <machine/hwfunc.h> 66181641Skmacy#include <machine/intr_machdep.h> 67181641Skmacy#include <machine/locore.h> 68181641Skmacy#include <machine/md_var.h> 69181641Skmacy#include <machine/pte.h> 70181641Skmacy#include <machine/sigframe.h> 71181641Skmacy#include <machine/trap.h> 72181641Skmacy#include <machine/vmparam.h> 73181641Skmacy 74181641Skmacy#ifdef SMP 75181641Skmacy#include <sys/smp.h> 76181641Skmacy#include <machine/smp.h> 77181641Skmacy#endif 78181641Skmacy 79181641Skmacy#ifdef CFE 80181641Skmacy#include <dev/cfe/cfe_api.h> 81181641Skmacy#endif 82181641Skmacy 83181641Skmacy#include "sb_scd.h" 84181641Skmacy 85181641Skmacy#ifdef DDB 86181641Skmacy#ifndef KDB 87181641Skmacy#error KDB must be enabled in order for DDB to work! 88181641Skmacy#endif 89181641Skmacy#endif 90181641Skmacy 91181641Skmacy#ifdef CFE_ENV 92181641Skmacyextern void cfe_env_init(void); 93181641Skmacy#endif 94181641Skmacy 95181641Skmacyextern int *edata; 96181641Skmacyextern int *end; 97181641Skmacy 98181641Skmacyextern char MipsTLBMiss[], MipsTLBMissEnd[]; 99181641Skmacy 100181641Skmacyvoid 101181641Skmacyplatform_cpu_init() 102181641Skmacy{ 103181641Skmacy /* Nothing special */ 104181641Skmacy} 105181641Skmacy 106181641Skmacystatic void 107181641Skmacysb_intr_init(int cpuid) 108181641Skmacy{ 109181641Skmacy int intrnum, intsrc; 110181641Skmacy 111181641Skmacy /* 112181641Skmacy * Disable all sources to the interrupt mapper and setup the mapping 113181641Skmacy * between an interrupt source and the mips hard interrupt number. 114241498Salc */ 115195949Skib for (intsrc = 0; intsrc < NUM_INTSRC; ++intsrc) { 116181641Skmacy intrnum = sb_route_intsrc(intsrc); 117181641Skmacy sb_disable_intsrc(cpuid, intsrc); 118181641Skmacy sb_write_intmap(cpuid, intsrc, intrnum); 119181641Skmacy#ifdef SMP 120181641Skmacy /* 121181641Skmacy * Set up the mailbox interrupt mapping. 122228923Salc * 123228923Salc * The mailbox interrupt is "special" in that it is not shared 124181641Skmacy * with any other interrupt source. 125181641Skmacy */ 126181641Skmacy if (intsrc == INTSRC_MAILBOX3) { 127181641Skmacy intrnum = platform_ipi_intrnum(); 128181641Skmacy sb_write_intmap(cpuid, INTSRC_MAILBOX3, intrnum); 129181641Skmacy sb_enable_intsrc(cpuid, INTSRC_MAILBOX3); 130181641Skmacy } 131181641Skmacy#endif 132181641Skmacy } 133181641Skmacy} 134181641Skmacy 135181641Skmacystatic void 136181641Skmacymips_init(void) 137181641Skmacy{ 138181641Skmacy int i, j, cfe_mem_idx, tmp; 139181641Skmacy uint64_t maxmem; 140181641Skmacy 141181641Skmacy#ifdef CFE_ENV 142181641Skmacy cfe_env_init(); 143181641Skmacy#endif 144181641Skmacy 145181641Skmacy TUNABLE_INT_FETCH("boothowto", &boothowto); 146181641Skmacy 147181641Skmacy if (boothowto & RB_VERBOSE) 148181641Skmacy bootverbose++; 149181641Skmacy 150181641Skmacy#ifdef MAXMEM 151186557Skmacy tmp = MAXMEM; 152181641Skmacy#else 153181641Skmacy tmp = 0; 154181641Skmacy#endif 155181641Skmacy TUNABLE_INT_FETCH("hw.physmem", &tmp); 156181641Skmacy maxmem = (uint64_t)tmp * 1024; 157181641Skmacy 158181641Skmacy /* 159181641Skmacy * XXX 160181641Skmacy * If we used vm_paddr_t consistently in pmap, etc., we could 161181641Skmacy * use 64-bit page numbers on !n64 systems, too, like i386 162181641Skmacy * does with PAE. 163181641Skmacy */ 164208651Salc#if !defined(__mips_n64) 165181641Skmacy if (maxmem == 0 || maxmem > 0xffffffff) 166208651Salc maxmem = 0xffffffff; 167204041Sed#endif 168208651Salc 169204041Sed#ifdef CFE 170202628Sed /* 171204041Sed * Query DRAM memory map from CFE. 172181641Skmacy */ 173181641Skmacy physmem = 0; 174181641Skmacy cfe_mem_idx = 0; 175181641Skmacy for (i = 0; i < 10; i += 2) { 176181641Skmacy int result; 177181641Skmacy uint64_t addr, len, type; 178181641Skmacy 179181641Skmacy result = cfe_enummem(cfe_mem_idx++, 0, &addr, &len, &type); 180181641Skmacy if (result < 0) { 181181641Skmacy phys_avail[i] = phys_avail[i + 1] = 0; 182181641Skmacy break; 183181641Skmacy } 184181641Skmacy 185181641Skmacy KASSERT(type == CFE_MI_AVAILABLE, 186181641Skmacy ("CFE DRAM region is not available?")); 187181641Skmacy 188181641Skmacy if (bootverbose) 189181641Skmacy printf("cfe_enummem: 0x%016jx/%ju.\n", addr, len); 190181641Skmacy 191181641Skmacy if (maxmem != 0) { 192181641Skmacy if (addr >= maxmem) { 193181641Skmacy printf("Ignoring %ju bytes of memory at 0x%jx " 194181641Skmacy "that is above maxmem %dMB\n", 195181641Skmacy len, addr, 196216960Scperciva (int)(maxmem / (1024 * 1024))); 197216960Scperciva continue; 198216960Scperciva } 199216960Scperciva 200216960Scperciva if (addr + len > maxmem) { 201181641Skmacy printf("Ignoring %ju bytes of memory " 202181641Skmacy "that is above maxmem %dMB\n", 203181641Skmacy (addr + len) - maxmem, 204181641Skmacy (int)(maxmem / (1024 * 1024))); 205181641Skmacy len = maxmem - addr; 206181641Skmacy } 207181641Skmacy } 208181641Skmacy 209181641Skmacy phys_avail[i] = addr; 210181641Skmacy if (i == 0 && addr == 0) { 211182902Skmacy /* 212181641Skmacy * If this is the first physical memory segment probed 213181641Skmacy * from CFE, omit the region at the start of physical 214181641Skmacy * memory where the kernel has been loaded. 215181641Skmacy */ 216181641Skmacy phys_avail[i] += MIPS_KSEG0_TO_PHYS(kernel_kseg0_end); 217181641Skmacy } 218181641Skmacy phys_avail[i + 1] = addr + len; 219228923Salc physmem += len; 220228923Salc } 221196726Sadrian 222196726Sadrian realmem = btoc(physmem); 223181641Skmacy#endif 224241498Salc 225241498Salc for (j = 0; j < i; j++) 226241498Salc dump_avail[j] = phys_avail[j]; 227241498Salc 228241498Salc physmem = realmem; 229241498Salc 230241498Salc init_param1(); 231181641Skmacy init_param2(physmem); 232181641Skmacy mips_cpu_init(); 233236240Salc 234181641Skmacy /* 235181641Skmacy * Sibyte has a L1 data cache coherent with DMA. This includes 236181641Skmacy * on-chip network interfaces as well as PCI/HyperTransport bus 237181641Skmacy * masters. 238181641Skmacy */ 239181641Skmacy cpuinfo.cache_coherent_dma = TRUE; 240181641Skmacy 241181641Skmacy /* 242181641Skmacy * XXX 243181641Skmacy * The kernel is running in 32-bit mode but the CFE is running in 244181641Skmacy * 64-bit mode. So the SR_KX bit in the status register is turned 245181641Skmacy * on by the CFE every time we call into it - for e.g. CFE_CONSOLE. 246181641Skmacy * 247181641Skmacy * This means that if get a TLB miss for any address above 0xc0000000 248181641Skmacy * and the SR_KX bit is set then we will end up in the XTLB exception 249181641Skmacy * vector. 250181641Skmacy * 251181641Skmacy * For now work around this by copying the TLB exception handling 252267964Sjhb * code to the XTLB exception vector. 253204160Skmacy */ 254267964Sjhb { 255181641Skmacy bcopy(MipsTLBMiss, (void *)MIPS_XTLB_MISS_EXC_VEC, 256181641Skmacy MipsTLBMissEnd - MipsTLBMiss); 257181641Skmacy 258181641Skmacy mips_icache_sync_all(); 259181641Skmacy mips_dcache_wbinv_all(); 260181641Skmacy } 261181641Skmacy 262181641Skmacy pmap_bootstrap(); 263181641Skmacy mips_proc0_init(); 264181641Skmacy mutex_init(); 265181641Skmacy 266181641Skmacy kdb_init(); 267181641Skmacy#ifdef KDB 268181641Skmacy if (boothowto & RB_KDB) 269181641Skmacy kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 270181641Skmacy#endif 271181641Skmacy} 272181641Skmacy 273181641Skmacyvoid 274181641Skmacyplatform_reset(void) 275181641Skmacy{ 276181641Skmacy 277181641Skmacy /* 278181641Skmacy * XXX SMP 279181641Skmacy * XXX flush data caches 280181641Skmacy */ 281236378Salc sb_system_reset(); 282181641Skmacy} 283236291Salc 284208651Salcstatic void 285208651Salckseg0_map_coherent(void) 286208651Salc{ 287181641Skmacy uint32_t config; 288181641Skmacy const int CFG_K0_COHERENT = 5; 289181641Skmacy 290228923Salc config = mips_rd_config(); 291228923Salc config &= ~MIPS_CONFIG_K0_MASK; 292181641Skmacy config |= CFG_K0_COHERENT; 293181641Skmacy mips_wr_config(config); 294181641Skmacy} 295181641Skmacy 296181641Skmacy#ifdef SMP 297181641Skmacyvoid 298181641Skmacyplatform_ipi_send(int cpuid) 299181641Skmacy{ 300181641Skmacy KASSERT(cpuid == 0 || cpuid == 1, 301270439Skib ("platform_ipi_send: invalid cpuid %d", cpuid)); 302181641Skmacy 303270439Skib sb_set_mailbox(cpuid, 1ULL); 304240126Salc} 305181641Skmacy 306181641Skmacyvoid 307181641Skmacyplatform_ipi_clear(void) 308181641Skmacy{ 309181641Skmacy int cpuid; 310196725Sadrian 311181747Skmacy cpuid = PCPU_GET(cpuid); 312181641Skmacy sb_clear_mailbox(cpuid, 1ULL); 313181641Skmacy} 314181641Skmacy 315181641Skmacyint 316181641Skmacyplatform_ipi_intrnum(void) 317181641Skmacy{ 318181641Skmacy 319181641Skmacy return (4); 320181641Skmacy} 321181641Skmacy 322181641Skmacystruct cpu_group * 323181641Skmacyplatform_smp_topo(void) 324181641Skmacy{ 325181641Skmacy 326181641Skmacy return (smp_topo_none()); 327181641Skmacy} 328181641Skmacy 329181641Skmacyvoid 330181641Skmacyplatform_init_ap(int cpuid) 331181641Skmacy{ 332181641Skmacy int ipi_int_mask, clock_int_mask; 333181641Skmacy 334181641Skmacy KASSERT(cpuid == 1, ("AP has an invalid cpu id %d", cpuid)); 335181641Skmacy 336181641Skmacy /* 337181641Skmacy * Make sure that kseg0 is mapped cacheable-coherent 338181641Skmacy */ 339181641Skmacy kseg0_map_coherent(); 340181641Skmacy 341181641Skmacy sb_intr_init(cpuid); 342181641Skmacy 343181641Skmacy /* 344181641Skmacy * Unmask the clock and ipi interrupts. 345181641Skmacy */ 346181641Skmacy clock_int_mask = hard_int_mask(5); 347181641Skmacy ipi_int_mask = hard_int_mask(platform_ipi_intrnum()); 348181641Skmacy set_intr_mask(ipi_int_mask | clock_int_mask); 349181641Skmacy} 350181641Skmacy 351181641Skmacyint 352181641Skmacyplatform_start_ap(int cpuid) 353181641Skmacy{ 354181641Skmacy#ifdef CFE 355181641Skmacy int error; 356181641Skmacy 357181641Skmacy if ((error = cfe_cpu_start(cpuid, mpentry, 0, 0, 0))) { 358181641Skmacy printf("cfe_cpu_start error: %d\n", error); 359181641Skmacy return (-1); 360181641Skmacy } else { 361181641Skmacy return (0); 362181641Skmacy } 363181641Skmacy#else 364181641Skmacy return (-1); 365181641Skmacy#endif /* CFE */ 366181641Skmacy} 367181641Skmacy#endif /* SMP */ 368181641Skmacy 369181641Skmacystatic u_int 370181641Skmacysb_get_timecount(struct timecounter *tc) 371228923Salc{ 372228923Salc 373228923Salc return ((u_int)sb_zbbus_cycle_count()); 374228923Salc} 375228923Salc 376181641Skmacystatic void 377181641Skmacysb_timecounter_init(void) 378181641Skmacy{ 379181641Skmacy static struct timecounter sb_timecounter = { 380181641Skmacy sb_get_timecount, 381181641Skmacy NULL, 382181641Skmacy ~0u, 383181641Skmacy 0, 384181641Skmacy "sibyte_zbbus_counter", 385181641Skmacy 2000 386181641Skmacy }; 387181641Skmacy 388181641Skmacy /* 389222813Sattilio * The ZBbus cycle counter runs at half the cpu frequency. 390181641Skmacy */ 391241498Salc sb_timecounter.tc_frequency = sb_cpu_speed() / 2; 392241498Salc platform_timecounter = &sb_timecounter; 393241498Salc} 394241498Salc 395241498Salcvoid 396241498Salcplatform_start(__register_t a0, __register_t a1, __register_t a2, 397181641Skmacy __register_t a3) 398181641Skmacy{ 399181641Skmacy /* 400181641Skmacy * Make sure that kseg0 is mapped cacheable-coherent 401181641Skmacy */ 402183342Skmacy kseg0_map_coherent(); 403183342Skmacy 404181641Skmacy /* clear the BSS and SBSS segments */ 405181641Skmacy memset(&edata, 0, (vm_offset_t)&end - (vm_offset_t)&edata); 406181641Skmacy mips_postboot_fixup(); 407181641Skmacy 408181641Skmacy sb_intr_init(0); 409181641Skmacy sb_timecounter_init(); 410181641Skmacy 411181641Skmacy /* Initialize pcpu stuff */ 412181641Skmacy mips_pcpu0_init(); 413181641Skmacy 414181641Skmacy#ifdef CFE 415181641Skmacy /* 416181641Skmacy * Initialize CFE firmware trampolines before 417181641Skmacy * we initialize the low-level console. 418181641Skmacy * 419181641Skmacy * CFE passes the following values in registers: 420181641Skmacy * a0: firmware handle 421181641Skmacy * a2: firmware entry point 422181641Skmacy * a3: entry point seal 423181641Skmacy */ 424204160Skmacy if (a3 == CFE_EPTSEAL) 425204160Skmacy cfe_init(a0, a2); 426181641Skmacy#endif 427181641Skmacy cninit(); 428181641Skmacy 429181641Skmacy mips_init(); 430181641Skmacy 431181641Skmacy mips_timer_init_params(sb_cpu_speed(), 0); 432181641Skmacy} 433181641Skmacy