summaryrefslogtreecommitdiff
path: root/kern/linux
diff options
context:
space:
mode:
Diffstat (limited to 'kern/linux')
-rw-r--r--kern/linux/linux_system.cc26
-rw-r--r--kern/linux/linux_system.hh4
2 files changed, 30 insertions, 0 deletions
diff --git a/kern/linux/linux_system.cc b/kern/linux/linux_system.cc
index db67c5619..798577ba5 100644
--- a/kern/linux/linux_system.cc
+++ b/kern/linux/linux_system.cc
@@ -33,11 +33,13 @@
#include "base/remote_gdb.hh"
#include "base/trace.hh"
#include "cpu/exec_context.hh"
+#include "cpu/base_cpu.hh"
#include "kern/linux/linux_events.hh"
#include "kern/linux/linux_system.hh"
#include "mem/functional_mem/memory_control.hh"
#include "mem/functional_mem/physical_memory.hh"
#include "sim/builder.hh"
+#include "dev/platform.hh"
#include "targetarch/isa_traits.hh"
#include "targetarch/vtophys.hh"
@@ -220,6 +222,10 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
skipScavengeBootEvent = new LinuxSkipFuncEvent(&pcEventQueue,
"pmap_scavenge_boot");
printfEvent = new LinuxPrintfEvent(&pcEventQueue, "printf");
+
+ skipDelayLoopEvent = new LinuxSkipDelayLoopEvent(&pcEventQueue,
+ "calibrate_delay");
+
/* debugPrintfEvent = new DebugPrintfEvent(&pcEventQueue,
"debug_printf", false);
debugPrintfrEvent = new DebugPrintfEvent(&pcEventQueue,
@@ -301,6 +307,9 @@ LinuxSystem::LinuxSystem(const string _name, const uint64_t _init_param,
if (kernelSymtab->findAddress("pmap_scavenge_boot", addr))
skipScavengeBootEvent->schedule(addr);
+ if (kernelSymtab->findAddress("calibrate_delay", addr))
+ skipDelayLoopEvent->schedule(addr+8);
+
#if TRACING_ON
if (kernelSymtab->findAddress("printk", addr))
printfEvent->schedule(addr);
@@ -581,6 +590,23 @@ LinuxSystem::~LinuxSystem()
#endif //FS_MEASURE
}
+void
+LinuxSystem::setDelayLoop(ExecContext *xc)
+{
+ Addr addr = 0;
+ if (kernelSymtab->findAddress("loops_per_jiffy", addr)) {
+ Addr paddr = vtophys(physmem, addr);
+
+ uint8_t *loops_per_jiffy =
+ physmem->dma_addr(paddr, sizeof(uint32_t));
+
+ Tick cpuFreq = xc->cpu->getFreq();
+ Tick intrFreq = platform->interrupt_frequency;
+ *(uint32_t *)loops_per_jiffy =
+ (uint32_t)((cpuFreq / intrFreq) * 0.9988);
+ }
+}
+
int
LinuxSystem::registerExecContext(ExecContext *xc)
{
diff --git a/kern/linux/linux_system.hh b/kern/linux/linux_system.hh
index cfb20f6dc..6aa29249a 100644
--- a/kern/linux/linux_system.hh
+++ b/kern/linux/linux_system.hh
@@ -45,6 +45,7 @@ class SymbolTable;
class BreakPCEvent;
class LinuxBadAddrEvent;
class LinuxSkipFuncEvent;
+class LinuxSkipDelayLoopEvent;
class LinuxPrintfEvent;
class LinuxDebugPrintfEvent;
class LinuxDumpMbufEvent;
@@ -105,6 +106,7 @@ class LinuxSystem : public System
LinuxBadAddrEvent *badaddrEvent;
LinuxSkipFuncEvent *skipPowerStateEvent;
LinuxSkipFuncEvent *skipScavengeBootEvent;
+ LinuxSkipDelayLoopEvent *skipDelayLoopEvent;
LinuxPrintfEvent *printfEvent;
LinuxDebugPrintfEvent *debugPrintfEvent;
LinuxDebugPrintfEvent *debugPrintfrEvent;
@@ -174,6 +176,8 @@ class LinuxSystem : public System
const bool _bin);
~LinuxSystem();
+ void setDelayLoop(ExecContext *xc);
+
int registerExecContext(ExecContext *xc);
void replaceExecContext(ExecContext *xc, int xcIndex);