summaryrefslogtreecommitdiff
path: root/src/arch/arm/linux/process.cc
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-06-09 23:39:07 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-06-09 23:39:07 -0700
commit37ac2871d5a65dfa19b63c3bed9c6622d6b8b6c9 (patch)
treeeb2826a0af77b3a9a7706313798146690ce482e5 /src/arch/arm/linux/process.cc
parent5daeefc5059ff98b63f06c963da2ffb17ef95df7 (diff)
downloadgem5-37ac2871d5a65dfa19b63c3bed9c6622d6b8b6c9.tar.xz
ARM: Implement TLS. This is not tested.
Diffstat (limited to 'src/arch/arm/linux/process.cc')
-rw-r--r--src/arch/arm/linux/process.cc43
1 files changed, 42 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));
+}