diff options
Diffstat (limited to 'src/cpu/kvm/timer.hh')
-rw-r--r-- | src/cpu/kvm/timer.hh | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/cpu/kvm/timer.hh b/src/cpu/kvm/timer.hh new file mode 100644 index 000000000..a5105e7fa --- /dev/null +++ b/src/cpu/kvm/timer.hh @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2012 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Sandberg + */ + +#ifndef __CPU_KVM_TIMER_HH__ +#define __CPU_KVM_TIMER_HH__ + +#include <ctime> + +#include "sim/core.hh" + +/** + * Timer functions to interrupt VM execution after a number of + * simulation ticks. The timer allows scaling of the host time to take + * performance differences between the simulated and real CPU into + * account. + * + * The performance scaling factor is ratio between the target's CPI + * and the host's CPI. It is larger than 1 if the host is faster than + * the target and lower than 1 if it is slower. + * + * When the timer times out, it sends a signal to the thread that + * started the timer. The signal forces KVM to drop out of the system + * call that started the guest and hands control to gem5. + */ +class BaseKvmTimer +{ + public: + /** + * Setup basic timer functionality shared by all timer + * implementations. + * + * @param signo Signal to deliver + * @param hostFactor Performance scaling factor + * @param hostFreq Clock frequency of the host + */ + BaseKvmTimer(int signo, float hostFactor, Tick hostFreq) + : signo(signo), _resolution(0), + hostFactor(hostFactor), hostFreq(hostFreq) {}; + virtual ~BaseKvmTimer() {}; + + /** + * Arm the timer so that it fires after a certain number of ticks. + * + * @note A timer implementation is free to convert between + * simulation ticks and virtualized time using any method it + * chooses. The accuracy of the timer therefore depends on what it + * measures, an accurate timer implementation should measure the + * number of cycles or instructions executed in the guest. If such + * counters are unavailable, it may fallback to wall clock time. + * + * @param ticks Number of ticks until the timer fires + */ + virtual void arm(Tick ticks) = 0; + /** + * Disarm the timer. + * + * When this method has returned, the timer may no longer deliver + * signals upon timeout. + */ + virtual void disarm() = 0; + + /** + * Determine the resolution of the timer in ticks. This method is + * mainly used to determine the smallest number of ticks the timer + * can wait before triggering a signal. + * + * @return Minimum number of ticks the timer can resolve + */ + Tick resolution() { + if (_resolution == 0) + _resolution = calcResolution(); + return _resolution; + } + + /** + * Convert cycles executed on the host into Ticks executed in the + * simulator. Scales the results using the hostFactor to take CPU + * performance differences into account. + * + * @return Host cycles executed in VM converted to simulation ticks + */ + Tick ticksFromHostCycles(uint64_t cycles) { + return cycles * hostFactor * hostFreq; + } + + /** + * Convert nanoseconds executed on the host into Ticks executed in + * the simulator. Scales the results using the hostFactor to take + * CPU performance differences into account. + * + * @return Nanoseconds executed in VM converted to simulation ticks + */ + Tick ticksFromHostNs(uint64_t ns) { + return ns * hostFactor * SimClock::Float::ns; + } + + protected: + /** + * Calculate the timer resolution, used by resolution() which + * caches the result. + * + * @return Minimum number of ticks the timer can resolve + */ + virtual Tick calcResolution() = 0; + + /** + * Convert a time in simulator ticks to host nanoseconds. + * + * @return Simulation ticks converted into nanoseconds on the host + */ + uint64_t hostNs(Tick ticks) { + return ticks / (SimClock::Float::ns * hostFactor); + } + + /** + * Convert a time in simulator ticks to host cycles + * + * + * @return Simulation ticks converted into CPU cycles on the host + */ + uint64_t hostCycles(Tick ticks) { + return ticks / (hostFreq * hostFactor); + } + + /** Signal to deliver when the timer times out */ + int signo; + + private: + /** Cached resolution */ + mutable Tick _resolution; + + /** Performance scaling factor */ + float hostFactor; + /** Host frequency */ + Tick hostFreq; +}; + +/** + * Timer based on standard POSIX timers. The POSIX timer API supports + * several different clock with different characteristics. + * + * @note It might be tempting to use + * CLOCK_(THREAD|PROCESS)_CPUTIME_ID, however, this clock usually has + * much lower resolution than the real-time clocks. + */ +class PosixKvmTimer : public BaseKvmTimer +{ + public: + /** + * @param signo Signal to deliver + * @param clockID ID of the clock to use + * @param hostFactor Performance scaling factor + * @param hostFreq Clock frequency of the host + */ + PosixKvmTimer(int signo, clockid_t clockID, + float hostFactor, Tick hostFreq); + ~PosixKvmTimer(); + + void arm(Tick ticks); + void disarm(); + + protected: + Tick calcResolution(); + + private: + clockid_t clockID; + timer_t timer; +}; + +#endif |