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$"); 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 171u_int32_t bootdev; 172struct bootinfo bootinfo; 173/* 174 * First kseg0 address available for use. By default it's equal to &end. 175 * But in some cases there might be additional data placed right after 176 * _end by loader or ELF trampoline. 177 */ 178vm_offset_t kernel_kseg0_end = (vm_offset_t)&end; 179 180static void 181cpu_startup(void *dummy) 182{ 183 184 if (boothowto & RB_VERBOSE) 185 bootverbose++; 186 187 printf("real memory = %ju (%juK bytes)\n", ptoa((uintmax_t)realmem), 188 ptoa((uintmax_t)realmem) / 1024); 189 190 /* 191 * Display any holes after the first chunk of extended memory. 192 */ 193 if (bootverbose) { 194 int indx; 195 196 printf("Physical memory chunk(s):\n"); 197 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 198 vm_paddr_t size1 = phys_avail[indx + 1] - phys_avail[indx]; 199 200 printf("0x%08jx - 0x%08jx, %ju bytes (%ju pages)\n", 201 (uintmax_t)phys_avail[indx], 202 (uintmax_t)phys_avail[indx + 1] - 1, 203 (uintmax_t)size1, 204 (uintmax_t)size1 / PAGE_SIZE); 205 } 206 } 207 208 vm_ksubmap_init(&kmi); 209 210 printf("avail memory = %ju (%juMB)\n", 211 ptoa((uintmax_t)vm_cnt.v_free_count), 212 ptoa((uintmax_t)vm_cnt.v_free_count) / 1048576); 213 cpu_init_interrupts(); 214 215 /* 216 * Set up buffers, so they can be used to read disk labels. 217 */ 218 bufinit(); 219 vm_pager_bufferinit(); 220} 221 222/* 223 * Shutdown the CPU as much as possible 224 */ 225void 226cpu_reset(void) 227{ 228 229 platform_reset(); 230} 231 232/* 233 * Flush the D-cache for non-DMA I/O so that the I-cache can 234 * be made coherent later. 235 */ 236void 237cpu_flush_dcache(void *ptr, size_t len) 238{ 239 /* TBD */ 240} 241 242/* Get current clock frequency for the given cpu id. */ 243int 244cpu_est_clockrate(int cpu_id, uint64_t *rate) 245{ 246 247 return (ENXIO); 248} 249 250/* 251 * Shutdown the CPU as much as possible 252 */ 253void 254cpu_halt(void) 255{ 256 for (;;) 257 ; 258} 259 260SYSCTL_STRUCT(_machdep, OID_AUTO, bootinfo, CTLFLAG_RD, &bootinfo, 261 bootinfo, "Bootinfo struct: kernel filename, BIOS harddisk geometry, etc"); 262 263/* 264 * Initialize per cpu data structures, include curthread. 265 */ 266void 267mips_pcpu0_init() 268{ 269 /* Initialize pcpu info of cpu-zero */ 270 pcpu_init(PCPU_ADDR(0), 0, sizeof(struct pcpu)); 271 PCPU_SET(curthread, &thread0); 272} 273 274/* 275 * Initialize mips and configure to run kernel 276 */ 277void 278mips_proc0_init(void) 279{ 280#ifdef SMP 281 if (platform_processor_id() != 0) 282 panic("BSP must be processor number 0"); 283#endif 284 proc_linkup0(&proc0, &thread0); 285 286 KASSERT((kstack0 & PAGE_MASK) == 0, 287 ("kstack0 is not aligned on a page boundary: 0x%0lx", 288 (long)kstack0)); 289 thread0.td_kstack = kstack0; 290 thread0.td_kstack_pages = KSTACK_PAGES; 291 /* 292 * Do not use cpu_thread_alloc to initialize these fields 293 * thread0 is the only thread that has kstack located in KSEG0 294 * while cpu_thread_alloc handles kstack allocated in KSEG2. 295 */ 296 thread0.td_pcb = (struct pcb *)(thread0.td_kstack + 297 thread0.td_kstack_pages * PAGE_SIZE) - 1; 298 thread0.td_frame = &thread0.td_pcb->pcb_regs; 299 300 /* Steal memory for the dynamic per-cpu area. */ 301 dpcpu_init((void *)pmap_steal_memory(DPCPU_SIZE), 0); 302 303 PCPU_SET(curpcb, thread0.td_pcb); 304 /* 305 * There is no need to initialize md_upte array for thread0 as it's 306 * located in .bss section and should be explicitly zeroed during 307 * kernel initialization. 308 */ 309} 310 311void 312cpu_initclocks(void) 313{ 314 315 platform_initclocks(); 316 cpu_initclocks_bsp(); 317} 318 319struct msgbuf *msgbufp = NULL; 320 321/* 322 * Initialize the hardware exception vectors, and the jump table used to 323 * call locore cache and TLB management functions, based on the kind 324 * of CPU the kernel is running on. 325 */ 326void 327mips_vector_init(void) 328{ 329 /* 330 * Make sure that the Wait region logic is not been 331 * changed 332 */ 333 if (MipsWaitEnd - MipsWaitStart != 16) 334 panic("startup: MIPS wait region not correct"); 335 /* 336 * Copy down exception vector code. 337 */ 338 if (MipsTLBMissEnd - MipsTLBMiss > 0x80) 339 panic("startup: UTLB code too large"); 340 341 if (MipsCacheEnd - MipsCache > 0x80) 342 panic("startup: Cache error code too large"); 343 344 bcopy(MipsTLBMiss, (void *)MIPS_UTLB_MISS_EXC_VEC, 345 MipsTLBMissEnd - MipsTLBMiss); 346 347 /* 348 * XXXRW: Why don't we install the XTLB handler for all 64-bit 349 * architectures? 350 */ 351#if defined(__mips_n64) || defined(CPU_RMI) || defined(CPU_NLM) || defined(CPU_BERI) 352/* Fake, but sufficient, for the 32-bit with 64-bit hardware addresses */ 353 bcopy(MipsTLBMiss, (void *)MIPS_XTLB_MISS_EXC_VEC, 354 MipsTLBMissEnd - MipsTLBMiss); 355#endif 356 357 bcopy(MipsException, (void *)MIPS_GEN_EXC_VEC, 358 MipsExceptionEnd - MipsException); 359 360 bcopy(MipsCache, (void *)MIPS_CACHE_ERR_EXC_VEC, 361 MipsCacheEnd - MipsCache); 362 363 /* 364 * Clear out the I and D caches. 365 */ 366 mips_icache_sync_all(); 367 mips_dcache_wbinv_all(); 368 369 /* 370 * Mask all interrupts. Each interrupt will be enabled 371 * when handler is installed for it 372 */ 373 set_intr_mask(0); 374 375 /* Clear BEV in SR so we start handling our own exceptions */ 376 mips_wr_status(mips_rd_status() & ~MIPS_SR_BEV); 377} 378 379/* 380 * Fix kernel_kseg0_end address in case trampoline placed debug sympols 381 * data there 382 */ 383void 384mips_postboot_fixup(void) 385{ 386 static char fake_preload[256]; 387 caddr_t preload_ptr = (caddr_t)&fake_preload[0]; 388 size_t size = 0; 389 390#define PRELOAD_PUSH_VALUE(type, value) do { \ 391 *(type *)(preload_ptr + size) = (value); \ 392 size += sizeof(type); \ 393} while (0); 394 395 /* 396 * Provide kernel module file information 397 */ 398 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_NAME); 399 PRELOAD_PUSH_VALUE(uint32_t, strlen("kernel") + 1); 400 strcpy((char*)(preload_ptr + size), "kernel"); 401 size += strlen("kernel") + 1; 402 size = roundup(size, sizeof(u_long)); 403 404 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_TYPE); 405 PRELOAD_PUSH_VALUE(uint32_t, strlen("elf kernel") + 1); 406 strcpy((char*)(preload_ptr + size), "elf kernel"); 407 size += strlen("elf kernel") + 1; 408 size = roundup(size, sizeof(u_long)); 409 410 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_ADDR); 411 PRELOAD_PUSH_VALUE(uint32_t, sizeof(vm_offset_t)); 412 PRELOAD_PUSH_VALUE(vm_offset_t, KERNLOADADDR); 413 size = roundup(size, sizeof(u_long)); 414 415 PRELOAD_PUSH_VALUE(uint32_t, MODINFO_SIZE); 416 PRELOAD_PUSH_VALUE(uint32_t, sizeof(size_t)); 417 PRELOAD_PUSH_VALUE(size_t, (size_t)&end - KERNLOADADDR); 418 size = roundup(size, sizeof(u_long)); 419 420 /* End marker */ 421 PRELOAD_PUSH_VALUE(uint32_t, 0); 422 PRELOAD_PUSH_VALUE(uint32_t, 0); 423 424#undef PRELOAD_PUSH_VALUE 425 426 KASSERT((size < sizeof(fake_preload)), 427 ("fake preload size is more thenallocated")); 428 429 preload_metadata = (void *)fake_preload; 430 431#ifdef DDB 432 Elf_Size *trampoline_data = (Elf_Size*)kernel_kseg0_end; 433 Elf_Size symtabsize = 0; 434 vm_offset_t ksym_start; 435 vm_offset_t ksym_end; 436 437 if (trampoline_data[0] == SYMTAB_MAGIC) { 438 symtabsize = trampoline_data[1]; 439 kernel_kseg0_end += 2 * sizeof(Elf_Size); 440 /* start of .symtab */ 441 ksym_start = kernel_kseg0_end; 442 kernel_kseg0_end += symtabsize; 443 /* end of .strtab */ 444 ksym_end = kernel_kseg0_end; 445 db_fetch_ksymtab(ksym_start, ksym_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