diff options
author | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
---|---|---|
committer | ARM gem5 Developers <none@none> | 2014-01-24 15:29:34 -0600 |
commit | 612f8f074fa1099cf70faf495d46cc647762a031 (patch) | |
tree | bd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/process.cc | |
parent | f3585c841e964c98911784a187fc4f081a02a0a6 (diff) | |
download | gem5-612f8f074fa1099cf70faf495d46cc647762a031.tar.xz |
arm: Add support for ARMv8 (AArch64 & AArch32)
Note: AArch64 and AArch32 interworking is not supported. If you use an AArch64
kernel you are restricted to AArch64 user-mode binaries. This will be addressed
in a later patch.
Note: Virtualization is only supported in AArch32 mode. This will also be fixed
in a later patch.
Contributors:
Giacomo Gabrielli (TrustZone, LPAE, system-level AArch64, AArch64 NEON, validation)
Thomas Grocutt (AArch32 Virtualization, AArch64 FP, validation)
Mbou Eyole (AArch64 NEON, validation)
Ali Saidi (AArch64 Linux support, code integration, validation)
Edmund Grimley-Evans (AArch64 FP)
William Wang (AArch64 Linux support)
Rene De Jong (AArch64 Linux support, performance opt.)
Matt Horsnell (AArch64 MP, validation)
Matt Evans (device models, code integration, validation)
Chris Adeniyi-Jones (AArch64 syscall-emulation)
Prakash Ramrakhyani (validation)
Dam Sunwoo (validation)
Chander Sudanthi (validation)
Stephan Diestelhorst (validation)
Andreas Hansson (code integration, performance opt.)
Eric Van Hensbergen (performance opt.)
Gabe Black
Diffstat (limited to 'src/arch/arm/process.cc')
-rw-r--r-- | src/arch/arm/process.cc | 132 |
1 files changed, 104 insertions, 28 deletions
diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 37999c905..dd23a5e21 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 ARM Limited + * Copyright (c) 2010, 2012 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -61,6 +61,12 @@ ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile, ObjectFile::Arch _arch) : LiveProcess(params, objFile), arch(_arch) { +} + +ArmLiveProcess32::ArmLiveProcess32(LiveProcessParams *params, + ObjectFile *objFile, ObjectFile::Arch _arch) + : ArmLiveProcess(params, objFile, _arch) +{ stack_base = 0xbf000000L; // Set pointer for next thread stack. Reserve 8M for main stack. @@ -74,11 +80,28 @@ ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile, mmap_start = mmap_end = 0x40000000L; } +ArmLiveProcess64::ArmLiveProcess64(LiveProcessParams *params, + ObjectFile *objFile, ObjectFile::Arch _arch) + : ArmLiveProcess(params, objFile, _arch) +{ + stack_base = 0x7fffff0000L; + + // Set pointer for next thread stack. Reserve 8M for main stack. + next_thread_stack_base = stack_base - (8 * 1024 * 1024); + + // Set up break point (Top of Heap) + brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize(); + brk_point = roundUp(brk_point, VMPageSize); + + // Set up region for mmaps. For now, start at bottom of kuseg space. + mmap_start = mmap_end = 0x4000000000L; +} + void -ArmLiveProcess::initState() +ArmLiveProcess32::initState() { LiveProcess::initState(); - argsInit(MachineBytes, VMPageSize); + argsInit<uint32_t>(VMPageSize, INTREG_SP); for (int i = 0; i < contextIds.size(); i++) { ThreadContext * tc = system->getThreadContext(contextIds[i]); CPACR cpacr = tc->readMiscReg(MISCREG_CPACR); @@ -94,9 +117,34 @@ ArmLiveProcess::initState() } void -ArmLiveProcess::argsInit(int intSize, int pageSize) +ArmLiveProcess64::initState() { - typedef AuxVector<uint32_t> auxv_t; + LiveProcess::initState(); + argsInit<uint64_t>(VMPageSize, INTREG_SP0); + for (int i = 0; i < contextIds.size(); i++) { + ThreadContext * tc = system->getThreadContext(contextIds[i]); + CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); + cpsr.mode = MODE_EL0T; + tc->setMiscReg(MISCREG_CPSR, cpsr); + CPACR cpacr = tc->readMiscReg(MISCREG_CPACR_EL1); + // Enable the floating point coprocessors. + cpacr.cp10 = 0x3; + cpacr.cp11 = 0x3; + tc->setMiscReg(MISCREG_CPACR_EL1, cpacr); + // Generically enable floating point support. + FPEXC fpexc = tc->readMiscReg(MISCREG_FPEXC); + fpexc.en = 1; + tc->setMiscReg(MISCREG_FPEXC, fpexc); + } +} + +template <class IntType> +void +ArmLiveProcess::argsInit(int pageSize, IntRegIndex spIndex) +{ + int intSize = sizeof(IntType); + + typedef AuxVector<IntType> auxv_t; std::vector<auxv_t> auxv; string filename; @@ -133,7 +181,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) //Auxilliary vectors are loaded only for elf formatted executables. ElfObject * elfObject = dynamic_cast<ElfObject *>(objFile); if (elfObject) { - uint32_t features = + IntType features = Arm_Swp | Arm_Half | Arm_Thumb | @@ -253,16 +301,16 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) allocateMem(roundDown(stack_min, pageSize), roundUp(stack_size, pageSize)); // map out initial stack contents - uint32_t sentry_base = stack_base - 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; - uint32_t platform_base = arg_data_base - platform_size; - uint32_t aux_random_base = platform_base - aux_random_size; - uint32_t auxv_array_base = aux_random_base - aux_array_size - aux_padding; - uint32_t envp_array_base = auxv_array_base - envp_array_size; - uint32_t argv_array_base = envp_array_base - argv_array_size; - uint32_t argc_base = argv_array_base - argc_size; + IntType sentry_base = stack_base - 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; + IntType platform_base = arg_data_base - platform_size; + IntType aux_random_base = platform_base - aux_random_size; + IntType auxv_array_base = aux_random_base - aux_array_size - aux_padding; + IntType envp_array_base = auxv_array_base - envp_array_size; + IntType argv_array_base = envp_array_base - argv_array_size; + IntType argc_base = argv_array_base - argc_size; DPRINTF(Stack, "The addresses of items on the initial stack:\n"); DPRINTF(Stack, "0x%x - aux data\n", aux_data_base); @@ -279,11 +327,11 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) // write contents to stack // figure out argc - uint32_t argc = argv.size(); - uint32_t guestArgc = ArmISA::htog(argc); + IntType argc = argv.size(); + IntType guestArgc = ArmISA::htog(argc); //Write out the sentry void * - uint32_t sentry_NULL = 0; + IntType sentry_NULL = 0; initVirtMem.writeBlob(sentry_base, (uint8_t*)&sentry_NULL, sentry_size); @@ -302,8 +350,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) } //Copy the aux stuff - for(int x = 0; x < auxv.size(); x++) - { + 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, @@ -321,7 +368,7 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) ThreadContext *tc = system->getThreadContext(contextIds[0]); //Set the stack pointer register - tc->setIntReg(StackPointerReg, stack_min); + tc->setIntReg(spIndex, stack_min); //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); @@ -342,6 +389,8 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) PCState pc; pc.thumb(arch == ObjectFile::Thumb); pc.nextThumb(pc.thumb()); + pc.aarch64(arch == ObjectFile::Arm64); + pc.nextAArch64(pc.aarch64()); pc.set(objFile->entryPoint() & ~mask(1)); tc->pcState(pc); @@ -350,14 +399,21 @@ ArmLiveProcess::argsInit(int intSize, int pageSize) } ArmISA::IntReg -ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i) +ArmLiveProcess32::getSyscallArg(ThreadContext *tc, int &i) { assert(i < 6); return tc->readIntReg(ArgumentReg0 + i++); } -uint64_t -ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) +ArmISA::IntReg +ArmLiveProcess64::getSyscallArg(ThreadContext *tc, int &i) +{ + assert(i < 8); + return tc->readIntReg(ArgumentReg0 + i++); +} + +ArmISA::IntReg +ArmLiveProcess32::getSyscallArg(ThreadContext *tc, int &i, int width) { assert(width == 32 || width == 64); if (width == 32) @@ -375,17 +431,37 @@ ArmLiveProcess::getSyscallArg(ThreadContext *tc, int &i, int width) return val; } +ArmISA::IntReg +ArmLiveProcess64::getSyscallArg(ThreadContext *tc, int &i, int width) +{ + return getSyscallArg(tc, i); +} + + +void +ArmLiveProcess32::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val) +{ + assert(i < 6); + tc->setIntReg(ArgumentReg0 + i, val); +} void -ArmLiveProcess::setSyscallArg(ThreadContext *tc, +ArmLiveProcess64::setSyscallArg(ThreadContext *tc, int i, ArmISA::IntReg val) { - assert(i < 4); + assert(i < 8); tc->setIntReg(ArgumentReg0 + i, val); } void -ArmLiveProcess::setSyscallReturn(ThreadContext *tc, +ArmLiveProcess32::setSyscallReturn(ThreadContext *tc, + SyscallReturn return_value) +{ + tc->setIntReg(ReturnValueReg, return_value.value()); +} + +void +ArmLiveProcess64::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value) { tc->setIntReg(ReturnValueReg, return_value.value()); |