machdep.c revision 262717
1 /* $OpenBSD: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp $ */ 2/* tracked to 1.38 */ 3/* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department, The Mach Operating System project at 11 * Carnegie-Mellon University and Ralph Campbell. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)machdep.c 8.3 (Berkeley) 1/12/94 38 * Id: machdep.c,v 1.33 1998/09/15 10:58:54 pefo Exp 39 * JNPR: machdep.c,v 1.11.2.3 2007/08/29 12:24:49 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: stable/10/sys/mips/mips/machdep.c 262717 2014-03-03 20:28:27Z brooks $"); 44 45#include "opt_ddb.h" 46#include "opt_md.h" 47 48#include <sys/param.h> 49#include <sys/proc.h> 50#include <sys/systm.h> 51#include <sys/buf.h> 52#include <sys/bus.h> 53#include <sys/conf.h> 54#include <sys/cpu.h> 55#include <sys/kernel.h> 56#include <sys/linker.h> 57#include <sys/malloc.h> 58#include <sys/mbuf.h> 59#include <sys/msgbuf.h> 60#include <sys/reboot.h> 61#include <sys/rwlock.h> 62#include <sys/sched.h> 63#include <sys/sysctl.h> 64#include <sys/sysproto.h> 65#include <sys/vmmeter.h> 66 67#include <vm/vm.h> 68#include <vm/vm_kern.h> 69#include <vm/vm_object.h> 70#include <vm/vm_page.h> 71#include <vm/pmap.h> 72#include <vm/vm_map.h> 73#include <vm/vm_pager.h> 74#include <vm/vm_extern.h> 75#include <sys/socket.h> 76 77#include <sys/user.h> 78#include <sys/interrupt.h> 79#include <sys/cons.h> 80#include <sys/syslog.h> 81#include <machine/asm.h> 82#include <machine/bootinfo.h> 83#include <machine/cache.h> 84#include <machine/clock.h> 85#include <machine/cpu.h> 86#include <machine/cpuregs.h> 87#include <machine/elf.h> 88#include <machine/hwfunc.h> 89#include <machine/intr_machdep.h> 90#include <machine/md_var.h> 91#include <machine/tlb.h> 92#ifdef DDB 93#include <sys/kdb.h> 94#include <ddb/ddb.h> 95#endif 96 97#include <sys/random.h> 98#include <net/if.h> 99 100#define BOOTINFO_DEBUG 0 101 102char machine[] = "mips"; 103SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class"); 104 105char cpu_model[80]; 106SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "Machine model"); 107 108char cpu_board[80]; 109SYSCTL_STRING(_hw, OID_AUTO, board, CTLFLAG_RD, cpu_board, 0, "Machine board"); 110 111int cold = 1; 112long realmem = 0; 113long Maxmem = 0; 114int cpu_clock = MIPS_DEFAULT_HZ; 115SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, 116 &cpu_clock, 0, "CPU instruction clock rate"); 117int clocks_running = 0; 118 119vm_offset_t kstack0; 120 121/* 122 * Each entry in the pcpu_space[] array is laid out in the following manner: 123 * struct pcpu for cpu 'n' pcpu_space[n] 124 * boot stack for cpu 'n' pcpu_space[n] + PAGE_SIZE * 2 - CALLFRAME_SIZ 125 * 126 * Note that the boot stack grows downwards and we assume that we never 127 * use enough stack space to trample over the 'struct pcpu' that is at 128 * the beginning of the array. 129 * 130 * The array is aligned on a (PAGE_SIZE * 2) boundary so that the 'struct pcpu' 131 * is always in the even page frame of the wired TLB entry on SMP kernels. 132 * 133 * The array is in the .data section so that the stack does not get zeroed out 134 * when the .bss section is zeroed. 135 */ 136char pcpu_space[MAXCPU][PAGE_SIZE * 2] \ 137 __aligned(PAGE_SIZE * 2) __section(".data"); 138 139struct pcpu *pcpup = (struct pcpu *)pcpu_space; 140 141vm_paddr_t phys_avail[PHYS_AVAIL_ENTRIES + 2]; 142vm_paddr_t physmem_desc[PHYS_AVAIL_ENTRIES + 2]; 143vm_paddr_t dump_avail[PHYS_AVAIL_ENTRIES + 2]; 144 145#ifdef UNIMPLEMENTED 146struct platform platform; 147#endif 148 149static void cpu_startup(void *); 150SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 151 152struct kva_md_info kmi; 153 154int cpucfg; /* Value of processor config register */ 155int num_tlbentries = 64; /* Size of the CPU tlb */ 156int cputype; 157 158extern char MipsException[], MipsExceptionEnd[]; 159 160/* TLB miss handler address and end */ 161extern char MipsTLBMiss[], MipsTLBMissEnd[]; 162 163/* Cache error handler */ 164extern char MipsCache[], MipsCacheEnd[]; 165 166/* MIPS wait skip region */ 167extern char MipsWaitStart[], MipsWaitEnd[]; 168 169extern char edata[], end[]; 170#ifdef DDB 171extern vm_offset_t ksym_start, ksym_end; 172#endif 173 174u_int32_t bootdev; 175struct bootinfo bootinfo; 176/* 177 * First kseg0 address available for use. By default it's equal to &end. 178 * But in some cases there might be additional data placed right after 179 * _end by loader or ELF trampoline. 180 */ 181vm_offset_t kernel_kseg0_end = (vm_offset_t)&end; 182 183static void 184cpu_startup(void *dummy) 185{ 186 187 if (boothowto & RB_VERBOSE) 188 bootverbose++; 189 190 printf("real memory = %ju (%juK bytes)\n", ptoa((uintmax_t)realmem), 191 ptoa((uintmax_t)realmem) / 1024); 192 193 /* 194 * Display any holes after the first chunk of extended memory. 195 */ 196 if (bootverbose) { 197 int indx; 198 199 printf("Physical memory chunk(s):\n"); 200 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 201 vm_paddr_t size1 = phys_avail[indx + 1] - phys_avail[indx]; 202 203 printf("0x%08jx - 0x%08jx, %ju bytes (%ju pages)\n", 204 (uintmax_t)phys_avail[indx], 205 (uintmax_t)phys_avail[indx + 1] - 1, 206 (uintmax_t)size1, 207 (uintmax_t)size1 / PAGE_SIZE); 208 } 209 } 210 211 vm_ksubmap_init(&kmi); 212 213 printf("avail memory = %ju (%juMB)\n", 214 ptoa((uintmax_t)cnt.v_free_count), 215 ptoa((uintmax_t)cnt.v_free_count) / 1048576); 216 cpu_init_interrupts(); 217 218 /* 219 * Set up buffers, so they can be used to read disk labels. 220 */ 221 bufinit(); 222 vm_pager_bufferinit(); 223} 224 225/* 226 * Shutdown the CPU as much as possible 227 */ 228void 229cpu_reset(void) 230{ 231 232 platform_reset(); 233} 234 235/* 236 * Flush the D-cache for non-DMA I/O so that the I-cache can 237 * be made coherent later. 238 */ 239void 240cpu_flush_dcache(void *ptr, size_t len) 241{ 242 /* TBD */ 243} 244 245/* Get current clock frequency for the given cpu id. */ 246int 247cpu_est_clockrate(int cpu_id, uint64_t *rate) 248{ 249 250 return (ENXIO); 251} 252 253/* 254 * Shutdown the CPU as much as possible 255 */ 256void 257cpu_halt(void) 258{ 259 for (;;) 260 ; 261} 262 263SYSCTL_STRUCT(_machdep, OID_AUTO, bootinfo, CTLFLAG_RD, &bootinfo, 264 bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc"); 265 266/* 267 * Initialize per cpu data structures, include curthread. 268 */ 269void 270mips_pcpu0_init() 271{ 272 /* Initialize pcpu info of cpu-zero */ 273 pcpu_init(PCPU_ADDR(0), 0, sizeof(struct pcpu)); 274 PCPU_SET(curthread, &thread0); 275} 276 277/* 278 * Initialize mips and configure to run kernel 279 */ 280void 281mips_proc0_init(void) 282{ 283#ifdef SMP 284 if (platform_processor_id() != 0) 285 panic("BSP must be processor number 0"); 286#endif 287 proc_linkup0(&proc0, &thread0); 288 289 KASSERT((kstack0 & PAGE_MASK) == 0, 290 ("kstack0 is not aligned on a page boundary: 0x%0lx", 291 (long)kstack0)); 292 thread0.td_kstack = kstack0; 293 thread0.td_kstack_pages = KSTACK_PAGES; 294 /* 295 * Do not use cpu_thread_alloc to initialize these fields 296 * thread0 is the only thread that has kstack located in KSEG0 297 * while cpu_thread_alloc handles kstack allocated in KSEG2. 298 */ 299 thread0.td_pcb = (struct pcb *)(thread0.td_kstack + 300 thread0.td_kstack_pages * PAGE_SIZE) - 1; 301 thread0.td_frame = &thread0.td_pcb->pcb_regs; 302 303 /* Steal memory for the dynamic per-cpu area. */ 304 dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0); 305 306 PCPU_SET(curpcb, thread0.td_pcb); 307 /* 308 * There is no need to initialize md_upte array for thread0 as it's 309 * located in .bss section and should be explicitly zeroed during 310 * kernel initialization. 311 */ 312} 313 314void 315cpu_initclocks(void) 316{ 317 318 platform_initclocks(); 319 cpu_initclocks_bsp(); 320} 321 322struct msgbuf *msgbufp=0; 323 324/* 325 * Initialize the hardware exception vectors, and the jump table used to 326 * call locore cache and TLB management functions, based on the kind 327 * of CPU the kernel is running on. 328 */ 329void 330mips_vector_init(void) 331{ 332 /* 333 * Make sure that the Wait region logic is not been 334 * changed 335 */ 336 if (MipsWaitEnd - MipsWaitStart != 16) 337 panic("startup: MIPS wait region not correct"); 338 /* 339 * Copy down exception vector code. 340 */ 341 if (MipsTLBMissEnd - MipsTLBMiss > 0x80) 342 panic("startup: UTLB code too large"); 343 344 if (MipsCacheEnd - MipsCache > 0x80) 345 panic("startup: Cache error code too large"); 346 347 bcopy(MipsTLBMiss, (void *)MIPS_UTLB_MISS_EXC_VEC, 348 MipsTLBMissEnd - MipsTLBMiss); 349 350 /* 351 * XXXRW: Why don't we install the XTLB handler for all 64-bit 352 * architectures? 353 */ 354#if defined(__mips_n64) || defined(CPU_RMI) || defined(CPU_NLM) || defined(CPU_BERI) 355/* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses */ 356 bcopy(MipsTLBMiss, (void *)MIPS_XTLB_MISS_EXC_VEC, 357 MipsTLBMissEnd - MipsTLBMiss); 358#endif 359 360 bcopy(MipsException, (void *)MIPS_GEN_EXC_VEC, 361 MipsExceptionEnd - MipsException); 362 363 bcopy(MipsCache, (void *)MIPS_CACHE_ERR_EXC_VEC, 364 MipsCacheEnd - MipsCache); 365 366 /* 367 * Clear out the I and D caches. 368 */ 369 mips_icache_sync_all(); 370 mips_dcache_wbinv_all(); 371 372 /* 373 * Mask all interrupts. Each interrupt will be enabled 374 * when handler is installed for it 375 */ 376 set_intr_mask(0); 377 378 /* Clear BEV in SR so we start handling our own exceptions */ 379 mips_wr_status(mips_rd_status() & ~MIPS_SR_BEV); 380} 381 382/* 383 * Fix kernel_kseg0_end address in case trampoline placed debug sympols 384 * data there 385 */ 386void 387mips_postboot_fixup(void) 388{ 389 static char fake_preload[256]; 390 caddr_t preload_ptr = (caddr_t)&fake_preload[0]; 391 size_t size = 0; 392 393#define PRELOAD_PUSH_VALUE(type, value) do { \ 394 *(type *)(preload_ptr + size) = (value); \ 395 size += sizeof(type); \ 396} while (0); 397 398 /* 399 * Provide kernel module file information 400 */ 401 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_NAME); 402 PRELOAD_PUSH_VALUE(uint32_t, strlen("kernel") + 1); 403 strcpy((char*)(preload_ptr + size), "kernel"); 404 size += strlen("kernel") + 1; 405 size = roundup(size, sizeof(u_long)); 406 407 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_TYPE); 408 PRELOAD_PUSH_VALUE(uint32_t, strlen("elf kernel") + 1); 409 strcpy((char*)(preload_ptr + size), "elf kernel"); 410 size += strlen("elf kernel") + 1; 411 size = roundup(size, sizeof(u_long)); 412 413 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_ADDR); 414 PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t)); 415 PRELOAD_PUSH_VALUE(vm_offset_t, KERNLOADADDR); 416 size = roundup(size, sizeof(u_long)); 417 418 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_SIZE); 419 PRELOAD_PUSH_VALUE(uint32_t, sizeof(size_t)); 420 PRELOAD_PUSH_VALUE(size_t, (size_t)&end - KERNLOADADDR); 421 size = roundup(size, sizeof(u_long)); 422 423 /* End marker */ 424 PRELOAD_PUSH_VALUE(uint32_t, 0); 425 PRELOAD_PUSH_VALUE(uint32_t, 0); 426 427#undef PRELOAD_PUSH_VALUE 428 429 KASSERT((size < sizeof(fake_preload)), 430 ("fake preload size is more thenallocated")); 431 432 preload_metadata = (void *)fake_preload; 433 434#ifdef DDB 435 Elf_Size *trampoline_data = (Elf_Size*)kernel_kseg0_end; 436 Elf_Size symtabsize = 0; 437 438 if (trampoline_data[0] == SYMTAB_MAGIC) { 439 symtabsize = trampoline_data[1]; 440 kernel_kseg0_end += 2 * sizeof(Elf_Size); 441 /* start of .symtab */ 442 ksym_start = kernel_kseg0_end; 443 kernel_kseg0_end += symtabsize; 444 /* end of .strtab */ 445 ksym_end = kernel_kseg0_end; 446 } 447#endif 448} 449 450#ifdef SMP 451void 452mips_pcpu_tlb_init(struct pcpu *pcpu) 453{ 454 vm_paddr_t pa; 455 pt_entry_t pte; 456 457 /* 458 * Map the pcpu structure at the virtual address 'pcpup'. 459 * We use a wired tlb index to do this one-time mapping. 460 */ 461 pa = vtophys(pcpu); 462 pte = PTE_D | PTE_V | PTE_G | PTE_C_CACHE; 463 tlb_insert_wired(PCPU_TLB_ENTRY, (vm_offset_t)pcpup, 464 TLBLO_PA_TO_PFN(pa) | pte, 465 TLBLO_PA_TO_PFN(pa + PAGE_SIZE) | pte); 466} 467#endif 468 469/* 470 * Initialise a struct pcpu. 471 */ 472void 473cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size) 474{ 475 476 pcpu->pc_next_asid = 1; 477 pcpu->pc_asid_generation = 1; 478#ifdef SMP 479 if ((vm_offset_t)pcpup >= VM_MIN_KERNEL_ADDRESS && 480 (vm_offset_t)pcpup <= VM_MAX_KERNEL_ADDRESS) { 481 mips_pcpu_tlb_init(pcpu); 482 } 483#endif 484} 485 486int 487fill_dbregs(struct thread *td, struct dbreg *dbregs) 488{ 489 490 /* No debug registers on mips */ 491 return (ENOSYS); 492} 493 494int 495set_dbregs(struct thread *td, struct dbreg *dbregs) 496{ 497 498 /* No debug registers on mips */ 499 return (ENOSYS); 500} 501 502void 503spinlock_enter(void) 504{ 505 struct thread *td; 506 register_t intr; 507 508 td = curthread; 509 if (td->td_md.md_spinlock_count == 0) { 510 intr = intr_disable(); 511 td->td_md.md_spinlock_count = 1; 512 td->td_md.md_saved_intr = intr; 513 } else 514 td->td_md.md_spinlock_count++; 515 critical_enter(); 516} 517 518void 519spinlock_exit(void) 520{ 521 struct thread *td; 522 register_t intr; 523 524 td = curthread; 525 critical_exit(); 526 intr = td->td_md.md_saved_intr; 527 td->td_md.md_spinlock_count--; 528 if (td->td_md.md_spinlock_count == 0) 529 intr_restore(intr); 530} 531 532/* 533 * call platform specific code to halt (until next interrupt) for the idle loop 534 */ 535void 536cpu_idle(int busy) 537{ 538 KASSERT((mips_rd_status() & MIPS_SR_INT_IE) != 0, 539 ("interrupts disabled in idle process.")); 540 KASSERT((mips_rd_status() & MIPS_INT_MASK) != 0, 541 ("all interrupts masked in idle process.")); 542 543 if (!busy) { 544 critical_enter(); 545 cpu_idleclock(); 546 } 547 mips_wait(); 548 if (!busy) { 549 cpu_activeclock(); 550 critical_exit(); 551 } 552} 553 554int 555cpu_idle_wakeup(int cpu) 556{ 557 558 return (0); 559} 560 561int 562is_cacheable_mem(vm_paddr_t pa) 563{ 564 int i; 565 566 for (i = 0; physmem_desc[i + 1] != 0; i += 2) { 567 if (pa >= physmem_desc[i] && pa < physmem_desc[i + 1]) 568 return (1); 569 } 570 571 return (0); 572} 573