diff options
author | Ali Saidi <Ali.Saidi@ARM.com> | 2011-03-17 19:20:20 -0500 |
---|---|---|
committer | Ali Saidi <Ali.Saidi@ARM.com> | 2011-03-17 19:20:20 -0500 |
commit | b78be240cf1c1269ed83548bf71095193487ca33 (patch) | |
tree | 6ee8630c22e3c72291bd9fb647a91d70efed332d /src/arch | |
parent | fe3d790ac8da41e8a0b9af93510cd874585c37e7 (diff) | |
download | gem5-b78be240cf1c1269ed83548bf71095193487ca33.tar.xz |
ARM: Detect and skip udelay() functions in linux kernel.
This change speeds up booting, especially in MP cases, by not executing
udelay() on the core but instead skipping ahead tha amount of time that is being
delayed.
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/arm/linux/system.cc | 24 | ||||
-rw-r--r-- | src/arch/arm/linux/system.hh | 13 |
2 files changed, 37 insertions, 0 deletions
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__ |