1176771Sraj/*- 2236324Sraj * Copyright (C) 2006-2012 Semihalf 3176771Sraj * All rights reserved. 4176771Sraj * 5176771Sraj * Redistribution and use in source and binary forms, with or without 6176771Sraj * modification, are permitted provided that the following conditions 7176771Sraj * are met: 8176771Sraj * 1. Redistributions of source code must retain the above copyright 9176771Sraj * notice, this list of conditions and the following disclaimer. 10176771Sraj * 2. Redistributions in binary form must reproduce the above copyright 11176771Sraj * notice, this list of conditions and the following disclaimer in the 12176771Sraj * documentation and/or other materials provided with the distribution. 13176771Sraj * 14176771Sraj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17176771Sraj * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 19176771Sraj * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20176771Sraj * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21176771Sraj * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22176771Sraj * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23176771Sraj * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24176771Sraj */ 25176771Sraj/*- 26176771Sraj * Copyright (C) 2001 Benno Rice 27176771Sraj * All rights reserved. 28176771Sraj * 29176771Sraj * Redistribution and use in source and binary forms, with or without 30176771Sraj * modification, are permitted provided that the following conditions 31176771Sraj * are met: 32176771Sraj * 1. Redistributions of source code must retain the above copyright 33176771Sraj * notice, this list of conditions and the following disclaimer. 34176771Sraj * 2. Redistributions in binary form must reproduce the above copyright 35176771Sraj * notice, this list of conditions and the following disclaimer in the 36176771Sraj * documentation and/or other materials provided with the distribution. 37176771Sraj * 38176771Sraj * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 39176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 40176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 41176771Sraj * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 42176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 43176771Sraj * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 44176771Sraj * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 45176771Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 46176771Sraj * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 47176771Sraj * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48176771Sraj * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 49176771Sraj */ 50176771Sraj/*- 51176771Sraj * Copyright (C) 1995, 1996 Wolfgang Solfrank. 52176771Sraj * Copyright (C) 1995, 1996 TooLs GmbH. 53176771Sraj * All rights reserved. 54176771Sraj * 55176771Sraj * Redistribution and use in source and binary forms, with or without 56176771Sraj * modification, are permitted provided that the following conditions 57176771Sraj * are met: 58176771Sraj * 1. Redistributions of source code must retain the above copyright 59176771Sraj * notice, this list of conditions and the following disclaimer. 60176771Sraj * 2. Redistributions in binary form must reproduce the above copyright 61176771Sraj * notice, this list of conditions and the following disclaimer in the 62176771Sraj * documentation and/or other materials provided with the distribution. 63176771Sraj * 3. All advertising materials mentioning features or use of this software 64176771Sraj * must display the following acknowledgement: 65176771Sraj * This product includes software developed by TooLs GmbH. 66176771Sraj * 4. The name of TooLs GmbH may not be used to endorse or promote products 67176771Sraj * derived from this software without specific prior written permission. 68176771Sraj * 69176771Sraj * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 70176771Sraj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 71176771Sraj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 72176771Sraj * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 73176771Sraj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 74176771Sraj * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 75176771Sraj * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 76176771Sraj * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 77176771Sraj * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 78176771Sraj * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79176771Sraj */ 80176771Sraj 81176771Sraj#include <sys/cdefs.h> 82176771Sraj__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/booke/machdep.c 266003 2014-05-14 04:14:58Z ian $"); 83176771Sraj 84176771Sraj#include "opt_compat.h" 85191362Smarcel#include "opt_ddb.h" 86176771Sraj#include "opt_kstack_pages.h" 87217523Smarcel#include "opt_platform.h" 88176771Sraj 89176771Sraj#include <sys/cdefs.h> 90176771Sraj#include <sys/types.h> 91176771Sraj#include <sys/param.h> 92176771Sraj#include <sys/proc.h> 93176771Sraj#include <sys/systm.h> 94176771Sraj#include <sys/time.h> 95176771Sraj#include <sys/bio.h> 96176771Sraj#include <sys/buf.h> 97176771Sraj#include <sys/bus.h> 98176771Sraj#include <sys/cons.h> 99176771Sraj#include <sys/cpu.h> 100176771Sraj#include <sys/kdb.h> 101176771Sraj#include <sys/kernel.h> 102176771Sraj#include <sys/lock.h> 103176771Sraj#include <sys/mutex.h> 104248084Sattilio#include <sys/rwlock.h> 105176771Sraj#include <sys/sysctl.h> 106176771Sraj#include <sys/exec.h> 107176771Sraj#include <sys/ktr.h> 108209613Sjhb#include <sys/syscallsubr.h> 109176771Sraj#include <sys/sysproto.h> 110176771Sraj#include <sys/signalvar.h> 111176771Sraj#include <sys/sysent.h> 112176771Sraj#include <sys/imgact.h> 113176771Sraj#include <sys/msgbuf.h> 114176771Sraj#include <sys/ptrace.h> 115176771Sraj 116176771Sraj#include <vm/vm.h> 117176771Sraj#include <vm/pmap.h> 118176771Sraj#include <vm/vm_page.h> 119176771Sraj#include <vm/vm_object.h> 120176771Sraj#include <vm/vm_pager.h> 121176771Sraj 122176771Sraj#include <machine/cpu.h> 123176771Sraj#include <machine/kdb.h> 124176771Sraj#include <machine/reg.h> 125176771Sraj#include <machine/vmparam.h> 126176771Sraj#include <machine/spr.h> 127176771Sraj#include <machine/hid.h> 128176771Sraj#include <machine/psl.h> 129176771Sraj#include <machine/trap.h> 130176771Sraj#include <machine/md_var.h> 131176771Sraj#include <machine/mmuvar.h> 132176771Sraj#include <machine/sigframe.h> 133236324Sraj#include <machine/machdep.h> 134176771Sraj#include <machine/metadata.h> 135192067Snwhitehorn#include <machine/platform.h> 136176771Sraj 137176771Sraj#include <sys/linker.h> 138176771Sraj#include <sys/reboot.h> 139176771Sraj 140265996Sian#include <contrib/libfdt/libfdt.h> 141209908Sraj#include <dev/fdt/fdt_common.h> 142209908Sraj#include <dev/ofw/openfirm.h> 143209908Sraj 144191362Smarcel#ifdef DDB 145191362Smarcelextern vm_offset_t ksym_start, ksym_end; 146191362Smarcel#endif 147191362Smarcel 148176771Sraj#ifdef DEBUG 149176771Sraj#define debugf(fmt, args...) printf(fmt, ##args) 150176771Sraj#else 151176771Sraj#define debugf(fmt, args...) 152176771Sraj#endif 153176771Sraj 154176771Srajextern unsigned char kernel_text[]; 155176771Srajextern unsigned char _etext[]; 156176771Srajextern unsigned char _edata[]; 157176771Srajextern unsigned char __bss_start[]; 158176771Srajextern unsigned char __sbss_start[]; 159176771Srajextern unsigned char __sbss_end[]; 160176771Srajextern unsigned char _end[]; 161176771Sraj 162217523Smarcel/* 163217523Smarcel * Bootinfo is passed to us by legacy loaders. Save the address of the 164217523Smarcel * structure to handle backward compatibility. 165217523Smarcel */ 166217523Smarceluint32_t *bootinfo; 167217523Smarcel 168176771Srajstruct kva_md_info kmi; 169176771Srajstruct pcpu __pcpu[MAXCPU]; 170176771Srajstruct trapframe frame0; 171176771Srajint cold = 1; 172176771Srajlong realmem = 0; 173176771Srajlong Maxmem = 0; 174176771Srajchar machine[] = "powerpc"; 175176771SrajSYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 176176771Sraj 177183319Snwhitehornint cacheline_size = 32; 178183319Snwhitehorn 179176771SrajSYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, 180183319Snwhitehorn CTLFLAG_RD, &cacheline_size, 0, ""); 181176771Sraj 182190681Snwhitehornint hw_direct_map = 0; 183190681Snwhitehorn 184236097Srajstatic void cpu_booke_startup(void *); 185236097SrajSYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_booke_startup, NULL); 186176771Sraj 187176771Srajvoid print_kernel_section_addr(void); 188186228Srajvoid print_kenv(void); 189222400Smarcelu_int booke_init(uint32_t, uint32_t); 190176771Sraj 191230767Skibextern int elf32_nxstack; 192230767Skib 193176771Srajstatic void 194236097Srajcpu_booke_startup(void *dummy) 195176771Sraj{ 196265954Sian int indx; 197265954Sian unsigned long size; 198176771Sraj 199176771Sraj /* Initialise the decrementer-based clock. */ 200176771Sraj decr_init(); 201176771Sraj 202176771Sraj /* Good {morning,afternoon,evening,night}. */ 203176771Sraj cpu_setup(PCPU_GET(cpuid)); 204176771Sraj 205265954Sian printf("real memory = %lu (%ld MB)\n", ptoa(physmem), 206182198Sraj ptoa(physmem) / 1048576); 207176771Sraj realmem = physmem; 208176771Sraj 209176771Sraj /* Display any holes after the first chunk of extended memory. */ 210176771Sraj if (bootverbose) { 211176771Sraj printf("Physical memory chunk(s):\n"); 212176771Sraj for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 213182198Sraj size = phys_avail[indx + 1] - phys_avail[indx]; 214186228Sraj 215265954Sian printf("0x%08x - 0x%08x, %lu bytes (%lu pages)\n", 216186228Sraj phys_avail[indx], phys_avail[indx + 1] - 1, 217186228Sraj size, size / PAGE_SIZE); 218176771Sraj } 219176771Sraj } 220176771Sraj 221176771Sraj vm_ksubmap_init(&kmi); 222176771Sraj 223265954Sian printf("avail memory = %lu (%ld MB)\n", ptoa(cnt.v_free_count), 224186228Sraj ptoa(cnt.v_free_count) / 1048576); 225176771Sraj 226176771Sraj /* Set up buffers, so they can be used to read disk labels. */ 227176771Sraj bufinit(); 228176771Sraj vm_pager_bufferinit(); 229230767Skib 230230767Skib /* Cpu supports execution permissions on the pages. */ 231230767Skib elf32_nxstack = 1; 232176771Sraj} 233176771Sraj 234176771Srajstatic char * 235176771Srajkenv_next(char *cp) 236176771Sraj{ 237176771Sraj 238176771Sraj if (cp != NULL) { 239176771Sraj while (*cp != 0) 240176771Sraj cp++; 241176771Sraj cp++; 242176771Sraj if (*cp == 0) 243176771Sraj cp = NULL; 244176771Sraj } 245176771Sraj return (cp); 246176771Sraj} 247176771Sraj 248176771Srajvoid 249186228Srajprint_kenv(void) 250176771Sraj{ 251176771Sraj int len; 252176771Sraj char *cp; 253176771Sraj 254176771Sraj debugf("loader passed (static) kenv:\n"); 255176771Sraj if (kern_envp == NULL) { 256176771Sraj debugf(" no env, null ptr\n"); 257176771Sraj return; 258176771Sraj } 259176771Sraj debugf(" kern_envp = 0x%08x\n", (u_int32_t)kern_envp); 260176771Sraj 261176771Sraj len = 0; 262176771Sraj for (cp = kern_envp; cp != NULL; cp = kenv_next(cp)) 263176771Sraj debugf(" %x %s\n", (u_int32_t)cp, cp); 264176771Sraj} 265176771Sraj 266176771Srajvoid 267176771Srajprint_kernel_section_addr(void) 268176771Sraj{ 269176771Sraj 270176771Sraj debugf("kernel image addresses:\n"); 271186228Sraj debugf(" kernel_text = 0x%08x\n", (uint32_t)kernel_text); 272186228Sraj debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext); 273186228Sraj debugf(" _edata = 0x%08x\n", (uint32_t)_edata); 274186228Sraj debugf(" __sbss_start = 0x%08x\n", (uint32_t)__sbss_start); 275186228Sraj debugf(" __sbss_end = 0x%08x\n", (uint32_t)__sbss_end); 276186228Sraj debugf(" __sbss_start = 0x%08x\n", (uint32_t)__bss_start); 277186228Sraj debugf(" _end = 0x%08x\n", (uint32_t)_end); 278176771Sraj} 279176771Sraj 280265996Sianstatic int 281265996Sianbooke_check_for_fdt(uint32_t arg1, vm_offset_t *dtbp) 282265996Sian{ 283265996Sian void *ptr; 284265996Sian 285265996Sian if (arg1 % 8 != 0) 286265996Sian return (-1); 287265996Sian 288265996Sian ptr = (void *)pmap_early_io_map(arg1, PAGE_SIZE); 289265996Sian if (fdt_check_header(ptr) != 0) 290265996Sian return (-1); 291265996Sian 292265996Sian *dtbp = (vm_offset_t)ptr; 293265996Sian 294265996Sian return (0); 295265996Sian} 296265996Sian 297182198Sraju_int 298222400Smarcelbooke_init(uint32_t arg1, uint32_t arg2) 299176771Sraj{ 300176771Sraj struct pcpu *pc; 301222400Smarcel void *kmdp, *mdp; 302209908Sraj vm_offset_t dtbp, end; 303176771Sraj 304176771Sraj kmdp = NULL; 305176771Sraj 306222400Smarcel end = (uintptr_t)_end; 307209908Sraj dtbp = (vm_offset_t)NULL; 308176771Sraj 309265996Sian /* Set up TLB initially */ 310265996Sian bootinfo = NULL; 311265996Sian tlb1_init(); 312265996Sian 313176771Sraj /* 314222400Smarcel * Handle the various ways we can get loaded and started: 315222400Smarcel * - FreeBSD's loader passes the pointer to the metadata 316222400Smarcel * in arg1, with arg2 undefined. arg1 has a value that's 317222400Smarcel * relative to the kernel's link address (i.e. larger 318222400Smarcel * than 0xc0000000). 319222400Smarcel * - Juniper's loader passes the metadata pointer in arg2 320222400Smarcel * and sets arg1 to zero. This is to signal that the 321222400Smarcel * loader maps the kernel and starts it at its link 322222400Smarcel * address (unlike the FreeBSD loader). 323222400Smarcel * - U-Boot passes the standard argc and argv parameters 324222400Smarcel * in arg1 and arg2 (resp). arg1 is between 1 and some 325222400Smarcel * relatively small number, such as 64K. arg2 is the 326222400Smarcel * physical address of the argv vector. 327265996Sian * - ePAPR loaders pass an FDT blob in r3 (arg1) and the magic hex 328265996Sian * string 0x45504150 ('ePAP') in r6 (which has been lost by now). 329265996Sian * r4 (arg2) is supposed to be set to zero, but is not always. 330222400Smarcel */ 331265996Sian 332265996Sian if (arg1 == 0) /* Juniper loader */ 333265996Sian mdp = (void *)arg2; 334265996Sian else if (booke_check_for_fdt(arg1, &dtbp) == 0) { /* ePAPR */ 335265996Sian end = roundup(end, 8); 336265996Sian memmove((void *)end, (void *)dtbp, fdt_totalsize((void *)dtbp)); 337265996Sian dtbp = end; 338265996Sian end += fdt_totalsize((void *)dtbp); 339265996Sian mdp = NULL; 340265996Sian } else if (arg1 > (uintptr_t)kernel_text) /* FreeBSD loader */ 341222400Smarcel mdp = (void *)arg1; 342222400Smarcel else /* U-Boot */ 343222400Smarcel mdp = NULL; 344222400Smarcel 345222400Smarcel /* 346209908Sraj * Parse metadata and fetch parameters. 347176771Sraj */ 348176771Sraj if (mdp != NULL) { 349176771Sraj preload_metadata = mdp; 350176771Sraj kmdp = preload_search_by_type("elf kernel"); 351176771Sraj if (kmdp != NULL) { 352176771Sraj boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 353176771Sraj kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 354209908Sraj dtbp = MD_FETCH(kmdp, MODINFOMD_DTBP, vm_offset_t); 355176771Sraj end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 356217523Smarcel 357217523Smarcel bootinfo = (uint32_t *)preload_search_info(kmdp, 358217523Smarcel MODINFO_METADATA | MODINFOMD_BOOTINFO); 359217523Smarcel 360191362Smarcel#ifdef DDB 361191362Smarcel ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); 362191362Smarcel ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); 363191362Smarcel#endif 364176771Sraj } 365176771Sraj } else { 366222400Smarcel bzero(__sbss_start, __sbss_end - __sbss_start); 367222400Smarcel bzero(__bss_start, _end - __bss_start); 368176771Sraj } 369176771Sraj 370217523Smarcel#if defined(FDT_DTB_STATIC) 371217523Smarcel /* 372217523Smarcel * In case the device tree blob was not retrieved (from metadata) try 373217523Smarcel * to use the statically embedded one. 374217523Smarcel */ 375217523Smarcel if (dtbp == (vm_offset_t)NULL) 376217523Smarcel dtbp = (vm_offset_t)&fdt_static_dtb; 377217523Smarcel#endif 378217523Smarcel 379209908Sraj if (OF_install(OFW_FDT, 0) == FALSE) 380209908Sraj while (1); 381209908Sraj 382209908Sraj if (OF_init((void *)dtbp) != 0) 383209908Sraj while (1); 384209908Sraj 385209908Sraj OF_interpret("perform-fixup", 0); 386236324Sraj 387265996Sian /* Reset TLB1 to get rid of temporary mappings */ 388265996Sian tlb1_init(); 389209908Sraj 390192532Sraj /* Reset Time Base */ 391192532Sraj mttb(0); 392192532Sraj 393176771Sraj /* Init params/tunables that can be overridden by the loader. */ 394176771Sraj init_param1(); 395176771Sraj 396176771Sraj /* Start initializing proc0 and thread0. */ 397203924Sraj proc_linkup0(&proc0, &thread0); 398176771Sraj thread0.td_frame = &frame0; 399176771Sraj 400176771Sraj /* Set up per-cpu data and store the pointer in SPR general 0. */ 401176771Sraj pc = &__pcpu[0]; 402176771Sraj pcpu_init(pc, 0, sizeof(struct pcpu)); 403176771Sraj pc->pc_curthread = &thread0; 404266001Sian#ifdef __powerpc64__ 405266001Sian __asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread)); 406266001Sian#else 407266001Sian __asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread)); 408266001Sian#endif 409176771Sraj __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 410176771Sraj 411176771Sraj /* Initialize system mutexes. */ 412176771Sraj mutex_init(); 413176771Sraj 414176771Sraj /* Initialize the console before printing anything. */ 415176771Sraj cninit(); 416176771Sraj 417176771Sraj /* Print out some debug info... */ 418222400Smarcel debugf("%s: console initialized\n", __func__); 419186228Sraj debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp); 420176771Sraj debugf(" end = 0x%08x\n", (u_int32_t)end); 421176771Sraj debugf(" boothowto = 0x%08x\n", boothowto); 422176771Sraj debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA); 423176771Sraj debugf(" MSR = 0x%08x\n", mfmsr()); 424236141Sraj#if defined(BOOKE_E500) 425186228Sraj debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0)); 426186228Sraj debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1)); 427192532Sraj debugf(" BUCSR = 0x%08x\n", mfspr(SPR_BUCSR)); 428236141Sraj#endif 429192532Sraj 430209908Sraj debugf(" dtbp = 0x%08x\n", (uint32_t)dtbp); 431209908Sraj 432176771Sraj print_kernel_section_addr(); 433186228Sraj print_kenv(); 434236141Sraj#if defined(BOOKE_E500) 435176771Sraj //tlb1_print_entries(); 436176771Sraj //tlb1_print_tlbentries(); 437236141Sraj#endif 438176771Sraj 439176771Sraj kdb_init(); 440176771Sraj 441176771Sraj#ifdef KDB 442176771Sraj if (boothowto & RB_KDB) 443176771Sraj kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger"); 444176771Sraj#endif 445176771Sraj 446192067Snwhitehorn /* Initialise platform module */ 447192067Snwhitehorn platform_probe_and_attach(); 448192067Snwhitehorn 449176771Sraj /* Initialise virtual memory. */ 450176771Sraj pmap_mmu_install(MMU_TYPE_BOOKE, 0); 451222400Smarcel pmap_bootstrap((uintptr_t)kernel_text, end); 452242526Smarcel pmap_bootstrapped = 1; 453176771Sraj debugf("MSR = 0x%08x\n", mfmsr()); 454236141Sraj#if defined(BOOKE_E500) 455176771Sraj //tlb1_print_entries(); 456176771Sraj //tlb1_print_tlbentries(); 457236141Sraj#endif 458176771Sraj 459176771Sraj /* Initialize params/tunables that are derived from memsize. */ 460176771Sraj init_param2(physmem); 461176771Sraj 462176771Sraj /* Finish setting up thread0. */ 463176771Sraj thread0.td_pcb = (struct pcb *) 464182198Sraj ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE - 465182198Sraj sizeof(struct pcb)) & ~15); 466176771Sraj bzero((void *)thread0.td_pcb, sizeof(struct pcb)); 467176771Sraj pc->pc_curpcb = thread0.td_pcb; 468176771Sraj 469176771Sraj /* Initialise the message buffer. */ 470217688Spluknet msgbufinit(msgbufp, msgbufsize); 471176771Sraj 472176771Sraj /* Enable Machine Check interrupt. */ 473176771Sraj mtmsr(mfmsr() | PSL_ME); 474176771Sraj isync(); 475176771Sraj 476236324Sraj /* Enable L1 caches */ 477236324Sraj booke_enable_l1_cache(); 478186228Sraj 479222400Smarcel debugf("%s: SP = 0x%08x\n", __func__, 480222400Smarcel ((uintptr_t)thread0.td_pcb - 16) & ~15); 481182198Sraj 482182198Sraj return (((uintptr_t)thread0.td_pcb - 16) & ~15); 483176771Sraj} 484176771Sraj 485192532Sraj#define RES_GRANULE 32 486192532Srajextern uint32_t tlb0_miss_locks[]; 487192532Sraj 488176771Sraj/* Initialise a struct pcpu. */ 489176771Srajvoid 490176771Srajcpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 491176771Sraj{ 492176771Sraj 493187149Sraj pcpu->pc_tid_next = TID_MIN; 494192532Sraj 495192532Sraj#ifdef SMP 496192532Sraj uint32_t *ptr; 497192532Sraj int words_per_gran = RES_GRANULE / sizeof(uint32_t); 498192532Sraj 499192532Sraj ptr = &tlb0_miss_locks[cpuid * words_per_gran]; 500192532Sraj pcpu->pc_booke_tlb_lock = ptr; 501215119Sraj *ptr = TLB_UNLOCKED; 502192532Sraj *(ptr + 1) = 0; /* recurse counter */ 503192532Sraj#endif 504176771Sraj} 505176771Sraj 506192323Smarcel/* 507192323Smarcel * Flush the D-cache for non-DMA I/O so that the I-cache can 508192323Smarcel * be made coherent later. 509192323Smarcel */ 510192323Smarcelvoid 511192323Smarcelcpu_flush_dcache(void *ptr, size_t len) 512192323Smarcel{ 513238030Smarcel register_t addr, off; 514238030Smarcel 515238030Smarcel /* 516238030Smarcel * Align the address to a cacheline and adjust the length 517238030Smarcel * accordingly. Then round the length to a multiple of the 518238030Smarcel * cacheline for easy looping. 519238030Smarcel */ 520238030Smarcel addr = (uintptr_t)ptr; 521238030Smarcel off = addr & (cacheline_size - 1); 522238030Smarcel addr -= off; 523238030Smarcel len = (len + off + cacheline_size - 1) & ~(cacheline_size - 1); 524238030Smarcel 525238030Smarcel while (len > 0) { 526238030Smarcel __asm __volatile ("dcbf 0,%0" :: "r"(addr)); 527238030Smarcel __asm __volatile ("sync"); 528238030Smarcel addr += cacheline_size; 529238030Smarcel len -= cacheline_size; 530238030Smarcel } 531192323Smarcel} 532192323Smarcel 533176771Srajvoid 534176771Srajspinlock_enter(void) 535176771Sraj{ 536176771Sraj struct thread *td; 537214835Sjhb register_t msr; 538176771Sraj 539176771Sraj td = curthread; 540214835Sjhb if (td->td_md.md_spinlock_count == 0) { 541214835Sjhb msr = intr_disable(); 542214835Sjhb td->td_md.md_spinlock_count = 1; 543214835Sjhb td->td_md.md_saved_msr = msr; 544214835Sjhb } else 545214835Sjhb td->td_md.md_spinlock_count++; 546176771Sraj critical_enter(); 547176771Sraj} 548176771Sraj 549176771Srajvoid 550176771Srajspinlock_exit(void) 551176771Sraj{ 552176771Sraj struct thread *td; 553214835Sjhb register_t msr; 554176771Sraj 555176771Sraj td = curthread; 556176771Sraj critical_exit(); 557214835Sjhb msr = td->td_md.md_saved_msr; 558176771Sraj td->td_md.md_spinlock_count--; 559176771Sraj if (td->td_md.md_spinlock_count == 0) 560214835Sjhb intr_restore(msr); 561176771Sraj} 562176771Sraj 563176771Sraj/* Shutdown the CPU as much as possible. */ 564176771Srajvoid 565176771Srajcpu_halt(void) 566176771Sraj{ 567176771Sraj 568176771Sraj mtmsr(mfmsr() & ~(PSL_CE | PSL_EE | PSL_ME | PSL_DE)); 569236097Sraj while (1) 570236097Sraj ; 571176771Sraj} 572176771Sraj 573176771Srajint 574176771Srajptrace_set_pc(struct thread *td, unsigned long addr) 575176771Sraj{ 576176771Sraj struct trapframe *tf; 577176771Sraj 578176771Sraj tf = td->td_frame; 579176771Sraj tf->srr0 = (register_t)addr; 580176771Sraj 581176771Sraj return (0); 582176771Sraj} 583176771Sraj 584176771Srajint 585176771Srajptrace_single_step(struct thread *td) 586176771Sraj{ 587176771Sraj struct trapframe *tf; 588176771Sraj 589176771Sraj tf = td->td_frame; 590176771Sraj tf->srr1 |= PSL_DE; 591189100Sraj tf->cpu.booke.dbcr0 |= (DBCR0_IDM | DBCR0_IC); 592176771Sraj return (0); 593176771Sraj} 594176771Sraj 595176771Srajint 596176771Srajptrace_clear_single_step(struct thread *td) 597176771Sraj{ 598176771Sraj struct trapframe *tf; 599176771Sraj 600176771Sraj tf = td->td_frame; 601176771Sraj tf->srr1 &= ~PSL_DE; 602189100Sraj tf->cpu.booke.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); 603176771Sraj return (0); 604176771Sraj} 605176771Sraj 606176771Srajvoid 607176771Srajkdb_cpu_clear_singlestep(void) 608176771Sraj{ 609176771Sraj register_t r; 610176771Sraj 611176771Sraj r = mfspr(SPR_DBCR0); 612176771Sraj mtspr(SPR_DBCR0, r & ~DBCR0_IC); 613176771Sraj kdb_frame->srr1 &= ~PSL_DE; 614176771Sraj} 615176771Sraj 616176771Srajvoid 617176771Srajkdb_cpu_set_singlestep(void) 618176771Sraj{ 619176771Sraj register_t r; 620176771Sraj 621176771Sraj r = mfspr(SPR_DBCR0); 622176771Sraj mtspr(SPR_DBCR0, r | DBCR0_IC | DBCR0_IDM); 623176771Sraj kdb_frame->srr1 |= PSL_DE; 624176771Sraj} 625176771Sraj 626176771Srajvoid 627176771Srajbzero(void *buf, size_t len) 628176771Sraj{ 629176771Sraj caddr_t p; 630176771Sraj 631176771Sraj p = buf; 632176771Sraj 633176771Sraj while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 634176771Sraj *p++ = 0; 635176771Sraj len--; 636176771Sraj } 637176771Sraj 638176771Sraj while (len >= sizeof(u_long) * 8) { 639176771Sraj *(u_long*) p = 0; 640176771Sraj *((u_long*) p + 1) = 0; 641176771Sraj *((u_long*) p + 2) = 0; 642176771Sraj *((u_long*) p + 3) = 0; 643176771Sraj len -= sizeof(u_long) * 8; 644176771Sraj *((u_long*) p + 4) = 0; 645176771Sraj *((u_long*) p + 5) = 0; 646176771Sraj *((u_long*) p + 6) = 0; 647176771Sraj *((u_long*) p + 7) = 0; 648176771Sraj p += sizeof(u_long) * 8; 649176771Sraj } 650176771Sraj 651176771Sraj while (len >= sizeof(u_long)) { 652176771Sraj *(u_long*) p = 0; 653176771Sraj len -= sizeof(u_long); 654176771Sraj p += sizeof(u_long); 655176771Sraj } 656176771Sraj 657176771Sraj while (len) { 658176771Sraj *p++ = 0; 659176771Sraj len--; 660176771Sraj } 661176771Sraj} 662176771Sraj 663