diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc index 64d0b54a9..9be1d6c85 100644 --- a/src/arch/alpha/process.cc +++ b/src/arch/alpha/process.cc @@ -50,21 +50,24 @@ using namespace std; AlphaProcess::AlphaProcess(ProcessParams *params, ObjectFile *objFile) : Process(params, objFile) { - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); + Addr brk_point = objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(); + brk_point = roundUp(brk_point, PageBytes); // Set up stack. On Alpha, stack goes below text section. This // code should get moved to some architecture-specific spot. - memState->stackBase = objFile->textBase() - (409600+4096); + Addr stack_base = objFile->textBase() - (409600+4096); - // Set up region for mmaps. Tru64 seems to start just above 0 and - // grow up from there. - memState->mmapEnd = 0x10000; + // Set up region for mmaps. + Addr mmap_end = 0x10000; + + Addr max_stack_size = 8 * 1024 * 1024; // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); + Addr next_thread_stack_base = stack_base - max_stack_size; + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -131,15 +134,16 @@ AlphaProcess::argsInit(int intSize, int pageSize) space_needed = 32*1024; // set bottom of stack - memState->stackMin = memState->stackBase - space_needed; + memState->setStackMin(memState->getStackBase() - space_needed); // align it - memState->stackMin = roundDown(memState->stackMin, pageSize); - memState->stackSize = memState->stackBase - memState->stackMin; + memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); + memState->setStackSize(memState->getStackBase() - memState->getStackMin()); // map memory - allocateMem(memState->stackMin, roundUp(memState->stackSize, pageSize)); + allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(), + pageSize)); // map out initial stack contents - Addr argv_array_base = memState->stackMin + intSize; // room for argc + Addr argv_array_base = memState->getStackMin() + intSize; // room for argc Addr envp_array_base = argv_array_base + argv_array_size; Addr auxv_array_base = envp_array_base + envp_array_size; Addr arg_data_base = auxv_array_base + auxv_array_size; @@ -154,7 +158,7 @@ AlphaProcess::argsInit(int intSize, int pageSize) else panic("Unknown int size"); - initVirtMem.writeBlob(memState->stackMin, (uint8_t*)&argc, intSize); + initVirtMem.writeBlob(memState->getStackMin(), (uint8_t*)&argc, intSize); copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); copyStringArray(envp, envp_array_base, env_data_base, initVirtMem); @@ -171,7 +175,7 @@ AlphaProcess::argsInit(int intSize, int pageSize) setSyscallArg(tc, 0, argc); setSyscallArg(tc, 1, argv_array_base); - tc->setIntReg(StackPointerReg, memState->stackMin); + tc->setIntReg(StackPointerReg, memState->getStackMin()); tc->pcState(getStartPC()); } diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index fd0243c44..eb8abfb4d 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -70,36 +70,30 @@ ArmProcess32::ArmProcess32(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - memState->stackBase = 0xbf000000L; + Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(), PageBytes); + Addr stack_base = 0xbf000000L; + Addr max_stack_size = 8 * 1024 * 1024; + Addr next_thread_stack_base = stack_base - max_stack_size; + Addr mmap_end = 0x40000000L; - // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - - // Set up break point (Top of Heap) - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); - - // Set up region for mmaps. For now, start at bottom of kuseg space. - memState->mmapEnd = 0x40000000L; + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } ArmProcess64::ArmProcess64(ProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : ArmProcess(params, objFile, _arch) { - memState->stackBase = 0x7fffff0000L; + Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(), PageBytes); + Addr stack_base = 0x7fffff0000L; + Addr max_stack_size = 8 * 1024 * 1024; + Addr next_thread_stack_base = stack_base - max_stack_size; + Addr mmap_end = 0x4000000000L; - // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - - // Set up break point (Top of Heap) - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); - - // Set up region for mmaps. For now, start at bottom of kuseg space. - memState->mmapEnd = 0x4000000000L; + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -302,16 +296,16 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) int space_needed = frame_size + aux_padding; - memState->stackMin = memState->stackBase - space_needed; - memState->stackMin = roundDown(memState->stackMin, align); - memState->stackSize = memState->stackBase - memState->stackMin; + memState->setStackMin(memState->getStackBase() - space_needed); + memState->setStackMin(roundDown(memState->getStackMin(), align)); + memState->setStackSize(memState->getStackBase() - memState->getStackMin()); // map memory - allocateMem(roundDown(memState->stackMin, pageSize), - roundUp(memState->stackSize, pageSize)); + allocateMem(roundDown(memState->getStackMin(), pageSize), + roundUp(memState->getStackSize(), pageSize)); // map out initial stack contents - IntType sentry_base = memState->stackBase - sentry_size; + IntType sentry_base = memState->getStackBase() - sentry_size; IntType aux_data_base = sentry_base - aux_data_size; IntType env_data_base = aux_data_base - env_data_size; IntType arg_data_base = env_data_base - arg_data_size; @@ -332,7 +326,7 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); DPRINTF(Stack, "0x%x - argc \n", argc_base); - DPRINTF(Stack, "0x%x - stack min\n", memState->stackMin); + DPRINTF(Stack, "0x%x - stack min\n", memState->getStackMin()); // write contents to stack @@ -378,7 +372,7 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set the stack pointer register - tc->setIntReg(spIndex, memState->stackMin); + tc->setIntReg(spIndex, memState->getStackMin()); //A pointer to a function to run when the program exits. We'll set this //to zero explicitly to make sure this isn't used. tc->setIntReg(ArgumentReg0, 0); @@ -405,7 +399,7 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) tc->pcState(pc); //Align the "stackMin" to a page boundary. - memState->stackMin = roundDown(memState->stackMin, pageSize); + memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); } ArmISA::IntReg diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index 4993b3c68..60e343578 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -53,18 +53,23 @@ MipsProcess::MipsProcess(ProcessParams * params, ObjectFile *objFile) { // Set up stack. On MIPS, stack starts at the top of kuseg // user address space. MIPS stack grows down from here - memState->stackBase = 0x7FFFFFFF; + Addr stack_base = 0x7FFFFFFF; + + Addr max_stack_size = 8 * 1024 * 1024; // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); + Addr next_thread_stack_base = stack_base - max_stack_size; // Set up break point (Top of Heap) - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); + Addr brk_point = objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(); + brk_point = roundUp(brk_point, PageBytes); // Set up region for mmaps. Start it 1GB above the top of the heap. - memState->mmapEnd = memState->brkPoint + 0x40000000L; + Addr mmap_end = brk_point + 0x40000000L; + + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -141,15 +146,16 @@ MipsProcess::argsInit(int pageSize) env_data_size; // set bottom of stack - memState->stackMin = memState->stackBase - space_needed; + memState->setStackMin(memState->getStackBase() - space_needed); // align it - memState->stackMin = roundDown(memState->stackMin, pageSize); - memState->stackSize = memState->stackBase - memState->stackMin; + memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); + memState->setStackSize(memState->getStackBase() - memState->getStackMin()); // map memory - allocateMem(memState->stackMin, roundUp(memState->stackSize, pageSize)); + allocateMem(memState->getStackMin(), roundUp(memState->getStackSize(), + pageSize)); - // map out initial stack contents - IntType argv_array_base = memState->stackMin + intSize; // room for argc + // map out initial stack contents; leave room for argc + IntType argv_array_base = memState->getStackMin() + intSize; IntType envp_array_base = argv_array_base + argv_array_size; IntType auxv_array_base = envp_array_base + envp_array_size; IntType arg_data_base = auxv_array_base + auxv_array_size; @@ -160,7 +166,7 @@ MipsProcess::argsInit(int pageSize) argc = htog((IntType)argc); - initVirtMem.writeBlob(memState->stackMin, (uint8_t*)&argc, intSize); + initVirtMem.writeBlob(memState->getStackMin(), (uint8_t*)&argc, intSize); copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem); @@ -185,7 +191,7 @@ MipsProcess::argsInit(int pageSize) setSyscallArg(tc, 0, argc); setSyscallArg(tc, 1, argv_array_base); - tc->setIntReg(StackPointerReg, memState->stackMin); + tc->setIntReg(StackPointerReg, memState->getStackMin()); tc->pcState(getStartPC()); } diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 5a32218ef..4b2efb0a6 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -51,18 +51,23 @@ using namespace PowerISA; PowerProcess::PowerProcess(ProcessParams *params, ObjectFile *objFile) : Process(params, objFile) { - memState->stackBase = 0xbf000000L; + // Set up break point (Top of Heap) + Addr brk_point = objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(); + brk_point = roundUp(brk_point, PageBytes); + + Addr stack_base = 0xbf000000L; + + Addr max_stack_size = 8 * 1024 * 1024; // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - - // Set up break point (Top of Heap) - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); + Addr next_thread_stack_base = stack_base - max_stack_size; // Set up region for mmaps. For now, start at bottom of kuseg space. - memState->mmapEnd = 0x70000000L; + Addr mmap_end = 0x70000000L; + + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -186,16 +191,17 @@ PowerProcess::argsInit(int intSize, int pageSize) int space_needed = frame_size + aux_padding; - memState->stackMin = memState->stackBase - space_needed; - memState->stackMin = roundDown(memState->stackMin, align); - memState->stackSize = memState->stackBase - memState->stackMin; + Addr stack_min = memState->getStackBase() - space_needed; + stack_min = roundDown(stack_min, align); + + memState->setStackSize(memState->getStackBase() - stack_min); // map memory - allocateMem(roundDown(memState->stackMin, pageSize), - roundUp(memState->stackSize, pageSize)); + allocateMem(roundDown(stack_min, pageSize), + roundUp(memState->getStackSize(), pageSize)); // map out initial stack contents - uint32_t sentry_base = memState->stackBase - sentry_size; + uint32_t sentry_base = memState->getStackBase() - sentry_size; uint32_t aux_data_base = sentry_base - aux_data_size; uint32_t env_data_base = aux_data_base - env_data_size; uint32_t arg_data_base = env_data_base - arg_data_size; @@ -214,7 +220,7 @@ PowerProcess::argsInit(int intSize, int pageSize) DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); DPRINTF(Stack, "0x%x - argc \n", argc_base); - DPRINTF(Stack, "0x%x - stack min\n", memState->stackMin); + DPRINTF(Stack, "0x%x - stack min\n", stack_min); // write contents to stack @@ -259,12 +265,12 @@ PowerProcess::argsInit(int intSize, int pageSize) ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set the stack pointer register - tc->setIntReg(StackPointerReg, memState->stackMin); + tc->setIntReg(StackPointerReg, stack_min); tc->pcState(getStartPC()); //Align the "stack_min" to a page boundary. - memState->stackMin = roundDown(memState->stackMin, pageSize); + memState->setStackMin(roundDown(stack_min, pageSize)); } PowerISA::IntReg diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index 8b168cb35..f50fb3196 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -56,16 +56,21 @@ RiscvProcess::RiscvProcess(ProcessParams * params, { // Set up stack. On RISC-V, stack starts at the top of kuseg // user address space. RISC-V stack grows down from here - memState->stackBase = (Addr)0x7FFFFFFF; + Addr stack_base = 0x7FFFFFFF; + + Addr max_stack_size = 8 * 1024 * 1024; // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); + Addr next_thread_stack_base = stack_base - max_stack_size; // Set up break point (Top of Heap) - memState->brkPoint = objFile->bssBase() + objFile->bssSize(); + Addr brk_point = objFile->bssBase() + objFile->bssSize(); // Set up region for mmaps. Start it 1GB above the top of the heap. - memState->mmapEnd = memState->brkPoint + 0x40000000L; + Addr mmap_end = brk_point + 0x40000000L; + + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -124,19 +129,24 @@ RiscvProcess::argsInit(int pageSize) env_data_size += env.size() + 1; int auxv_array_size = 2 * sizeof(IntType)*auxv.size(); - memState->stackSize = sizeof(IntType) + argv_array_size + 2 * + Addr stack_size = sizeof(IntType) + argv_array_size + 2 * sizeof(Addr) + sizeof(Addr) + arg_data_size + 2 * sizeof(Addr); if (!envp.empty()) { - memState->stackSize += 2 * sizeof(Addr) + envp_array_size + 2 * + stack_size += 2 * sizeof(Addr) + envp_array_size + 2 * sizeof(Addr) + env_data_size; } if (!auxv.empty()) - memState->stackSize += 2 * sizeof(Addr) + auxv_array_size; - memState->stackMin = roundDown(memState->stackBase - memState->stackSize, - pageSize); - allocateMem(memState->stackMin, roundUp(memState->stackSize, pageSize)); + stack_size += 2 * sizeof(Addr) + auxv_array_size; - Addr argv_array_base = memState->stackMin + sizeof(IntType); + memState->setStackSize(stack_size); + + Addr stack_min = roundDown(memState->getStackBase() - + stack_size, pageSize); + allocateMem(stack_min, roundUp(memState->getStackSize(), pageSize)); + + memState->setStackMin(stack_min); + + Addr argv_array_base = memState->getStackMin() + sizeof(IntType); Addr arg_data_base = argv_array_base + argv_array_size + 2 * sizeof(Addr); Addr envp_array_base = arg_data_base + arg_data_size; if (!envp.empty()) @@ -161,7 +171,7 @@ RiscvProcess::argsInit(int pageSize) } } - Addr sp = memState->stackMin; + Addr sp = memState->getStackMin(); initVirtMem.writeBlob(sp, (uint8_t *)&argc, sizeof(IntType)); sp += sizeof(IntType); for (Addr arg_pointer: arg_pointers) { @@ -212,7 +222,7 @@ RiscvProcess::argsInit(int pageSize) } ThreadContext *tc = system->getThreadContext(contextIds[0]); - tc->setIntReg(StackPointerReg, memState->stackMin); + tc->setIntReg(StackPointerReg, memState->getStackMin()); tc->pcState(getStartPC()); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index a64bc587f..d8384b470 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -57,15 +57,6 @@ SparcProcess::SparcProcess(ProcessParams * params, ObjectFile *objFile, Addr _StackBias) : Process(params, objFile), StackBias(_StackBias) { - - // XXX all the below need to be updated for SPARC - Ali - memState->brkPoint = objFile->dataBase() + objFile->dataSize() + - objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); - - // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - // Initialize these to 0s fillStart = 0; spillStart = 0; @@ -325,16 +316,16 @@ SparcProcess::argsInit(int pageSize) aux_padding + frame_size; - memState->stackMin = memState->stackBase - space_needed; - memState->stackMin = roundDown(memState->stackMin, align); - memState->stackSize = memState->stackBase - memState->stackMin; + memState->setStackMin(memState->getStackBase() - space_needed); + memState->setStackMin(roundDown(memState->getStackMin(), align)); + memState->setStackSize(memState->getStackBase() - memState->getStackMin()); // Allocate space for the stack - allocateMem(roundDown(memState->stackMin, pageSize), - roundUp(memState->stackSize, pageSize)); + allocateMem(roundDown(memState->getStackMin(), pageSize), + roundUp(memState->getStackSize(), pageSize)); // map out initial stack contents - IntType sentry_base = memState->stackBase - sentry_size; + IntType sentry_base = memState->getStackBase() - sentry_size; IntType file_name_base = sentry_base - file_name_size; IntType env_data_base = file_name_base - env_data_size; IntType arg_data_base = env_data_base - arg_data_size; @@ -358,9 +349,9 @@ SparcProcess::argsInit(int pageSize) DPRINTF(Stack, "%#x - argv array\n", argv_array_base); DPRINTF(Stack, "%#x - argc \n", argc_base); DPRINTF(Stack, "%#x - window save\n", window_save_base); - DPRINTF(Stack, "%#x - stack min\n", memState->stackMin); + DPRINTF(Stack, "%#x - stack min\n", memState->getStackMin()); - assert(window_save_base == memState->stackMin); + assert(window_save_base == memState->getStackMin()); // write contents to stack @@ -399,7 +390,7 @@ SparcProcess::argsInit(int pageSize) // 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 = memState->stackBase; + fillStart = memState->getStackBase(); spillStart = fillStart + sizeof(MachInst) * numFillInsts; ThreadContext *tc = system->getThreadContext(contextIds[0]); @@ -407,7 +398,7 @@ SparcProcess::argsInit(int pageSize) // assert(NumArgumentRegs >= 2); // tc->setIntReg(ArgumentReg[0], argc); // tc->setIntReg(ArgumentReg[1], argv_array_base); - tc->setIntReg(StackPointerReg, memState->stackMin - StackBias); + tc->setIntReg(StackPointerReg, memState->getStackMin() - 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. @@ -416,7 +407,7 @@ SparcProcess::argsInit(int pageSize) tc->pcState(getStartPC()); // Align the "stack_min" to a page boundary. - memState->stackMin = roundDown(memState->stackMin, pageSize); + memState->setStackMin(roundDown(memState->getStackMin(), pageSize)); } void diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 96901fde3..6a203a400 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -32,15 +32,16 @@ #ifndef __SPARC_PROCESS_HH__ #define __SPARC_PROCESS_HH__ +#include #include #include +#include "arch/sparc/isa_traits.hh" +#include "base/loader/object_file.hh" #include "mem/page_table.hh" #include "sim/byteswap.hh" #include "sim/process.hh" -class ObjectFile; - class SparcProcess : public Process { protected: @@ -77,12 +78,27 @@ class Sparc32Process : public SparcProcess Sparc32Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 0) { + Addr brk_point = objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(); + brk_point = roundUp(brk_point, SparcISA::PageBytes); + + // Reserve 8M for main stack. + Addr max_stack_size = 8 * 1024 * 1024; + // Set up stack. On SPARC Linux, stack goes from the top of memory // downward, less the hole for the kernel address space. - memState->stackBase = (Addr)0xf0000000ULL; + Addr stack_base = 0xf0000000ULL; + + // Set pointer for next thread stack. + Addr next_thread_stack_base = stack_base - max_stack_size; // Set up region for mmaps. - memState->mmapEnd = 0x70000000; + Addr mmap_end = 0x70000000; + + memState = std::make_shared(brk_point, stack_base, + max_stack_size, + next_thread_stack_base, + mmap_end); } void initState(); @@ -107,12 +123,26 @@ class Sparc64Process : public SparcProcess Sparc64Process(ProcessParams * params, ObjectFile *objFile) : SparcProcess(params, objFile, 2047) { + Addr brk_point = objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(); + brk_point = roundUp(brk_point, SparcISA::PageBytes); + + Addr max_stack_size = 8 * 1024 * 1024; + // Set up stack. On SPARC Linux, stack goes from the top of memory // downward, less the hole for the kernel address space. - memState->stackBase = (Addr)0x80000000000ULL; + Addr stack_base = 0x80000000000ULL; + + // Set pointer for next thread stack. Reserve 8M for main stack. + Addr next_thread_stack_base = stack_base - max_stack_size; // Set up region for mmaps. - memState->mmapEnd = 0xfffff80000000000ULL; + Addr mmap_end = 0xfffff80000000000ULL; + + memState = std::make_shared(brk_point, stack_base, + max_stack_size, + next_thread_stack_base, + mmap_end); } void initState(); diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index a929897ca..1e6401b10 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -100,9 +100,6 @@ X86Process::X86Process(ProcessParams * params, ObjectFile *objFile, : Process(params, objFile), syscallDescs(_syscallDescs), numSyscallDescs(_numSyscallDescs) { - memState->brkPoint = objFile->dataBase() + objFile->dataSize() - + objFile->bssSize(); - memState->brkPoint = roundUp(memState->brkPoint, PageBytes); } void X86Process::clone(ThreadContext *old_tc, ThreadContext *new_tc, @@ -123,23 +120,15 @@ X86_64Process::X86_64Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vtimeOffset = 0x400; vsyscallPage.vgettimeofdayOffset = 0x0; - // Set up stack. On X86_64 Linux, stack goes from the top of memory - // downward, less the hole for the kernel address space plus one page - // for undertermined purposes. - memState->stackBase = (Addr)0x7FFFFFFFF000ULL; + Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(), PageBytes); + Addr stack_base = 0x7FFFFFFFF000ULL; + Addr max_stack_size = 8 * 1024 * 1024; + Addr next_thread_stack_base = stack_base - max_stack_size; + Addr mmap_end = 0x7FFFF7FFF000ULL; - // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - - // "mmap_base" is a function which defines where mmap region starts in - // the process address space. - // mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd()) - // TASK_SIZE: (1<<47)-PAGE_SIZE - // MIN_GAP: 128*1024*1024+stack_maxrandom_size() - // We do not use any address space layout randomization in gem5 - // therefore the random fields become zero; the smallest gap space was - // chosen but gap could potentially be much larger. - memState->mmapEnd = (Addr)0x7FFFF7FFF000ULL; + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } void @@ -168,20 +157,15 @@ I386Process::I386Process(ProcessParams *params, ObjectFile *objFile, vsyscallPage.vsyscallOffset = 0x400; vsyscallPage.vsysexitOffset = 0x410; - memState->stackBase = _gdtStart; + Addr brk_point = roundUp(objFile->dataBase() + objFile->dataSize() + + objFile->bssSize(), PageBytes); + Addr stack_base = _gdtStart; + Addr max_stack_size = 8 * 1024 * 1024; + Addr next_thread_stack_base = stack_base - max_stack_size; + Addr mmap_end = 0xB7FFF000ULL; - // Set pointer for next thread stack. Reserve 8M for main stack. - memState->nextThreadStackBase = memState->stackBase - (8 * 1024 * 1024); - - // "mmap_base" is a function which defines where mmap region starts in - // the process address space. - // mmap_base: PAGE_ALIGN(TASK_SIZE-MIN_GAP-mmap_rnd()) - // TASK_SIZE: 0xC0000000 - // MIN_GAP: 128*1024*1024+stack_maxrandom_size() - // We do not use any address space layout randomization in gem5 - // therefore the random fields become zero; the smallest gap space was - // chosen but gap could potentially be much larger. - memState->mmapEnd = (Addr)0xB7FFF000ULL; + memState = make_shared(brk_point, stack_base, max_stack_size, + next_thread_stack_base, mmap_end); } SyscallDesc* @@ -955,21 +939,23 @@ X86Process::argsInit(int pageSize, aux_padding + frame_size; - memState->stackMin = memState->stackBase - space_needed; - memState->stackMin = roundDown(memState->stackMin, align); - memState->stackSize = roundUp(memState->stackBase - memState->stackMin, - pageSize); + Addr stack_base = memState->getStackBase(); + + Addr stack_min = stack_base - space_needed; + stack_min = roundDown(stack_min, align); + + unsigned stack_size = stack_base - stack_min; + stack_size = roundUp(stack_size, pageSize); + memState->setStackSize(stack_size); // map memory - Addr stack_end = roundDown(memState->stackBase - memState->stackSize, - pageSize); + Addr stack_end = roundDown(stack_base - stack_size, pageSize); - DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", - stack_end, memState->stackSize); - allocateMem(stack_end, memState->stackSize); + DPRINTF(Stack, "Mapping the stack: 0x%x %dB\n", stack_end, stack_size); + allocateMem(stack_end, stack_size); // map out initial stack contents - IntType sentry_base = memState->stackBase - sentry_size; + IntType sentry_base = stack_base - sentry_size; IntType file_name_base = sentry_base - file_name_size; IntType env_data_base = file_name_base - env_data_size; IntType arg_data_base = env_data_base - arg_data_size; @@ -988,7 +974,7 @@ X86Process::argsInit(int pageSize, DPRINTF(Stack, "0x%x - envp array\n", envp_array_base); DPRINTF(Stack, "0x%x - argv array\n", argv_array_base); DPRINTF(Stack, "0x%x - argc \n", argc_base); - DPRINTF(Stack, "0x%x - stack min\n", memState->stackMin); + DPRINTF(Stack, "0x%x - stack min\n", stack_min); // write contents to stack @@ -1035,14 +1021,14 @@ X86Process::argsInit(int pageSize, ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set the stack pointer register - tc->setIntReg(StackPointerReg, memState->stackMin); + tc->setIntReg(StackPointerReg, stack_min); // There doesn't need to be any segment base added in since we're dealing // with the flat segmentation model. tc->pcState(getStartPC()); //Align the "stack_min" to a page boundary. - memState->stackMin = roundDown(memState->stackMin, pageSize); + memState->setStackMin(roundDown(stack_min, pageSize)); } void diff --git a/src/gpu-compute/shader.cc b/src/gpu-compute/shader.cc index 6c328a7fd..6d6154503 100644 --- a/src/gpu-compute/shader.cc +++ b/src/gpu-compute/shader.cc @@ -83,15 +83,16 @@ Shader::mmap(int length) if (proc->mmapGrowsDown()) { DPRINTF(HSAIL, "GROWS DOWN"); - start = mem_state->mmapEnd - length; - mem_state->mmapEnd = start; + start = mem_state->getMmapEnd() - length; + mem_state->setMmapEnd(start); } else { DPRINTF(HSAIL, "GROWS UP"); - start = mem_state->mmapEnd; - mem_state->mmapEnd += length; + start = mem_state->getMmapEnd(); + mem_state->setMmapEnd(start + length); // assertion to make sure we don't overwrite the stack (it grows down) - assert(mem_state->stackBase - proc->maxStackSize > mem_state->mmapEnd); + assert(mem_state->getStackBase() - mem_state->getMaxStackSize() > + mem_state->getMmapEnd()); } DPRINTF(HSAIL,"Shader::mmap start= %#x, %#x\n", start, length); diff --git a/src/sim/mem_state.hh b/src/sim/mem_state.hh new file mode 100644 index 000000000..03a719752 --- /dev/null +++ b/src/sim/mem_state.hh @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 Advanced Micro Devices, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Author: Brandon Potter + */ + +#ifndef SRC_SIM_MEM_STATE_HH +#define SRC_SIM_MEM_STATE_HH + +/** + * This class holds the memory state for the Process class and all of its + * derived, architecture-specific children. + * + * The fields held in this class dynamically change as the process object + * is run in the simulator. They are updated by system calls and faults; + * each change represents a modification to the process address space. + * The stack, heap, and mmap boundaries are held with this class along with + * the base of the next thread stack. + * + * The class is meant to be allocated dynamically and shared through a + * pointer interface because two process can potentially share their virtual + * address space if certain options are passed into the clone(2). + */ +class MemState +{ + public: + MemState(Addr brk_point, Addr stack_base, Addr max_stack_size, + Addr next_thread_stack_base, Addr mmap_end) + : _brkPoint(brk_point), _stackBase(stack_base), _stackSize(0), + _maxStackSize(max_stack_size), _stackMin(0), + _nextThreadStackBase(next_thread_stack_base), _mmapEnd(mmap_end) + { } + + MemState& + operator=(const MemState &in) + { + if (this == &in) + return *this; + + _brkPoint = in._brkPoint; + _stackBase = in._stackBase; + _stackSize = in._stackSize; + _maxStackSize = in._maxStackSize; + _stackMin = in._stackMin; + _nextThreadStackBase = in._nextThreadStackBase; + _mmapEnd = in._mmapEnd; + return *this; + } + + Addr getBrkPoint() const { return _brkPoint; } + Addr getStackBase() const { return _stackBase; } + Addr getStackSize() const { return _stackSize; } + Addr getMaxStackSize() const { return _maxStackSize; } + Addr getStackMin() const { return _stackMin; } + Addr getNextThreadStackBase() const { return _nextThreadStackBase; } + Addr getMmapEnd() const { return _mmapEnd; } + + void setBrkPoint(Addr brk_point) { _brkPoint = brk_point; } + void setStackBase(Addr stack_base) { _stackBase = stack_base; } + void setStackSize(Addr stack_size) { _stackSize = stack_size; } + void setMaxStackSize(Addr max_stack) { _maxStackSize = max_stack; } + void setStackMin(Addr stack_min) { _stackMin = stack_min; } + void setNextThreadStackBase(Addr ntsb) { _nextThreadStackBase = ntsb; } + void setMmapEnd(Addr mmap_end) { _mmapEnd = mmap_end; } + + private: + Addr _brkPoint; + Addr _stackBase; + Addr _stackSize; + Addr _maxStackSize; + Addr _stackMin; + Addr _nextThreadStackBase; + Addr _mmapEnd; +}; + +#endif diff --git a/src/sim/process.cc b/src/sim/process.cc index 7cfaf6530..e516e2a05 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -111,7 +111,6 @@ Process::Process(ProcessParams * params, ObjectFile * obj_file) _pid(params->pid), _ppid(params->ppid), _pgid(params->pgid), drivers(params->drivers), fds(make_shared(params->input, params->output, params->errout)), - maxStackSize(params->maxStackSize), childClearTID(0) { if (_pid >= System::maxPID) @@ -136,7 +135,6 @@ Process::Process(ProcessParams * params, ObjectFile * obj_file) _tgid = params->pid; exitGroup = new bool(); - memState = new MemState(); sigchld = new bool(); if (!debugSymbolTable) { @@ -164,7 +162,6 @@ Process::clone(ThreadContext *otc, ThreadContext *ntc, np->pTable = pTable; ntc->getMemProxy().setPageTable(np->pTable); - delete np->memState; np->memState = memState; } else { /** @@ -323,24 +320,28 @@ Process::replicatePage(Addr vaddr, Addr new_paddr, ThreadContext *old_tc, bool Process::fixupStackFault(Addr vaddr) { + Addr stack_min = memState->getStackMin(); + Addr stack_base = memState->getStackBase(); + Addr max_stack_size = memState->getMaxStackSize(); + // Check if this is already on the stack and there's just no page there // yet. - if (vaddr >= memState->stackMin && vaddr < memState->stackBase) { + if (vaddr >= stack_min && vaddr < stack_base) { allocateMem(roundDown(vaddr, PageBytes), PageBytes); return true; } // We've accessed the next page of the stack, so extend it to include // this address. - if (vaddr < memState->stackMin - && vaddr >= memState->stackBase - maxStackSize) { - while (vaddr < memState->stackMin) { - memState->stackMin -= TheISA::PageBytes; - if (memState->stackBase - memState->stackMin > maxStackSize) + if (vaddr < stack_min && vaddr >= stack_base - max_stack_size) { + while (vaddr < stack_min) { + stack_min -= TheISA::PageBytes; + if (stack_base - stack_min > max_stack_size) fatal("Maximum stack size exceeded\n"); - allocateMem(memState->stackMin, TheISA::PageBytes); + allocateMem(stack_min, TheISA::PageBytes); inform("Increasing stack size by one page."); }; + memState->setStackMin(stack_min); return true; } return false; @@ -349,12 +350,6 @@ Process::fixupStackFault(Addr vaddr) void Process::serialize(CheckpointOut &cp) const { - SERIALIZE_SCALAR(memState->brkPoint); - SERIALIZE_SCALAR(memState->stackBase); - SERIALIZE_SCALAR(memState->stackSize); - SERIALIZE_SCALAR(memState->stackMin); - SERIALIZE_SCALAR(memState->nextThreadStackBase); - SERIALIZE_SCALAR(memState->mmapEnd); pTable->serialize(cp); /** * Checkpoints for file descriptors currently do not work. Need to @@ -372,12 +367,6 @@ Process::serialize(CheckpointOut &cp) const void Process::unserialize(CheckpointIn &cp) { - UNSERIALIZE_SCALAR(memState->brkPoint); - UNSERIALIZE_SCALAR(memState->stackBase); - UNSERIALIZE_SCALAR(memState->stackSize); - UNSERIALIZE_SCALAR(memState->stackMin); - UNSERIALIZE_SCALAR(memState->nextThreadStackBase); - UNSERIALIZE_SCALAR(memState->mmapEnd); pTable->unserialize(cp); /** * Checkpoints for file descriptors currently do not work. Need to @@ -446,13 +435,14 @@ Process::updateBias() // We are allocating the memory area; set the bias to the lowest address // in the allocated memory region. - Addr *end = &memState->mmapEnd; - Addr ld_bias = mmapGrowsDown() ? *end - interp_mapsize : *end; + Addr mmap_end = memState->getMmapEnd(); + Addr ld_bias = mmapGrowsDown() ? mmap_end - interp_mapsize : mmap_end; // Adjust the process mmap area to give the interpreter room; the real // execve system call would just invoke the kernel's internal mmap // functions to make these adjustments. - *end = mmapGrowsDown() ? ld_bias : *end + interp_mapsize; + mmap_end = mmapGrowsDown() ? ld_bias : mmap_end + interp_mapsize; + memState->setMmapEnd(mmap_end); interp->updateBias(ld_bias); } diff --git a/src/sim/process.hh b/src/sim/process.hh index 52a06bedd..da538f8da 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -47,6 +47,7 @@ #include "mem/se_translating_port_proxy.hh" #include "sim/fd_array.hh" #include "sim/fd_entry.hh" +#include "sim/mem_state.hh" #include "sim/sim_object.hh" struct ProcessParams; @@ -62,40 +63,6 @@ class ThreadContext; class Process : public SimObject { public: - - struct MemState - { - Addr brkPoint; - Addr stackBase; - unsigned stackSize; - Addr stackMin; - Addr nextThreadStackBase; - Addr mmapEnd; - - MemState() - : brkPoint(0), stackBase(0), stackSize(0), stackMin(0), - nextThreadStackBase(0), mmapEnd(0) - { } - - MemState& - operator=(const MemState &in) - { - if (this == &in) - return *this; - - brkPoint = in.brkPoint; - stackBase = in.stackBase; - stackSize = in.stackSize; - stackMin = in.stackMin; - nextThreadStackBase = in.nextThreadStackBase; - mmapEnd = in.mmapEnd; - return *this; - } - - void serialize(CheckpointOut &cp) const; - void unserialize(CheckpointIn &cp); - }; - Process(ProcessParams *params, ObjectFile *obj_file); void serialize(CheckpointOut &cp) const override; @@ -236,9 +203,7 @@ class Process : public SimObject std::shared_ptr fds; bool *exitGroup; - - Addr maxStackSize; - MemState *memState; + std::shared_ptr memState; /** * Calls a futex wakeup at the address specified by this pointer when diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 07899ec9a..f61de229c 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -150,22 +150,25 @@ brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) int index = 0; Addr new_brk = p->getSyscallArg(tc, index); + std::shared_ptr mem_state = p->memState; + Addr brk_point = mem_state->getBrkPoint(); + // in Linux at least, brk(0) returns the current break value // (note that the syscall and the glibc function have different behavior) if (new_brk == 0) - return p->memState->brkPoint; + return brk_point; - if (new_brk > p->memState->brkPoint) { + if (new_brk > brk_point) { // might need to allocate some new pages - for (ChunkGenerator gen(p->memState->brkPoint, - new_brk - p->memState->brkPoint, + for (ChunkGenerator gen(brk_point, + new_brk - brk_point, PageBytes); !gen.done(); gen.next()) { if (!p->pTable->translate(gen.addr())) p->allocateMem(roundDown(gen.addr(), PageBytes), PageBytes); // if the address is already there, zero it out else { - uint8_t zero = 0; + uint8_t zero = 0; SETranslatingPortProxy &tp = tc->getMemProxy(); // split non-page aligned accesses @@ -183,10 +186,10 @@ brkFunc(SyscallDesc *desc, int num, Process *p, ThreadContext *tc) } } - p->memState->brkPoint = new_brk; + mem_state->setBrkPoint(new_brk); DPRINTF_SYSCALL(Verbose, "brk: break point changed to: %#X\n", - p->memState->brkPoint); - return p->memState->brkPoint; + mem_state->getBrkPoint()); + return mem_state->getBrkPoint(); } SyscallReturn diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index 8a34c3415..8cca6ebcb 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -885,11 +885,14 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) new_length = roundUp(new_length, TheISA::PageBytes); if (new_length > old_length) { - if ((start + old_length) == process->memState->mmapEnd && + std::shared_ptr mem_state = process->memState; + Addr mmap_end = mem_state->getMmapEnd(); + + if ((start + old_length) == mmap_end && (!use_provided_address || provided_address == start)) { uint64_t diff = new_length - old_length; - process->allocateMem(process->memState->mmapEnd, diff); - process->memState->mmapEnd += diff; + process->allocateMem(mmap_end, diff); + mem_state->setMmapEnd(mmap_end + diff); return start; } else { if (!use_provided_address && !(flags & OS::TGT_MREMAP_MAYMOVE)) { @@ -897,7 +900,7 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) return -ENOMEM; } else { uint64_t new_start = use_provided_address ? - provided_address : process->memState->mmapEnd; + provided_address : mmap_end; process->pTable->remap(start, old_length, new_start); warn("mremapping to new vaddr %08p-%08p, adding %d\n", new_start, new_start + new_length, @@ -907,9 +910,9 @@ mremapFunc(SyscallDesc *desc, int callnum, Process *process, ThreadContext *tc) new_length - old_length, use_provided_address /* clobber */); if (!use_provided_address) - process->memState->mmapEnd += new_length; + mem_state->setMmapEnd(mmap_end + new_length); if (use_provided_address && - new_start + new_length > process->memState->mmapEnd) { + new_start + new_length > mem_state->getMmapEnd()) { // something fishy going on here, at least notify the user // @todo: increase mmap_end? warn("mmap region limit exceeded with MREMAP_FIXED\n"); @@ -1214,7 +1217,6 @@ cloneFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) pp->executable.assign(*(new std::string(p->progName()))); pp->cmd.push_back(*(new std::string(p->progName()))); pp->system = p->system; - pp->maxStackSize = p->maxStackSize; pp->cwd.assign(p->getcwd()); pp->input.assign("stdin"); pp->output.assign("stdout"); @@ -1457,9 +1459,13 @@ mmapImpl(SyscallDesc *desc, int num, Process *p, ThreadContext *tc, // Extend global mmap region if necessary. Note that we ignore the // start address unless MAP_FIXED is specified. if (!(tgt_flags & OS::TGT_MAP_FIXED)) { - Addr *end = &p->memState->mmapEnd; - start = p->mmapGrowsDown() ? *end - length : *end; - *end = p->mmapGrowsDown() ? start : *end + length; + std::shared_ptr mem_state = p->memState; + Addr mmap_end = mem_state->getMmapEnd(); + + start = p->mmapGrowsDown() ? mmap_end - length : mmap_end; + mmap_end = p->mmapGrowsDown() ? start : mmap_end + length; + + mem_state->setMmapEnd(mmap_end); } DPRINTF_SYSCALL(Verbose, " mmap range is 0x%x - 0x%x\n", @@ -1768,7 +1774,6 @@ execveFunc(SyscallDesc *desc, int callnum, Process *p, ThreadContext *tc) pp->errout.assign("cerr"); pp->cwd.assign(p->getcwd()); pp->system = p->system; - pp->maxStackSize = p->maxStackSize; /** * Prevent process object creation with identical PIDs (which will trip * a fatal check in Process constructor). The execve call is supposed to