The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
    3  * Copyright (C) 1995, 1996 TooLs GmbH.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by TooLs GmbH.
   17  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 /*-
   32  * Copyright (C) 2001 Benno Rice
   33  * All rights reserved.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  *
   44  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   47  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   49  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   50  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   52  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   53  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   54  *      $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
   55  */
   56 
   57 #include <sys/cdefs.h>
   58 __FBSDID("$FreeBSD: releng/11.2/sys/powerpc/powerpc/machdep.c 302280 2016-06-29 16:34:56Z nwhitehorn $");
   59 
   60 #include "opt_compat.h"
   61 #include "opt_ddb.h"
   62 #include "opt_kstack_pages.h"
   63 #include "opt_platform.h"
   64 
   65 #include <sys/param.h>
   66 #include <sys/proc.h>
   67 #include <sys/systm.h>
   68 #include <sys/bio.h>
   69 #include <sys/buf.h>
   70 #include <sys/bus.h>
   71 #include <sys/cons.h>
   72 #include <sys/cpu.h>
   73 #include <sys/eventhandler.h>
   74 #include <sys/exec.h>
   75 #include <sys/imgact.h>
   76 #include <sys/kdb.h>
   77 #include <sys/kernel.h>
   78 #include <sys/ktr.h>
   79 #include <sys/linker.h>
   80 #include <sys/lock.h>
   81 #include <sys/malloc.h>
   82 #include <sys/mbuf.h>
   83 #include <sys/msgbuf.h>
   84 #include <sys/mutex.h>
   85 #include <sys/ptrace.h>
   86 #include <sys/reboot.h>
   87 #include <sys/rwlock.h>
   88 #include <sys/signalvar.h>
   89 #include <sys/syscallsubr.h>
   90 #include <sys/sysctl.h>
   91 #include <sys/sysent.h>
   92 #include <sys/sysproto.h>
   93 #include <sys/ucontext.h>
   94 #include <sys/uio.h>
   95 #include <sys/vmmeter.h>
   96 #include <sys/vnode.h>
   97 
   98 #include <net/netisr.h>
   99 
  100 #include <vm/vm.h>
  101 #include <vm/vm_extern.h>
  102 #include <vm/vm_kern.h>
  103 #include <vm/vm_page.h>
  104 #include <vm/vm_map.h>
  105 #include <vm/vm_object.h>
  106 #include <vm/vm_pager.h>
  107 
  108 #include <machine/altivec.h>
  109 #ifndef __powerpc64__
  110 #include <machine/bat.h>
  111 #endif
  112 #include <machine/cpu.h>
  113 #include <machine/elf.h>
  114 #include <machine/fpu.h>
  115 #include <machine/hid.h>
  116 #include <machine/kdb.h>
  117 #include <machine/md_var.h>
  118 #include <machine/metadata.h>
  119 #include <machine/mmuvar.h>
  120 #include <machine/pcb.h>
  121 #include <machine/reg.h>
  122 #include <machine/sigframe.h>
  123 #include <machine/spr.h>
  124 #include <machine/trap.h>
  125 #include <machine/vmparam.h>
  126 #include <machine/ofw_machdep.h>
  127 
  128 #include <ddb/ddb.h>
  129 
  130 #include <dev/ofw/openfirm.h>
  131 
  132 int cold = 1;
  133 #ifdef __powerpc64__
  134 int cacheline_size = 128;
  135 #else
  136 int cacheline_size = 32;
  137 #endif
  138 int hw_direct_map = 1;
  139 
  140 extern void *ap_pcpu;
  141 
  142 struct pcpu __pcpu[MAXCPU];
  143 
  144 static struct trapframe frame0;
  145 
  146 char            machine[] = "powerpc";
  147 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
  148 
  149 static void     cpu_startup(void *);
  150 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
  151 
  152 SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
  153            CTLFLAG_RD, &cacheline_size, 0, "");
  154 
  155 uintptr_t       powerpc_init(vm_offset_t, vm_offset_t, vm_offset_t, void *);
  156 
  157 long            Maxmem = 0;
  158 long            realmem = 0;
  159 
  160 struct kva_md_info kmi;
  161 
  162 static void
  163 cpu_startup(void *dummy)
  164 {
  165 
  166         /*
  167          * Initialise the decrementer-based clock.
  168          */
  169         decr_init();
  170 
  171         /*
  172          * Good {morning,afternoon,evening,night}.
  173          */
  174         cpu_setup(PCPU_GET(cpuid));
  175 
  176 #ifdef PERFMON
  177         perfmon_init();
  178 #endif
  179         printf("real memory  = %ju (%ju MB)\n", ptoa((uintmax_t)physmem),
  180             ptoa((uintmax_t)physmem) / 1048576);
  181         realmem = physmem;
  182 
  183         if (bootverbose)
  184                 printf("available KVA = %zu (%zu MB)\n",
  185                     virtual_end - virtual_avail,
  186                     (virtual_end - virtual_avail) / 1048576);
  187 
  188         /*
  189          * Display any holes after the first chunk of extended memory.
  190          */
  191         if (bootverbose) {
  192                 int indx;
  193 
  194                 printf("Physical memory chunk(s):\n");
  195                 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
  196                         vm_paddr_t size1 =
  197                             phys_avail[indx + 1] - phys_avail[indx];
  198 
  199                         #ifdef __powerpc64__
  200                         printf("0x%016jx - 0x%016jx, %jd bytes (%jd pages)\n",
  201                         #else
  202                         printf("0x%09jx - 0x%09jx, %ju bytes (%ju pages)\n",
  203                         #endif
  204                             (uintmax_t)phys_avail[indx],
  205                             (uintmax_t)phys_avail[indx + 1] - 1,
  206                             (uintmax_t)size1, (uintmax_t)size1 / PAGE_SIZE);
  207                 }
  208         }
  209 
  210         vm_ksubmap_init(&kmi);
  211 
  212         printf("avail memory = %ju (%ju MB)\n",
  213             ptoa((uintmax_t)vm_cnt.v_free_count),
  214             ptoa((uintmax_t)vm_cnt.v_free_count) / 1048576);
  215 
  216         /*
  217          * Set up buffers, so they can be used to read disk labels.
  218          */
  219         bufinit();
  220         vm_pager_bufferinit();
  221 }
  222 
  223 extern vm_offset_t      __startkernel, __endkernel;
  224 extern unsigned char    __bss_start[];
  225 extern unsigned char    __sbss_start[];
  226 extern unsigned char    __sbss_end[];
  227 extern unsigned char    _end[];
  228 
  229 void aim_cpu_init(vm_offset_t toc);
  230 void booke_cpu_init(void);
  231 
  232 uintptr_t
  233 powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
  234 {
  235         struct          pcpu *pc;
  236         vm_offset_t     startkernel, endkernel;
  237         void            *kmdp;
  238         char            *env;
  239 #ifdef DDB
  240         vm_offset_t ksym_start;
  241         vm_offset_t ksym_end;
  242 #endif
  243 
  244         kmdp = NULL;
  245 
  246         /* First guess at start/end kernel positions */
  247         startkernel = __startkernel;
  248         endkernel = __endkernel;
  249 
  250         /* Check for ePAPR loader, which puts a magic value into r6 */
  251         if (mdp == (void *)0x65504150)
  252                 mdp = NULL;
  253 
  254 #ifdef AIM
  255         /*
  256          * If running from an FDT, make sure we are in real mode to avoid
  257          * tromping on firmware page tables. Everything in the kernel assumes
  258          * 1:1 mappings out of firmware, so this won't break anything not
  259          * already broken. This doesn't work if there is live OF, since OF
  260          * may internally use non-1:1 mappings.
  261          */
  262         if (ofentry == 0)
  263                 mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
  264 #endif
  265 
  266         /*
  267          * Parse metadata if present and fetch parameters.  Must be done
  268          * before console is inited so cninit gets the right value of
  269          * boothowto.
  270          */
  271         if (mdp != NULL) {
  272                 preload_metadata = mdp;
  273                 kmdp = preload_search_by_type("elf kernel");
  274                 if (kmdp != NULL) {
  275                         boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
  276                         init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *),
  277                             0);
  278                         endkernel = ulmax(endkernel, MD_FETCH(kmdp,
  279                             MODINFOMD_KERNEND, vm_offset_t));
  280 #ifdef DDB
  281                         ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
  282                         ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
  283                         db_fetch_ksymtab(ksym_start, ksym_end);
  284 #endif
  285                 }
  286         } else {
  287                 bzero(__sbss_start, __sbss_end - __sbss_start);
  288                 bzero(__bss_start, _end - __bss_start);
  289                 init_static_kenv(NULL, 0);
  290         }
  291 #ifdef BOOKE
  292         tlb1_init();
  293 #endif
  294 
  295         /* Store boot environment state */
  296         OF_initial_setup((void *)fdt, NULL, (int (*)(void *))ofentry);
  297 
  298         /*
  299          * Init params/tunables that can be overridden by the loader
  300          */
  301         init_param1();
  302 
  303         /*
  304          * Start initializing proc0 and thread0.
  305          */
  306         proc_linkup0(&proc0, &thread0);
  307         thread0.td_frame = &frame0;
  308 
  309         /*
  310          * Set up per-cpu data.
  311          */
  312         pc = __pcpu;
  313         pcpu_init(pc, 0, sizeof(struct pcpu));
  314         pc->pc_curthread = &thread0;
  315 #ifdef __powerpc64__
  316         __asm __volatile("mr 13,%0" :: "r"(pc->pc_curthread));
  317 #else
  318         __asm __volatile("mr 2,%0" :: "r"(pc->pc_curthread));
  319 #endif
  320         pc->pc_cpuid = 0;
  321 
  322         __asm __volatile("mtsprg 0, %0" :: "r"(pc));
  323 
  324         /*
  325          * Init mutexes, which we use heavily in PMAP
  326          */
  327 
  328         mutex_init();
  329 
  330         /*
  331          * Install the OF client interface
  332          */
  333 
  334         OF_bootstrap();
  335 
  336         /*
  337          * Initialize the console before printing anything.
  338          */
  339         cninit();
  340 
  341         /*
  342          * Complain if there is no metadata.
  343          */
  344         if (mdp == NULL || kmdp == NULL) {
  345                 printf("powerpc_init: no loader metadata.\n");
  346         }
  347 
  348         /*
  349          * Init KDB
  350          */
  351 
  352         kdb_init();
  353 
  354 #ifdef AIM
  355         aim_cpu_init(toc);
  356 #else /* BOOKE */
  357         booke_cpu_init();
  358 
  359         /* Make sure the kernel icache is valid before we go too much further */
  360         __syncicache((caddr_t)startkernel, endkernel - startkernel);
  361 #endif
  362 
  363         /*
  364          * Choose a platform module so we can get the physical memory map.
  365          */
  366 
  367         platform_probe_and_attach();
  368 
  369         /*
  370          * Bring up MMU
  371          */
  372         pmap_bootstrap(startkernel, endkernel);
  373         mtmsr(PSL_KERNSET & ~PSL_EE);
  374 
  375         /*
  376          * Initialize params/tunables that are derived from memsize
  377          */
  378         init_param2(physmem);
  379 
  380         /*
  381          * Grab booted kernel's name
  382          */
  383         env = kern_getenv("kernelname");
  384         if (env != NULL) {
  385                 strlcpy(kernelname, env, sizeof(kernelname));
  386                 freeenv(env);
  387         }
  388 
  389         /*
  390          * Finish setting up thread0.
  391          */
  392         thread0.td_pcb = (struct pcb *)
  393             ((thread0.td_kstack + thread0.td_kstack_pages * PAGE_SIZE -
  394             sizeof(struct pcb)) & ~15UL);
  395         bzero((void *)thread0.td_pcb, sizeof(struct pcb));
  396         pc->pc_curpcb = thread0.td_pcb;
  397 
  398         /* Initialise the message buffer. */
  399         msgbufinit(msgbufp, msgbufsize);
  400 
  401 #ifdef KDB
  402         if (boothowto & RB_KDB)
  403                 kdb_enter(KDB_WHY_BOOTFLAGS,
  404                     "Boot flags requested debugger");
  405 #endif
  406 
  407         return (((uintptr_t)thread0.td_pcb -
  408             (sizeof(struct callframe) - 3*sizeof(register_t))) & ~15UL);
  409 }
  410 
  411 void
  412 bzero(void *buf, size_t len)
  413 {
  414         caddr_t p;
  415 
  416         p = buf;
  417 
  418         while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) {
  419                 *p++ = 0;
  420                 len--;
  421         }
  422 
  423         while (len >= sizeof(u_long) * 8) {
  424                 *(u_long*) p = 0;
  425                 *((u_long*) p + 1) = 0;
  426                 *((u_long*) p + 2) = 0;
  427                 *((u_long*) p + 3) = 0;
  428                 len -= sizeof(u_long) * 8;
  429                 *((u_long*) p + 4) = 0;
  430                 *((u_long*) p + 5) = 0;
  431                 *((u_long*) p + 6) = 0;
  432                 *((u_long*) p + 7) = 0;
  433                 p += sizeof(u_long) * 8;
  434         }
  435 
  436         while (len >= sizeof(u_long)) {
  437                 *(u_long*) p = 0;
  438                 len -= sizeof(u_long);
  439                 p += sizeof(u_long);
  440         }
  441 
  442         while (len) {
  443                 *p++ = 0;
  444                 len--;
  445         }
  446 }
  447 
  448 /*
  449  * Flush the D-cache for non-DMA I/O so that the I-cache can
  450  * be made coherent later.
  451  */
  452 void
  453 cpu_flush_dcache(void *ptr, size_t len)
  454 {
  455         register_t addr, off;
  456 
  457         /*
  458          * Align the address to a cacheline and adjust the length
  459          * accordingly. Then round the length to a multiple of the
  460          * cacheline for easy looping.
  461          */
  462         addr = (uintptr_t)ptr;
  463         off = addr & (cacheline_size - 1);
  464         addr -= off;
  465         len = roundup2(len + off, cacheline_size);
  466 
  467         while (len > 0) {
  468                 __asm __volatile ("dcbf 0,%0" :: "r"(addr));
  469                 __asm __volatile ("sync");
  470                 addr += cacheline_size;
  471                 len -= cacheline_size;
  472         }
  473 }
  474 
  475 int
  476 ptrace_set_pc(struct thread *td, unsigned long addr)
  477 {
  478         struct trapframe *tf;
  479 
  480         tf = td->td_frame;
  481         tf->srr0 = (register_t)addr;
  482 
  483         return (0);
  484 }
  485 
  486 void
  487 spinlock_enter(void)
  488 {
  489         struct thread *td;
  490         register_t msr;
  491 
  492         td = curthread;
  493         if (td->td_md.md_spinlock_count == 0) {
  494                 __asm __volatile("or 2,2,2"); /* Set high thread priority */
  495                 msr = intr_disable();
  496                 td->td_md.md_spinlock_count = 1;
  497                 td->td_md.md_saved_msr = msr;
  498         } else
  499                 td->td_md.md_spinlock_count++;
  500         critical_enter();
  501 }
  502 
  503 void
  504 spinlock_exit(void)
  505 {
  506         struct thread *td;
  507         register_t msr;
  508 
  509         td = curthread;
  510         critical_exit();
  511         msr = td->td_md.md_saved_msr;
  512         td->td_md.md_spinlock_count--;
  513         if (td->td_md.md_spinlock_count == 0) {
  514                 intr_restore(msr);
  515                 __asm __volatile("or 6,6,6"); /* Set normal thread priority */
  516         }
  517 }
  518 

Cache object: 2587c27b6d6d94d0c518940aafbf2e2e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.