📄 driver.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//**************************************************************** * driver.c * This file contains the entry points to mshade. The init functions * in this file are responsible for initializing all of the needed * data structures. * We also try to concentrate the policy #defines in this file. * * Author: $Author: bosch $ * Date: $Date: 1998/02/10 00:30:32 $ *****************************************************************/#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <strings.h>#include <unistd.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/time.h>#include <fcntl.h>#include <setjmp.h>#include "simmisc.h"#include "annotations.h"#include "checkpoint.h"#include "embra.h"#include "driver.h"#include "tc.h"#include "translator.h"#include "mem_control.h"#include "callout.h"#include "main_run.h"#include "cp0.h"#include "clock.h"#include "qc.h"#include "cache.h"#include "stats.h"#include "embra_interface.h"#include "directory.h"#include "decoder.h"#include "stats.h"#include "clock.h"#include "simutil.h"#include "tcl_init.h"#include "debug.h"#include "tc_coherence.h"CptCallback EmbraExecStateCheckpointCB;/* Globals *//* Wouldn't it be nice if we lived in a world where compiliers could deal with alignment information? That way maybe our much abused typing system in C could stand a ghost of a chance */#ifdef COMMENTOUTunsigned PE_space[ ( SIM_MAXCPUS * sizeof(EmbraState) + DEFAULT_PAGESZ)/ sizeof(unsigned)];#endifEmbraState* EMP;/*int curr_cpu; */EmbraState* curEmp;EmbraParams embra;jmp_buf embra_env;struct timeval run_start;struct timeval run_end;/* This is necessary to allow the cp0 module to fool the rest of us *//* into thinking that ASID 0 never runs *//* It is set in cp0.c */int quick_ASID[SIM_MAXCPUS];#if 0 int EmUseETLB = 0;int barrCPUs = 0;int MPinUP = 0;int useVQC = 0;int K0FromDevZero = 0;int alreadyAlloc = 0;#endifint* gBarrier = 0;int* debugBarrier = 0;int* checkpointBarrier = 0;int* tnsLock = 0;int* exitBarrier = 0;int deschedNumCPUs = -1;/* XXX - this is really depended on CPUType */int log2sizeofcputype = 2;static void EmbraConfigureTC(void);static void VerifyOffsets(void);/* On startup the mmu gets initialized, so we must go through and zero out the appropriate pages. We could just rely on the fact that qc_map_page won't map pages with annotations, but this will make sure kernel addresses are zerod out.*/voidEmbraInstallMemAnnotation(VA vAddr) { uint page = PAGE_NUMBER(vAddr); if (embra.emode == EMBRA_PAGE) { if (TOTAL_CPUS==1 || embra.MPinUP) { int cpu; for (cpu = 0; cpu < TOTAL_CPUS; cpu++) {#ifdef EMBRA_USE_QC64 qc64_remove_addr(cpu,vAddr);#else EMP[cpu].mmu[page] = 0;#endif } } else { CPUWarning("Fix InstallMemAnnotations for MPinMP\n"); } } else { }}C_LINK int _is_mips2(void);void Embra_Init(int cpuNum, int swtch){ static int embra_initialized; /* Should always be up to date *//* curr_cpu = cpuNum; */ VerifyOffsets(); curEmp = &EMP[cpuNum]; if( !embra_initialized ) { embra_initialized = 1; /* Quick runtime way of deciding if we are on an R4000 */ if( !_is_mips2() ) { CPUPut("Embra only runs on machines that supports at least the mips2 ISA\n"); exit( 1 ); } EmbraClockInit(); if( embra.MPinUP ) { int i; EmbraState *state = &EMP[TOTAL_CPUS]; for( i = 0; i <= TOTAL_CPUS; i++ ) { EMP[i].myNum = i; EMP[i].myBit = (1<<i); /* Assume that if any cpu is out of slave loop, then they */ /* all are */ /*if( EMP[TOTAL_CPUS-1].outOfSlaveLoop ) {*/ if( deschedNumCPUs >= 0 && EMP[i].outOfSlaveLoop ) { state->next = &EMP[i]; EMP[i].next = &EMP[TOTAL_CPUS]; state = state->next; deschedNumCPUs++; } if( deschedNumCPUs < 0 ) { if( 1 ) { EMP[i].next = &EMP[(i+1)%(TOTAL_CPUS+1)]; /* Either C handles mod wierd, or I learned them wrong */ if( i == 0 ) EMP[i].prev = &EMP[TOTAL_CPUS]; else EMP[i].prev = &EMP[(i-1)%(TOTAL_CPUS+1)]; } else { /* Then we must be booting so only add CPU 0 */ EMP[0].next = &EMP[TOTAL_CPUS]; EMP[TOTAL_CPUS].next = &EMP[0]; } } } /* * figure out the backpointer in the doubly linked list */ ASSERT( EMP[TOTAL_CPUS].next != &EMP[TOTAL_CPUS]); for(state = &EMP[TOTAL_CPUS]; !state->next->prev;state = state->next) { state->next->prev = state; } } else { EMP[cpuNum].myNum = cpuNum; EMP[cpuNum].myBit = (1<<cpuNum); } gBarrier = ZMALLOC(256,"Embra::gBarrier"); debugBarrier = ZMALLOC(256,"Embra::debugBarrier"); checkpointBarrier = ZMALLOC(256,"Embra::checkpointBarrier"); exitBarrier = ZMALLOC(256,"Embra::exitBarrier"); tnsLock = ZMALLOC(256,"Embra::tnsLock"); } Embra_Clock_Init(cpuNum); /* Initialize translation caches & space for dynamic interface code */ EmbraConfigureTC(); /* Initialize interface code and register allocation stuff */ Translator_Init(); /* Initialize maxInGroup */ DecoderInit(); Stat_Init(); emSMHT = ZMALLOC(TOTAL_CPUS * sizeof(EmSMHT),"Embra:SMHT"); TCcoherence_init(SIM_MEM_ADDR(0)); Cache_Init(cpuNum); Em_Tlb_Init(cpuNum, swtch); Directory_Init(); Cache_Init(cpuNum); if (cpuNum == 0) { if (embra.emode == EMBRA_PAGE) { AnnFMInit(DEFAULT_PAGESZ); } else { /* embra.emode == EMBRA_CACHE */ AnnFMInit(SCACHE_LINE_SIZE); } if (!swtch) { AnnCommonSetup(); } } if( embra.MPinUP ) { /* XXX - Note the space for the extra processor is not actualy */ /* mapped shared. It should be allocated elsewhere */ /* The mythical extra processor just holds the callback address */ EMP[TOTAL_CPUS].PC = (Reg)EmEventPoll; EMP[TOTAL_CPUS].R[31] = (Reg)EmEventPoll; /* This needs to be set for the code in main_run which tries to do a */ /* lookup on the PC, but it is a backdoor, so that look up will */ /* fail. May want to check for backdoor directly in that code */ EMP[TOTAL_CPUS].mmu = EMP[0].mmu; /* Have to activate this processor */ EMP[TOTAL_CPUS].outOfSlaveLoop = 1; }}void Init_Proc_State(int cpu ){ EMP[cpu].Sdhit_count = 0; EMP[cpu].Sihit_count = 0; EMP[cpu].jumpPC = (uint)continue_run_without_chaining; /* Shave 32 bytes off so routines called by continue_run can */ /* store into it and continue_run itself can store 4 words */ if((embra.emode == EMBRA_PAGE)||(!embra.useVQC)) EMP[cpu].Ssreg2 = 0x7fffffff;}/* This setjmp allows us to unwind the stack (e.g. after we've flushed * the translation cache, taken exceptions, etc.) and return to * running in the TC */jmp_buf Embra_Run_Setjmp;/* We call this routine to unwind the stack and continue running * in the TC */void ReenterTC(EmbraState *emp){ curEmp = emp; longjmp(Embra_Run_Setjmp, 1); /* Not Reached */ ASSERT(0);}/* We call this routine to unwind the stack and continue running * in the TC */void ReenterTC_CX(EmbraState *emp){ curEmp = emp; longjmp(Embra_Run_Setjmp, 2); /* 2 -> do context switch */ /* Not Reached */ ASSERT(0);}/* This is the entry point to Embra. Embra_Init should be called *//* before calling this function */void Embra_Run( int cpuNum, int clobber_machine_regs ){ /* Call the main run routine which does translation on the fly. */ /* Note that the stack grows down, so we start at the top */ if( embra.MPinUP ) { int cpu; for( cpu = 0; cpu <= TOTAL_CPUS; cpu++ ) { Init_Proc_State(cpu); CPUPrint("%d entering TC at 0x%x\n", cpu, EMP[cpu].PC); } EMP[TOTAL_CPUS].jumpPC = (Reg)EmEventPoll; } else { Init_Proc_State(cpuNum); CPUPrint("%d entering TC at 0x%x\n", cpuNum, EMP[cpuNum].PC); } ASSERT(embra.emode == EMBRA_PAGE ||embra.sequential || EMP[cpuNum].outTC );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -