summaryrefslogtreecommitdiff
path: root/src/arch/sparc/process.cc
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-11-29 00:00:02 -0800
committerGabe Black <gblack@eecs.umich.edu>2007-11-29 00:00:02 -0800
commit16e99e4677c24147e09ff10d375751a7b114a8d7 (patch)
tree1a34802e53a58e475ba2faeb27c6e9778ffaa08c /src/arch/sparc/process.cc
parenta84d9716d63e16e01bdcef34b115c6dcd20e4146 (diff)
downloadgem5-16e99e4677c24147e09ff10d375751a7b114a8d7.tar.xz
SPARC: Combine the 64 and 32 bit process initialization code.
Alignment is done as it was for 32 bit processes. --HG-- extra : convert_revision : 9368ad40dcc7911f8fc7ec1468c6a28aa92d196f
Diffstat (limited to 'src/arch/sparc/process.cc')
-rw-r--r--src/arch/sparc/process.cc425
1 files changed, 83 insertions, 342 deletions
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 0c40fe58d..e1e7c24ad 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -48,8 +48,8 @@ using namespace SparcISA;
SparcLiveProcess::SparcLiveProcess(LiveProcessParams * params,
- ObjectFile *objFile)
- : LiveProcess(params, objFile)
+ ObjectFile *objFile, Addr _StackBias)
+ : LiveProcess(params, objFile), StackBias(_StackBias)
{
// XXX all the below need to be updated for SPARC - Ali
@@ -108,23 +108,17 @@ void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
}
void
-Sparc32LiveProcess::startup()
+SparcLiveProcess::startup()
{
- if (checkpointRestored)
- return;
-
- argsInit(32 / 8, VMPageSize);
+ Process::startup();
//From the SPARC ABI
- //The process runs in user mode with 32 bit addresses
- threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
-
//Setup default FP state
threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
- //
+
/*
* Register window management registers
*/
@@ -159,73 +153,42 @@ Sparc32LiveProcess::startup()
}
void
-Sparc64LiveProcess::startup()
+Sparc32LiveProcess::startup()
{
if (checkpointRestored)
return;
- argsInit(sizeof(IntReg), VMPageSize);
-
- //From the SPARC ABI
+ SparcLiveProcess::startup();
- //The process runs in user mode
- threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
+ //The process runs in user mode with 32 bit addresses
+ threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x0a);
- //Setup default FP state
- threadContexts[0]->setMiscRegNoEffect(MISCREG_FSR, 0);
+ argsInit(32 / 8, VMPageSize);
+}
- threadContexts[0]->setMiscRegNoEffect(MISCREG_TICK, 0);
+void
+Sparc64LiveProcess::startup()
+{
+ if (checkpointRestored)
+ return;
- /*
- * Register window management registers
- */
+ SparcLiveProcess::startup();
- //No windows contain info from other programs
- //threadContexts[0]->setMiscRegNoEffect(MISCREG_OTHERWIN, 0);
- threadContexts[0]->setIntReg(NumIntArchRegs + 6, 0);
- //There are no windows to pop
- //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANRESTORE, 0);
- threadContexts[0]->setIntReg(NumIntArchRegs + 4, 0);
- //All windows are available to save into
- //threadContexts[0]->setMiscRegNoEffect(MISCREG_CANSAVE, NWindows - 2);
- threadContexts[0]->setIntReg(NumIntArchRegs + 3, NWindows - 2);
- //All windows are "clean"
- //threadContexts[0]->setMiscRegNoEffect(MISCREG_CLEANWIN, NWindows);
- threadContexts[0]->setIntReg(NumIntArchRegs + 5, NWindows);
- //Start with register window 0
- threadContexts[0]->setMiscRegNoEffect(MISCREG_CWP, 0);
- //Always use spill and fill traps 0
- //threadContexts[0]->setMiscRegNoEffect(MISCREG_WSTATE, 0);
- threadContexts[0]->setIntReg(NumIntArchRegs + 7, 0);
- //Set the trap level to 0
- threadContexts[0]->setMiscRegNoEffect(MISCREG_TL, 0);
- //Set the ASI register to something fixed
- threadContexts[0]->setMiscRegNoEffect(MISCREG_ASI, ASI_PRIMARY);
+ //The process runs in user mode
+ threadContexts[0]->setMiscReg(MISCREG_PSTATE, 0x02);
- /*
- * T1 specific registers
- */
- //Turn on the icache, dcache, dtb translation, and itb translation.
- threadContexts[0]->setMiscRegNoEffect(MISCREG_MMU_LSU_CTRL, 15);
+ argsInit(sizeof(IntReg), VMPageSize);
}
-M5_32_auxv_t::M5_32_auxv_t(int32_t type, int32_t val)
+template<class IntType>
+void
+SparcLiveProcess::argsInit(int pageSize)
{
- a_type = TheISA::htog(type);
- a_val = TheISA::htog(val);
-}
+ int intSize = sizeof(IntType);
-M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val)
-{
- a_type = TheISA::htog(type);
- a_val = TheISA::htog(val);
-}
+ typedef M5_auxv_t<IntType> auxv_t;
-void
-Sparc64LiveProcess::argsInit(int intSize, int pageSize)
-{
- typedef M5_64_auxv_t auxv_t;
- Process::startup();
+ std::vector<auxv_t> auxv;
string filename;
if(argv.size() < 1)
@@ -233,7 +196,9 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
else
filename = argv[0];
- Addr alignmentMask = ~(intSize - 1);
+ //Even for a 32 bit process, the ABI says we still need to
+ //maintain double word alignment of the stack pointer.
+ Addr alignmentMask = ~(sizeof(uint64_t) - 1);
// load object file into target memory
objFile->loadSections(initVirtMem);
@@ -259,7 +224,6 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
M5_HWCAP_SPARC_V9 |
M5_HWCAP_SPARC_ULTRA3;
-
//Setup the auxilliary vectors. These will already have endian conversion.
//Auxilliary vectors are loaded only for elf formatted executables.
ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
@@ -298,250 +262,6 @@ Sparc64LiveProcess::argsInit(int intSize, int pageSize)
//Figure out how big the initial stack needs to be
- // The unaccounted for 0 at the top of the stack
- int mysterious_size = intSize;
-
- //This is the name of the file which is present on the initial stack
- //It's purpose is to let the user space linker examine the original file.
- int file_name_size = filename.size() + 1;
-
- 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;
- }
-
- //The info_block needs to be padded so it's size is a multiple of the
- //alignment mask. Also, it appears that there needs to be at least some
- //padding, so if the size is already a multiple, we need to increase it
- //anyway.
- int info_block_size =
- (file_name_size +
- env_data_size +
- arg_data_size +
- intSize) & alignmentMask;
-
- int info_block_padding =
- info_block_size -
- file_name_size -
- env_data_size -
- arg_data_size;
-
- //Each auxilliary vector is two 8 byte words
- int aux_array_size = intSize * 2 * (auxv.size() + 1);
-
- int envp_array_size = intSize * (envp.size() + 1);
- int argv_array_size = intSize * (argv.size() + 1);
-
- int argc_size = intSize;
- int window_save_size = intSize * 16;
-
- int space_needed =
- mysterious_size +
- 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 mysterious_base = stack_base - mysterious_size;
- Addr file_name_base = mysterious_base - file_name_size;
- Addr env_data_base = file_name_base - env_data_size;
- Addr arg_data_base = env_data_base - arg_data_size;
- Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
- Addr envp_array_base = auxv_array_base - envp_array_size;
- Addr argv_array_base = envp_array_base - argv_array_size;
- Addr argc_base = argv_array_base - argc_size;
-#ifndef NDEBUG
- // only used in DPRINTF
- Addr window_save_base = argc_base - window_save_size;
-#endif
-
- DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
- DPRINTF(Sparc, "0x%x - file name\n", file_name_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 - auxv array\n", auxv_array_base);
- DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
- DPRINTF(Sparc, "0x%x - argv 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
-
- // figure out argc
- uint64_t argc = argv.size();
- uint64_t guestArgc = TheISA::htog(argc);
-
- //Write out the mysterious 0
- uint64_t mysterious_zero = 0;
- initVirtMem->writeBlob(mysterious_base,
- (uint8_t*)&mysterious_zero, mysterious_size);
-
- //Write the file name
- initVirtMem->writeString(file_name_base, filename.c_str());
-
- //Copy the aux stuff
- for(int x = 0; x < auxv.size(); x++)
- {
- initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
- (uint8_t*)&(auxv[x].a_type), intSize);
- initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
- (uint8_t*)&(auxv[x].a_val), intSize);
- }
- //Write out the terminating zeroed auxilliary vector
- const uint64_t zero = 0;
- initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
- (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*)&guestArgc, intSize);
-
- //Stuff the trap handlers into the processes address space.
- //Since the stack grows down and is the highest area in the processes
- //address space, we can put stuff above it and stay out of the way.
- int fillSize = sizeof(MachInst) * numFillInsts;
- int spillSize = sizeof(MachInst) * numSpillInsts;
- fillStart = stack_base;
- spillStart = fillStart + fillSize;
- initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler64, fillSize);
- initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler64, spillSize);
-
- //Set up the thread context to start running the process
- assert(NumArgumentRegs >= 2);
- threadContexts[0]->setIntReg(ArgumentReg[0], argc);
- threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
- threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
-
- // %g1 is a pointer to a function that should be run at exit. Since we
- // don't have anything like that, it should be set to 0.
- threadContexts[0]->setIntReg(1, 0);
-
- Addr prog_entry = objFile->entryPoint();
- threadContexts[0]->setPC(prog_entry);
- threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
- threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
-
- //Align the "stack_min" to a page boundary.
- stack_min = roundDown(stack_min, pageSize);
-
-// num_processes++;
-}
-
-void
-Sparc32LiveProcess::argsInit(int intSize, int pageSize)
-{
- typedef M5_32_auxv_t auxv_t;
- Process::startup();
-
- string filename;
- if(argv.size() < 1)
- filename = "";
- else
- filename = argv[0];
-
- //Even though this is a 32 bit process, the ABI says we still need to
- //maintain double word alignment of the stack pointer.
- Addr alignmentMask = ~(8 - 1);
-
- // load object file into target memory
- objFile->loadSections(initVirtMem);
-
- //These are the auxilliary vector types
- enum auxTypes
- {
- SPARC_AT_HWCAP = 16,
- SPARC_AT_PAGESZ = 6,
- SPARC_AT_CLKTCK = 17,
- SPARC_AT_PHDR = 3,
- SPARC_AT_PHENT = 4,
- SPARC_AT_PHNUM = 5,
- SPARC_AT_BASE = 7,
- SPARC_AT_FLAGS = 8,
- SPARC_AT_ENTRY = 9,
- SPARC_AT_UID = 11,
- SPARC_AT_EUID = 12,
- SPARC_AT_GID = 13,
- SPARC_AT_EGID = 14,
- SPARC_AT_SECURE = 23
- };
-
- enum hardwareCaps
- {
- M5_HWCAP_SPARC_FLUSH = 1,
- M5_HWCAP_SPARC_STBAR = 2,
- M5_HWCAP_SPARC_SWAP = 4,
- M5_HWCAP_SPARC_MULDIV = 8,
- M5_HWCAP_SPARC_V9 = 16,
- //This one should technically only be set
- //if there is a cheetah or cheetah_plus tlb,
- //but we'll use it all the time
- M5_HWCAP_SPARC_ULTRA3 = 32
- };
-
- const int64_t hwcap =
- M5_HWCAP_SPARC_FLUSH |
- M5_HWCAP_SPARC_STBAR |
- M5_HWCAP_SPARC_SWAP |
- M5_HWCAP_SPARC_MULDIV |
- M5_HWCAP_SPARC_V9 |
- M5_HWCAP_SPARC_ULTRA3;
-
-
- //Setup the auxilliary vectors. These will already have endian conversion.
- //Auxilliary vectors are loaded only for elf formatted executables.
- ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile);
- if(elfObject)
- {
- //Bits which describe the system hardware capabilities
- auxv.push_back(auxv_t(SPARC_AT_HWCAP, hwcap));
- //The system page size
- auxv.push_back(auxv_t(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
- //Defined to be 100 in the kernel source.
- //Frequency at which times() increments
- auxv.push_back(auxv_t(SPARC_AT_CLKTCK, 100));
- // For statically linked executables, this is the virtual address of the
- // program header tables if they appear in the executable image
- auxv.push_back(auxv_t(SPARC_AT_PHDR, elfObject->programHeaderTable()));
- // This is the size of a program header entry from the elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHENT, elfObject->programHeaderSize()));
- // This is the number of program headers from the original elf file.
- auxv.push_back(auxv_t(SPARC_AT_PHNUM, elfObject->programHeaderCount()));
- //This is the address of the elf "interpreter", It should be set
- //to 0 for regular executables. It should be something else
- //(not sure what) for dynamic libraries.
- auxv.push_back(auxv_t(SPARC_AT_BASE, 0));
- //This is hardwired to 0 in the elf loading code in the kernel
- auxv.push_back(auxv_t(SPARC_AT_FLAGS, 0));
- //The entry point to the program
- auxv.push_back(auxv_t(SPARC_AT_ENTRY, objFile->entryPoint()));
- //Different user and group IDs
- auxv.push_back(auxv_t(SPARC_AT_UID, uid()));
- auxv.push_back(auxv_t(SPARC_AT_EUID, euid()));
- auxv.push_back(auxv_t(SPARC_AT_GID, gid()));
- auxv.push_back(auxv_t(SPARC_AT_EGID, egid()));
- //Whether to enable "secure mode" in the executable
- auxv.push_back(auxv_t(SPARC_AT_SECURE, 0));
- }
-
- //Figure out how big the initial stack needs to be
-
// The unaccounted for 8 byte 0 at the top of the stack
int mysterious_size = 8;
@@ -565,7 +285,7 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
env_data_size +
arg_data_size + intSize);
- //Each auxilliary vector is two 4 byte words
+ //Each auxilliary vector is two words
int aux_array_size = intSize * 2 * (auxv.size() + 1);
int envp_array_size = intSize * (envp.size() + 1);
@@ -586,39 +306,39 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
stack_min &= alignmentMask;
stack_size = stack_base - stack_min;
- // map memory
+ // Allocate space for the stack
pTable->allocate(roundDown(stack_min, pageSize),
roundUp(stack_size, pageSize));
// map out initial stack contents
- uint32_t window_save_base = stack_min;
- uint32_t argc_base = window_save_base + window_save_size;
- uint32_t argv_array_base = argc_base + argc_size;
- uint32_t envp_array_base = argv_array_base + argv_array_size;
- uint32_t auxv_array_base = envp_array_base + envp_array_size;
+ IntType window_save_base = stack_min;
+ IntType argc_base = window_save_base + window_save_size;
+ IntType argv_array_base = argc_base + argc_size;
+ IntType envp_array_base = argv_array_base + argv_array_size;
+ IntType auxv_array_base = envp_array_base + envp_array_size;
//The info block is pushed up against the top of the stack, while
//the rest of the initial stack frame is aligned to an 8 byte boudary.
- uint32_t arg_data_base = stack_base - info_block_size + intSize;
- uint32_t env_data_base = arg_data_base + arg_data_size;
- uint32_t file_name_base = env_data_base + env_data_size;
- uint32_t mysterious_base = file_name_base + file_name_size;
+ IntType arg_data_base = stack_base - info_block_size + intSize;
+ IntType env_data_base = arg_data_base + arg_data_size;
+ IntType file_name_base = env_data_base + env_data_size;
+ IntType mysterious_base = file_name_base + file_name_size;
DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
- DPRINTF(Sparc, "0x%x - file name\n", file_name_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 - auxv array\n", auxv_array_base);
- DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
- DPRINTF(Sparc, "0x%x - argv 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);
+ DPRINTF(Sparc, "%#x - file name\n", file_name_base);
+ DPRINTF(Sparc, "%#x - env data\n", env_data_base);
+ DPRINTF(Sparc, "%#x - arg data\n", arg_data_base);
+ DPRINTF(Sparc, "%#x - auxv array\n", auxv_array_base);
+ DPRINTF(Sparc, "%#x - envp array\n", envp_array_base);
+ DPRINTF(Sparc, "%#x - argv array\n", argv_array_base);
+ DPRINTF(Sparc, "%#x - argc \n", argc_base);
+ DPRINTF(Sparc, "%#x - window save\n", window_save_base);
+ DPRINTF(Sparc, "%#x - stack min\n", stack_min);
// write contents to stack
// figure out argc
- uint32_t argc = argv.size();
- uint32_t guestArgc = TheISA::htog(argc);
+ IntType argc = argv.size();
+ IntType guestArgc = TheISA::htog(argc);
//Write out the mysterious 0
uint64_t mysterious_zero = 0;
@@ -636,8 +356,9 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
(uint8_t*)&(auxv[x].a_val), intSize);
}
+
//Write out the terminating zeroed auxilliary vector
- const uint64_t zero = 0;
+ const IntType zero = 0;
initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
(uint8_t*)&zero, 2 * intSize);
@@ -646,27 +367,23 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
- //Stuff the trap handlers into the processes address space.
- //Since the stack grows down and is the highest area in the processes
- //address space, we can put stuff above it and stay out of the way.
- int fillSize = sizeof(MachInst) * numFillInsts;
- int spillSize = sizeof(MachInst) * numSpillInsts;
+ //Set up space for the trap handlers into the processes address space.
+ //Since the stack grows down and there is reserved address space abov
+ //it, we can put stuff above it and stay out of the way.
fillStart = stack_base;
- spillStart = fillStart + fillSize;
- initVirtMem->writeBlob(fillStart, (uint8_t*)fillHandler32, fillSize);
- initVirtMem->writeBlob(spillStart, (uint8_t*)spillHandler32, spillSize);
+ spillStart = fillStart + sizeof(MachInst) * numFillInsts;
//Set up the thread context to start running the process
//assert(NumArgumentRegs >= 2);
//threadContexts[0]->setIntReg(ArgumentReg[0], argc);
//threadContexts[0]->setIntReg(ArgumentReg[1], argv_array_base);
- threadContexts[0]->setIntReg(StackPointerReg, stack_min);
+ threadContexts[0]->setIntReg(StackPointerReg, stack_min - StackBias);
// %g1 is a pointer to a function that should be run at exit. Since we
// don't have anything like that, it should be set to 0.
threadContexts[0]->setIntReg(1, 0);
- uint32_t prog_entry = objFile->entryPoint();
+ Addr prog_entry = objFile->entryPoint();
threadContexts[0]->setPC(prog_entry);
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
@@ -677,6 +394,30 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
// num_processes++;
}
+void
+Sparc64LiveProcess::argsInit(int intSize, int pageSize)
+{
+ SparcLiveProcess::argsInit<uint64_t>(pageSize);
+
+ // Stuff the trap handlers into the process address space
+ initVirtMem->writeBlob(fillStart,
+ (uint8_t*)fillHandler64, sizeof(MachInst) * numFillInsts);
+ initVirtMem->writeBlob(spillStart,
+ (uint8_t*)spillHandler64, sizeof(MachInst) * numSpillInsts);
+}
+
+void
+Sparc32LiveProcess::argsInit(int intSize, int pageSize)
+{
+ SparcLiveProcess::argsInit<uint32_t>(pageSize);
+
+ // Stuff the trap handlers into the process address space
+ initVirtMem->writeBlob(fillStart,
+ (uint8_t*)fillHandler32, sizeof(MachInst) * numFillInsts);
+ initVirtMem->writeBlob(spillStart,
+ (uint8_t*)spillHandler32, sizeof(MachInst) * numSpillInsts);
+}
+
void Sparc32LiveProcess::flushWindows(ThreadContext *tc)
{
IntReg Cansave = tc->readIntReg(NumIntArchRegs + 3);