diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/arm/linux/process.cc | 43 | ||||
-rw-r--r-- | src/arch/arm/linux/process.hh | 5 |
2 files changed, 47 insertions, 1 deletions
diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 25307e106..620bcf116 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -40,6 +40,7 @@ #include "sim/process.hh" #include "sim/syscall_emul.hh" +#include "sim/system.hh" using namespace std; using namespace ArmISA; @@ -411,12 +412,25 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = { /* 346 */ SyscallDesc("epoll_pwait", unimplementedFunc), }; +/// Target set_tls() handler. +static SyscallReturn +setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process, + ThreadContext *tc) +{ + uint32_t tlsPtr = process->getSyscallArg(tc, 0); + TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0)); + + tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0, + (uint8_t *)&tlsPtr, sizeof(tlsPtr)); + return 0; +} + SyscallDesc ArmLinuxProcess::privSyscallDescs[] = { /* 1 */ SyscallDesc("breakpoint", unimplementedFunc), /* 2 */ SyscallDesc("cacheflush", unimplementedFunc), /* 3 */ SyscallDesc("usr26", unimplementedFunc), /* 4 */ SyscallDesc("usr32", unimplementedFunc), - /* 5 */ SyscallDesc("set_tls", unimplementedFunc) + /* 5 */ SyscallDesc("set_tls", setTLSFunc) }; ArmLinuxProcess::ArmLinuxProcess(LiveProcessParams * params, @@ -426,6 +440,8 @@ ArmLinuxProcess::ArmLinuxProcess(LiveProcessParams * params, Num_Priv_Syscall_Descs(sizeof(privSyscallDescs) / sizeof(SyscallDesc)) { } +const Addr ArmLinuxProcess::commPage = 0xffff0000; + SyscallDesc* ArmLinuxProcess::getDesc(int callnum) { @@ -448,3 +464,28 @@ ArmLinuxProcess::getDesc(int callnum) return &syscallDescs[callnum]; } + +void +ArmLinuxProcess::startup() +{ + ArmLiveProcess::startup(); + pTable->allocate(commPage, PageBytes); + ThreadContext *tc = system->getThreadContext(contextIds[0]); + + uint8_t swiNeg1[] = { + 0xff, 0xff, 0xff, 0xef //swi -1 + }; + + // Fill this page with swi -1 so we'll no if we land in it somewhere. + for (Addr addr = 0; addr < PageBytes; addr += sizeof(swiNeg1)) { + tc->getMemPort()->writeBlob(commPage + addr, + swiNeg1, sizeof(swiNeg1)); + } + + uint8_t get_tls[] = + { + 0x08, 0x00, 0x9f, 0xe5, //ldr r0, [pc, #(16 - 8)] + 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr + }; + tc->getMemPort()->writeBlob(commPage + 0x0fe0, get_tls, sizeof(get_tls)); +} diff --git a/src/arch/arm/linux/process.hh b/src/arch/arm/linux/process.hh index 205a40418..835b94161 100644 --- a/src/arch/arm/linux/process.hh +++ b/src/arch/arm/linux/process.hh @@ -42,9 +42,14 @@ class ArmLinuxProcess : public ArmLiveProcess virtual SyscallDesc* getDesc(int callnum); + void startup(); + /// The target system's hostname. static const char *hostname; + /// A page to hold "kernel" provided functions. The name might be wrong. + static const Addr commPage; + /// Array of syscall descriptors, indexed by call number. static SyscallDesc syscallDescs[]; |