machdep.c revision 265996
1285242Sachim/*- 2285242Sachim * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3285242Sachim * Copyright (C) 1995, 1996 TooLs GmbH. 4285242Sachim * All rights reserved. 5285242Sachim * 6285242Sachim * Redistribution and use in source and binary forms, with or without 7285242Sachim * modification, are permitted provided that the following conditions 8285242Sachim * are met: 9285242Sachim * 1. Redistributions of source code must retain the above copyright 10285242Sachim * notice, this list of conditions and the following disclaimer. 11285242Sachim * 2. Redistributions in binary form must reproduce the above copyright 12285242Sachim * notice, this list of conditions and the following disclaimer in the 13285242Sachim * documentation and/or other materials provided with the distribution. 14285242Sachim * 3. All advertising materials mentioning features or use of this software 15285242Sachim * must display the following acknowledgement: 16285242Sachim * This product includes software developed by TooLs GmbH. 17285242Sachim * 4. The name of TooLs GmbH may not be used to endorse or promote products 18285242Sachim * derived from this software without specific prior written permission. 19285242Sachim * 20285242Sachim * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21285242Sachim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22285242Sachim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23285242Sachim * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24285242Sachim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25285242Sachim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26285242Sachim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27285242Sachim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28285242Sachim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29285242Sachim * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30285242Sachim */ 31285242Sachim/*- 32285242Sachim * Copyright (C) 2001 Benno Rice 33285242Sachim * All rights reserved. 34285242Sachim * 35285242Sachim * Redistribution and use in source and binary forms, with or without 36285242Sachim * modification, are permitted provided that the following conditions 37285242Sachim * are met: 38285242Sachim * 1. Redistributions of source code must retain the above copyright 39285242Sachim * notice, this list of conditions and the following disclaimer. 40285242Sachim * 2. Redistributions in binary form must reproduce the above copyright 41285242Sachim * notice, this list of conditions and the following disclaimer in the 42285242Sachim * documentation and/or other materials provided with the distribution. 43285242Sachim * 44285242Sachim * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 45285242Sachim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46285242Sachim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47285242Sachim * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48285242Sachim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 49285242Sachim * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 50285242Sachim * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51285242Sachim * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 52285242Sachim * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 53285242Sachim * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54285242Sachim * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 55285242Sachim */ 56285242Sachim 57285242Sachim#include <sys/cdefs.h> 58285242Sachim__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/machdep.c 265996 2014-05-14 00:51:26Z ian $"); 59285242Sachim 60285242Sachim#include "opt_compat.h" 61285242Sachim#include "opt_ddb.h" 62285242Sachim#include "opt_kstack_pages.h" 63285242Sachim#include "opt_platform.h" 64285242Sachim 65285242Sachim#include <sys/param.h> 66285242Sachim#include <sys/proc.h> 67285242Sachim#include <sys/systm.h> 68285242Sachim#include <sys/bio.h> 69285242Sachim#include <sys/buf.h> 70285242Sachim#include <sys/bus.h> 71285242Sachim#include <sys/cons.h> 72285242Sachim#include <sys/cpu.h> 73285242Sachim#include <sys/eventhandler.h> 74285242Sachim#include <sys/exec.h> 75285242Sachim#include <sys/imgact.h> 76285242Sachim#include <sys/kdb.h> 77285242Sachim#include <sys/kernel.h> 78285242Sachim#include <sys/ktr.h> 79285242Sachim#include <sys/linker.h> 80285242Sachim#include <sys/lock.h> 81285242Sachim#include <sys/malloc.h> 82285242Sachim#include <sys/mbuf.h> 83285242Sachim#include <sys/msgbuf.h> 84285242Sachim#include <sys/mutex.h> 85285242Sachim#include <sys/ptrace.h> 86285242Sachim#include <sys/reboot.h> 87285242Sachim#include <sys/rwlock.h> 88285242Sachim#include <sys/signalvar.h> 89285242Sachim#include <sys/syscallsubr.h> 90285242Sachim#include <sys/sysctl.h> 91285242Sachim#include <sys/sysent.h> 92285242Sachim#include <sys/sysproto.h> 93285242Sachim#include <sys/ucontext.h> 94285242Sachim#include <sys/uio.h> 95285242Sachim#include <sys/vmmeter.h> 96285242Sachim#include <sys/vnode.h> 97285242Sachim 98285242Sachim#include <net/netisr.h> 99285242Sachim 100285242Sachim#include <vm/vm.h> 101285242Sachim#include <vm/vm_extern.h> 102285242Sachim#include <vm/vm_kern.h> 103285242Sachim#include <vm/vm_page.h> 104285242Sachim#include <vm/vm_map.h> 105285242Sachim#include <vm/vm_object.h> 106285242Sachim#include <vm/vm_pager.h> 107285242Sachim 108285242Sachim#include <machine/altivec.h> 109285242Sachim#ifndef __powerpc64__ 110285242Sachim#include <machine/bat.h> 111285242Sachim#endif 112285242Sachim#include <machine/cpu.h> 113285242Sachim#include <machine/elf.h> 114285242Sachim#include <machine/fpu.h> 115285242Sachim#include <machine/hid.h> 116285242Sachim#include <machine/kdb.h> 117285242Sachim#include <machine/md_var.h> 118285242Sachim#include <machine/metadata.h> 119285242Sachim#include <machine/mmuvar.h> 120285242Sachim#include <machine/pcb.h> 121285242Sachim#include <machine/reg.h> 122285242Sachim#include <machine/sigframe.h> 123285242Sachim#include <machine/spr.h> 124285242Sachim#include <machine/trap.h> 125285242Sachim#include <machine/vmparam.h> 126285242Sachim#include <machine/ofw_machdep.h> 127285242Sachim 128285242Sachim#include <ddb/ddb.h> 129285242Sachim 130285242Sachim#include <dev/ofw/openfirm.h> 131285242Sachim 132285242Sachim#ifdef DDB 133285242Sachimextern vm_offset_t ksym_start, ksym_end; 134285242Sachim#endif 135285242Sachim 136285242Sachimint cold = 1; 137285242Sachim#ifdef __powerpc64__ 138285242Sachimextern int n_slbs; 139285242Sachimint cacheline_size = 128; 140285242Sachim#else 141285242Sachimint cacheline_size = 32; 142285242Sachim#endif 143285242Sachimint hw_direct_map = 1; 144285242Sachim 145285242Sachimextern void *ap_pcpu; 146285242Sachim 147285242Sachimstruct pcpu __pcpu[MAXCPU]; 148285242Sachim 149285242Sachimstatic struct trapframe frame0; 150285242Sachim 151285242Sachimchar machine[] = "powerpc"; 152285242SachimSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 153285242Sachim 154285242Sachimstatic void cpu_startup(void *); 155285242SachimSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL); 156285242Sachim 157285242SachimSYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, 158285242Sachim CTLFLAG_RD, &cacheline_size, 0, ""); 159285242Sachim 160285242Sachimuintptr_t powerpc_init(vm_offset_t, vm_offset_t, vm_offset_t, void *); 161285242Sachim 162285242Sachimint setfault(faultbuf); /* defined in locore.S */ 163285242Sachim 164285242Sachimlong Maxmem = 0; 165285242Sachimlong realmem = 0; 166285242Sachim 167285242Sachim#ifndef __powerpc64__ 168285242Sachimstruct bat battable[16]; 169285242Sachim#endif 170285242Sachim 171285242Sachimstruct kva_md_info kmi; 172285242Sachim 173285242Sachimstatic void 174285242Sachimcpu_startup(void *dummy) 175285242Sachim{ 176285242Sachim 177285242Sachim /* 178285242Sachim * Initialise the decrementer-based clock. 179285242Sachim */ 180285242Sachim decr_init(); 181285242Sachim 182285242Sachim /* 183285242Sachim * Good {morning,afternoon,evening,night}. 184285242Sachim */ 185285242Sachim cpu_setup(PCPU_GET(cpuid)); 186285242Sachim 187285242Sachim#ifdef PERFMON 188285242Sachim perfmon_init(); 189285242Sachim#endif 190285242Sachim printf("real memory = %ld (%ld MB)\n", ptoa(physmem), 191285242Sachim ptoa(physmem) / 1048576); 192285242Sachim realmem = physmem; 193285242Sachim 194285242Sachim if (bootverbose) 195285242Sachim printf("available KVA = %zd (%zd MB)\n", 196285242Sachim virtual_end - virtual_avail, 197285242Sachim (virtual_end - virtual_avail) / 1048576); 198285242Sachim 199285242Sachim /* 200285242Sachim * Display any holes after the first chunk of extended memory. 201285242Sachim */ 202285242Sachim if (bootverbose) { 203285242Sachim int indx; 204285242Sachim 205285242Sachim printf("Physical memory chunk(s):\n"); 206285242Sachim for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 207285242Sachim vm_offset_t size1 = 208285242Sachim phys_avail[indx + 1] - phys_avail[indx]; 209285242Sachim 210285242Sachim #ifdef __powerpc64__ 211285242Sachim printf("0x%016lx - 0x%016lx, %ld bytes (%ld pages)\n", 212285242Sachim #else 213285242Sachim printf("0x%08x - 0x%08x, %d bytes (%ld pages)\n", 214285242Sachim #endif 215285242Sachim phys_avail[indx], phys_avail[indx + 1] - 1, size1, 216285242Sachim size1 / PAGE_SIZE); 217285242Sachim } 218285242Sachim } 219285242Sachim 220285242Sachim vm_ksubmap_init(&kmi); 221285242Sachim 222285242Sachim printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count), 223285242Sachim ptoa(cnt.v_free_count) / 1048576); 224285242Sachim 225285242Sachim /* 226285242Sachim * Set up buffers, so they can be used to read disk labels. 227285242Sachim */ 228285242Sachim bufinit(); 229285242Sachim vm_pager_bufferinit(); 230285242Sachim} 231285242Sachim 232285242Sachimextern char kernel_text[], _end[]; 233285242Sachim 234285242Sachim#ifndef __powerpc64__ 235285242Sachim/* Bits for running on 64-bit systems in 32-bit mode. */ 236285242Sachimextern void *testppc64, *testppc64size; 237285242Sachimextern void *restorebridge, *restorebridgesize; 238285242Sachimextern void *rfid_patch, *rfi_patch1, *rfi_patch2; 239285242Sachimextern void *trapcode64; 240285242Sachim#endif 241285242Sachim 242285242Sachimextern void *rstcode, *rstsize; 243285242Sachimextern void *trapcode, *trapsize; 244285242Sachimextern void *slbtrap, *slbtrapsize; 245285242Sachimextern void *alitrap, *alisize; 246285242Sachimextern void *dsitrap, *dsisize; 247285242Sachimextern void *decrint, *decrsize; 248285242Sachimextern void *extint, *extsize; 249285242Sachimextern void *dblow, *dbsize; 250285242Sachimextern void *imisstrap, *imisssize; 251285242Sachimextern void *dlmisstrap, *dlmisssize; 252285242Sachimextern void *dsmisstrap, *dsmisssize; 253285242Sachimchar save_trap_init[0x2f00]; /* EXC_LAST */ 254285242Sachim 255285242Sachimuintptr_t 256285242Sachimpowerpc_init(vm_offset_t startkernel, vm_offset_t endkernel, 257285242Sachim vm_offset_t basekernel, void *mdp) 258285242Sachim{ 259285242Sachim struct pcpu *pc; 260285242Sachim void *generictrap; 261285242Sachim size_t trap_offset; 262285242Sachim void *kmdp; 263285242Sachim char *env; 264285242Sachim register_t msr, scratch; 265285242Sachim#ifdef WII 266285242Sachim register_t vers; 267285242Sachim#endif 268285242Sachim uint8_t *cache_check; 269285242Sachim int cacheline_warn; 270285242Sachim #ifndef __powerpc64__ 271285242Sachim int ppc64; 272285242Sachim #endif 273285242Sachim 274285242Sachim kmdp = NULL; 275285242Sachim trap_offset = 0; 276285242Sachim cacheline_warn = 0; 277285242Sachim 278285242Sachim /* Save trap vectors. */ 279285242Sachim ofw_save_trap_vec(save_trap_init); 280285242Sachim 281285242Sachim#ifdef WII 282285242Sachim /* 283285242Sachim * The Wii loader doesn't pass us any environment so, mdp 284285242Sachim * points to garbage at this point. The Wii CPU is a 750CL. 285285242Sachim */ 286285242Sachim vers = mfpvr(); 287285242Sachim if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL)) 288285242Sachim mdp = NULL; 289285242Sachim#endif 290285242Sachim 291285242Sachim /* 292285242Sachim * Parse metadata if present and fetch parameters. Must be done 293285242Sachim * before console is inited so cninit gets the right value of 294285242Sachim * boothowto. 295285242Sachim */ 296285242Sachim if (mdp != NULL) { 297285242Sachim preload_metadata = mdp; 298285242Sachim kmdp = preload_search_by_type("elf kernel"); 299285242Sachim if (kmdp != NULL) { 300285242Sachim boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 301285242Sachim kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 302285242Sachim endkernel = ulmax(endkernel, MD_FETCH(kmdp, 303285242Sachim MODINFOMD_KERNEND, vm_offset_t)); 304285242Sachim#ifdef DDB 305285242Sachim ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); 306285242Sachim ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); 307285242Sachim#endif 308285242Sachim } 309285242Sachim } 310285242Sachim 311285242Sachim /* 312285242Sachim * Init params/tunables that can be overridden by the loader 313285242Sachim */ 314285242Sachim init_param1(); 315285242Sachim 316285242Sachim /* 317285242Sachim * Start initializing proc0 and thread0. 318285242Sachim */ 319285242Sachim proc_linkup0(&proc0, &thread0); 320285242Sachim thread0.td_frame = &frame0; 321285242Sachim 322285242Sachim /* 323285242Sachim * Set up per-cpu data. 324285242Sachim */ 325285242Sachim pc = __pcpu; 326285242Sachim pcpu_init(pc, 0, sizeof(struct pcpu)); 327285242Sachim pc->pc_curthread = &thread0; 328285242Sachim#ifdef __powerpc64__ 329285242Sachim __asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread)); 330285242Sachim#else 331285242Sachim __asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread)); 332285242Sachim#endif 333285242Sachim pc->pc_cpuid = 0; 334285242Sachim 335285242Sachim __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 336285242Sachim 337285242Sachim /* 338285242Sachim * Init mutexes, which we use heavily in PMAP 339285242Sachim */ 340285242Sachim 341285242Sachim mutex_init(); 342285242Sachim 343285242Sachim /* 344285242Sachim * Install the OF client interface 345285242Sachim */ 346285242Sachim 347285242Sachim OF_bootstrap(); 348285242Sachim 349285242Sachim /* 350285242Sachim * Initialize the console before printing anything. 351285242Sachim */ 352285242Sachim cninit(); 353285242Sachim 354285242Sachim /* 355285242Sachim * Complain if there is no metadata. 356285242Sachim */ 357285242Sachim if (mdp == NULL || kmdp == NULL) { 358285242Sachim printf("powerpc_init: no loader metadata.\n"); 359285242Sachim } 360285242Sachim 361285242Sachim /* 362285242Sachim * Init KDB 363285242Sachim */ 364285242Sachim 365285242Sachim kdb_init(); 366285242Sachim 367285242Sachim /* Various very early CPU fix ups */ 368285242Sachim switch (mfpvr() >> 16) { 369285242Sachim /* 370285242Sachim * PowerPC 970 CPUs have a misfeature requested by Apple that 371285242Sachim * makes them pretend they have a 32-byte cacheline. Turn this 372285242Sachim * off before we measure the cacheline size. 373285242Sachim */ 374285242Sachim case IBM970: 375285242Sachim case IBM970FX: 376285242Sachim case IBM970MP: 377285242Sachim case IBM970GX: 378285242Sachim scratch = mfspr(SPR_HID5); 379285242Sachim scratch &= ~HID5_970_DCBZ_SIZE_HI; 380285242Sachim mtspr(SPR_HID5, scratch); 381285242Sachim break; 382285242Sachim #ifdef __powerpc64__ 383285242Sachim case IBMPOWER7: 384285242Sachim /* XXX: get from ibm,slb-size in device tree */ 385285242Sachim n_slbs = 32; 386285242Sachim break; 387285242Sachim #endif 388285242Sachim } 389285242Sachim 390285242Sachim /* 391285242Sachim * Initialize the interrupt tables and figure out our cache line 392285242Sachim * size and whether or not we need the 64-bit bridge code. 393285242Sachim */ 394285242Sachim 395285242Sachim /* 396285242Sachim * Disable translation in case the vector area hasn't been 397285242Sachim * mapped (G5). Note that no OFW calls can be made until 398285242Sachim * translation is re-enabled. 399285242Sachim */ 400285242Sachim 401285242Sachim msr = mfmsr(); 402285242Sachim mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI); 403285242Sachim 404285242Sachim /* 405285242Sachim * Measure the cacheline size using dcbz 406285242Sachim * 407285242Sachim * Use EXC_PGM as a playground. We are about to overwrite it 408285242Sachim * anyway, we know it exists, and we know it is cache-aligned. 409285242Sachim */ 410285242Sachim 411285242Sachim cache_check = (void *)EXC_PGM; 412285242Sachim 413285242Sachim for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++) 414285242Sachim cache_check[cacheline_size] = 0xff; 415285242Sachim 416285242Sachim __asm __volatile("dcbz 0,%0":: "r" (cache_check) : "memory"); 417285242Sachim 418285242Sachim /* Find the first byte dcbz did not zero to get the cache line size */ 419285242Sachim for (cacheline_size = 0; cacheline_size < 0x100 && 420285242Sachim cache_check[cacheline_size] == 0; cacheline_size++); 421285242Sachim 422285242Sachim /* Work around psim bug */ 423285242Sachim if (cacheline_size == 0) { 424285242Sachim cacheline_warn = 1; 425285242Sachim cacheline_size = 32; 426285242Sachim } 427285242Sachim 428285242Sachim /* Make sure the kernel icache is valid before we go too much further */ 429285242Sachim __syncicache((caddr_t)startkernel, endkernel - startkernel); 430285242Sachim 431285242Sachim #ifndef __powerpc64__ 432285242Sachim /* 433285242Sachim * Figure out whether we need to use the 64 bit PMAP. This works by 434285242Sachim * executing an instruction that is only legal on 64-bit PPC (mtmsrd), 435285242Sachim * and setting ppc64 = 0 if that causes a trap. 436285242Sachim */ 437285242Sachim 438285242Sachim ppc64 = 1; 439285242Sachim 440285242Sachim bcopy(&testppc64, (void *)EXC_PGM, (size_t)&testppc64size); 441285242Sachim __syncicache((void *)EXC_PGM, (size_t)&testppc64size); 442285242Sachim 443285242Sachim __asm __volatile("\ 444285242Sachim mfmsr %0; \ 445285242Sachim mtsprg2 %1; \ 446285242Sachim \ 447285242Sachim mtmsrd %0; \ 448285242Sachim mfsprg2 %1;" 449285242Sachim : "=r"(scratch), "=r"(ppc64)); 450285242Sachim 451285242Sachim if (ppc64) 452285242Sachim cpu_features |= PPC_FEATURE_64; 453285242Sachim 454285242Sachim /* 455285242Sachim * Now copy restorebridge into all the handlers, if necessary, 456285242Sachim * and set up the trap tables. 457285242Sachim */ 458285242Sachim 459285242Sachim if (cpu_features & PPC_FEATURE_64) { 460285242Sachim /* Patch the two instances of rfi -> rfid */ 461285242Sachim bcopy(&rfid_patch,&rfi_patch1,4); 462285242Sachim #ifdef KDB 463285242Sachim /* rfi_patch2 is at the end of dbleave */ 464285242Sachim bcopy(&rfid_patch,&rfi_patch2,4); 465285242Sachim #endif 466285242Sachim 467285242Sachim /* 468285242Sachim * Copy a code snippet to restore 32-bit bridge mode 469285242Sachim * to the top of every non-generic trap handler 470285242Sachim */ 471285242Sachim 472285242Sachim trap_offset += (size_t)&restorebridgesize; 473285242Sachim bcopy(&restorebridge, (void *)EXC_RST, trap_offset); 474285242Sachim bcopy(&restorebridge, (void *)EXC_DSI, trap_offset); 475285242Sachim bcopy(&restorebridge, (void *)EXC_ALI, trap_offset); 476285242Sachim bcopy(&restorebridge, (void *)EXC_PGM, trap_offset); 477285242Sachim bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset); 478285242Sachim bcopy(&restorebridge, (void *)EXC_TRC, trap_offset); 479285242Sachim bcopy(&restorebridge, (void *)EXC_BPT, trap_offset); 480285242Sachim 481285242Sachim /* 482285242Sachim * Set the common trap entry point to the one that 483285242Sachim * knows to restore 32-bit operation on execution. 484285242Sachim */ 485285242Sachim 486285242Sachim generictrap = &trapcode64; 487285242Sachim } else { 488285242Sachim generictrap = &trapcode; 489285242Sachim } 490285242Sachim 491285242Sachim #else /* powerpc64 */ 492285242Sachim cpu_features |= PPC_FEATURE_64; 493285242Sachim generictrap = &trapcode; 494285242Sachim #endif 495285242Sachim 496285242Sachim bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstsize); 497285242Sachim 498285242Sachim#ifdef KDB 499285242Sachim bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbsize); 500285242Sachim bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbsize); 501285242Sachim bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbsize); 502285242Sachim bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbsize); 503285242Sachim#else 504285242Sachim bcopy(generictrap, (void *)EXC_MCHK, (size_t)&trapsize); 505285242Sachim bcopy(generictrap, (void *)EXC_PGM, (size_t)&trapsize); 506285242Sachim bcopy(generictrap, (void *)EXC_TRC, (size_t)&trapsize); 507285242Sachim bcopy(generictrap, (void *)EXC_BPT, (size_t)&trapsize); 508285242Sachim#endif 509285242Sachim bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&alisize); 510285242Sachim bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsisize); 511285242Sachim bcopy(generictrap, (void *)EXC_ISI, (size_t)&trapsize); 512285242Sachim #ifdef __powerpc64__ 513285242Sachim bcopy(&slbtrap, (void *)EXC_DSE, (size_t)&slbtrapsize); 514285242Sachim bcopy(&slbtrap, (void *)EXC_ISE, (size_t)&slbtrapsize); 515285242Sachim #endif 516285242Sachim bcopy(generictrap, (void *)EXC_EXI, (size_t)&trapsize); 517285242Sachim bcopy(generictrap, (void *)EXC_FPU, (size_t)&trapsize); 518285242Sachim bcopy(generictrap, (void *)EXC_DECR, (size_t)&trapsize); 519285242Sachim bcopy(generictrap, (void *)EXC_SC, (size_t)&trapsize); 520285242Sachim bcopy(generictrap, (void *)EXC_FPA, (size_t)&trapsize); 521285242Sachim bcopy(generictrap, (void *)EXC_VEC, (size_t)&trapsize); 522285242Sachim bcopy(generictrap, (void *)EXC_PERF, (size_t)&trapsize); 523285242Sachim bcopy(generictrap, (void *)EXC_VECAST_G4, (size_t)&trapsize); 524285242Sachim bcopy(generictrap, (void *)EXC_VECAST_G5, (size_t)&trapsize); 525285242Sachim #ifndef __powerpc64__ 526285242Sachim /* G2-specific TLB miss helper handlers */ 527285242Sachim bcopy(&imisstrap, (void *)EXC_IMISS, (size_t)&imisssize); 528285242Sachim bcopy(&dlmisstrap, (void *)EXC_DLMISS, (size_t)&dlmisssize); 529285242Sachim bcopy(&dsmisstrap, (void *)EXC_DSMISS, (size_t)&dsmisssize); 530285242Sachim #endif 531285242Sachim __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); 532285242Sachim 533285242Sachim /* 534285242Sachim * Restore MSR 535285242Sachim */ 536285242Sachim mtmsr(msr); 537285242Sachim 538285242Sachim /* Warn if cachline size was not determined */ 539285242Sachim if (cacheline_warn == 1) { 540285242Sachim printf("WARNING: cacheline size undetermined, setting to 32\n"); 541285242Sachim } 542285242Sachim 543285242Sachim /* 544285242Sachim * Choose a platform module so we can get the physical memory map. 545285242Sachim */ 546285242Sachim 547285242Sachim platform_probe_and_attach(); 548285242Sachim 549285242Sachim /* 550285242Sachim * Initialise virtual memory. Use BUS_PROBE_GENERIC priority 551285242Sachim * in case the platform module had a better idea of what we 552285242Sachim * should do. 553285242Sachim */ 554285242Sachim if (cpu_features & PPC_FEATURE_64) 555285242Sachim pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC); 556285242Sachim else 557285242Sachim pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC); 558285242Sachim 559285242Sachim pmap_bootstrap(startkernel, endkernel); 560285242Sachim mtmsr(PSL_KERNSET & ~PSL_EE); 561285242Sachim 562285242Sachim /* 563285242Sachim * Initialize params/tunables that are derived from memsize 564285242Sachim */ 565285242Sachim init_param2(physmem); 566285242Sachim 567285242Sachim /* 568285242Sachim * Grab booted kernel's name 569285242Sachim */ 570285242Sachim env = getenv("kernelname"); 571285242Sachim if (env != NULL) { 572285242Sachim strlcpy(kernelname, env, sizeof(kernelname)); 573285242Sachim freeenv(env); 574285242Sachim } 575285242Sachim 576285242Sachim /* 577285242Sachim * Finish setting up thread0. 578285242Sachim */ 579285242Sachim thread0.td_pcb = (struct pcb *) 580285242Sachim ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE - 581285242Sachim sizeof(struct pcb)) & ~15UL); 582285242Sachim bzero((void *)thread0.td_pcb, sizeof(struct pcb)); 583285242Sachim pc->pc_curpcb = thread0.td_pcb; 584285242Sachim 585285242Sachim /* Initialise the message buffer. */ 586285242Sachim msgbufinit(msgbufp, msgbufsize); 587285242Sachim 588285242Sachim#ifdef KDB 589285242Sachim if (boothowto & RB_KDB) 590285242Sachim kdb_enter(KDB_WHY_BOOTFLAGS, 591285242Sachim "Boot flags requested debugger"); 592285242Sachim#endif 593285242Sachim 594285242Sachim return (((uintptr_t)thread0.td_pcb - 595285242Sachim (sizeof(struct callframe) - 3*sizeof(register_t))) & ~15UL); 596285242Sachim} 597285242Sachim 598285242Sachimvoid 599285242Sachimbzero(void *buf, size_t len) 600285242Sachim{ 601285242Sachim caddr_t p; 602285242Sachim 603285242Sachim p = buf; 604285242Sachim 605285242Sachim while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 606285242Sachim *p++ = 0; 607285242Sachim len--; 608285242Sachim } 609285242Sachim 610285242Sachim while (len >= sizeof(u_long) * 8) { 611285242Sachim *(u_long*) p = 0; 612285242Sachim *((u_long*) p + 1) = 0; 613285242Sachim *((u_long*) p + 2) = 0; 614285242Sachim *((u_long*) p + 3) = 0; 615285242Sachim len -= sizeof(u_long) * 8; 616285242Sachim *((u_long*) p + 4) = 0; 617285242Sachim *((u_long*) p + 5) = 0; 618285242Sachim *((u_long*) p + 6) = 0; 619285242Sachim *((u_long*) p + 7) = 0; 620285242Sachim p += sizeof(u_long) * 8; 621285242Sachim } 622285242Sachim 623285242Sachim while (len >= sizeof(u_long)) { 624285242Sachim *(u_long*) p = 0; 625285242Sachim len -= sizeof(u_long); 626285242Sachim p += sizeof(u_long); 627285242Sachim } 628285242Sachim 629285242Sachim while (len) { 630285242Sachim *p++ = 0; 631285242Sachim len--; 632285242Sachim } 633285242Sachim} 634285242Sachim 635285242Sachimvoid 636285242Sachimcpu_boot(int howto) 637285242Sachim{ 638285242Sachim} 639285242Sachim 640285242Sachim/* 641285242Sachim * Flush the D-cache for non-DMA I/O so that the I-cache can 642285242Sachim * be made coherent later. 643285242Sachim */ 644285242Sachimvoid 645285242Sachimcpu_flush_dcache(void *ptr, size_t len) 646285242Sachim{ 647285242Sachim /* TBD */ 648285242Sachim} 649285242Sachim 650285242Sachim/* 651285242Sachim * Shutdown the CPU as much as possible. 652285242Sachim */ 653285242Sachimvoid 654285242Sachimcpu_halt(void) 655285242Sachim{ 656285242Sachim 657285242Sachim OF_exit(); 658285242Sachim} 659285242Sachim 660285242Sachimint 661285242Sachimptrace_set_pc(struct thread *td, unsigned long addr) 662285242Sachim{ 663285242Sachim struct trapframe *tf; 664285242Sachim 665285242Sachim tf = td->td_frame; 666285242Sachim tf->srr0 = (register_t)addr; 667285242Sachim 668285242Sachim return (0); 669285242Sachim} 670285242Sachim 671285242Sachimint 672285242Sachimptrace_single_step(struct thread *td) 673285242Sachim{ 674285242Sachim struct trapframe *tf; 675285242Sachim 676285242Sachim tf = td->td_frame; 677285242Sachim tf->srr1 |= PSL_SE; 678285242Sachim 679285242Sachim return (0); 680285242Sachim} 681285242Sachim 682285242Sachimint 683285242Sachimptrace_clear_single_step(struct thread *td) 684285242Sachim{ 685285242Sachim struct trapframe *tf; 686285242Sachim 687285242Sachim tf = td->td_frame; 688285242Sachim tf->srr1 &= ~PSL_SE; 689285242Sachim 690285242Sachim return (0); 691285242Sachim} 692285242Sachim 693285242Sachimvoid 694285242Sachimkdb_cpu_clear_singlestep(void) 695285242Sachim{ 696285242Sachim 697285242Sachim kdb_frame->srr1 &= ~PSL_SE; 698285242Sachim} 699285242Sachim 700285242Sachimvoid 701285242Sachimkdb_cpu_set_singlestep(void) 702285242Sachim{ 703285242Sachim 704285242Sachim kdb_frame->srr1 |= PSL_SE; 705285242Sachim} 706285242Sachim 707285242Sachim/* 708285242Sachim * Initialise a struct pcpu. 709285242Sachim */ 710285242Sachimvoid 711285242Sachimcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 712285242Sachim{ 713285242Sachim#ifdef __powerpc64__ 714285242Sachim/* Copy the SLB contents from the current CPU */ 715285242Sachimmemcpy(pcpu->pc_slb, PCPU_GET(slb), sizeof(pcpu->pc_slb)); 716285242Sachim#endif 717285242Sachim} 718285242Sachim 719285242Sachimvoid 720285242Sachimspinlock_enter(void) 721285242Sachim{ 722285242Sachim struct thread *td; 723285242Sachim register_t msr; 724285242Sachim 725285242Sachim td = curthread; 726285242Sachim if (td->td_md.md_spinlock_count == 0) { 727285242Sachim msr = intr_disable(); 728285242Sachim td->td_md.md_spinlock_count = 1; 729285242Sachim td->td_md.md_saved_msr = msr; 730285242Sachim } else 731285242Sachim td->td_md.md_spinlock_count++; 732285242Sachim critical_enter(); 733285242Sachim} 734285242Sachim 735285242Sachimvoid 736285242Sachimspinlock_exit(void) 737285242Sachim{ 738285242Sachim struct thread *td; 739285242Sachim register_t msr; 740285242Sachim 741285242Sachim td = curthread; 742285242Sachim critical_exit(); 743285242Sachim msr = td->td_md.md_saved_msr; 744285242Sachim td->td_md.md_spinlock_count--; 745285242Sachim if (td->td_md.md_spinlock_count == 0) 746285242Sachim intr_restore(msr); 747285242Sachim} 748285242Sachim 749285242Sachimint db_trap_glue(struct trapframe *); /* Called from trap_subr.S */ 750285242Sachim 751285242Sachimint 752285242Sachimdb_trap_glue(struct trapframe *frame) 753285242Sachim{ 754285242Sachim if (!(frame->srr1 & PSL_PR) 755285242Sachim && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC 756285242Sachim || (frame->exc == EXC_PGM 757285242Sachim && (frame->srr1 & 0x20000)) 758285242Sachim || frame->exc == EXC_BPT 759285242Sachim || frame->exc == EXC_DSI)) { 760285242Sachim int type = frame->exc; 761285242Sachim if (type == EXC_PGM && (frame->srr1 & 0x20000)) { 762285242Sachim type = T_BREAKPOINT; 763285242Sachim } 764285242Sachim return (kdb_trap(type, 0, frame)); 765285242Sachim } 766285242Sachim 767285242Sachim return (0); 768285242Sachim} 769285242Sachim 770285242Sachim#ifndef __powerpc64__ 771285242Sachim 772285242Sachimuint64_t 773285242Sachimva_to_vsid(pmap_t pm, vm_offset_t va) 774285242Sachim{ 775285242Sachim return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK); 776285242Sachim} 777285242Sachim 778285242Sachim#endif 779285242Sachim 780285242Sachimvm_offset_t 781285242Sachimpmap_early_io_map(vm_paddr_t pa, vm_size_t size) 782285242Sachim{ 783285242Sachim 784285242Sachim return (pa); 785285242Sachim} 786285242Sachim 787285242Sachim/* From p3-53 of the MPC7450 RISC Microprocessor Family Reference Manual */ 788285242Sachimvoid 789285242Sachimflush_disable_caches(void) 790285242Sachim{ 791285242Sachim register_t msr; 792285242Sachim register_t msscr0; 793285242Sachim register_t cache_reg; 794285242Sachim volatile uint32_t *memp; 795285242Sachim uint32_t temp; 796285242Sachim int i; 797285242Sachim int x; 798285242Sachim 799285242Sachim msr = mfmsr(); 800285242Sachim powerpc_sync(); 801285242Sachim mtmsr(msr & ~(PSL_EE | PSL_DR)); 802285242Sachim msscr0 = mfspr(SPR_MSSCR0); 803285242Sachim msscr0 &= ~MSSCR0_L2PFE; 804285242Sachim mtspr(SPR_MSSCR0, msscr0); 805285242Sachim powerpc_sync(); 806285242Sachim isync(); 807285242Sachim __asm__ __volatile__("dssall; sync"); 808285242Sachim powerpc_sync(); 809285242Sachim isync(); 810285242Sachim __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); 811285242Sachim __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); 812285242Sachim __asm__ __volatile__("dcbf 0,%0" :: "r"(0)); 813285242Sachim 814285242Sachim /* Lock the L1 Data cache. */ 815285242Sachim mtspr(SPR_LDSTCR, mfspr(SPR_LDSTCR) | 0xFF); 816285242Sachim powerpc_sync(); 817285242Sachim isync(); 818285242Sachim 819285242Sachim mtspr(SPR_LDSTCR, 0); 820285242Sachim 821285242Sachim /* 822285242Sachim * Perform this in two stages: Flush the cache starting in RAM, then do it 823285242Sachim * from ROM. 824285242Sachim */ 825285242Sachim memp = (volatile uint32_t *)0x00000000; 826285242Sachim for (i = 0; i < 128 * 1024; i++) { 827285242Sachim temp = *memp; 828285242Sachim __asm__ __volatile__("dcbf 0,%0" :: "r"(memp)); 829285242Sachim memp += 32/sizeof(*memp); 830285242Sachim } 831285242Sachim 832285242Sachim memp = (volatile uint32_t *)0xfff00000; 833285242Sachim x = 0xfe; 834285242Sachim 835285242Sachim for (; x != 0xff;) { 836285242Sachim mtspr(SPR_LDSTCR, x); 837285242Sachim for (i = 0; i < 128; i++) { 838285242Sachim temp = *memp; 839285242Sachim __asm__ __volatile__("dcbf 0,%0" :: "r"(memp)); 840285242Sachim memp += 32/sizeof(*memp); 841285242Sachim } 842285242Sachim x = ((x << 1) | 1) & 0xff; 843285242Sachim } 844285242Sachim mtspr(SPR_LDSTCR, 0); 845285242Sachim 846285242Sachim cache_reg = mfspr(SPR_L2CR); 847285242Sachim if (cache_reg & L2CR_L2E) { 848285242Sachim cache_reg &= ~(L2CR_L2IO_7450 | L2CR_L2DO_7450); 849285242Sachim mtspr(SPR_L2CR, cache_reg); 850285242Sachim powerpc_sync(); 851285242Sachim mtspr(SPR_L2CR, cache_reg | L2CR_L2HWF); 852285242Sachim while (mfspr(SPR_L2CR) & L2CR_L2HWF) 853285242Sachim ; /* Busy wait for cache to flush */ 854285242Sachim powerpc_sync(); 855285242Sachim cache_reg &= ~L2CR_L2E; 856285242Sachim mtspr(SPR_L2CR, cache_reg); 857285242Sachim powerpc_sync(); 858285242Sachim mtspr(SPR_L2CR, cache_reg | L2CR_L2I); 859285242Sachim powerpc_sync(); 860285242Sachim while (mfspr(SPR_L2CR) & L2CR_L2I) 861285242Sachim ; /* Busy wait for L2 cache invalidate */ 862285242Sachim powerpc_sync(); 863285242Sachim } 864285242Sachim 865285242Sachim cache_reg = mfspr(SPR_L3CR); 866285242Sachim if (cache_reg & L3CR_L3E) { 867285242Sachim cache_reg &= ~(L3CR_L3IO | L3CR_L3DO); 868285242Sachim mtspr(SPR_L3CR, cache_reg); 869285242Sachim powerpc_sync(); 870285242Sachim mtspr(SPR_L3CR, cache_reg | L3CR_L3HWF); 871285242Sachim while (mfspr(SPR_L3CR) & L3CR_L3HWF) 872285242Sachim ; /* Busy wait for cache to flush */ 873285242Sachim powerpc_sync(); 874285242Sachim cache_reg &= ~L3CR_L3E; 875285242Sachim mtspr(SPR_L3CR, cache_reg); 876285242Sachim powerpc_sync(); 877285242Sachim mtspr(SPR_L3CR, cache_reg | L3CR_L3I); 878285242Sachim powerpc_sync(); 879285242Sachim while (mfspr(SPR_L3CR) & L3CR_L3I) 880285242Sachim ; /* Busy wait for L3 cache invalidate */ 881285242Sachim powerpc_sync(); 882285242Sachim } 883285242Sachim 884285242Sachim mtspr(SPR_HID0, mfspr(SPR_HID0) & ~HID0_DCE); 885285242Sachim powerpc_sync(); 886285242Sachim isync(); 887285242Sachim 888285242Sachim mtmsr(msr); 889285242Sachim} 890285242Sachim 891285242Sachimvoid 892285242Sachimcpu_sleep() 893285242Sachim{ 894285242Sachim static u_quad_t timebase = 0; 895285242Sachim static register_t sprgs[4]; 896285242Sachim static register_t srrs[2]; 897285242Sachim 898285242Sachim jmp_buf resetjb; 899285242Sachim struct thread *fputd; 900285242Sachim struct thread *vectd; 901285242Sachim register_t hid0; 902285242Sachim register_t msr; 903285242Sachim register_t saved_msr; 904285242Sachim 905285242Sachim ap_pcpu = pcpup; 906285242Sachim 907285242Sachim PCPU_SET(restore, &resetjb); 908285242Sachim 909285242Sachim saved_msr = mfmsr(); 910285242Sachim fputd = PCPU_GET(fputhread); 911285242Sachim vectd = PCPU_GET(vecthread); 912285242Sachim if (fputd != NULL) 913285242Sachim save_fpu(fputd); 914285242Sachim if (vectd != NULL) 915285242Sachim save_vec(vectd); 916285242Sachim if (setjmp(resetjb) == 0) { 917285242Sachim sprgs[0] = mfspr(SPR_SPRG0); 918285242Sachim sprgs[1] = mfspr(SPR_SPRG1); 919285242Sachim sprgs[2] = mfspr(SPR_SPRG2); 920285242Sachim sprgs[3] = mfspr(SPR_SPRG3); 921285242Sachim srrs[0] = mfspr(SPR_SRR0); 922285242Sachim srrs[1] = mfspr(SPR_SRR1); 923 timebase = mftb(); 924 powerpc_sync(); 925 flush_disable_caches(); 926 hid0 = mfspr(SPR_HID0); 927 hid0 = (hid0 & ~(HID0_DOZE | HID0_NAP)) | HID0_SLEEP; 928 powerpc_sync(); 929 isync(); 930 msr = mfmsr() | PSL_POW; 931 mtspr(SPR_HID0, hid0); 932 powerpc_sync(); 933 934 while (1) 935 mtmsr(msr); 936 } 937 mttb(timebase); 938 PCPU_SET(curthread, curthread); 939 PCPU_SET(curpcb, curthread->td_pcb); 940 pmap_activate(curthread); 941 powerpc_sync(); 942 mtspr(SPR_SPRG0, sprgs[0]); 943 mtspr(SPR_SPRG1, sprgs[1]); 944 mtspr(SPR_SPRG2, sprgs[2]); 945 mtspr(SPR_SPRG3, sprgs[3]); 946 mtspr(SPR_SRR0, srrs[0]); 947 mtspr(SPR_SRR1, srrs[1]); 948 mtmsr(saved_msr); 949 if (fputd == curthread) 950 enable_fpu(curthread); 951 if (vectd == curthread) 952 enable_vec(curthread); 953 powerpc_sync(); 954}