Merge m5.eecs.umich.edu:/bk/newmem
into ewok.(none):/home/gblack/m5/newmem --HG-- extra : convert_revision : 3eb97976caf57e43119a998c31128ca6f163c05b
This commit is contained in:
commit
cae6b571d6
21 changed files with 327 additions and 68 deletions
|
@ -693,7 +693,7 @@ decode OPCODE default Unknown::unknown() {
|
|||
SimExit(curTick, "halt instruction encountered");
|
||||
}}, IsNonSpeculative);
|
||||
0x83: callsys({{
|
||||
xc->syscall();
|
||||
xc->syscall(R0);
|
||||
}}, IsNonSpeculative);
|
||||
// Read uniq reg into ABI return value register (r0)
|
||||
0x9e: rduniq({{ R0 = Runiq; }});
|
||||
|
|
|
@ -119,7 +119,7 @@ decode OPCODE_HI default Unknown::unknown() {
|
|||
}
|
||||
|
||||
format BasicOp {
|
||||
0x4: syscall({{ xc->syscall(); }},IsNonSpeculative);
|
||||
0x4: syscall({{ xc->syscall(R2); }},IsNonSpeculative);
|
||||
0x5: break({{ panic("Not implemented break yet"); }},IsNonSpeculative);
|
||||
0x7: sync({{ panic("Not implemented sync yet"); }},IsNonSpeculative);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ def operands {{
|
|||
'Rt': ('IntReg', 'uw', 'RT', 'IsInteger', 3),
|
||||
'r31': ('IntReg', 'uw','R31','IsInteger', 4),
|
||||
'R0': ('IntReg', 'uw','R0', 'IsInteger', 5),
|
||||
'R2': ('IntReg', 'uw','2', 'IsInteger', 5),
|
||||
|
||||
'IntImm': ('IntReg', 'uw', 'INTIMM', 'IsInteger', 3),
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ output header {{
|
|||
OverflowSet=0x7
|
||||
};
|
||||
|
||||
extern char * CondTestAbbrev[];
|
||||
|
||||
/**
|
||||
* Base class for all SPARC static instructions.
|
||||
*/
|
||||
|
@ -65,6 +67,29 @@ output header {{
|
|||
}
|
||||
}};
|
||||
|
||||
output decoder {{
|
||||
|
||||
char * CondTestAbbrev[] =
|
||||
{
|
||||
"nev", //Never
|
||||
"e", //Equal
|
||||
"le", //Less or Equal
|
||||
"l", //Less
|
||||
"leu", //Less or Equal Unsigned
|
||||
"c", //Carry set
|
||||
"n", //Negative
|
||||
"o", //Overflow set
|
||||
"a", //Always
|
||||
"ne", //Not Equal
|
||||
"g", //Greater
|
||||
"ge", //Greater or Equal
|
||||
"gu", //Greater Unsigned
|
||||
"cc", //Carry clear
|
||||
"p", //Positive
|
||||
"oc" //Overflow Clear
|
||||
};
|
||||
}};
|
||||
|
||||
def template ROrImmDecode {{
|
||||
{
|
||||
return (I ? (SparcStaticInst *)(new %(class_name)sImm(machInst))
|
||||
|
|
|
@ -423,41 +423,70 @@ decode OP default Unknown::unknown()
|
|||
}
|
||||
}});
|
||||
0x39: Branch::return({{
|
||||
//If both MemAddressNotAligned and
|
||||
//a fill trap happen, it's not clear
|
||||
//which one should be returned.
|
||||
Addr target = Rs1 + Rs2_or_imm13;
|
||||
if(target & 0x3)
|
||||
fault = new MemAddressNotAligned;
|
||||
else
|
||||
NNPC = target;
|
||||
//This needs to change the register window
|
||||
//like restore does
|
||||
if(fault == NoFault)
|
||||
{
|
||||
//CWP should be set directly so that it always happens
|
||||
//Also, this will allow writing to the new window and
|
||||
//reading from the old one
|
||||
Cwp = (Cwp - 1 + NWindows) % NWindows;
|
||||
if(Canrestore == 0)
|
||||
{
|
||||
if(Otherwin)
|
||||
fault = new FillNOther(WstateOther);
|
||||
else
|
||||
fault = new FillNNormal(WstateNormal);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rd = Rs1 + Rs2_or_imm13;
|
||||
Cansave = Cansave + 1;
|
||||
Canrestore = Canrestore - 1;
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
//are written in the new window as well.
|
||||
xc->setMiscRegWithEffect(MISCREG_CWP, Cwp);
|
||||
}
|
||||
}});
|
||||
0x3A: decode CC
|
||||
{
|
||||
0x0: Trap::tcci({{
|
||||
#if FULL_SYSTEM
|
||||
fault = new TrapInstruction;
|
||||
#else
|
||||
if(passesCondition(CcrIcc, machInst<25:28>))
|
||||
if(passesCondition(CcrIcc, COND2))
|
||||
{
|
||||
// At least glibc only uses trap 0,
|
||||
// solaris/sunos may use others
|
||||
assert((I ? Rs1 + Rs2 : Rs1 + SW_TRAP) == 0);
|
||||
xc->syscall();
|
||||
}
|
||||
int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
|
||||
DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
|
||||
#if FULL_SYSTEM
|
||||
fault = new TrapInstruction(lTrapNum);
|
||||
#else
|
||||
DPRINTF(Sparc, "The syscall number is %d\n", R1);
|
||||
xc->syscall(R1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTF(Sparc, "Didn't fire on %s\n", CondTestAbbrev[machInst<25:28>]);
|
||||
}
|
||||
}});
|
||||
0x2: Trap::tccx({{
|
||||
#if FULL_SYSTEM
|
||||
fault = new TrapInstruction;
|
||||
#else
|
||||
if(passesCondition(CcrXcc, machInst<25:28>))
|
||||
if(passesCondition(CcrXcc, COND2))
|
||||
{
|
||||
// At least glibc only uses trap 0,
|
||||
// solaris/sunos may use others
|
||||
assert((I ? Rs1 + Rs2 : Rs1 + SW_TRAP) == 0);
|
||||
xc->syscall();
|
||||
}
|
||||
int lTrapNum = I ? (Rs1 + SW_TRAP) : (Rs1 + Rs2);
|
||||
DPRINTF(Sparc, "The trap number is %d\n", lTrapNum);
|
||||
#if FULL_SYSTEM
|
||||
fault = new TrapInstruction(lTrapNum);
|
||||
#else
|
||||
DPRINTF(Sparc, "The syscall number is %d\n", R1);
|
||||
xc->syscall(R1);
|
||||
#endif
|
||||
}
|
||||
}});
|
||||
}
|
||||
0x3B: Nop::flush({{/*Instruction memory flush*/}});
|
||||
|
@ -482,8 +511,8 @@ decode OP default Unknown::unknown()
|
|||
{
|
||||
Cwp = (Cwp + 1) % NWindows;
|
||||
Rd = Rs1 + Rs2_or_imm13;
|
||||
Cansave--;
|
||||
Canrestore++;
|
||||
Cansave = Cansave - 1;
|
||||
Canrestore = Canrestore + 1;
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
|
@ -505,8 +534,8 @@ decode OP default Unknown::unknown()
|
|||
else
|
||||
{
|
||||
Rd = Rs1 + Rs2_or_imm13;
|
||||
Cansave++;
|
||||
Canrestore--;
|
||||
Cansave = Cansave + 1;
|
||||
Canrestore = Canrestore - 1;
|
||||
}
|
||||
//This is here to make sure the CWP is written
|
||||
//no matter what. This ensures that the results
|
||||
|
@ -607,15 +636,15 @@ decode OP default Unknown::unknown()
|
|||
format Trap {
|
||||
0x20: ldf({{fault = new FpDisabled;}});
|
||||
0x21: decode X {
|
||||
0x0: ldfsr({{fault = new FpDisabled;}});
|
||||
0x1: ldxfsr({{fault = new FpDisabled;}});
|
||||
0x0: Load::ldfsr({{Fsr = Mem<31:0> | Fsr<63:32>;}}, {{32}});
|
||||
0x1: Load::ldxfsr({{Fsr = Mem;}}, {{64}});
|
||||
}
|
||||
0x22: ldqf({{fault = new FpDisabled;}});
|
||||
0x23: lddf({{fault = new FpDisabled;}});
|
||||
0x24: stf({{fault = new FpDisabled;}});
|
||||
0x25: decode X {
|
||||
0x0: stfsr({{fault = new FpDisabled;}});
|
||||
0x1: stxfsr({{fault = new FpDisabled;}});
|
||||
0x0: Store::stfsr({{Mem = Fsr<31:0>;}}, {{32}});
|
||||
0x1: Store::stxfsr({{Mem = Fsr;}}, {{64}});
|
||||
}
|
||||
0x26: stqf({{fault = new FpDisabled;}});
|
||||
0x27: stdf({{fault = new FpDisabled;}});
|
||||
|
|
|
@ -230,14 +230,13 @@ def template BranchExecute {{
|
|||
def format Branch(code, *opt_flags) {{
|
||||
(usesImm, code, immCode,
|
||||
rString, iString) = splitOutImm(code)
|
||||
codeBlk = CodeBlock(code)
|
||||
iop = InstObjParams(name, Name, 'Branch', codeBlk, opt_flags)
|
||||
iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
decoder_output = BasicConstructor.subst(iop)
|
||||
exec_output = BranchExecute.subst(iop)
|
||||
if usesImm:
|
||||
imm_iop = InstObjParams(name, Name + 'Imm', 'BranchImm' + iString,
|
||||
codeBlk, opt_flags)
|
||||
immCode, opt_flags)
|
||||
header_output += BasicDeclare.subst(imm_iop)
|
||||
decoder_output += BasicConstructor.subst(imm_iop)
|
||||
exec_output += BranchExecute.subst(imm_iop)
|
||||
|
|
|
@ -243,8 +243,8 @@ def template IntOpExecute {{
|
|||
//Write the resulting state to the execution context
|
||||
if(fault == NoFault)
|
||||
{
|
||||
%(op_wb)s;
|
||||
%(cc_code)s;
|
||||
%(op_wb)s;
|
||||
}
|
||||
return fault;
|
||||
}
|
||||
|
|
|
@ -47,17 +47,18 @@ output decoder {{
|
|||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(!load)
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[load ? 0 : 1]);
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
ccprintf(response, " + ");
|
||||
printReg(response, _srcRegIdx[load ? 1 : 2]);
|
||||
printReg(response, _srcRegIdx[!save ? 1 : 2]);
|
||||
ccprintf(response, " ]");
|
||||
if(load)
|
||||
{
|
||||
|
@ -73,15 +74,16 @@ output decoder {{
|
|||
{
|
||||
std::stringstream response;
|
||||
bool load = flags[IsLoad];
|
||||
bool save = flags[IsStore];
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
if(!load)
|
||||
if(save)
|
||||
{
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", ");
|
||||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[load ? 0 : 1]);
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
ccprintf(response, " + 0x%x ]", imm);
|
||||
if(load)
|
||||
{
|
||||
|
|
|
@ -14,12 +14,14 @@ output header {{
|
|||
|
||||
// Constructor
|
||||
Trap(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
SparcStaticInst(mnem, _machInst, __opClass)
|
||||
SparcStaticInst(mnem, _machInst, __opClass), trapNum(SW_TRAP)
|
||||
{
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const;
|
||||
|
||||
int trapNum;
|
||||
};
|
||||
}};
|
||||
|
||||
|
@ -27,7 +29,15 @@ output decoder {{
|
|||
std::string Trap::generateDisassembly(Addr pc,
|
||||
const SymbolTable *symtab) const
|
||||
{
|
||||
return "Trap instruction";
|
||||
std::stringstream response;
|
||||
|
||||
printMnemonic(response, mnemonic);
|
||||
ccprintf(response, " ");
|
||||
printReg(response, _srcRegIdx[0]);
|
||||
ccprintf(response, ", 0x%x", trapNum);
|
||||
ccprintf(response, ", or ");
|
||||
printReg(response, _srcRegIdx[1]);
|
||||
return response.str();
|
||||
}
|
||||
}};
|
||||
|
||||
|
|
|
@ -30,8 +30,9 @@ def operands {{
|
|||
#'Runiq': ('ControlReg', 'uq', 'Uniq', None, 1),
|
||||
#'FPCR': ('ControlReg', 'uq', 'Fpcr', None, 1),
|
||||
'R0': ('IntReg', 'udw', '0', None, 6),
|
||||
'R15': ('IntReg', 'udw', '15', 'IsInteger', 7),
|
||||
'R16': ('IntReg', 'udw', '16', None, 8),
|
||||
'R1': ('IntReg', 'udw', '1', None, 7),
|
||||
'R15': ('IntReg', 'udw', '15', 'IsInteger', 8),
|
||||
'R16': ('IntReg', 'udw', '16', None, 9),
|
||||
# Control registers
|
||||
'Pstate': ('ControlReg', 'udw', 'MISCREG_PSTATE', None, 1),
|
||||
'PstateAg': ('ControlReg', 'udw', 'MISCREG_PSTATE_AG', None, 2),
|
||||
|
|
|
@ -118,13 +118,12 @@ namespace SparcISA
|
|||
const int ArgumentReg3 = 11;
|
||||
const int ArgumentReg4 = 12;
|
||||
const int ArgumentReg5 = 13;
|
||||
const int SyscallNumReg = 1;
|
||||
// Some OS syscall use a second register (o1) to return a second value
|
||||
const int SyscallPseudoReturnReg = ArgumentReg1;
|
||||
|
||||
//XXX These numbers are bogus
|
||||
const int MaxInstSrcRegs = 8;
|
||||
const int MaxInstDestRegs = 3;
|
||||
const int MaxInstDestRegs = 9;
|
||||
|
||||
typedef uint64_t IntReg;
|
||||
|
||||
|
@ -174,11 +173,11 @@ namespace SparcISA
|
|||
// and put the return value itself in the standard return value reg ().
|
||||
if (return_value.successful()) {
|
||||
// no error
|
||||
regs->setMiscReg(MISCREG_CCR_ICC_C, 0);
|
||||
regs->setMiscReg(MISCREG_CCR_XCC_C, 0);
|
||||
regs->setIntReg(ReturnValueReg, return_value.value());
|
||||
} else {
|
||||
// got an error, return details
|
||||
regs->setMiscReg(MISCREG_CCR_ICC_C, 1);
|
||||
regs->setMiscReg(MISCREG_CCR_XCC_C, 1);
|
||||
regs->setIntReg(ReturnValueReg, return_value.value());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,9 @@
|
|||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "arch/sparc/linux/process.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/linux/process.hh"
|
||||
#include "arch/sparc/regfile.hh"
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "cpu/exec_context.hh"
|
||||
|
@ -54,6 +55,40 @@ unameFunc(SyscallDesc *desc, int callnum, Process *process,
|
|||
strcpy(name->machine, "sparc");
|
||||
|
||||
name.copyOut(xc->getMemPort());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SyscallReturn SparcISA::getresuidFunc(SyscallDesc *desc, int num,
|
||||
Process *p, ExecContext *xc)
|
||||
{
|
||||
const IntReg id = htog(100);
|
||||
Addr ruid = xc->getSyscallArg(0);
|
||||
Addr euid = xc->getSyscallArg(1);
|
||||
Addr suid = xc->getSyscallArg(2);
|
||||
//Handle the EFAULT case
|
||||
//Set the ruid
|
||||
if(ruid)
|
||||
{
|
||||
BufferArg ruidBuff(ruid, sizeof(IntReg));
|
||||
memcpy(ruidBuff.bufferPtr(), &id, sizeof(IntReg));
|
||||
ruidBuff.copyOut(xc->getMemPort());
|
||||
}
|
||||
//Set the euid
|
||||
if(euid)
|
||||
{
|
||||
BufferArg euidBuff(euid, sizeof(IntReg));
|
||||
memcpy(euidBuff.bufferPtr(), &id, sizeof(IntReg));
|
||||
euidBuff.copyOut(xc->getMemPort());
|
||||
}
|
||||
//Set the suid
|
||||
if(suid)
|
||||
{
|
||||
BufferArg suidBuff(suid, sizeof(IntReg));
|
||||
memcpy(suidBuff.bufferPtr(), &id, sizeof(IntReg));
|
||||
suidBuff.copyOut(xc->getMemPort());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -167,7 +202,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 106 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
|
||||
/* 107 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
|
||||
/* 108 */ SyscallDesc("setresuid", unimplementedFunc),
|
||||
/* 109 */ SyscallDesc("getresuid", unimplementedFunc),
|
||||
/* 109 */ SyscallDesc("getresuid", getresuidFunc),
|
||||
/* 110 */ SyscallDesc("setresgid", unimplementedFunc),
|
||||
/* 111 */ SyscallDesc("getresgid", unimplementedFunc),
|
||||
/* 112 */ SyscallDesc("setregid32", unimplementedFunc),
|
||||
|
|
|
@ -57,5 +57,8 @@ class SparcLinuxProcess : public SparcLiveProcess
|
|||
const int Num_Syscall_Descs;
|
||||
};
|
||||
|
||||
SyscallReturn getresuidFunc(SyscallDesc *desc, int num,
|
||||
Process *p, ExecContext *xc);
|
||||
|
||||
} // namespace SparcISA
|
||||
#endif // __ALPHA_LINUX_PROCESS_HH__
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include "base/loader/object_file.hh"
|
||||
#include "base/misc.hh"
|
||||
#include "cpu/exec_context.hh"
|
||||
#include "mem/page_table.hh"
|
||||
#include "mem/translating_port.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
|
@ -81,9 +83,9 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
|||
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
|
||||
brk_point = roundUp(brk_point, VMPageSize);
|
||||
|
||||
// Set up stack. On Alpha, stack goes below text section. This
|
||||
// code should get moved to some architecture-specific spot.
|
||||
stack_base = objFile->textBase() - (409600+4096);
|
||||
// Set up stack. On SPARC Linux, stack goes from the top of memory
|
||||
// downward, less the hole for the kernel address space.
|
||||
stack_base = ((Addr)0x80000000000);
|
||||
|
||||
// Set up region for mmaps. Tru64 seems to start just above 0 and
|
||||
// grow up from there.
|
||||
|
@ -91,16 +93,151 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
|||
|
||||
// Set pointer for next thread stack. Reserve 8M for main stack.
|
||||
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
SparcLiveProcess::startup()
|
||||
{
|
||||
argsInit(MachineBytes, VMPageSize);
|
||||
|
||||
//From the SPARC ABI
|
||||
|
||||
//The process runs in user mode
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_PRIV, 0);
|
||||
//Interrupts are enabled
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_PSTATE_IE, 1);
|
||||
//Round to nearest
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_RD, 0);
|
||||
//Floating point traps are not enabled
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_TEM, 0);
|
||||
//Turn non standard mode off
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_NS, 0);
|
||||
//The floating point queue is empty
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_QNE, 0);
|
||||
//There are no accrued eexecContext[0]eptions
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_AEXC, 0);
|
||||
//There are no current eexecContext[0]eptions
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_FSR_CEXC, 0);
|
||||
|
||||
/*
|
||||
* Register window management registers
|
||||
*/
|
||||
|
||||
//No windows contain info from other programs
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_OTHERWIN, 0);
|
||||
//There are no windows to pop
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_CANRESTORE, 0);
|
||||
//All windows are available to save into
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_CANSAVE, NWindows - 2);
|
||||
//All windows are "clean"
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_CLEANWIN, NWindows);
|
||||
//Start with register window 0
|
||||
execContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
|
||||
}
|
||||
|
||||
void
|
||||
SparcLiveProcess::argsInit(int intSize, int pageSize)
|
||||
{
|
||||
Process::startup();
|
||||
|
||||
Addr alignmentMask = ~(intSize - 1);
|
||||
|
||||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
//Figure out how big the initial stack needs to be
|
||||
|
||||
int aux_data_size = 0;
|
||||
//Figure out the aux_data_size?
|
||||
int env_data_size = 0;
|
||||
for (int i = 0; i < envp.size(); ++i) {
|
||||
env_data_size += envp[i].size() + 1;
|
||||
}
|
||||
int arg_data_size = 0;
|
||||
for (int i = 0; i < argv.size(); ++i) {
|
||||
arg_data_size += argv[i].size() + 1;
|
||||
}
|
||||
|
||||
int aux_array_size = intSize * 2 * (auxv.size() + 1);
|
||||
|
||||
int argv_array_size = intSize * (argv.size() + 1);
|
||||
int envp_array_size = intSize * (envp.size() + 1);
|
||||
|
||||
int argc_size = intSize;
|
||||
int window_save_size = intSize * 16;
|
||||
|
||||
int info_block_size =
|
||||
(aux_data_size +
|
||||
env_data_size +
|
||||
arg_data_size +
|
||||
~alignmentMask) & alignmentMask;
|
||||
|
||||
int info_block_padding =
|
||||
info_block_size -
|
||||
aux_data_size -
|
||||
env_data_size -
|
||||
arg_data_size;
|
||||
|
||||
int space_needed =
|
||||
info_block_size +
|
||||
aux_array_size +
|
||||
envp_array_size +
|
||||
argv_array_size +
|
||||
argc_size +
|
||||
window_save_size;
|
||||
|
||||
stack_min = stack_base - space_needed;
|
||||
stack_min &= alignmentMask;
|
||||
stack_size = stack_base - stack_min;
|
||||
|
||||
// map memory
|
||||
pTable->allocate(roundDown(stack_min, pageSize),
|
||||
roundUp(stack_size, pageSize));
|
||||
|
||||
// map out initial stack contents
|
||||
Addr aux_data_base = stack_base - aux_data_size - info_block_padding;
|
||||
Addr env_data_base = aux_data_base - env_data_size;
|
||||
Addr arg_data_base = env_data_base - arg_data_size;
|
||||
Addr aux_array_base = arg_data_base - aux_array_size;
|
||||
Addr envp_array_base = aux_array_base - envp_array_size;
|
||||
Addr argv_array_base = envp_array_base - argv_array_size;
|
||||
Addr argc_base = argv_array_base - argc_size;
|
||||
Addr window_save_base = argc_base - window_save_size;
|
||||
|
||||
DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
|
||||
DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base);
|
||||
DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
|
||||
DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
|
||||
DPRINTF(Sparc, "0x%x - aux array\n", aux_array_base);
|
||||
DPRINTF(Sparc, "0x%x - env array\n", envp_array_base);
|
||||
DPRINTF(Sparc, "0x%x - arg array\n", argv_array_base);
|
||||
DPRINTF(Sparc, "0x%x - argc \n", argc_base);
|
||||
DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
|
||||
DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
|
||||
|
||||
// write contents to stack
|
||||
uint64_t argc = argv.size();
|
||||
|
||||
//Copy the aux stuff? For now just put in the null vect
|
||||
const uint64_t zero = 0;
|
||||
initVirtMem->writeBlob(aux_array_base, (uint8_t*)&zero, 2 * intSize);
|
||||
|
||||
copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
|
||||
copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
|
||||
|
||||
initVirtMem->writeBlob(argc_base, (uint8_t*)&argc, intSize);
|
||||
|
||||
execContexts[0]->setIntReg(ArgumentReg0, argc);
|
||||
execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
|
||||
execContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
|
||||
|
||||
Addr prog_entry = objFile->entryPoint();
|
||||
execContexts[0]->setPC(prog_entry);
|
||||
execContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
|
||||
execContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
|
||||
|
||||
// num_processes++;
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcLiveProcess)
|
||||
|
|
|
@ -39,6 +39,20 @@ class System;
|
|||
class SparcLiveProcess : public LiveProcess
|
||||
{
|
||||
protected:
|
||||
typedef struct
|
||||
{
|
||||
int64_t a_type;
|
||||
union {
|
||||
int64_t a_val;
|
||||
Addr a_ptr;
|
||||
Addr a_fcn;
|
||||
};
|
||||
} m5_auxv_t;
|
||||
|
||||
static const Addr StackBias = 2047;
|
||||
|
||||
std::vector<m5_auxv_t> auxv;
|
||||
|
||||
SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
||||
System *_system, int stdin_fd, int stdout_fd, int stderr_fd,
|
||||
std::vector<std::string> &argv,
|
||||
|
@ -57,6 +71,8 @@ class SparcLiveProcess : public LiveProcess
|
|||
std::vector<std::string> &argv,
|
||||
std::vector<std::string> &envp);
|
||||
|
||||
void argsInit(int intSize, int pageSize);
|
||||
|
||||
};
|
||||
|
||||
#endif // __SPARC_PROCESS_HH__
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace SparcISA
|
|||
const int MaxTL = 4;
|
||||
|
||||
// NWINDOWS - number of register windows, can be 3 to 32
|
||||
const int NWindows = 6;
|
||||
const int NWindows = 32;
|
||||
|
||||
class IntRegFile
|
||||
{
|
||||
|
@ -581,7 +581,7 @@ namespace SparcISA
|
|||
tickFields.npt = 1; //The TICK register is unreadable by
|
||||
//non-priveleged software
|
||||
#else
|
||||
//This sets up the initial state of the processor for usermode processes
|
||||
/* //This sets up the initial state of the processor for usermode processes
|
||||
pstateFields.priv = 0; //Process runs in user mode
|
||||
pstateFields.ie = 1; //Interrupts are enabled
|
||||
fsrFields.rd = 0; //Round to nearest
|
||||
|
@ -595,7 +595,7 @@ namespace SparcISA
|
|||
otherwin = 0; //No windows contain info from other programs
|
||||
canrestore = 0; //There are no windows to pop
|
||||
cansave = MaxTL - 2; //All windows are available to save into
|
||||
cleanwin = MaxTL;
|
||||
cleanwin = MaxTL;*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -518,9 +518,9 @@ class CPUExecContext
|
|||
TheISA::setSyscallReturn(return_value, ®s);
|
||||
}
|
||||
|
||||
void syscall()
|
||||
void syscall(int64_t callnum)
|
||||
{
|
||||
process->syscall(proxy);
|
||||
process->syscall(callnum, proxy);
|
||||
}
|
||||
|
||||
Counter readFuncExeInst() { return func_exe_inst; }
|
||||
|
|
|
@ -234,7 +234,7 @@ class ExecContext
|
|||
|
||||
virtual void setSyscallReturn(SyscallReturn return_value) = 0;
|
||||
|
||||
virtual void syscall() = 0;
|
||||
virtual void syscall(int64_t callnum) = 0;
|
||||
|
||||
// Same with st cond failures.
|
||||
virtual Counter readFuncExeInst() = 0;
|
||||
|
@ -432,7 +432,7 @@ class ProxyExecContext : public ExecContext
|
|||
void setSyscallReturn(SyscallReturn return_value)
|
||||
{ actualXC->setSyscallReturn(return_value); }
|
||||
|
||||
void syscall() { actualXC->syscall(); }
|
||||
void syscall(int64_t callnum) { actualXC->syscall(callnum); }
|
||||
|
||||
Counter readFuncExeInst() { return actualXC->readFuncExeInst(); }
|
||||
|
||||
|
|
|
@ -414,7 +414,7 @@ class SimpleCPU : public BaseCPU
|
|||
void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
|
||||
bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
|
||||
#else
|
||||
void syscall() { cpuXC->syscall(); }
|
||||
void syscall(int64_t callnum) { cpuXC->syscall(callnum); }
|
||||
#endif
|
||||
|
||||
bool misspeculating() { return cpuXC->misspeculating(); }
|
||||
|
|
|
@ -240,7 +240,7 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
|
|||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
|
||||
TranslatingPort* memPort)
|
||||
{
|
||||
|
@ -348,12 +348,10 @@ LiveProcess::argsInit(int intSize, int pageSize)
|
|||
}
|
||||
|
||||
void
|
||||
LiveProcess::syscall(ExecContext *xc)
|
||||
LiveProcess::syscall(int64_t callnum, ExecContext *xc)
|
||||
{
|
||||
num_syscalls++;
|
||||
|
||||
int64_t callnum = xc->readIntReg(SyscallNumReg);
|
||||
|
||||
SyscallDesc *desc = getDesc(callnum);
|
||||
if (desc == NULL)
|
||||
fatal("Syscall %d out of range", callnum);
|
||||
|
|
|
@ -50,6 +50,10 @@ class PageTable;
|
|||
class TranslatingPort;
|
||||
class System;
|
||||
|
||||
void
|
||||
copyStringArray(std::vector<std::string> &strings, Addr array_ptr,
|
||||
Addr data_ptr, TranslatingPort* memPort);
|
||||
|
||||
class Process : public SimObject
|
||||
{
|
||||
public:
|
||||
|
@ -155,7 +159,7 @@ class Process : public SimObject
|
|||
// look up simulator fd for given target fd
|
||||
int sim_fd(int tgt_fd);
|
||||
|
||||
virtual void syscall(ExecContext *xc) = 0;
|
||||
virtual void syscall(int64_t callnum, ExecContext *xc) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -174,10 +178,10 @@ class LiveProcess : public Process
|
|||
std::vector<std::string> &argv,
|
||||
std::vector<std::string> &envp);
|
||||
|
||||
void argsInit(int intSize, int pageSize);
|
||||
virtual void argsInit(int intSize, int pageSize);
|
||||
|
||||
public:
|
||||
virtual void syscall(ExecContext *xc);
|
||||
virtual void syscall(int64_t callnum, ExecContext *xc);
|
||||
|
||||
virtual SyscallDesc* getDesc(int callnum) = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue