/* * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * @OSF_COPYRIGHT@ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern unsigned int mckFlags; extern vm_offset_t intstack; extern vm_offset_t debstack; int pc_trace_buf[1024] = {0}; int pc_trace_cnt = 1024; extern unsigned int extPatchMCK; extern unsigned int extPatch32; extern unsigned int hwulckPatch_isync; extern unsigned int hwulckPatch_eieio; extern unsigned int hwulckbPatch_isync; extern unsigned int hwulckbPatch_eieio; extern unsigned int mulckPatch_isync; extern unsigned int mulckPatch_eieio; extern unsigned int mulckePatch_isync; extern unsigned int mulckePatch_eieio; extern unsigned int sulckPatch_isync; extern unsigned int sulckPatch_eieio; extern unsigned int rwlesPatch_isync; extern unsigned int rwlesPatch_eieio; extern unsigned int rwldPatch_isync; extern unsigned int rwldPatch_eieio; extern unsigned int retfsectPatch_eieio; extern unsigned int retfsectPatch_isync; extern unsigned int bcopy_nop_if_32bit; extern unsigned int bcopy_nc_nop_if_32bit; extern unsigned int memcpy_nop_if_32bit; extern unsigned int xsum_nop_if_32bit; extern unsigned int uft_nop_if_32bit; extern unsigned int uft_uaw_nop_if_32bit; extern unsigned int uft_cuttrace; int forcenap = 0; int wcte = 0; /* Non-cache gather timer disabled */ patch_entry_t patch_table[] = { {&extPatch32, 0x60000000, PATCH_FEATURE, PatchExt32}, {&extPatchMCK, 0x60000000, PATCH_PROCESSOR, CPU_SUBTYPE_POWERPC_970}, {&hwulckPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&hwulckPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&hwulckbPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&hwulckbPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&mulckPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&mulckPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&mulckePatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&mulckePatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&sulckPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&sulckPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&rwlesPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&rwlesPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&rwldPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&rwldPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, {&bcopy_nop_if_32bit, 0x60000000, PATCH_FEATURE, PatchExt32}, {&bcopy_nc_nop_if_32bit,0x60000000, PATCH_FEATURE, PatchExt32}, {&memcpy_nop_if_32bit, 0x60000000, PATCH_FEATURE, PatchExt32}, #if !MACH_LDEBUG {&retfsectPatch_isync, 0x60000000, PATCH_FEATURE, PatchLwsync}, {&retfsectPatch_eieio, 0x7c2004ac, PATCH_FEATURE, PatchLwsync}, #endif {&xsum_nop_if_32bit, 0x60000000, PATCH_FEATURE, PatchExt32}, {&uft_nop_if_32bit, 0x60000000, PATCH_FEATURE, PatchExt32}, {&uft_uaw_nop_if_32bit, 0x60000000, PATCH_FEATURE, PatchExt32}, {&uft_cuttrace, 0x60000000, PATCH_FEATURE, PatchExt32}, {NULL, 0x00000000, PATCH_END_OF_TABLE, 0} }; /* * Forward definition */ void ppc_init( boot_args *args); void ppc_init_cpu( struct per_proc_info *proc_info); /* * Routine: ppc_init * Function: */ void ppc_init( boot_args *args) { unsigned int maxmem; uint64_t xmaxmem; uint64_t newhid; unsigned int cputrace; unsigned int novmx; unsigned int mcksoft; thread_t thread; mapping_t *mp; uint64_t scdata; /* * Setup per_proc info for first cpu. */ BootProcInfo.cpu_number = 0; BootProcInfo.cpu_flags = 0; BootProcInfo.istackptr = 0; /* we're on the interrupt stack */ BootProcInfo.intstack_top_ss = (vm_offset_t)&intstack + INTSTACK_SIZE - FM_SIZE; BootProcInfo.debstack_top_ss = (vm_offset_t)&debstack + KERNEL_STACK_SIZE - FM_SIZE; BootProcInfo.debstackptr = BootProcInfo.debstack_top_ss; BootProcInfo.interrupts_enabled = 0; BootProcInfo.pending_ast = AST_NONE; BootProcInfo.FPU_owner = 0; BootProcInfo.VMX_owner = 0; BootProcInfo.pp_cbfr = console_per_proc_alloc(TRUE); BootProcInfo.rtcPop = 0xFFFFFFFFFFFFFFFFULL; mp = (mapping_t *)BootProcInfo.ppUMWmp; mp->mpFlags = 0x01000000 | mpLinkage | mpPerm | 1; mp->mpSpace = invalSpace; thread_bootstrap(); thread = current_thread(); thread->machine.curctx = &thread->machine.facctx; thread->machine.facctx.facAct = thread; thread->machine.umwSpace = invalSpace; /* Initialize user memory window space to invalid */ thread->machine.preemption_count = 1; cpu_bootstrap(); cpu_init(); master_cpu = 0; processor_bootstrap(); timer_switch((uint32_t)mach_absolute_time(), &thread->system_timer); static_memory_end = round_page(args->topOfKernelData);; PE_init_platform(FALSE, args); /* Get platform expert set up */ if (!PE_parse_boot_arg("novmx", &novmx)) novmx=0; /* Special run without VMX? */ if(novmx) { /* Yeah, turn it off */ BootProcInfo.pf.Available &= ~pfAltivec; /* Turn off Altivec available */ __asm__ volatile("mtsprg 2,%0" : : "r" (BootProcInfo.pf.Available)); /* Set live value */ } if (!PE_parse_boot_arg("fn", &forcenap)) forcenap = 0; /* If force nap not set, make 0 */ else { if(forcenap < 2) forcenap = forcenap + 1; /* Else set 1 for off, 2 for on */ else forcenap = 0; /* Clear for error case */ } if (!PE_parse_boot_arg("diag", &dgWork.dgFlags)) dgWork.dgFlags=0; /* Set diagnostic flags */ if (!PE_parse_boot_arg("lcks", &LcksOpts)) LcksOpts=0; /* Set lcks options */ if(dgWork.dgFlags & enaExpTrace) trcWork.traceMask = 0xFFFFFFFF; /* If tracing requested, enable it */ if(PE_parse_boot_arg("ctrc", &cputrace)) { /* See if tracing is limited to a specific cpu */ trcWork.traceMask = (trcWork.traceMask & 0xFFFFFFF0) | (cputrace & 0xF); /* Limit to 4 */ } if(!PE_parse_boot_arg("tb", &trcWork.traceSize)) { /* See if non-default trace buffer size */ #if DEBUG trcWork.traceSize = 32; /* Default 32 page trace table for DEBUG */ #else trcWork.traceSize = 8; /* Default 8 page trace table for RELEASE */ #endif } if(trcWork.traceSize < 1) trcWork.traceSize = 1; /* Minimum size of 1 page */ if(trcWork.traceSize > 256) trcWork.traceSize = 256; /* Maximum size of 256 pages */ trcWork.traceSize = trcWork.traceSize * 4096; /* Change page count to size */ if (!PE_parse_boot_arg("maxmem", &maxmem)) xmaxmem=0; else xmaxmem = (uint64_t)maxmem * (1024 * 1024); if (!PE_parse_boot_arg("wcte", &wcte)) wcte = 0; /* If write combine timer enable not supplied, make 1 */ else wcte = (wcte != 0); /* Force to 0 or 1 */ if (!PE_parse_boot_arg("mcklog", &mckFlags)) mckFlags = 0; /* If machine check flags not specified, clear */ else if(mckFlags > 1) mckFlags = 0; /* If bogus, clear */ if (!PE_parse_boot_arg("ht_shift", &hash_table_shift)) /* should we use a non-default hash table size? */ hash_table_shift = 0; /* no, use default size */ /* * VM initialization, after this we're using page tables... */ ppc_vm_init(xmaxmem, args); if(BootProcInfo.pf.Available & pf64Bit) { /* Are we on a 64-bit machine */ if(!wcte) { (void)ml_scom_read(GUSModeReg << 8, &scdata); /* Get GUS mode register */ scdata = scdata | GUSMstgttoff; /* Disable the NCU store gather timer */ (void)ml_scom_write(GUSModeReg << 8, scdata); /* Get GUS mode register */ } if(PE_parse_boot_arg("mcksoft", &mcksoft)) { /* Have they supplied "machine check software recovery? */ newhid = BootProcInfo.pf.pfHID5; /* Get the old HID5 */ if(mcksoft < 2) { newhid &= 0xFFFFFFFFFFFFDFFFULL; /* Clear the old one */ newhid |= (mcksoft & 1) << 13; /* Set new value to enable machine check recovery */ BootProcInfo.pf.pfHID5 = newhid; /* Set the new one */ hid5set64(newhid); /* Set the hid for this processir */ } } } PE_init_platform(TRUE, args); machine_startup(args); } /* * Routine: ppc_init_cpu * Function: */ void ppc_init_cpu( struct per_proc_info *proc_info) { uint64_t scdata; proc_info->cpu_flags &= ~SleepState; if((BootProcInfo.pf.Available & pf64Bit) && !wcte) { /* Should we disable the store gather timer? */ (void)ml_scom_read(GUSModeReg << 8, &scdata); /* Get GUS mode register */ scdata = scdata | GUSMstgttoff; /* Disable the NCU store gather timer */ (void)ml_scom_write(GUSModeReg << 8, scdata); /* Get GUS mode register */ } cpu_init(); slave_main(); }