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/osfmk/ppc/ppc_vm_init.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) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_COPYRIGHT@
   27  */
   28 /*
   29  * @APPLE_FREE_COPYRIGHT@
   30  */
   31 
   32 #include <mach_debug.h>
   33 #include <mach_kdb.h>
   34 #include <mach_kdp.h>
   35 #include <debug.h>
   36 #include <cpus.h>
   37 
   38 #include <mach/vm_types.h>
   39 #include <mach/vm_param.h>
   40 #include <mach/thread_status.h>
   41 #include <kern/misc_protos.h>
   42 #include <kern/assert.h>
   43 #include <kern/cpu_number.h>
   44 
   45 #include <ppc/proc_reg.h>
   46 #include <ppc/Firmware.h>
   47 #include <ppc/boot.h>
   48 #include <ppc/misc_protos.h>
   49 #include <ppc/pmap.h>
   50 #include <ppc/mem.h>
   51 #include <ppc/mappings.h>
   52 #include <ppc/exception.h>
   53 #include <ppc/mp.h>
   54 #include <ppc/lowglobals.h>
   55 
   56 #include <mach-o/mach_header.h>
   57 
   58 extern const char version[];
   59 extern const char version_variant[];
   60 
   61 extern unsigned int intstack[];                 /* declared in aligned_data.s */
   62 extern unsigned int intstack_top_ss;    /* declared in aligned_data.s */
   63 
   64 addr64_t hash_table_base;                               /* Hash table base */
   65 unsigned int hash_table_size;                   /* Hash table size */
   66 vm_offset_t taproot_addr;                               /* (BRINGUP) */
   67 unsigned int taproot_size;                              /* (BRINGUP) */
   68 unsigned int serialmode;                                /* Serial mode keyboard and console control */
   69 extern int disableConsoleOutput;
   70 
   71 struct shadowBAT shadow_BAT;
   72 
   73 /*
   74  *      NOTE: mem_size is bogus on large memory machines.  We will pin it to 0x80000000 if there is more than 2 GB
   75  *      This is left only for compatibility and max_mem should be used.
   76  */
   77 vm_offset_t mem_size;                                   /* Size of actual physical memory present
   78                                                                                    minus any performance buffer and possibly limited
   79                                                                                    by mem_limit in bytes */
   80 uint64_t        mem_actual;                                     /* The "One True" physical memory size 
   81                                                                                    actually, it's the highest physical address + 1 */
   82 uint64_t        max_mem;                                        /* Size of physical memory (bytes), adjusted by maxmem */
   83 uint64_t        sane_size;                                      /* Memory size to use for defaults calculations */
   84                                                   
   85 
   86 mem_region_t pmap_mem_regions[PMAP_MEM_REGION_MAX + 1];
   87 int      pmap_mem_regions_count = 0;            /* Assume no non-contiguous memory regions */
   88 
   89 unsigned int avail_remaining = 0;
   90 vm_offset_t first_avail;
   91 vm_offset_t static_memory_end;
   92 addr64_t vm_last_addr = VM_MAX_KERNEL_ADDRESS;  /* Highest kernel virtual address known to the VM system */
   93 
   94 extern struct mach_header _mh_execute_header;
   95 vm_offset_t sectTEXTB;
   96 int sectSizeTEXT;
   97 vm_offset_t sectDATAB;
   98 int sectSizeDATA;
   99 vm_offset_t sectLINKB;
  100 int sectSizeLINK;
  101 vm_offset_t sectKLDB;
  102 int sectSizeKLD;
  103 vm_offset_t sectPRELINKB;
  104 int sectSizePRELINK;
  105 
  106 vm_offset_t end, etext, edata;
  107 
  108 extern unsigned long exception_entry;
  109 extern unsigned long exception_end;
  110 
  111 
  112 void ppc_vm_init(uint64_t mem_limit, boot_args *args)
  113 {
  114         unsigned int htabmask;
  115         unsigned int i, j, batsize, kmapsize, pvr;
  116         vm_offset_t  addr, ioAddr, videoAddr;
  117         int boot_task_end_offset;
  118         const char *cpus;
  119         mapping         *mp;
  120         vm_offset_t             sizeadj, oldstart;
  121         unsigned int *xtaproot, bank_shift;
  122         uint64_t        cbsize, xhid0;
  123 
  124 
  125 /*
  126  *      Invalidate all shadow BATs
  127  */
  128 
  129         /* Initialize shadow IBATs */
  130         shadow_BAT.IBATs[0].upper=BAT_INVALID;
  131         shadow_BAT.IBATs[0].lower=BAT_INVALID;
  132         shadow_BAT.IBATs[1].upper=BAT_INVALID;
  133         shadow_BAT.IBATs[1].lower=BAT_INVALID;
  134         shadow_BAT.IBATs[2].upper=BAT_INVALID;
  135         shadow_BAT.IBATs[2].lower=BAT_INVALID;
  136         shadow_BAT.IBATs[3].upper=BAT_INVALID;
  137         shadow_BAT.IBATs[3].lower=BAT_INVALID;
  138 
  139         /* Initialize shadow DBATs */
  140         shadow_BAT.DBATs[0].upper=BAT_INVALID;
  141         shadow_BAT.DBATs[0].lower=BAT_INVALID;
  142         shadow_BAT.DBATs[1].upper=BAT_INVALID;
  143         shadow_BAT.DBATs[1].lower=BAT_INVALID;
  144         shadow_BAT.DBATs[2].upper=BAT_INVALID;
  145         shadow_BAT.DBATs[2].lower=BAT_INVALID;
  146         shadow_BAT.DBATs[3].upper=BAT_INVALID;
  147         shadow_BAT.DBATs[3].lower=BAT_INVALID;
  148 
  149 
  150         /*
  151          * Go through the list of memory regions passed in via the boot_args
  152          * and copy valid entries into the pmap_mem_regions table, adding
  153          * further calculated entries.
  154          *
  155          * boot_args version 1 has address instead of page numbers
  156          * in the PhysicalDRAM banks, set bank_shift accordingly.
  157          */
  158         
  159         bank_shift = 0;
  160         if (args->Version == kBootArgsVersion1) bank_shift = 12;
  161         
  162         pmap_mem_regions_count = 0;
  163         max_mem = 0;                                                                                                                    /* Will use to total memory found so far */
  164         mem_actual = 0;                                                                                                                 /* Actual size of memory */
  165         
  166         if (mem_limit == 0) mem_limit = 0xFFFFFFFFFFFFFFFFULL;                                  /* If there is no set limit, use all */
  167         
  168         for (i = 0; i < kMaxDRAMBanks; i++) {                                                                   /* Look at all of the banks */
  169                 
  170                 cbsize = (uint64_t)args->PhysicalDRAM[i].size << (12 - bank_shift);     /* Remember current size */
  171                 
  172                 if (!cbsize) continue;                                                                                          /* Skip if the bank is empty */
  173                 
  174                 mem_actual = mem_actual + cbsize;                                                                       /* Get true memory size */
  175 
  176                 if(mem_limit == 0) continue;                                                                            /* If we hit restriction, just keep counting */
  177 
  178                 if (cbsize > mem_limit) cbsize = mem_limit;                                                     /* Trim to max allowed */
  179                 max_mem += cbsize;                                                                                                      /* Total up what we have so far */
  180                 mem_limit = mem_limit - cbsize;                                                                         /* Calculate amount left to do */
  181                 
  182                 pmap_mem_regions[pmap_mem_regions_count].mrStart  = args->PhysicalDRAM[i].base >> bank_shift;   /* Set the start of the bank */
  183                 pmap_mem_regions[pmap_mem_regions_count].mrAStart = pmap_mem_regions[pmap_mem_regions_count].mrStart;           /* Set the start of allocatable area */
  184                 pmap_mem_regions[pmap_mem_regions_count].mrEnd    = ((uint64_t)args->PhysicalDRAM[i].base >> bank_shift) + (cbsize >> 12) - 1;  /* Set the end address of bank */
  185                 pmap_mem_regions[pmap_mem_regions_count].mrAEnd   = pmap_mem_regions[pmap_mem_regions_count].mrEnd;     /* Set the end address of allocatable area */
  186 
  187                 /* Regions must be provided in ascending order */
  188                 assert ((pmap_mem_regions_count == 0) ||
  189                         pmap_mem_regions[pmap_mem_regions_count].mrStart >
  190                         pmap_mem_regions[pmap_mem_regions_count-1].mrStart);
  191 
  192                 pmap_mem_regions_count++;                                                                                       /* Count this region */
  193         }
  194         
  195         mem_size = (unsigned int)max_mem;                                                                               /* Get size of memory */
  196         if(max_mem > 0x0000000080000000ULL) mem_size = 0x80000000;                              /* Pin at 2 GB */
  197 
  198         sane_size = max_mem;                                                                                                    /* Calculate a sane value to use for init */
  199         if(sane_size > (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1)) 
  200                 sane_size = (addr64_t)(VM_MAX_KERNEL_ADDRESS + 1);                                      /* If flush with ram, use addressible portion */
  201 
  202 
  203 /* 
  204  * Initialize the pmap system, using space above `first_avail'
  205  * for the necessary data structures.
  206  * NOTE : assume that we'll have enough space mapped in already
  207  */
  208 
  209         first_avail = static_memory_end;
  210 
  211 /* Now retrieve addresses for end, edata, and etext 
  212  * from MACH-O headers.
  213  */
  214         sectTEXTB = (vm_offset_t)getsegdatafromheader(
  215                 &_mh_execute_header, "__TEXT", &sectSizeTEXT);
  216         sectDATAB = (vm_offset_t)getsegdatafromheader(
  217                 &_mh_execute_header, "__DATA", &sectSizeDATA);
  218         sectLINKB = (vm_offset_t)getsegdatafromheader(
  219                 &_mh_execute_header, "__LINKEDIT", &sectSizeLINK);
  220         sectKLDB = (vm_offset_t)getsegdatafromheader(
  221                 &_mh_execute_header, "__KLD", &sectSizeKLD);
  222         sectPRELINKB = (vm_offset_t)getsegdatafromheader(
  223                 &_mh_execute_header, "__PRELINK", &sectSizePRELINK);
  224 
  225         etext = (vm_offset_t) sectTEXTB + sectSizeTEXT;
  226         edata = (vm_offset_t) sectDATAB + sectSizeDATA;
  227         end = round_page_32(getlastaddr());                                     /* Force end to next page */
  228         
  229         kmapsize = (round_page_32(exception_end) - trunc_page_32(exception_entry)) +    /* Get size we will map later */
  230                 (round_page_32(sectTEXTB+sectSizeTEXT) - trunc_page_32(sectTEXTB)) +
  231                 (round_page_32(sectDATAB+sectSizeDATA) - trunc_page_32(sectDATAB)) +
  232                 (round_page_32(sectLINKB+sectSizeLINK) - trunc_page_32(sectLINKB)) +
  233                 (round_page_32(sectKLDB+sectSizeKLD) - trunc_page_32(sectKLDB)) +
  234                 (round_page_32(sectPRELINKB+sectSizePRELINK) - trunc_page_32(sectPRELINKB)) +
  235                 (round_page_32(static_memory_end) - trunc_page_32(end));
  236 
  237         pmap_bootstrap(max_mem, &first_avail, kmapsize);
  238 
  239         pmap_map(trunc_page_32(exception_entry), trunc_page_32(exception_entry), 
  240                 round_page_32(exception_end), VM_PROT_READ|VM_PROT_EXECUTE);
  241 
  242         pmap_map(trunc_page_32(sectTEXTB), trunc_page_32(sectTEXTB), 
  243                 round_page_32(sectTEXTB+sectSizeTEXT), VM_PROT_READ|VM_PROT_EXECUTE);
  244 
  245         pmap_map(trunc_page_32(sectDATAB), trunc_page_32(sectDATAB), 
  246                 round_page_32(sectDATAB+sectSizeDATA), VM_PROT_READ|VM_PROT_WRITE);
  247 
  248 /* The KLD and LINKEDIT segments are unloaded in toto after boot completes,
  249 * but via ml_static_mfree(), through IODTFreeLoaderInfo(). Hence, we have
  250 * to map both segments page-by-page.
  251 */
  252         
  253         for (addr = trunc_page_32(sectPRELINKB);
  254              addr < round_page_32(sectPRELINKB+sectSizePRELINK);
  255              addr += PAGE_SIZE) {
  256 
  257             pmap_enter(kernel_pmap, addr, addr>>12, 
  258                         VM_PROT_READ|VM_PROT_WRITE, 
  259                         VM_WIMG_USE_DEFAULT, TRUE);
  260 
  261         }
  262 
  263         for (addr = trunc_page_32(sectKLDB);
  264              addr < round_page_32(sectKLDB+sectSizeKLD);
  265              addr += PAGE_SIZE) {
  266 
  267             pmap_enter(kernel_pmap, addr, addr>>12, 
  268                         VM_PROT_READ|VM_PROT_WRITE, 
  269                         VM_WIMG_USE_DEFAULT, TRUE);
  270 
  271         }
  272 
  273         for (addr = trunc_page_32(sectLINKB);
  274              addr < round_page_32(sectLINKB+sectSizeLINK);
  275              addr += PAGE_SIZE) {
  276 
  277            pmap_enter(kernel_pmap, addr, addr>>12, 
  278                         VM_PROT_READ|VM_PROT_WRITE, 
  279                         VM_WIMG_USE_DEFAULT, TRUE);
  280 
  281         }
  282 
  283         pmap_enter(kernel_pmap, &sharedPage, (unsigned int)&sharedPage >> 12,   /* Make sure the sharedPage is mapped */
  284                 VM_PROT_READ|VM_PROT_WRITE, 
  285                 VM_WIMG_USE_DEFAULT, TRUE);
  286 
  287         pmap_enter(kernel_pmap, &lowGlo, (unsigned int)&lowGlo >> 12,                   /* Make sure the low memory globals are mapped */
  288                 VM_PROT_READ|VM_PROT_WRITE, 
  289                 VM_WIMG_USE_DEFAULT, TRUE);
  290                 
  291 /*
  292  *      We need to map the remainder page-by-page because some of this will
  293  *      be released later, but not all.  Ergo, no block mapping here 
  294  */
  295 
  296         for(addr = trunc_page_32(end); addr < round_page_32(static_memory_end); addr += PAGE_SIZE) {
  297 
  298                 pmap_enter(kernel_pmap, addr, addr>>12, 
  299                         VM_PROT_READ|VM_PROT_WRITE, 
  300                         VM_WIMG_USE_DEFAULT, TRUE);
  301 
  302         }
  303 
  304         MapUserAddressSpaceInit();                      /* Go initialize copy in/out */
  305 
  306 /*
  307  *      At this point, there is enough mapped memory and all hw mapping structures are
  308  *      allocated and initialized.  Here is where we turn on translation for the
  309  *      VERY first time....
  310  *
  311  *      NOTE: Here is where our very first interruption will happen.
  312  *
  313  */
  314 
  315         hw_start_trans();                                       /* Start translating */
  316 
  317 #if 0
  318         GratefulDebInit((bootBumbleC *)&(args->Video)); /* Initialize the GratefulDeb debugger */
  319 #endif
  320 
  321 
  322         printf_init();                                          /* Init this in case we need debugger */
  323         panic_init();                                           /* Init this in case we need debugger */
  324         PE_init_kprintf(TRUE);                          /* Note on PPC we only call this after VM is set up */
  325 
  326         kprintf("kprintf initialized\n");
  327 
  328         serialmode = 0;                                         /* Assume normal keyboard and console */
  329         if(PE_parse_boot_arg("serial", &serialmode)) {          /* Do we want a serial keyboard and/or console? */
  330                 kprintf("Serial mode specified: %08X\n", serialmode);
  331         }
  332         if(serialmode & 1) {                            /* Start serial if requested */
  333                 (void)switch_to_serial_console();       /* Switch into serial mode */
  334                 disableConsoleOutput = FALSE;   /* Allow printfs to happen */
  335         }
  336         
  337         kprintf("max_mem: %ld M\n", (unsigned long)(max_mem >> 20));
  338         kprintf("version_variant = %s\n", version_variant);
  339         kprintf("version         = %s\n\n", version);
  340         __asm__ ("mfpvr %0" : "=r" (pvr));
  341         kprintf("proc version    = %08x\n", pvr);
  342         if(per_proc_info[0].pf.Available & pf64Bit) {   /* 64-bit processor? */
  343                 xhid0 = hid0get64();                    /* Get the hid0 */
  344                 if(xhid0 & (1ULL << (63 - 19))) kprintf("Time base is externally clocked\n");
  345                 else kprintf("Time base is internally clocked\n");
  346         }
  347 
  348 
  349         taproot_size = PE_init_taproot(&taproot_addr);  /* (BRINGUP) See if there is a taproot */
  350         if(taproot_size) {                                      /* (BRINGUP) */
  351                 kprintf("TapRoot card configured to use vaddr = %08X, size = %08X\n", taproot_addr, taproot_size);
  352                 bcopy_nc((void *)version, (void *)(taproot_addr + 16), strlen(version));        /* (BRINGUP) Pass it our kernel version */
  353                 __asm__ volatile("eieio");              /* (BRINGUP) */
  354                 xtaproot = (unsigned int *)taproot_addr;        /* (BRINGUP) */
  355                 xtaproot[0] = 1;                                /* (BRINGUP) */
  356                 __asm__ volatile("eieio");              /* (BRINGUP) */
  357         }
  358 
  359         PE_create_console();                            /* create the console for verbose or pretty mode */
  360 
  361         /* setup console output */
  362         PE_init_printf(FALSE);
  363 
  364 #if DEBUG
  365         printf("\n\n\nThis program was compiled using gcc %d.%d for powerpc\n",
  366                __GNUC__,__GNUC_MINOR__);
  367 
  368 
  369         /* Processor version information */
  370         {       
  371                 unsigned int pvr;
  372                 __asm__ ("mfpvr %0" : "=r" (pvr));
  373                 printf("processor version register : %08X\n", pvr);
  374         }
  375 
  376         kprintf("Args at %08X\n", args);
  377         for (i = 0; i < pmap_mem_regions_count; i++) {
  378                         printf("DRAM at %08X size %08X\n",
  379                                args->PhysicalDRAM[i].base,
  380                                args->PhysicalDRAM[i].size);
  381         }
  382 #endif /* DEBUG */
  383 
  384 #if DEBUG
  385         kprintf("Mapped memory:\n");
  386         kprintf("   exception vector: %08X, %08X - %08X\n", trunc_page_32(exception_entry), 
  387                 trunc_page_32(exception_entry), round_page_32(exception_end));
  388         kprintf("          sectTEXTB: %08X, %08X - %08X\n", trunc_page_32(sectTEXTB), 
  389                 trunc_page_32(sectTEXTB), round_page_32(sectTEXTB+sectSizeTEXT));
  390         kprintf("          sectDATAB: %08X, %08X - %08X\n", trunc_page_32(sectDATAB), 
  391                 trunc_page_32(sectDATAB), round_page_32(sectDATAB+sectSizeDATA));
  392         kprintf("          sectLINKB: %08X, %08X - %08X\n", trunc_page_32(sectLINKB), 
  393                 trunc_page_32(sectLINKB), round_page_32(sectLINKB+sectSizeLINK));
  394         kprintf("           sectKLDB: %08X, %08X - %08X\n", trunc_page_32(sectKLDB), 
  395                 trunc_page_32(sectKLDB), round_page_32(sectKLDB+sectSizeKLD));
  396         kprintf("                end: %08X, %08X - %08X\n", trunc_page_32(end), 
  397                 trunc_page_32(end), static_memory_end);
  398 
  399 #endif
  400 
  401         return;
  402 }
  403 
  404 void ppc_vm_cpu_init(
  405         struct per_proc_info *proc_info)
  406 {
  407         hw_setup_trans();                                                                       /* Set up hardware needed for translation */
  408         hw_start_trans();                                                                       /* Start translating */
  409 }

Cache object: 1f87f385dff0ea84ecfd5b35f2d56211


[ 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.