summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorPaul Rosenfeld <prosenfeld@micron.com>2017-04-04 09:06:38 -0600
committerPaul Rosenfeld <prosenfeld@micron.com>2017-06-22 13:32:04 +0000
commit1d7ff84f126e5e1b138c7250a275ebe3a46fa27c (patch)
tree629f6fb5b21b3f8603cdb32477108547d90881c3 /src/arch/arm
parent9cdfcf93470ca11c12eeac50aea9536ef914790f (diff)
downloadgem5-1d7ff84f126e5e1b138c7250a275ebe3a46fa27c.tar.xz
arm,sim: fix context switch stats dumps for ARM64/Linux
32bit and 64bit Linux have different arguments passed to the __switch_to() function that gem5 hooks into in order to collect context switch statistics. 64bit Linux provides the task_struct pointer to the next task that will be switched to, which means we don't have to look up the task_struct from thread_info as we do in 32bit ARM Linux. This patch adds a second set of accessors to ThreadInfo to extract details such as the pid, tgid, task name, etc., directly from a task_struct. The existing accessors maintain their existing behavior by first looking up the task_struct and then calling these new accessors. A 64-bit variant of the DumpStatsPCEvent class is added that uses these new accessors to get the task details for the context switch dumps directly from the task_struct passed to __switch_to(). Change-Id: I63c4b3e1ad64446751a91f6340901d5180d7382d Reviewed-on: https://gem5-review.googlesource.com/2640 Reviewed-by: Curtis Dunham <curtis.dunham@arm.com> Reviewed-by: Jason Lowe-Power <jason@lowepower.com> Reviewed-by: Pau Cabre <pau.cabre@metempsy.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/linux/system.cc68
-rw-r--r--src/arch/arm/linux/system.hh14
2 files changed, 71 insertions, 11 deletions
diff --git a/src/arch/arm/linux/system.cc b/src/arch/arm/linux/system.cc
index 52e075d8f..7f0647512 100644
--- a/src/arch/arm/linux/system.cc
+++ b/src/arch/arm/linux/system.cc
@@ -236,7 +236,14 @@ void
LinuxArmSystem::startup()
{
if (enableContextSwitchStatsDump) {
- dumpStatsPCEvent = addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
+ if (!highestELIs64()) {
+ dumpStatsPCEvent =
+ addKernelFuncEvent<DumpStatsPCEvent>("__switch_to");
+ } else {
+ dumpStatsPCEvent =
+ addKernelFuncEvent<DumpStatsPCEvent64>("__switch_to");
+ }
+
if (!dumpStatsPCEvent)
panic("dumpStatsPCEvent not created!");
@@ -276,25 +283,64 @@ LinuxArmSystem::dumpDmesg()
Linux::dumpDmesg(getThreadContext(0), std::cout);
}
-/** This function is called whenever the the kernel function
- * "__switch_to" is called to change running tasks.
+/**
+ * Extracts the information used by the DumpStatsPCEvent by reading the
+ * thread_info pointer passed to __switch_to() in 32 bit ARM Linux
*
* r0 = task_struct of the previously running process
- * r1 = task_info of the previously running process
- * r2 = task_info of the next process to run
+ * r1 = thread_info of the previously running process
+ * r2 = thread_info of the next process to run
*/
void
-DumpStatsPCEvent::process(ThreadContext *tc)
-{
+DumpStatsPCEvent::getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
+
Linux::ThreadInfo ti(tc);
Addr task_descriptor = tc->readIntReg(2);
- uint32_t pid = ti.curTaskPID(task_descriptor);
- uint32_t tgid = ti.curTaskTGID(task_descriptor);
- std::string next_task_str = ti.curTaskName(task_descriptor);
+ pid = ti.curTaskPID(task_descriptor);
+ tgid = ti.curTaskTGID(task_descriptor);
+ next_task_str = ti.curTaskName(task_descriptor);
// Streamline treats pid == -1 as the kernel process.
// Also pid == 0 implies idle process (except during Linux boot)
- int32_t mm = ti.curTaskMm(task_descriptor);
+ mm = ti.curTaskMm(task_descriptor);
+}
+
+/**
+ * Extracts the information used by the DumpStatsPCEvent64 by reading the
+ * task_struct pointer passed to __switch_to() in 64 bit ARM Linux
+ *
+ * r0 = task_struct of the previously running process
+ * r1 = task_struct of next process to run
+ */
+void
+DumpStatsPCEvent64::getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm) {
+
+ Linux::ThreadInfo ti(tc);
+ Addr task_struct = tc->readIntReg(1);
+ pid = ti.curTaskPIDFromTaskStruct(task_struct);
+ tgid = ti.curTaskTGIDFromTaskStruct(task_struct);
+ next_task_str = ti.curTaskNameFromTaskStruct(task_struct);
+
+ // Streamline treats pid == -1 as the kernel process.
+ // Also pid == 0 implies idle process (except during Linux boot)
+ mm = ti.curTaskMmFromTaskStruct(task_struct);
+}
+
+/** This function is called whenever the the kernel function
+ * "__switch_to" is called to change running tasks.
+ */
+void
+DumpStatsPCEvent::process(ThreadContext *tc)
+{
+ uint32_t pid = 0;
+ uint32_t tgid = 0;
+ std::string next_task_str;
+ int32_t mm = 0;
+
+ getTaskDetails(tc, pid, tgid, next_task_str, mm);
+
bool is_kernel = (mm == 0);
if (is_kernel && (pid != 0)) {
pid = -1;
diff --git a/src/arch/arm/linux/system.hh b/src/arch/arm/linux/system.hh
index 709776ffc..247ebae13 100644
--- a/src/arch/arm/linux/system.hh
+++ b/src/arch/arm/linux/system.hh
@@ -132,6 +132,20 @@ class DumpStatsPCEvent : public PCEvent
{}
virtual void process(ThreadContext* tc);
+ protected:
+ virtual void getTaskDetails(ThreadContext *tc, uint32_t &pid,
+ uint32_t &tgid, std::string &next_task_str, int32_t &mm);
+
+};
+
+class DumpStatsPCEvent64 : public DumpStatsPCEvent {
+ public:
+ DumpStatsPCEvent64(PCEventQueue *q, const std::string &desc, Addr addr)
+ : DumpStatsPCEvent(q, desc, addr)
+ {}
+ private:
+ void getTaskDetails(ThreadContext *tc, uint32_t &pid, uint32_t &tgid,
+ std::string &next_task_str, int32_t &mm) override;
};