startup.c revision ca622e3ab18bb72e81149987556769fb415fb5da
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * Global Data Definitions: 2N/A * XXX - Don't port this to new architectures 2N/A * A 3rd party volume manager driver (vxdm) depends on the symbol romp. 2N/A * 'romp' has no use with a prom with an IEEE 1275 client interface. 2N/A * The driver doesn't use the value, but it depends on the symbol. 2N/Avoid *
romp;
/* veritas driver won't load without romp 4154976 */ * Declare these as initialized data so we can patch them. pgcnt_t physmem = 0;
/* memory size in pages, patch if you want less */ int use_cache =
1;
/* cache not reliable (605 bugs) with MP */ * End of first block of contiguous kernel in 32-bit virtual address space struct memlist ndata;
/* memlist of nucleus allocatable memory */ long page_hashsz;
/* Size of page hash table (power of two) */ struct page *
pp_base;
/* Base of system page struct array */ struct seg ktextseg;
/* Segment used for kernel executable image */ struct seg kvalloc;
/* Segment used for "valloc" mapping */ struct seg kpseg;
/* Segment used for pageable kernel virt mem */ struct seg ktexthole;
/* Segment used for nucleus text hole */ struct seg kmapseg;
/* Segment used for generic kernel mappings */ struct seg kpmseg;
/* Segment used for physical mapping */ struct seg kdebugseg;
/* Segment used for the kernel debugger */ struct seg *
segkp = &
kpseg;
/* Pageable kernel virtual memory segment */ * debugger pages (if allocated) * VA range available to the debugger * Segment for relocated kernel structures in 64-bit large RAM kernels * VM data structures allocated early during boot. * Hooks for unsupported platforms and down-rev firmware * After receiving a thermal interrupt, this is the number of seconds * to delay before shutting off the system, assuming * shutdown fails. Use /etc/system to change the delay if this isn't * Used to hold off page relocations into the cage until OBP has completed * its boot-time handoff of its resources to the kernel. * Indicate if kmem64 allocation was done in small chunks * Enable some debugging messages concerning memory usage... "pfn = 0x%x, epfn = 0x%x\n",
#
else /* DEBUGGING_MEM */#
endif /* DEBUGGING_MEM */ * Kernel's Virtual Memory Layout. * /-----------------------\ * 0xFFFFFFFF.FFFFFFFF -| |- * 0xFFFFFFFC.00000000 -|-----------------------|- * -|-----------------------|- * | segzio | (base and size vary) * 0xFFFFFE00.00000000 -|-----------------------|- * | | Ultrasparc I/II support * | segkpm segment | up to 2TB of physical * | (64-bit kernel ONLY) | memory, VAC has 2 colors * 0xFFFFFA00.00000000 -|-----------------------|- 2TB segkpm alignment * 0xFFFFF810.00000000 -|-----------------------|- hole_end * | UltraSPARC I/II call | | * | bug requires an extra | | * | 4 GB of space between | | * | hole and used RAM | | * 0xFFFFF800.00000000 -|-----------------------|- | * | Virtual Address Hole | UltraSPARC * | on UltraSPARC I/II | I/II * ONLY * * 0x00000800.00000000 -|-----------------------|- | * | UltraSPARC I/II call | | * | bug requires an extra | | * | 4 GB of space between | | * | hole and used RAM | | * 0x000007FF.00000000 -|-----------------------|- hole_start ----- * |-----------------------| | * | ecache flush area | | * | (twice largest e$) | | * 0x00000XXX.XXX00000 -|-----------------------|- kmem64_ | * | overmapped area | alignend_end | * | (kmem64_alignsize | | * 0x00000XXX.XXXXXXXX -|-----------------------|- kmem64_end | * | 64-bit kernel ONLY | | * | (Relocated extra HME | Approximately * | block allocations, | 1 TB of virtual * | memnode freelists, | address space * | HME hash buckets, | | * | mml_table, kpmp_table,| | * | hashblock pool to | | * 0x00000700.00000000 -|-----------------------|- SYSLIMIT (kmem64_base) * | segkmem segment | (SYSLIMIT - SYSBASE = 4TB) * 0x00000300.00000000 -|-----------------------|- SYSBASE * -|-----------------------|- * | segmap segment | SEGMAPSIZE (1/8th physmem, * 0x000002a7.50000000 -|-----------------------|- SEGMAPBASE * -|-----------------------|- * | segkp | SEGKPSIZE (2GB) * 0x000002a1.00000000 -|-----------------------|- SEGKPBASE * 0x000002a0.00000000 -|-----------------------|- MEMSCRUBBASE * | | (SEGKPBASE - 0x400000) * 0x0000029F.FFE00000 -|-----------------------|- ARGSBASE * | | (MEMSCRUBBASE - NCARGS) * 0x0000029F.FFD80000 -|-----------------------|- PPMAPBASE * | | (ARGSBASE - PPMAPSIZE) * 0x0000029F.FFD00000 -|-----------------------|- PPMAP_FAST_BASE * 0x0000029F.FF980000 -|-----------------------|- PIOMAPBASE * 0x0000029F.FF580000 -|-----------------------|- NARG_BASE * 0x00000000.FFFFFFFF -|-----------------------|- OFW_END_ADDR * 0x00000000.F0000000 -|-----------------------|- OFW_START_ADDR * 0x00000000.EDD00000 -|-----------------------|- SEGDEBUGBASE * 0x00000000.7c000000 -|-----------------------|- SYSLIMIT32 * | segkmem32 segment | (SYSLIMIT32 - SYSBASE32 = * 0x00000000.70002000 -|-----------------------| * 0x00000000.70000000 -|-----------------------|- SYSBASE32 * 0x00000000.4C000000 -|-----------------------|- BOOTTMPBASE * |-----------------------|- econtig32 * 0x00000000.01C00000 |-----------------------|- nalloc_end * 0x00000000.01800000 -|-----------------------| * 0x00000000.01400000 -|-----------------------| * |-----------------------| * |-----------------------| * 0x00000000.01000000 -|-----------------------|- KERNELBASE * | reserved for trapstat |} TSTAT_TOTAL_SIZE * |-----------------------| * 0x00000000.00000000 _|_______________________| * 32-bit User Virtual Memory Layout. * /-----------------------\ * 0xFFC00000 -|-----------------------|- USERLIMIT * -|-----------------------|- * 0x00002000 -|-----------------------|- * 0x00000000 _|_______________________| * 64-bit User Virtual Memory Layout. * /-----------------------\ * 0xFFFFFFFF.80000000 -|-----------------------|- USERLIMIT * -|-----------------------|- * 0x00000000.01000000 -|-----------------------|- * 0x00000000.00000000 _|_______________________| * By default the DR Cage is enabled for maximum OS * MPSS performance. Users needing to disable the cage mechanism * can set this variable to zero via /etc/system. * Disabling the cage on systems supporting Dynamic Reconfiguration (DR) * will result in loss of DR functionality. * Platforms wishing to disable kernel Cage by default * should do so in their set_platform_defaults() routine. * Machine-dependent startup code * Prevent trying to talk to the other CPUs since they are * sitting in the prom and won't reply. for (i = 0; i <
NCPU; i++) {
* We've managed to get here without going through the * normal panic code path. Try and save some useful * If we're re-entering the panic path, update the signature * block so that the SC knows we're in the second part of panic. nopanicdebug =
1;
/* do not perform debug_enter() prior to dump */ * We want to save the registers while we're still in OBP * so that we know they haven't been fiddled with since. * (In principle, OBP can't change them just because it * makes a callback, but we'd rather not depend on that "warning @ warning off : sync " "%%tl-c %%tstate h# %p x! " "%%g1 h# %p x! %%g2 h# %p x! %%g3 h# %p x! " "%%g4 h# %p x! %%g5 h# %p x! %%g6 h# %p x! " "%%g7 h# %p x! %%o0 h# %p x! %%o1 h# %p x! " "%%o2 h# %p x! %%o3 h# %p x! %%o4 h# %p x! " "%%o5 h# %p x! %%o6 h# %p x! %%o7 h# %p x! " "%%tl-c %%tpc h# %p x! %%tl-c %%tnpc h# %p x! " "%%y h# %p l! %%tl-c %%tt h# %p x! " * 20 == num of %p substrings * 16 == max num of chars %p will expand to. * Initialize ptl1 stack for the 1st CPU. * Initialize the address map for cache consistent mappings * to random pages; must be done after vac_size is set. * Initialize the PROM callback handler. * have prom call sync_callback() to handle the sync and * save some useful information which will be stored in the * Avoid fragmentation problems in kphysm_init() * by allocating for all of physical memory * The page structure hash table size is a power of 2 * such that the average hash chain length is PAGE_HASHAVELEN. * Make one large memory alloc after figuring out the 64-bit size. This * will enable use of the largest page size appropriate for the system /* limit page size for small memory */ /* return failure to try small allocations */ * Install a temporary tte handler in OBP for kmem64 area. * We map kmem64 area with large pages before the trap table is taken * over. Since OBP makes 8K mappings, it can create 8K tlb entries in * the same area. Duplicate tlb entries with different page sizes * cause unpredicatble behavior. To avoid this, we don't create * kmem64 mappings via BOP_ALLOC (ends up as prom_alloc() call to * OBP). Instead, we manage translations with a temporary va>tte-data * handler (kmem64-tte). This handler is replaced by unix-tte when * the trap table is taken over. * The temporary handler knows the physical address of the kmem64 * area. It uses the prom's pgmap@ Forth word for other addresses. * We have to use BOP_ALLOC() method for C-OBP platforms because * pgmap@ is not defined in C-OBP. C-OBP is only used on serengeti * sun4u platforms. On sun4u we flush tlb after trap table is taken * over if we use large pages for kernel heap and kmem64. Since sun4u * prom (unlike sun4v) calls va>tte-data first for client address * translation prom's ttes for kmem64 can't get into TLB even if we * later switch to prom's trap table again. C-OBP uses 4M pages for * client mappings when possible so on all platforms we get the * benefit from large mappings for kmem64 area immediately during * } else if (miss_va in range[kmem64_base, kmem64_end)) { * (((miss_va & pagemask) - kmem64_base)); "h# %lx constant kmem64-base " "h# %lx constant kmem64-end " "h# %lx constant kmem64-pagemask " "h# %lx constant kmem64-template " ": kmem64-tte ( addr cnum -- false | tte-data true ) " " drop false exit then ( false ) " " dup kmem64-base kmem64-end within if ( addr ) " " kmem64-pagemask and ( addr' ) " " kmem64-base - ( addr' ) " " kmem64-template + ( tte ) " " dup 0< if true else drop false then ( tte true | false ) " " then ( tte true | false ) " "' kmem64-tte is va>tte-data " * As OBP takes up some RAM when the system boots, pages will already be "lost" * to the system and reflected in npages by the time we see it. * We only want to allocate kernel structures in the 64-bit virtual address * space on systems with enough RAM to make the overhead of keeping track of * an extra kernel memory segment worthwhile. * Since OBP has already performed its memory allocations by this point, if we * have more than MINMOVE_RAM_MB MB of RAM left free, go ahead and map * memory in the 64-bit virtual address space; otherwise keep allocations * contiguous with we've mapped so far in the 32-bit virtual address space. * Initialize enough of the system to allow kmem_alloc to work by * calling boot to allocate its memory until the time that * kvm_init is completed. The page structs are allocated after * rounding up end to the nearest page boundary; the memsegs are * initialized and the space they use comes from the kernel heap. * With appropriate initialization, they can be reallocated later * to a size appropriate for the machine's configuration. * At this point, memory is allocated for things that will never * need to be freed, this used to be "valloced". This allows a * savings as the pages don't need page structures to describe * them because them will not be managed by the vm system. * We're loaded by boot with the following configuration (as * text: 4 MB chunk aligned on a 4MB boundary * data & bss: 4 MB chunk aligned on a 4MB boundary * These two chunks will eventually be mapped by 2 locked 4MB * ttes and will represent the nucleus of the kernel. This gives * us some free space that is already allocated, some or all of * which is made available to kernel module text. * The free space in the data-bss chunk is used for nucleus * allocatable data structures and we reserve it using the * nalloc_base and nalloc_end variables. This space is currently * being used for hat data structures required for tlb miss * handling operations. We align nalloc_base to a l2 cache * linesize because this is the line size the hardware uses to * maintain cache coherency. * 512K is carved out for module data. * Calculate the start of the data segment. * Remember any slop after e_text so we can give it to the modules. * Remember what the physically available highest page is * so that dumpsys works properly, and find out how much /* Fill out memory nodes config structure */ * npages is the maximum of available physical memory possible. * (ie. it will never be more than this) * When we boot from a ramdisk, the ramdisk memory isn't free, so * using phys_avail will underestimate what will end up being freed. * A better initial guess is just total memory minus the kernel text * First allocate things that can go in the nucleus data page * (fault status, TSBs, dmv, CPUs) "no more nucleus memory after page free lists alloc");
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING * There are comments all over the SFMMU code warning of dire * consequences if the TSBs are moved out of 32-bit space. This * is largely because the asm code uses "sethi %hi(addr)"-type * instructions which will not provide the expected result if the * address is a 64-bit one. * WARNING WARNING WARNING WARNING WARNING WARNING WARNING * Allocate IOMMU TSB array. We do this here so that the physical * memory gets deducted from the PROM's physical memory list. * Allow for an early allocation of physically contiguous memory. * Platforms like Starcat and OPL need special structures assigned in * 32-bit virtual address space because their probing routines execute * FCode, and FCode can't handle 64-bit virtual addresses... * Save off where the contiguous allocations to date have ended * Place the array that protects pp->p_selock in the kmem64 wad. * Now allocate the whole wad * Attempt for kmem64 to allocate one big * contiguous chunk of memory failed. * We get here because we are sun4v. * We will proceed by breaking up * the allocation into two attempts. * First, we allocate kpm_pp_sz, hmehash_sz, * pagehash_sz, pagelist_sz, tt_sz & psetable_sz as * one contiguous chunk. This is a much smaller * chunk and we should get it, if not we panic. * Note that hmehash and tt need to be physically * (in the real address sense) contiguous. * Next, we use bop_alloc_chunk() to * to allocate the page_t structures. * This will allow the page_t to be allocated * in multiple smaller chunks. * In doing so, the assumption that page_t is * physically contiguous no longer hold, this is ok * for sun4v but not for sun4u. * Allocate kpm_pp_sz, hmehash_sz, * pagehash_sz, pagelist_sz, tt_sz & psetable_sz prom_panic(
"kmem64 bop_alloc_chunk page_t failed");
* We need to adjust pp_sz for the normal * case where kmem64 can allocate one large chunk /* kpm_npages based on physinstalled, don't reset */ * Note that if we use small chunk allocations for * kmem64, we need to ensure kmem64_end is the same as * kmem64_aligned_end to prevent subsequent logic from * trying to reuse the overmapping. * Otherwise we adjust kmem64_end to what we really allocated. * If physmem is patched to be non-zero, use it instead of * the monitor value unless physmem is larger than the total * amount of memory on hand. * root_is_ramdisk is set via /etc/system when the ramdisk miniroot * is mounted as root. This memory is held down by OBP and unlike * the stub boot_archive is never released. * In order to get things sized correctly on lower memory * machines (where the memory used by the ramdisk represents * a significant portion of memory), physmem is adjusted. * This is done by subtracting the ramdisk_size which is set * to the size of the ramdisk (in Kb) in /etc/system at the * time the miniroot archive is constructed. * Allocate space for the interrupt vector table. prom_panic(
"interrupt vector table allocation failure");
* Between now and when we finish copying in the memory lists, * allocations happen so the space gets fragmented and the * lists longer. Leave enough space for lists twice as * long as we have now; then roundup to a pagesize. * Take the most current snapshot we can by calling mem-update. * Remove the space used by prom_alloc from the kernel heap * plus the area actually used by the OBP (if any) * ignoring virtual addresses in virt_avail, above syslimit. * Limit the range to end at syslimit. * Add any extra memory at the end of the ndata region if there's at * least a page to add. There might be a few more pages available in * the middle of the ndata region, but for now they are ignored. * Copy physinstalled list into kernel space. * Create list of physical addrs we don't need pp's for: * kernel data 4M page - ndata_remain_sz * NB if adding any pages here, make sure no kpm page * overlaps can occur (see ASSERTs in kphysm_memsegs) /* Don't add to nopp_list if kmem64 was allocated in smchunks */ * Size the pcf array based on the number of cpus in the box at * Initialize the page structures from the memory lists. * Some of the locks depend on page_hashsz being set! * kmem_init() depends on this; so, keep it here. * Initialize kernel memory allocator. * Factor in colorequiv to check additional 'equivalent' bins * Reserve space for panicbuf, intr_vec_table, reserved interrupt * vector data structures and MPO mblock structs from the 32-bit heap. * Let the platforms have a chance to change default * values before reading system file. * Calculate default settings of system parameters based upon * maxusers, yet allow to be overridden via the /etc/system file. * If this is a positron, complain and halt. " by this release of Solaris.\n");
* If we are running firmware that isn't 64-bit ready * then complain and halt. * Initialize system parameters * maxmem is the amount of physical memory we're playing with. * Initialize the hat layer. * Initialize segment management stuff. * Create the va>tte handler, so the prom can understand * kernel translations. The handler is installed later, just * as we are about to take over the trap table from the prom. * Load the forthdebugger (optional) * Create OBP node for console input callbacks halt(
"Can't load specfs");
halt(
"Can't load devfs");
halt(
"Can't load swapgeneric");
* Infer meanings to the members of the idprom buffer. /* Read cluster configuration data. */ * Lets take this opportunity to load the root device. * Load tod driver module for the tod part found on this system. * tends to keep time more accurately. * Allow platforms to load modules which might * be needed after bootops are gone. * Calculation and allocation of hmeblks needed to remap * the memory allocated by PROM till now. * Overestimate the number of hblk1 elements by assuming * worst case of TTE64K mappings. * sfmmu_hblk_alloc will panic if this calculation is wrong. /* sfmmu_init_nucleus_hblks expects properly aligned data structures */ * Since hblk8's can hold up to 64k of mappings aligned on a 64k * boundary, the number of hblk8's needed to map the entries in the * boot_virtavail list needs to be adjusted to take this into * consideration. Thus, we need to add additional hblk8's since it * is possible that an hblk8 will not have all 8 slots used due to * alignment constraints. Since there were boot_virtavail_len entries * in that list, we need to add that many hblk8's to the number * already calculated to make sure we don't underestimate. /* Allocate in pagesize chunks */ * Destroy the MD initialized at startup * The startup initializes the MD framework * using prom and BOP alloc free it now. * We're done with prom allocations. * setup physically contiguous area twice as large as the ecache. * this is used while doing displacement flush of ecaches "startup: no memory to set ecache_flushaddr");
* Virtual available next. * startup_fixup_physavail - called from mach_sfmmu.c after the final * allocations have been performed. We can't call it in startup_bop_gone * since later operations can cause obp to allocate more memory. * take the most current snapshot we can by calling mem-update * Copy phys_avail list, again. * Both the kernel/boot and the prom have been allocating * from the original list we copied earlier. * Add any unused kmem64 memory from overmapped page * (Note: va_to_pa does not work for kmem64_end) * Add any extra memory after e_data we added to the phys_avail list * There isn't any bounds checking on the memlist area * so ensure it hasn't overgrown. * The kernel removes the pages that were allocated for it from * the freelist, but we now have to find any -extra- pages that * the prom has allocated for it's own book-keeping, and remove * them from the freelist too. sigh. /* catch this in debug kernels */ * get prom's mappings, create hments for them and switch * Install the va>tte handler, so that the prom can handle * misses and understand the kernel table layout in case * we need call into the prom. * Set a flag to indicate that the tba has been taken over. /* initialize MMU primary context register */ * The boot cpu can now take interrupts, x-calls, x-traps * Set a flag to tell write_scb_int() that it can access V_TBR_WR_ADDR. * Initialize VM system, and map kernel address space. * If the following is true, someone has patched * phsymem to be less than the number of pages that * the system actually has. Remove pages until system * memory is limited to the requested amount. Since we * have allocated page structures for all pages, we * correct the amount of memory we want to remove * by the size of the memory used to hold page structures * for the non-used pages. * When printing memory, show the total as physmem less * that stolen by a debugger. * For small memory systems disable automatic large pages. * Perform platform specific freelist processing * Initialize the segkp segment type. We position it * after the configured tables and buffers (whose end * is given by econtig) and before V_WKBASE_ADDR. * Also in this area is segkmap (size SEGMAPSIZE). /* XXX - cache alignment? */ "segkpsize has been reset to %ld pages",
segkpsize);
* The segkpm virtual range range is larger than the * actual physical memory size and also covers gaps in * the physical address range for the following reasons: * . keep conversion between segkpm and physical addresses * simple, cheap and unambiguous. * . avoid complexity for handling of virtual addressed * caches, segkpm and the regular mapping scheme must be * kept in sync wrt. the virtual color of mapped pages. * Any accesses to virtual segkpm ranges not backed by * physical memory will fall through the memseg pfn hash * and will be handled in segkpm_fault. * Additional kpm_size spaces needed for vac alias prevention. panic(
"segkpm_create segkpm");
/* size is in bytes, segziosize is in pages */ * On 64-bit x86, we only have 2TB of KVA. This exists * SEGZIOMAXSIZE is capped at 512gb so that segzio * doesn't consume all of KVA. However, if we have a * system that has more thant 512gb of physical memory, * we can actually consume about half of the difference * between 512gb and the rest of the available physical /* put the base of the ZIO segment after the kpm segment */ * On some platforms, kvm_init is called after the kpm * sizes have been determined. On SPARC, kvm_init is called * before, so we have to attach the kzioseg after kvm is * initialized, otherwise we'll try to allocate from the boot * area since the kernel heap hasn't yet been configured. /* create zio area covering new segment */ * Now create generic mapping segment. This mapping * goes SEGMAPSIZE beyond SEGMAPBASE. But if the total * virtual address is greater than the amount of free * memory that is available, then we trim back the * segment size to that amount * 1201049: segkmap base address must be MAXBSIZE aligned * Set size of segmap to percentage of freemem at boot, * but stay within the allowable range * Note we take percentage before converting from pages * to bytes to avoid an overflow on 32-bit kernels. i &=
MAXBMASK;
/* 1201049: segkmap size must be MAXBSIZE aligned */ a.
nfreelist = 0;
/* use segmap driver defaults */ panic(
"segmap_create segkmap");
panic(
"memlist overflow 2");
/* enable page_relocation since OBP is now done */ * Perform tasks that get done after most of the VM * initialization has been done but before the clock * and other devices get started. * Intialize the VM arenas for allocating physically * contiguus memory chunk for interrupt queues snd * allocate dump buffer for sun4v systems to store * extra crash information during crash dump * Initialize interrupt related stuff (
void)
splzs();
/* allow hi clock ints but not zs */ * Note that we may have already used kernel bcopy before this * point - but if you really care about this, adb the use_hw_* * variables to 0 before rebooting. * Install the "real" preemption guards before DDI services * Initialize segnf (kernel support for non-faulting loads). * Configure the root devinfo node. #
endif /* PTL1_PANIC_DEBUG */ * Set the system wide, processor-specific flags to be passed * to userland via the aux vector for performance hints and * instruction set extensions. * Startup memory scrubber (if any) * Allocate soft interrupt to handle abort sequence. * Configure the rest of the system. * Perform forceloading tasks for /etc/system. * ON4.0: Force /proc module in until clock interrupt handle fixed * ON4.0: This must be fixed or restated in /etc/systems. /* load machine class specific drivers */ /* load platform specific drivers */ /* load vis simulation module, if we are running w/fpu off */ #
endif /* PTL1_PANIC_DEBUG */ * Called once per second by timeout() to wake up * the ptl1_panic thread to see if it should cause * a trap to the ptl1_panic() code. * ptl1_panic cross call function: * Needed because xc_one() and xc_some() can pass * 64 bit args but ptl1_recurse() expects ints. * The ptl1 thread waits for a global flag to be set * and uses the recurse thresholds to set the stack depth * to cause a ptl1_panic() directly via a call to ptl1_recurse * or indirectly via the cross call and cross trap functions. * This is useful testing stack overflows and normal * ptl1_panic() states with a know stack frame. * sets the {In, Local, Out, and Global} registers to a * know state on the stack and just prior to causing a * Find potential targets for x-call and x-trap, * if any exist while preempt is disabled we * start a ptl1_panic if requested via a * Called during early startup to create the ptl1_thread #
endif /* PTL1_PANIC_DEBUG */ * start = start of new memory segment * len = length of new memory segment in bytes * memlistp = pointer to array of available memory segment structures * curmemlistp = memory list to which to add segment. * The memseg list is for the chunks of physical memory that * will be managed by the vm system. The number calculated is * a guess as boot may fragment it more when memory allocations * are made before kphysm_init(). * In the case of architectures that support dynamic addition of * memory at run-time there are two cases where memsegs need to * be initialized and added to the memseg list. * 1) memsegs that are constructed at startup. * 2) memsegs that are constructed at run-time on * hot-plug capable architectures. * This code was originally part of the function kphysm_init(). /* insert in memseg list, decreasing number of pages order */ * PSM add_physmem_cb(). US-II and newer processors have some * flavor of the prefetch capability implemented. We exploit * this capability for optimum performance. * Prefetch one more page_t into E$. To prevent future * mishaps with the sizeof(page_t) changing on us, we * catch this on debug kernels if we can't bring in the * entire hpage with 2 PREFETCH_BYTES reads. See * Find memseg with given pfn * Put page allocated by OBP on prom_ppages * init it, lock it, and hashin on prom_pages vp. * XXX vnode offsets on the prom_ppages vnode * are page numbers (gack) for >32 bit * physical memory machines. panic(
"kphysm_memseg: kpm_pp overflow");
* In the kpm_smallpage case, the kpm array * is 1-1 wrt the page array /* ASSERT no kpm overlaps */ * page should be locked on prom_ppages * add_physmem() initializes the PSM part of the page * struct by calling the PSM back with add_physmem_cb(). * In addition it coalesces pages into larger pages as * kphysm_init() tackles the problem of initializing physical memory. * installed pages not on nopp_memlist go in memseg list * Erase pages that aren't available * Kernel VM initialization. * Assumptions about kernel address space ordering: * (5) kernel data structures * (7) debugger (optional) * (9) gap (possibly null) * Put the kernel segments in kernel address space. * We're about to map out /boot. This is the beginning of the * system resource management transition. We can no longer * call into /boot for I/O or memory allocations. * we need to preallocate pages for DR operations before enabling large * page kernel heap because of memseg_remap_init() hat_unload() hack. /* at this point we are ready to use large page heap */ * Create a segment for the debugger. "h# %x constant MMU_PAGESHIFT " "h# %x constant SFHME_SIZE " "h# %x constant SFHME_TTE " "h# %x constant HMEBLK_TAG " "h# %x constant HMEBLK_NEXT " "h# %x constant HMEBLK_MISC " "h# %x constant HMEBLK_HME1 " "h# %x constant NHMENTS " "h# %x constant HBLK_SZMASK " "h# %x constant HBLK_RANGE_SHIFT " "h# %x constant HMEBP_HBLK " "h# %x constant HMEBUCKET_SIZE " "h# %x constant HTAG_SFMMUPSZ " "h# %x constant HTAG_BSPAGE_SHIFT " "h# %x constant HTAG_REHASH_SHIFT " "h# %x constant SFMMU_INVALID_SHMERID " "h# %x constant mmu_hashcnt " "h# %p constant uhme_hash " "h# %p constant khme_hash " "h# %x constant UHMEHASH_SZ " "h# %x constant KHMEHASH_SZ " "h# %p constant KCONTEXT " "h# %x constant ASI_MEM " ": PHYS-X@ ( phys -- data ) " ": PHYS-W@ ( phys -- data ) " ": PHYS-L@ ( phys -- data ) " ": TTE_PAGE_SHIFT ( ttesz -- hmeshift ) " ": TTE_IS_VALID ( ttep -- flag ) " ": HME_HASH_SHIFT ( ttesz -- hmeshift ) " " drop HBLK_RANGE_SHIFT " ": HME_HASH_BSPAGE ( addr hmeshift -- bspage ) " " tuck >> swap MMU_PAGESHIFT - << " ": HME_HASH_FUNCTION ( sfmmup addr hmeshift -- hmebp ) " " >> over xor swap ( hash sfmmup ) " " KHATID <> if ( hash ) " " UHMEHASH_SZ and ( bucket ) " " HMEBUCKET_SIZE * uhme_hash + ( hmebp ) " " KHMEHASH_SZ and ( bucket ) " " HMEBUCKET_SIZE * khme_hash + ( hmebp ) " ": HME_HASH_TABLE_SEARCH " " ( sfmmup hmebp hblktag -- sfmmup null | sfmmup hmeblkp ) " " >r hmebp_hblk + phys-x@ begin ( sfmmup hmeblkp ) ( r: hblktag ) " " dup if ( sfmmup hmeblkp ) ( r: hblktag ) " " dup hmeblk_tag + phys-x@ r@ = if ( sfmmup hmeblkp ) " " dup hmeblk_tag + 8 + phys-x@ 2 pick = if " " true ( sfmmup hmeblkp true ) ( r: hblktag ) " " hmeblk_next + phys-x@ false " " ( sfmmup hmeblkp false ) ( r: hblktag ) " " hmeblk_next + phys-x@ false " " ( sfmmup hmeblkp false ) ( r: hblktag ) " ": HME_HASH_TAG ( sfmmup rehash addr -- hblktag ) " " over HME_HASH_SHIFT HME_HASH_BSPAGE ( sfmmup rehash bspage ) " " HTAG_BSPAGE_SHIFT << ( sfmmup rehash htag-bspage )" " swap HTAG_REHASH_SHIFT << or ( sfmmup htag-bspage-rehash )" " SFMMU_INVALID_SHMERID or nip ( hblktag ) " ": HBLK_TO_TTEP ( hmeblkp addr -- ttep ) " " over HMEBLK_MISC + PHYS-L@ HBLK_SZMASK and ( hmeblkp addr ttesz ) " " TTE8K = if ( hmeblkp addr ) " " MMU_PAGESHIFT >> NHMENTS 1- and ( hmeblkp hme-index ) " " else ( hmeblkp addr ) " " then ( hmeblkp hme-index ) " " SFHME_SIZE * + HMEBLK_HME1 + ( hmep ) " ": unix-tte ( addr cnum -- false | tte-data true ) " " KCONTEXT = if ( addr ) " " KHATID ( addr khatid ) " " drop false exit ( false ) " " mmu_hashcnt 1+ 1 do ( addr sfmmup ) " " 2dup swap i HME_HASH_SHIFT " "( addr sfmmup sfmmup addr hmeshift ) " " HME_HASH_FUNCTION ( addr sfmmup hmebp ) " "( addr sfmmup hmebp sfmmup rehash addr ) " " HME_HASH_TAG ( addr sfmmup hmebp hblktag ) " " HME_HASH_TABLE_SEARCH " "( addr sfmmup { null | hmeblkp } ) " " ?dup if ( addr sfmmup hmeblkp ) " " nip swap HBLK_TO_TTEP ( ttep ) " " dup TTE_IS_VALID if ( valid-ttep ) " " PHYS-X@ true ( tte-data true ) " " then ( false | tte-data true ) " " unloop exit ( false | tte-data true ) " " 2drop false ( false ) " * Teach obp how to parse our sw ttes. * advise prom that he can use unix-tte * Here we add "device-type=console" for /os-io node, for currently * our kernel console output only supports displaying text and * performing cursor-positioning operations (through kernel framebuffer * driver) and it doesn't support other functionalities required for a * standard "display" device as specified in 1275 spec. The main missing * interface defined by the 1275 spec is "draw-logo". * also see the comments above prom_stdout_is_framebuffer(). "\" os-io\" device-name " ": cb-r/w ( adr,len method$ -- #read/#written ) " " 2>r swap 2 2r> ['] $callback catch if " ": read ( adr,len -- #read ) " " \" read\" ['] cb-r/w catch if 2drop 2drop -2 exit then " " swap >r 1- 0 ?do drop loop r> " ": write ( adr,len -- #written ) " " \" write\" ['] cb-r/w catch if 2drop 2drop 0 exit then " " swap >r 1- 0 ?do drop loop r> " ": install-abort ( -- ) ['] poll-tty d# 10 alarm ; " ": remove-abort ( -- ) ['] poll-tty 0 alarm ; " " 0 -rot ['] $callback catch ?dup if " " >r 2drop 2drop r> throw " ": open ( -- ok? ) true ; " * Create the OBP input/output node (FCode serial driver). * It is needed for both USB console keyboard and for * the kernel terminal emulator. It is too early to check for a * kernel console compatible framebuffer now, so we create this * so that we're ready if we need to enable kernel terminal emulation. * When the USB software takes over the input device at the time * consconfig runs, OBP's stdin is redirected to this node. * Whenever the FORTH user interface is used after this switch, * the node will call back into the kernel for console input. * If a serial device such as ttya or a UART with a Type 5 keyboard * attached is used, OBP takes over the serial device when the system * goes to the debugger after the system is booted. This sharing * of the relatively simple serial device is difficult but possible. * Sharing the USB host controller is impossible due its complexity. * Similarly to USB keyboard input redirection, after consconfig_dacf * configures a kernel console framebuffer as the standard output * device, OBP's stdout is switched to to vector through the * /os-io node into the kernel terminal emulator. static char drev[] =
"Down-rev firmware detected%s\n" "\tPlease upgrade to the following minimum version:\n" * The other possibility is that this is a server running * good firmware, but down-rev firmware was detected on at * least one other cpu board. We just complain if we see * Must be defined in platform dependent code. * Before we initialize the text_arena, we want to punch holes in the * underlying heaptext_arena. This guarantees that for any text * address we can find a text hole less than HEAPTEXT_MAPPED away. * Allocate one page at the oversize to break up the text region * from the oversized region. * First, try a sleeping allocation. * We didn't get the area that we wanted. We're going to try to do an * allocation with explicit constraints. * That worked. Free our first attempt and return. * That didn't work; we'll have to return our first attempt. * If this is an oversized allocation, there is no text hole * available for it; return NULL. "heaptext_holesrc_%d",
arena);