machdep.c revision 202046
1178172Simp /* $OpenBSD: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp $ */ 2178172Simp/* tracked to 1.38 */ 3178172Simp/* 4178172Simp * Copyright (c) 1988 University of Utah. 5178172Simp * Copyright (c) 1992, 1993 6178172Simp * The Regents of the University of California. All rights reserved. 7178172Simp * 8178172Simp * This code is derived from software contributed to Berkeley by 9178172Simp * the Systems Programming Group of the University of Utah Computer 10178172Simp * Science Department, The Mach Operating System project at 11178172Simp * Carnegie-Mellon University and Ralph Campbell. 12178172Simp * 13178172Simp * Redistribution and use in source and binary forms, with or without 14178172Simp * modification, are permitted provided that the following conditions 15178172Simp * are met: 16178172Simp * 1. Redistributions of source code must retain the above copyright 17178172Simp * notice, this list of conditions and the following disclaimer. 18178172Simp * 2. Redistributions in binary form must reproduce the above copyright 19178172Simp * notice, this list of conditions and the following disclaimer in the 20178172Simp * documentation and/or other materials provided with the distribution. 21178172Simp * 4. Neither the name of the University nor the names of its contributors 22178172Simp * may be used to endorse or promote products derived from this software 23178172Simp * without specific prior written permission. 24178172Simp * 25178172Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26178172Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27178172Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28178172Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29178172Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30178172Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31178172Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32178172Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33178172Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34178172Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35178172Simp * SUCH DAMAGE. 36178172Simp * 37178172Simp * from: @(#)machdep.c 8.3 (Berkeley) 1/12/94 38178172Simp * Id: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp 39187305Simp * JNPR: machdep.c,v 1.11.2.3 2007/08/29 12:24:49 40178172Simp */ 41178172Simp 42178172Simp#include <sys/cdefs.h> 43178172Simp__FBSDID("$FreeBSD: head/sys/mips/mips/machdep.c 202046 2010-01-10 20:29:20Z imp $"); 44178172Simp 45202046Simp#include "opt_cputype.h" 46183771Simp#include "opt_ddb.h" 47178172Simp#include "opt_md.h" 48183771Simp#include "opt_msgbuf.h" 49178172Simp 50178172Simp#include <sys/param.h> 51178172Simp#include <sys/proc.h> 52178172Simp#include <sys/systm.h> 53178172Simp#include <sys/buf.h> 54178172Simp#include <sys/bus.h> 55178172Simp#include <sys/conf.h> 56178172Simp#include <sys/cpu.h> 57178172Simp#include <sys/kernel.h> 58178172Simp#include <sys/linker.h> 59178172Simp#include <sys/malloc.h> 60178172Simp#include <sys/mbuf.h> 61178172Simp#include <sys/msgbuf.h> 62178172Simp#include <sys/reboot.h> 63178172Simp#include <sys/sched.h> 64178172Simp#include <sys/sysctl.h> 65178172Simp#include <sys/sysproto.h> 66178172Simp#include <sys/vmmeter.h> 67178172Simp 68178172Simp#include <vm/vm.h> 69178172Simp#include <vm/vm_kern.h> 70178172Simp#include <vm/vm_object.h> 71178172Simp#include <vm/vm_page.h> 72178172Simp#include <vm/pmap.h> 73178172Simp#include <vm/vm_map.h> 74178172Simp#include <vm/vm_pager.h> 75178172Simp#include <vm/vm_extern.h> 76178172Simp#include <sys/socket.h> 77178172Simp 78178172Simp#include <sys/user.h> 79202046Simp#include <sys/interrupt.h> 80178172Simp#include <sys/cons.h> 81178172Simp#include <sys/syslog.h> 82202046Simp#include <machine/asm.h> 83202046Simp#include <machine/bootinfo.h> 84178172Simp#include <machine/cache.h> 85202046Simp#include <machine/clock.h> 86178172Simp#include <machine/cpu.h> 87202046Simp#include <machine/hwfunc.h> 88202046Simp#include <machine/intr_machdep.h> 89178172Simp#include <machine/md_var.h> 90178172Simp#ifdef DDB 91178172Simp#include <sys/kdb.h> 92178172Simp#include <ddb/ddb.h> 93178172Simp#endif 94178172Simp 95178172Simp#include <sys/random.h> 96178172Simp#include <net/if.h> 97178172Simp 98178172Simp#define BOOTINFO_DEBUG 0 99178172Simp 100178172Simpchar machine[] = "mips"; 101178172SimpSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class"); 102178172Simp 103178172Simpstatic char cpu_model[30]; 104178172SimpSYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model"); 105178172Simp 106178172Simpint cold = 1; 107178172Simplong realmem = 0; 108202046Simplong Maxmem = 0; 109178172Simpint cpu_clock = MIPS_DEFAULT_HZ; 110178172SimpSYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 111178172Simp &cpu_clock, 0, "CPU instruction clock rate"); 112178172Simpint clocks_running = 0; 113178172Simp 114178172Simpvm_offset_t kstack0; 115178172Simp 116178172Simp#ifdef SMP 117202046Simpstruct pcpu __pcpu[MAXCPU]; 118202046Simpchar pcpu_boot_stack[KSTACK_PAGES * PAGE_SIZE * MAXCPU]; 119178172Simp#else 120178172Simpstruct pcpu pcpu; 121178172Simpstruct pcpu *pcpup = &pcpu; 122178172Simp#endif 123178172Simp 124202046Simpvm_offset_t phys_avail[PHYS_AVAIL_ENTRIES + 2]; 125202046Simpvm_offset_t physmem_desc[PHYS_AVAIL_ENTRIES + 2]; 126202046Simp 127178172Simp#ifdef UNIMPLEMENTED 128178172Simpstruct platform platform; 129178172Simp#endif 130178172Simp 131178172Simpvm_paddr_t mips_wired_tlb_physmem_start; 132178172Simpvm_paddr_t mips_wired_tlb_physmem_end; 133178172Simpu_int need_wired_tlb_page_pool; 134178172Simp 135178172Simpstatic void cpu_startup(void *); 136178172SimpSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 137178172Simp 138178172Simpstruct kva_md_info kmi; 139178172Simp 140178172Simpint cpucfg; /* Value of processor config register */ 141178172Simpint num_tlbentries = 64; /* Size of the CPU tlb */ 142178172Simpint cputype; 143178172Simp 144178172Simpextern char MipsException[], MipsExceptionEnd[]; 145178172Simp 146178172Simp/* TLB miss handler address and end */ 147178172Simpextern char MipsTLBMiss[], MipsTLBMissEnd[]; 148178172Simp 149178172Simp/* Cache error handler */ 150178172Simpextern char MipsCache[], MipsCacheEnd[]; 151178172Simp 152178172Simpextern char edata[], end[]; 153178172Simp 154178172Simpu_int32_t bootdev; 155178172Simpstruct bootinfo bootinfo; 156178172Simp 157178172Simpstatic void 158178172Simpcpu_startup(void *dummy) 159178172Simp{ 160178172Simp 161178172Simp if (boothowto & RB_VERBOSE) 162178172Simp bootverbose++; 163178172Simp 164187305Simp bootverbose++; 165187305Simp printf("real memory = %lu (%luK bytes)\n", ptoa(realmem), 166187305Simp ptoa(realmem) / 1024); 167187305Simp 168178172Simp /* 169178172Simp * Display any holes after the first chunk of extended memory. 170178172Simp */ 171178172Simp if (bootverbose) { 172178172Simp int indx; 173178172Simp 174178172Simp printf("Physical memory chunk(s):\n"); 175178172Simp for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 176202046Simp uintptr_t size1 = phys_avail[indx + 1] - phys_avail[indx]; 177178172Simp 178202046Simp printf("0x%08llx - 0x%08llx, %llu bytes (%llu pages)\n", 179202046Simp (unsigned long long)phys_avail[indx], 180202046Simp (unsigned long long)phys_avail[indx + 1] - 1, 181202046Simp (unsigned long long)size1, 182202046Simp (unsigned long long)size1 / PAGE_SIZE); 183178172Simp } 184178172Simp } 185178172Simp 186178172Simp vm_ksubmap_init(&kmi); 187178172Simp 188178172Simp printf("avail memory = %lu (%luMB)\n", ptoa(cnt.v_free_count), 189178172Simp ptoa(cnt.v_free_count) / 1048576); 190202046Simp cpu_init_interrupts(); 191178172Simp 192178172Simp /* 193178172Simp * Set up buffers, so they can be used to read disk labels. 194178172Simp */ 195178172Simp bufinit(); 196178172Simp vm_pager_bufferinit(); 197178172Simp} 198178172Simp 199178172Simp/* 200178172Simp * Shutdown the CPU as much as possible 201178172Simp */ 202178172Simpvoid 203178172Simpcpu_reset(void) 204178172Simp{ 205187294Simp 206187294Simp platform_reset(); 207178172Simp} 208178172Simp 209192323Smarcel/* 210192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 211192323Smarcel * be made coherent later. 212192323Smarcel */ 213192323Smarcelvoid 214192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 215192323Smarcel{ 216192323Smarcel /* TBD */ 217192323Smarcel} 218192323Smarcel 219178172Simp/* Get current clock frequency for the given cpu id. */ 220178172Simpint 221178172Simpcpu_est_clockrate(int cpu_id, uint64_t *rate) 222178172Simp{ 223178172Simp 224187294Simp return (ENXIO); 225178172Simp} 226178172Simp 227178172Simp/* 228178172Simp * Shutdown the CPU as much as possible 229178172Simp */ 230178172Simpvoid 231178172Simpcpu_halt(void) 232178172Simp{ 233178172Simp for (;;) 234178172Simp ; 235178172Simp} 236178172Simp 237187326SimpSYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, CTLFLAG_RD, &bootinfo, 238187326Simp bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc"); 239187326Simp 240178172Simp#ifdef PORT_TO_JMIPS 241178172Simpstatic int 242178172Simpsysctl_machdep_adjkerntz(SYSCTL_HANDLER_ARGS) 243178172Simp{ 244178172Simp} 245178172Simp 246178172SimpSYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT | CTLFLAG_RW, 247181236Strhodes &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", 248181236Strhodes "Local offset from GMT in seconds"); 249178172SimpSYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, CTLFLAG_RW, 250181236Strhodes &disable_rtc_set, 0, "Disable setting the real time clock to system time"); 251178172SimpSYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, CTLFLAG_RW, 252181236Strhodes &wall_cmos_clock, 0, "Wall CMOS clock assumed"); 253178172Simp#endif /* PORT_TO_JMIPS */ 254178172Simp 255178172Simp/* 256202046Simp * Initialize per cpu data structures, include curthread. 257178172Simp */ 258178172Simpvoid 259202046Simpmips_pcpu0_init() 260178172Simp{ 261178172Simp /* Initialize pcpu info of cpu-zero */ 262178172Simp#ifdef SMP 263178172Simp pcpu_init(&__pcpu[0], 0, sizeof(struct pcpu)); 264178172Simp#else 265178172Simp pcpu_init(pcpup, 0, sizeof(struct pcpu)); 266178172Simp#endif 267202046Simp PCPU_SET(curthread, &thread0); 268202046Simp} 269202046Simp 270202046Simp/* 271202046Simp * Initialize mips and configure to run kernel 272202046Simp */ 273202046Simpvoid 274202046Simpmips_proc0_init(void) 275202046Simp{ 276202046Simp proc_linkup0(&proc0, &thread0); 277202046Simp 278202046Simp KASSERT((kstack0 & PAGE_MASK) == 0, 279202046Simp ("kstack0 is not aligned on a page boundary: 0x%0lx", 280202046Simp (long)kstack0)); 281202046Simp thread0.td_kstack = kstack0; 282202046Simp thread0.td_kstack_pages = KSTACK_PAGES; 283202046Simp thread0.td_md.md_realstack = roundup2(thread0.td_kstack, PAGE_SIZE * 2); 284178172Simp /* 285178172Simp * Do not use cpu_thread_alloc to initialize these fields 286178172Simp * thread0 is the only thread that has kstack located in KSEG0 287178172Simp * while cpu_thread_alloc handles kstack allocated in KSEG2. 288178172Simp */ 289178172Simp thread0.td_pcb = (struct pcb *)(thread0.td_md.md_realstack + 290178172Simp (thread0.td_kstack_pages - 1) * PAGE_SIZE) - 1; 291178172Simp thread0.td_frame = &thread0.td_pcb->pcb_regs; 292187326Simp 293199114Sgonzo /* Steal memory for the dynamic per-cpu area. */ 294199114Sgonzo dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0); 295199114Sgonzo 296202046Simp PCPU_SET(curpcb, thread0.td_pcb); 297178172Simp /* 298178172Simp * There is no need to initialize md_upte array for thread0 as it's 299178172Simp * located in .bss section and should be explicitly zeroed during 300178172Simp * kernel initialization. 301178172Simp */ 302202046Simp} 303178172Simp 304202046Simpvoid 305202046Simpcpu_initclocks(void) 306202046Simp{ 307202046Simp platform_initclocks(); 308178172Simp} 309178172Simp 310178172Simpstruct msgbuf *msgbufp=0; 311178172Simp 312178172Simp/* 313178172Simp * Initialize the hardware exception vectors, and the jump table used to 314178172Simp * call locore cache and TLB management functions, based on the kind 315178172Simp * of CPU the kernel is running on. 316178172Simp */ 317178172Simpvoid 318178172Simpmips_vector_init(void) 319178172Simp{ 320178172Simp /* 321178172Simp * Copy down exception vector code. 322178172Simp */ 323178172Simp if (MipsTLBMissEnd - MipsTLBMiss > 0x80) 324178172Simp panic("startup: UTLB code too large"); 325178172Simp 326178172Simp if (MipsCacheEnd - MipsCache > 0x80) 327178172Simp panic("startup: Cache error code too large"); 328178172Simp 329178172Simp bcopy(MipsTLBMiss, (void *)TLB_MISS_EXC_VEC, 330178172Simp MipsTLBMissEnd - MipsTLBMiss); 331178172Simp 332178172Simp#ifdef TARGET_OCTEON 333178172Simp/* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses */ 334178172Simp bcopy(MipsTLBMiss, (void *)XTLB_MISS_EXC_VEC, 335178172Simp MipsTLBMissEnd - MipsTLBMiss); 336178172Simp#endif 337178172Simp 338178172Simp bcopy(MipsException, (void *)GEN_EXC_VEC, 339178172Simp MipsExceptionEnd - MipsException); 340178172Simp 341178172Simp bcopy(MipsCache, (void *)CACHE_ERR_EXC_VEC, 342178172Simp MipsCacheEnd - MipsCache); 343178172Simp 344178172Simp /* 345178172Simp * Clear out the I and D caches. 346178172Simp */ 347178172Simp mips_icache_sync_all(); 348178172Simp mips_dcache_wbinv_all(); 349178172Simp 350178172Simp /* 351178172Simp * Mask all interrupts. Each interrupt will be enabled 352178172Simp * when handler is installed for it 353178172Simp */ 354178172Simp set_intr_mask (ALL_INT_MASK); 355178172Simp /* Clear BEV in SR so we start handling our own exceptions */ 356178172Simp mips_cp0_status_write(mips_cp0_status_read() & ~SR_BOOT_EXC_VEC); 357178172Simp 358178172Simp} 359178172Simp 360178172Simp/* 361178172Simp * Initialise a struct pcpu. 362178172Simp */ 363178172Simpvoid 364178172Simpcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 365178172Simp{ 366178172Simp#ifdef SMP 367178172Simp if (cpuid != 0) 368178172Simp pcpu->pc_boot_stack = (void *)(pcpu_boot_stack + cpuid * 369178172Simp (KSTACK_PAGES * PAGE_SIZE)); 370178172Simp#endif 371178172Simp pcpu->pc_next_asid = 1; 372178172Simp pcpu->pc_asid_generation = 1; 373178172Simp} 374178172Simp 375178172Simpint 376178172Simpfill_dbregs(struct thread *td, struct dbreg *dbregs) 377178172Simp{ 378178172Simp 379178172Simp /* No debug registers on mips */ 380178172Simp return (ENOSYS); 381178172Simp} 382178172Simp 383178172Simpint 384178172Simpset_dbregs(struct thread *td, struct dbreg *dbregs) 385178172Simp{ 386178172Simp 387178172Simp /* No debug registers on mips */ 388178172Simp return (ENOSYS); 389178172Simp} 390178172Simp 391178172Simpvoid 392178172Simpspinlock_enter(void) 393178172Simp{ 394178172Simp struct thread *td; 395178172Simp 396178172Simp td = curthread; 397178172Simp if (td->td_md.md_spinlock_count == 0) 398178172Simp td->td_md.md_saved_intr = disableintr(); 399178172Simp td->td_md.md_spinlock_count++; 400178172Simp critical_enter(); 401178172Simp} 402178172Simp 403178172Simpvoid 404178172Simpspinlock_exit(void) 405178172Simp{ 406178172Simp struct thread *td; 407178172Simp 408178172Simp td = curthread; 409178172Simp critical_exit(); 410178172Simp td->td_md.md_spinlock_count--; 411178172Simp if (td->td_md.md_spinlock_count == 0) 412178172Simp restoreintr(td->td_md.md_saved_intr); 413178172Simp} 414178172Simp 415178172Simpu_int32_t 416178172Simpget_cyclecount(void) 417178172Simp{ 418178172Simp u_int32_t count; 419178172Simp 420178172Simp mfc0_macro(count, 9); 421178172Simp return (count); 422178172Simp} 423178172Simp 424178172Simp/* 425178172Simp * call platform specific code to halt (until next interrupt) for the idle loop 426178172Simp */ 427178172Simpvoid 428178471Sjeffcpu_idle(int busy) 429178172Simp{ 430178172Simp if (mips_cp0_status_read() & SR_INT_ENAB) 431178172Simp __asm __volatile ("wait"); 432178172Simp else 433178172Simp panic("ints disabled in idleproc!"); 434178172Simp} 435178172Simp 436187293Simpvoid 437187293Simpdumpsys(struct dumperinfo *di __unused) 438178471Sjeff{ 439178471Sjeff 440187293Simp printf("Kernel dumps not implemented on this architecture\n"); 441178471Sjeff} 442178471Sjeff 443187293Simpint 444187293Simpcpu_idle_wakeup(int cpu) 445178172Simp{ 446178172Simp 447187293Simp return (0); 448178172Simp} 449202046Simp 450202046Simpint 451202046Simpis_physical_memory(vm_offset_t addr) 452202046Simp{ 453202046Simp int i; 454202046Simp 455202046Simp for (i = 0; physmem_desc[i + 1] != 0; i += 2) { 456202046Simp if (addr >= physmem_desc[i] && addr < physmem_desc[i + 1]) 457202046Simp return (1); 458202046Simp } 459202046Simp 460202046Simp return (0); 461202046Simp} 462