| /* |
| * 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. |
| */ |
| |
| #ifndef __CPU_KVM_TIMER_HH__ |
| #define __CPU_KVM_TIMER_HH__ |
| |
| #include <ctime> |
| |
| #include "cpu/kvm/perfevent.hh" |
| #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; |
| }; |
| |
| /** |
| * PerfEvent based timer using the host's CPU cycle counter. |
| * |
| * @warning There is a known problem in some versions of the PerfEvent |
| * API that prevents the counter overflow period from being updated |
| * reliably, which might break this timer. See PerfKvmCounter::period() |
| * for details. |
| */ |
| class PerfKvmTimer : public BaseKvmTimer |
| { |
| public: |
| /** |
| * Create a timer that uses an existing hardware cycle counter. |
| * |
| * @note The performance counter must be configured for overflow |
| * sampling, which in practice means that it must have a non-zero |
| * sample period. The initial sample period is ignored since |
| * period will be updated when arm() is called. |
| * |
| * @param ctr Attached performance counter configured for overflow |
| * reporting. |
| * @param signo Signal to deliver |
| * @param hostFactor Performance scaling factor |
| * @param hostFreq Clock frequency of the host |
| */ |
| PerfKvmTimer(PerfKvmCounter &ctr, |
| int signo, |
| float hostFactor, Tick hostFreq); |
| ~PerfKvmTimer(); |
| |
| void arm(Tick ticks); |
| void disarm(); |
| |
| protected: |
| Tick calcResolution(); |
| |
| private: |
| PerfKvmCounter &hwOverflow; |
| }; |
| |
| #endif |