addrspace.cc
来自「操作系统课程设计。在UNIX平台下实现Solary操作系统的一些功能」· CC 代码 · 共 216 行
CC
216 行
/////////////////////////////////////////////////////////////
//FileName : AddrSpace.cc
//
//Creator : Li Shouchao(0410716)
//CreateTime : 2007-1-3
//
//File Desc:
// 1. Routines to manage address spaces (executing user programs).
//
/////////////////////////////////////////////////////////////
#include "copyright.h"
#include "system.h"
#include "addrspace.h"
#include "noff.h"
#ifdef HOST_SPARC
#include <strings.h>
#endif
//----------------------------------------------------------------------
// SwapHeader
// Do little endian to big endian conversion on the bytes in the
// object file header, in case the file was generated on a little
// endian machine, and we're now running on a big endian machine.
//----------------------------------------------------------------------
static void
SwapHeader (NoffHeader *noffH)
{
noffH->noffMagic = WordToHost(noffH->noffMagic);
noffH->code.size = WordToHost(noffH->code.size);
noffH->code.virtualAddr = WordToHost(noffH->code.virtualAddr);
noffH->code.inFileAddr = WordToHost(noffH->code.inFileAddr);
noffH->initData.size = WordToHost(noffH->initData.size);
noffH->initData.virtualAddr = WordToHost(noffH->initData.virtualAddr);
noffH->initData.inFileAddr = WordToHost(noffH->initData.inFileAddr);
noffH->uninitData.size = WordToHost(noffH->uninitData.size);
noffH->uninitData.virtualAddr = WordToHost(noffH->uninitData.virtualAddr);
noffH->uninitData.inFileAddr = WordToHost(noffH->uninitData.inFileAddr);
}
//////////////////////////////////////////////////////
// Function name : AddrSpace::AddrSpace
// Creator : Fang Wenbin(0410706)
// CreateTime : 2007-1-19 21:58:44
//
// Function Desc : Create an address space to run a user program.
// The steps of AddrSpace::AddrSpace
// 1.Load the program from a file "executable", and set everything
// up so that we can start executing user instructions.
// 2. set up the translation from program memory to physical
// memory.
// 3. load the disk content to memory
// Fails if:
// 1.
// 2.
// 3.
// Note :
// Return type :
// Argument : OpenFile *executable
//////////////////////////////////////////////////////
AddrSpace::AddrSpace(OpenFile *executable)
{
NoffHeader noffH;
unsigned int i, size;
executable->Read((char *)&noffH, sizeof(noffH));
if ((noffH.noffMagic != NOFFMAGIC) &&
(WordToHost(noffH.noffMagic) == NOFFMAGIC))
SwapHeader(&noffH);
ASSERT(noffH.noffMagic == NOFFMAGIC);
size = noffH.code.size + noffH.initData.size + noffH.uninitData.size
+ UserStackSize;
numPages = divRoundUp(size, PageSize);
size = numPages * PageSize;
ASSERT(numPages <= NumPhysPages);
DEBUG('a', "Initializing address space, num pages %d, size %d\n",
numPages, size);
pageTable = new TranslationEntry[numPages];
for (i = 0; i < numPages; i++)
{
pageTable[i].physicalPage = machine->s_FindPage();
pageTable[i].virtualPage = pageTable[i].physicalPage;
pageTable[i].valid = TRUE;
pageTable[i].use = FALSE;
pageTable[i].dirty = FALSE;
pageTable[i].readOnly = FALSE;
}//end for (i = 0...)
//bzero(machine->mainMemory, size);
if (noffH.code.size > 0)
{
int readSize = noffH.code.size;
///
/// must convert virtual addr to physical addr
///
int curAddr = pageTable[noffH.code.virtualAddr/PageSize].physicalPage*PageSize + noffH.code.virtualAddr%PageSize;
int guard = noffH.code.inFileAddr;
executable->ReadAt(&(machine->mainMemory[curAddr]),
readSize, guard);
}// end if (noffH.code...)
if (noffH.initData.size > 0)
{
int readSize = noffH.initData.size;
///
/// must convert virtual addr to physical addr
///
int curAddr = pageTable[noffH.initData.virtualAddr/PageSize].physicalPage*PageSize + noffH.initData.virtualAddr%PageSize;
int guard = noffH.initData.inFileAddr;
executable->ReadAt(&(machine->mainMemory[curAddr]),
readSize, guard);
}//end if (noffH.initData...)
}
//----------------------------------------------------------------------
// AddrSpace::~AddrSpace
// Dealloate an address space. Nothing for now!
//----------------------------------------------------------------------
AddrSpace::~AddrSpace()
{
delete pageTable;
}
//----------------------------------------------------------------------
// AddrSpace::InitRegisters
// Set the initial values for the user-level register set.
//
// We write these directly into the "machine" registers, so
// that we can immediately jump to user code. Note that these
// will be saved/restored into the currentThread->userRegisters
// when this thread is context switched out.
//----------------------------------------------------------------------
void
AddrSpace::InitRegisters()
{
int i;
for (i = 0; i < NumTotalRegs; i++)
machine->WriteRegister(i, 0);
// Initial program counter -- must be location of "Start"
machine->WriteRegister(PCReg, 0);
// Need to also tell MIPS where next instruction is, because
// of branch delay possibility
machine->WriteRegister(NextPCReg, 4);
// Set the stack register to the end of the address space, where we
// allocated the stack; but subtract off a bit, to make sure we don't
// accidentally reference off the end!
machine->WriteRegister(StackReg, numPages * PageSize - 16);
DEBUG('a', "Initializing stack register to %d\n", numPages * PageSize - 16);
}
//////////////////////////////////////////////////////
// Function name : AddrSpace::SaveState
// Creator : Li Showchao(0410716)
// CreateTime : 2007-1-19 21:52:44
//
// Function Desc :
// The steps of AddrSpace::SaveState
// 1. save registers thar this user program used
//
// Fails if:
// 1.
// 2.
// 3.
// Note :
// Return type : void
//////////////////////////////////////////////////////
void AddrSpace::SaveState()
{
for (int i = 0; i < NumTotalRegs; i++)
s_reg[i] = machine->ReadRegister(i);
}
//////////////////////////////////////////////////////
// Function name : AddrSpace::RestoreState
// Creator : Fang Wenbin(0410706)
// CreateTime : 2007-1-19 21:57:21
//
// Function Desc :
// The steps of AddrSpace::RestoreState
// 1. restore page table
// 2. restore registers
//
// Fails if:
// 1.
// 2.
// 3.
// Note :
// Return type : void
//////////////////////////////////////////////////////
void AddrSpace::RestoreState()
{
machine->pageTable = pageTable;
machine->pageTableSize = numPages;
for (int i = 0; i < NumTotalRegs; i++)
machine->WriteRegister(i, s_reg[i]);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?