void kmain(MultibootInfo *info) { ASM("cli"); kernelStatus = KERNEL_RUNNING; initConsole(); kprintf("Successfully booted into 64-bit mode\n"); if (info->modsCount != 1) { panic("the initrd was not loaded"); }; kprintf_debug(" *** TO TRAP THE KERNEL *** \n"); kprintf_debug(" set r15=rip\n"); kprintf_debug(" set rip=%a\n", &trapKernel); kprintf_debug(" *** END OF INFO *** \n"); kprintf("Initializing the IDT... "); initIDT(); kprintf("%$\x02" "Done%#\n"); kprintf("Checking amount of memory... "); int memSize = info->memLower + info->memUpper; if (info->flags & 1) { kprintf("%$\x01%dMB%#\n", (memSize/1024)); } else { kprintf("%$\x04" "Failed%#\n"); panic("could not determine memory size"); }; if ((info->flags & (1 << 6)) == 0) { panic("no memory map from bootloader"); }; uint64_t mmapAddr = (uint64_t) info->mmapAddr + 0xFFFF800000000000; uint64_t mmapEnd = mmapAddr + info->mmapLen; kprintf("Memory map address: %a memory map size = %d\n", mmapAddr, info->mmapLen); MultibootMemoryMap *mmap = (MultibootMemoryMap*) mmapAddr; kprintf("Size\tBase\tLen\tType\n"); while ((uint64_t)mmap < mmapEnd) { kprintf("%d\t%a\t%d\t%d\n", mmap->size, mmap->baseAddr, mmap->len, mmap->type); mmap = (MultibootMemoryMap*) ((uint64_t) mmap + mmap->size + 4); }; MultibootModule *mod = (MultibootModule*) ((uint64_t) info->modsAddr + 0xFFFF800000000000); uint64_t end = (uint64_t) mod->modEnd + 0xFFFF800000000000; kprintf("Initializing memory allocation phase 1 (base=%a)... ", end); initMemoryPhase1(end); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the physical memory manager (%d pages)... ", (memSize/4)); initPhysMem(memSize/4, (MultibootMemoryMap*) mmapAddr, mmapEnd); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the ISP... "); ispInit(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing memory allocation phase 2... "); initMemoryPhase2(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the frame stack... "); initPhysMem2(); kprintf("%$\x02" "Done%#\n"); initModuleInterface(); kprintf("Getting ACPI info... "); acpiInit(); msrWrite(0x1B, 0xFEE00000 | (1 << 11) /*| (1 << 8)*/ ); apic->sivr = 0x1FF; kprintf("Initializing the FPU... "); fpuInit(); DONE(); kprintf("Initializing the VFS... "); vfsInit(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the initrdfs... "); initInitrdfs(info); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the procfs... "); initProcfs(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the devfs... "); initDevfs(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing PCI... "); pciInit(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the FS driver interface... "); initFSDrivers(); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the PIT... "); uint16_t divisor = 1193180 / 1000; // 1000 Hz outb(0x43, 0x36); uint8_t l = (uint8_t)(divisor & 0xFF); uint8_t h = (uint8_t)( (divisor>>8) & 0xFF ); outb(0x40, l); outb(0x40, h); kprintf("%$\x02" "Done%#\n"); kprintf("Initializing the APIC timer..."); ASM("sti"); apic->timerDivide = 3; apic->timerInitCount = 0xFFFFFFFF; sleep(35); apic->lvtTimer = 0; quantumTicks = 0xFFFFFFFF - apic->timerCurrentCount; apic->timerInitCount = 0; // put the timer in single-shot mode at the appropriate interrupt vector. apic->lvtTimer = I_APIC_TIMER; DONE(); kprintf("Initializing the scheduler and syscalls... "); //msrWrite(0xC0000080, msrRead(0xC0000080) | 1); //msrWrite(0xC0000081, ((uint64_t)8 << 32)); //msrWrite(0xC0000082, (uint64_t)(&_syscall_entry)); //msrWrite(0xC0000084, (1 << 9)); initSched(); // "Done" will be displayed by initSched(), and then kmain2() will be called. };
int FC_MAIN(int argc,char **argv) { MDL mdl; MSR msr; FILE *fpLog = NULL; char achFile[256]; /*DEBUG use MAXPATHLEN here (& elsewhere)? -- DCR*/ double dTime; double E=0,T=0,U=0,Eth=0,L[3]={0,0,0},F[3]={0,0,0},W=0; double dMultiEff=0; long lSec=0,lStart; int i,iStep,iSec=0,iStop=0; uint64_t nActive; #ifdef TINY_PTHREAD_STACK static int first = 1; static char **save_argv; /* * Hackery to get around SGI's tiny pthread stack. * Main will be called twice. The second time, argc and argv * will be garbage, so we have to save them from the first. * Another way to do this would involve changing the interface * to mdlInitialize(), so that this hackery could be hidden * down there. */ if (first) { save_argv = malloc((argc+1)*sizeof(*save_argv)); for (i = 0; i < argc; i++) save_argv[i] = strdup(argv[i]); save_argv[argc] = NULL; } else { argv = save_argv; } first = 0; #endif /* TINY_PTHREAD_STACK */ #ifdef USE_BT bt_initialize(); #endif #ifdef ENABLE_FE feenableexcept(FE_INVALID|FE_DIVBYZERO|FE_OVERFLOW); #endif #ifndef CCC /* no stdout buffering */ setbuf(stdout,(char *) NULL); #endif lStart=time(0); #ifdef USE_MDL_IO mdlInitialize(&mdl,argv,main_ch,main_io); #else mdlInitialize(&mdl,argv,main_ch,0); #endif for (argc = 0; argv[argc]; argc++); /* some MDLs can trash argv */ printf("%s\n", PACKAGE_STRING ); msrInitialize(&msr,mdl,argc,argv); /* ** Establish safety lock. */ if (!msrGetLock(msr)) { msrFinish(msr); mdlFinish(mdl); return 1; } /* ** Output the host names to make troubleshooting easier */ msrHostname(msr); /* ** Read in the binary file, this may set the number of timesteps or ** the size of the timestep when the zto parameter is used. */ #ifdef USE_GRAFIC if (prmSpecified(msr->prm,"nGrid")) { dTime = msrGenerateIC(msr); msrInitStep(msr); if (prmSpecified(msr->prm,"dSoft")) msrSetSoft(msr,msrSoft(msr)); } else { #endif if ( msr->param.achInFile[0] ) { dTime = msrRead(msr,msr->param.achInFile); msrInitStep(msr); if (msr->param.bAddDelete) msrGetNParts(msr); if (prmSpecified(msr->prm,"dRedFrom")) { double aOld, aNew; aOld = csmTime2Exp(msr->param.csm,dTime); aNew = 1.0 / (1.0 + msr->param.dRedFrom); dTime = msrAdjustTime(msr,aOld,aNew); /* Seriously, we shouldn't need to send parameters *again*. When we remove sending parameters, we should remove this. */ msrInitStep(msr); } if (prmSpecified(msr->prm,"dSoft")) msrSetSoft(msr,msrSoft(msr)); } else { #ifdef USE_PYTHON if ( !msr->param.achScriptFile[0] ) { #endif printf("No input file specified\n"); return 1; } #ifdef USE_PYTHON } #endif #ifdef USE_GRAFIC } #endif if ( msr->param.bWriteIC ) { msrBuildIoName(msr,achFile,0); msrWrite( msr,achFile,dTime,msr->param.bWriteIC-1); } /* ** Now we have all the parameters for the simulation we can make a ** log file entry. */ if (msrLogInterval(msr)) { sprintf(achFile,"%s.log",msrOutName(msr)); fpLog = fopen(achFile,"a"); assert(fpLog != NULL); setbuf(fpLog,(char *) NULL); /* no buffering */ /* ** Include a comment at the start of the log file showing the ** command line options. */ fprintf(fpLog,"# "); for (i=0;i<argc;++i) fprintf(fpLog,"%s ",argv[i]); fprintf(fpLog,"\n"); msrLogParams(msr,fpLog); } #ifdef USE_PYTHON /* If a script file was specified, enter analysis mode */ if ( msr->param.achScriptFile[0] ) iStep = 0; else #endif iStep = msrSteps(msr); if (iStep > 0) { if (msrComove(msr)) { msrSwitchTheta(msr,dTime); } /* ** Build tree, activating all particles first (just in case). */ msrActiveRung(msr,0,1); /* Activate all particles */ msrDomainDecomp(msr,0,1,0); msrUpdateSoft(msr,dTime); msrBuildTree(msr,dTime,msr->param.bEwald); if (msrDoGravity(msr)) { msrGravity(msr,0,MAX_RUNG,dTime,msr->param.iStartStep,msr->param.bEwald,&iSec,&nActive); msrMemStatus(msr); if (msr->param.bGravStep) { msrBuildTree(msr,dTime,msr->param.bEwald); msrGravity(msr,0,MAX_RUNG,dTime,msr->param.iStartStep,msr->param.bEwald,&iSec,&nActive); msrMemStatus(msr); } } if (msrDoGas(msr)) { /* Initialize SPH, Cooling and SF/FB and gas time step */ #ifdef COOLING msrCoolSetup(msr,dTime); #endif /* Fix dTuFac conversion of T in InitSPH */ msrInitSph(msr,dTime); } msrCalcEandL(msr,MSR_INIT_E,dTime,&E,&T,&U,&Eth,L,F,&W); dMultiEff = 1.0; if (msrLogInterval(msr)) { (void) fprintf(fpLog,"%e %e %.16e %e %e %e %.16e %.16e %.16e " "%.16e %.16e %.16e %.16e %i %e\n",dTime, 1.0/csmTime2Exp(msr->param.csm,dTime)-1.0, E,T,U,Eth,L[0],L[1],L[2],F[0],F[1],F[2],W,iSec,dMultiEff); } #ifdef PLANETS if (msr->param.bHeliocentric) { msrGravSun(msr); } #ifdef SYMBA msrDriftSun(msr,dTime,0.5*msrDelta(msr)); #endif #endif if ( msr->param.bTraceRelaxation) { msrInitRelaxation(msr); } #ifdef HERMITE if (msr->param.bHermite) { msrActiveRung(msr,0,1); /* Activate all particles */ msrCopy0(msr, dTime); if (msr->param.bAarsethStep) { msrFirstDt(msr); } } #endif for (iStep=msr->param.iStartStep+1;iStep<=msrSteps(msr)&&!iStop;++iStep) { if (msrComove(msr)) { msrSwitchTheta(msr,dTime); } dMultiEff = 0.0; lSec = time(0); #ifdef HERMITE if (msr->param.bHermite) { msrTopStepHermite(msr,iStep-1,dTime, msrDelta(msr),0,0,msrMaxRung(msr),1, &dMultiEff,&iSec); } else #endif #ifdef SYMBA if (msr->param.bSymba) { msrTopStepSymba(msr,iStep-1,dTime, msrDelta(msr),0,0,msrMaxRung(msr),1, &dMultiEff,&iSec); } else #endif { msrTopStepKDK(msr,iStep-1,dTime, msrDelta(msr),0,0,msrMaxRung(msr),1, &dMultiEff,&iSec); } dTime += msrDelta(msr); lSec = time(0) - lSec; msrMemStatus(msr); /* ** Output a log file line if requested. ** Note: no extra gravity calculation required. */ if (msrLogInterval(msr) && iStep%msrLogInterval(msr) == 0) { msrCalcEandL(msr,MSR_STEP_E,dTime,&E,&T,&U,&Eth,L,F,&W); (void) fprintf(fpLog,"%e %e %.16e %e %e %e %.16e %.16e " "%.16e %.16e %.16e %.16e %.16e %li %e\n",dTime, 1.0/csmTime2Exp(msr->param.csm,dTime)-1.0, E,T,U,Eth,L[0],L[1],L[2],F[0],F[1],F[2],W,lSec,dMultiEff); } if ( msr->param.bTraceRelaxation) { msrActiveRung(msr,0,1); /* Activate all particles */ msrDomainDecomp(msr,0,1,0); msrBuildTree(msr,dTime,0); msrRelaxation(msr,dTime,msrDelta(msr),SMX_RELAXATION,0); } /* ** Check for user interrupt. */ iStop = msrCheckForStop(msr); /* ** Check to see if the runtime has been exceeded. */ if (!iStop && msr->param.iWallRunTime > 0) { if (msr->param.iWallRunTime*60 - (time(0)-lStart) < ((int) (lSec*1.5)) ) { printf("RunTime limit exceeded. Writing checkpoint and exiting.\n"); printf(" iWallRunTime(sec): %d Time running: %ld Last step: %ld\n", msr->param.iWallRunTime*60,time(0)-lStart,lSec); iStop = 1; } } /* ** Output if 1) we've hit an output time ** 2) We are stopping ** 3) we're at an output interval */ if (msrOutTime(msr,dTime) || iStep == msrSteps(msr) || iStop || (msrOutInterval(msr) > 0 && iStep%msrOutInterval(msr) == 0) || (msrCheckInterval(msr) > 0 && iStep%msrCheckInterval(msr) == 0)) { msrOutput(msr,iStep,dTime, msrCheckInterval(msr)>0 && (iStep%msrCheckInterval(msr) == 0 || iStep == msrSteps(msr) || iStop)); } } } /* No steps were requested */ else { #ifdef USE_PYTHON if ( msr->param.achScriptFile[0] ) { PPY ppy; ppyInitialize(&ppy,msr,dTime); msr->prm->script_argv[0] = msr->param.achScriptFile; ppyRunScript(ppy,msr->prm->script_argc,msr->prm->script_argv); ppyFinish(ppy); } else { #endif if (msrDoGravity(msr) ||msrDoGas(msr)) { msrActiveRung(msr,0,1); /* Activate all particles */ msrDomainDecomp(msr,0,1,0); msrUpdateSoft(msr,dTime); msrBuildTree(msr,dTime,msr->param.bEwald); if (msrDoGravity(msr)) { msrGravity(msr,0,MAX_RUNG,dTime,msr->param.iStartStep,msr->param.bEwald,&iSec,&nActive); msrMemStatus(msr); if (msr->param.bGravStep) { msrBuildTree(msr,dTime,msr->param.bEwald); msrGravity(msr,0,MAX_RUNG,dTime,msr->param.iStartStep,msr->param.bEwald,&iSec,&nActive); msrMemStatus(msr); } } if (msrDoGas(msr)) { /* Initialize SPH, Cooling and SF/FB and gas time step */ #ifdef COOLING msrCoolSetup(msr,dTime); #endif /* Fix dTuFac conversion of T in InitSPH */ msrInitSph(msr,dTime); } msrUpdateRung(msr,0); /* set rungs for output */ msrCalcEandL(msr,MSR_INIT_E,dTime,&E,&T,&U,&Eth,L,F,&W); dMultiEff = 1.0; if (msrLogInterval(msr)) { (void) fprintf(fpLog,"%e %e %.16e %e %e %e %.16e %.16e " "%.16e %.16e %.16e %.16e %.16e %i %e\n",dTime, 1.0/csmTime2Exp(msr->param.csm,dTime)-1.0, E,T,U,Eth,L[0],L[1],L[2],F[0],F[1],F[2],W,iSec,dMultiEff); } } msrOutput(msr,0,dTime,0); /* JW: Will trash gas density */ #ifdef USE_PYTHON } #endif } if (msrLogInterval(msr)) (void) fclose(fpLog); #ifdef PP_SIMD_BENCHMARK PPDumpStats(); #endif msrFinish(msr); mdlFinish(mdl); return 0; }