summaryrefslogtreecommitdiff
path: root/src/arch/arm/linux
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/linux')
-rw-r--r--src/arch/arm/linux/process.cc34
-rw-r--r--src/arch/arm/linux/system.cc24
-rw-r--r--src/arch/arm/linux/system.hh13
3 files changed, 57 insertions, 14 deletions
diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc
index e3455d211..fc48ec12d 100644
--- a/src/arch/arm/linux/process.cc
+++ b/src/arch/arm/linux/process.cc
@@ -197,7 +197,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 117 */ SyscallDesc("ipc", unimplementedFunc),
/* 118 */ SyscallDesc("fsync", unimplementedFunc),
/* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
- /* 120 */ SyscallDesc("clone", unimplementedFunc),
+ /* 120 */ SyscallDesc("clone", cloneFunc),
/* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
/* 122 */ SyscallDesc("uname", unameFunc),
/* 123 */ SyscallDesc("unused#123", unimplementedFunc),
@@ -239,7 +239,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
/* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
/* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
- /* 162 */ SyscallDesc("nanosleep", unimplementedFunc),
+ /* 162 */ SyscallDesc("nanosleep", ignoreWarnOnceFunc),
/* 163 */ SyscallDesc("mremap", mremapFunc<ArmLinux>), // ARM-specific
/* 164 */ SyscallDesc("setresuid", unimplementedFunc),
/* 165 */ SyscallDesc("getresuid", unimplementedFunc),
@@ -251,8 +251,8 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 171 */ SyscallDesc("getresgid", unimplementedFunc),
/* 172 */ SyscallDesc("prctl", unimplementedFunc),
/* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
- /* 174 */ SyscallDesc("rt_sigaction", ignoreFunc),
- /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+ /* 174 */ SyscallDesc("rt_sigaction", ignoreWarnOnceFunc),
+ /* 175 */ SyscallDesc("rt_sigprocmask", ignoreWarnOnceFunc),
/* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc),
/* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
/* 178 */ SyscallDesc("rt_sigqueueinfo", ignoreFunc),
@@ -317,7 +317,7 @@ SyscallDesc ArmLinuxProcess::syscallDescs[] = {
/* 237 */ SyscallDesc("fremovexattr", unimplementedFunc),
/* 238 */ SyscallDesc("tkill", unimplementedFunc),
/* 239 */ SyscallDesc("sendfile64", unimplementedFunc),
- /* 240 */ SyscallDesc("futex", unimplementedFunc),
+ /* 240 */ SyscallDesc("futex", ignoreWarnOnceFunc),
/* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
/* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
/* 243 */ SyscallDesc("io_setup", unimplementedFunc),
@@ -456,6 +456,7 @@ setTLSFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
tc->getMemPort()->writeBlob(ArmLinuxProcess::commPage + 0x0ff0,
(uint8_t *)&tlsPtr, sizeof(tlsPtr));
+ tc->setMiscReg(MISCREG_TPIDRURO,tlsPtr);
return 0;
}
@@ -508,7 +509,7 @@ ArmLinuxProcess::startup()
ThreadContext *tc = system->getThreadContext(contextIds[0]);
uint8_t swiNeg1[] = {
- 0xff, 0xff, 0xff, 0xef //swi -1
+ 0xff, 0xff, 0xff, 0xef // swi -1
};
// Fill this page with swi -1 so we'll no if we land in it somewhere.
@@ -521,7 +522,8 @@ ArmLinuxProcess::startup()
// @todo Add a barrrier in this code
uint8_t memory_barrier[] =
{
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ 0x5f, 0xf0, 0x7f, 0xf5, // dmb
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fa0, memory_barrier,
sizeof(memory_barrier));
@@ -531,18 +533,22 @@ ArmLinuxProcess::startup()
// @todo replace this with ldrex/strex and dmb
uint8_t cmpxchg[] =
{
- 0x00, 0x30, 0x92, 0xe5, //ldr r3, [r2]
- 0x00, 0x30, 0x53, 0xe0, //subs r3, r3, r0
- 0x00, 0x10, 0x82, 0x05, //streq r1, [r2]
- 0x03, 0x00, 0xa0, 0xe1, //mov r0, r3
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ 0x9f, 0x3f, 0x92, 0xe1, // ldrex r3, [r2]
+ 0x00, 0x30, 0x53, 0xe0, // subs r3, r3, r0
+ 0x91, 0x3f, 0x82, 0x01, // strexeq r3, r1, [r2]
+ 0x01, 0x00, 0x33, 0x03, // teqeq r3, #1
+ 0xfa, 0xff, 0xff, 0x0a, // beq 1b
+ 0x00, 0x00, 0x73, 0xe2, // rsbs r0, r3, #0
+ 0x5f, 0xf0, 0x7f, 0xf5, // dmb
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fc0, cmpxchg, sizeof(cmpxchg));
uint8_t get_tls[] =
{
- 0x08, 0x00, 0x9f, 0xe5, //ldr r0, [pc, #(16 - 8)]
- 0x0e, 0xf0, 0xa0, 0xe1 //usr_ret lr
+ // read user read-only thread id register
+ 0x70, 0x0f, 0x1d, 0xee, // mrc p15, 0, r0, c13, c0, 3
+ 0x0e, 0xf0, 0xa0, 0xe1 // return
};
tc->getMemPort()->writeBlob(commPage + 0x0fe0, get_tls, sizeof(get_tls));
}
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 38024c058..7aff2b6ef 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -47,9 +47,11 @@
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
#include "cpu/thread_context.hh"
+#include "kern/linux/events.hh"
#include "mem/physical.hh"
using namespace ArmISA;
+using namespace Linux;
LinuxArmSystem::LinuxArmSystem(Params *p)
: ArmSystem(p)
@@ -96,6 +98,24 @@ LinuxArmSystem::LinuxArmSystem(Params *p)
if (!kernelPanicEvent)
panic("could not find kernel symbol \'panic\'");
#endif
+
+ // With ARM udelay() is #defined to __udelay
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("__udelay", addr)) {
+ uDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__udelay",
+ fixFuncEventAddr(addr), 1000, 0);
+ } else {
+ panic("couldn't find kernel symbol \'udelay\'");
+ }
+
+ // constant arguments to udelay() have some precomputation done ahead of
+ // time. Constant comes from code.
+ if (kernelSymtab->findAddress("__const_udelay", addr)) {
+ constUDelaySkipEvent = new UDelayEvent(&pcEventQueue, "__const_udelay",
+ fixFuncEventAddr(addr), 1000, 107374);
+ } else {
+ panic("couldn't find kernel symbol \'udelay\'");
+ }
}
void
@@ -115,6 +135,10 @@ LinuxArmSystem::initState()
LinuxArmSystem::~LinuxArmSystem()
{
+ if (uDelaySkipEvent)
+ delete uDelaySkipEvent;
+ if (constUDelaySkipEvent)
+ delete constUDelaySkipEvent;
}
LinuxArmSystem *
diff --git a/src/arch/arm/linux/system.hh b/src/arch/arm/linux/system.hh
index 4e5ebcd73..2ef65fea2 100644
--- a/src/arch/arm/linux/system.hh
+++ b/src/arch/arm/linux/system.hh
@@ -74,6 +74,19 @@ class LinuxArmSystem : public ArmSystem
/** Event to halt the simulator if the kernel calls panic() */
BreakPCEvent *kernelPanicEvent;
#endif
+ /**
+ * PC based event to skip udelay(<time>) calls and quiesce the
+ * processor for the appropriate amount of time. This is not functionally
+ * required but does speed up simulation.
+ */
+ Linux::UDelayEvent *uDelaySkipEvent;
+
+ /** Another PC based skip event for const_udelay(). Similar to the udelay
+ * skip, but this function precomputes the first multiply that is done
+ * in the generic case since the parameter is known at compile time.
+ * Thus we need to do some division to get back to us.
+ */
+ Linux::UDelayEvent *constUDelaySkipEvent;
};
#endif // __ARCH_ARM_LINUX_SYSTEM_HH__