19651SAndreas.Sandberg@ARM.com/* 29651SAndreas.Sandberg@ARM.com * Copyright (c) 2012 ARM Limited 39651SAndreas.Sandberg@ARM.com * All rights reserved 49651SAndreas.Sandberg@ARM.com * 59651SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 69651SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 79651SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 89651SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 99651SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 109651SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 119651SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 129651SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 139651SAndreas.Sandberg@ARM.com * 149651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 159651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 169651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 179651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 189651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 199651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 209651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 219651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 229651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 239651SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 249651SAndreas.Sandberg@ARM.com * 259651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369651SAndreas.Sandberg@ARM.com * 379651SAndreas.Sandberg@ARM.com * Authors: Andreas Sandberg 389651SAndreas.Sandberg@ARM.com */ 399651SAndreas.Sandberg@ARM.com 409651SAndreas.Sandberg@ARM.com#ifndef __CPU_KVM_TIMER_HH__ 419651SAndreas.Sandberg@ARM.com#define __CPU_KVM_TIMER_HH__ 429651SAndreas.Sandberg@ARM.com 439651SAndreas.Sandberg@ARM.com#include <ctime> 449651SAndreas.Sandberg@ARM.com 459655SAndreas.Sandberg@ARM.com#include "cpu/kvm/perfevent.hh" 469651SAndreas.Sandberg@ARM.com#include "sim/core.hh" 479651SAndreas.Sandberg@ARM.com 489651SAndreas.Sandberg@ARM.com/** 499651SAndreas.Sandberg@ARM.com * Timer functions to interrupt VM execution after a number of 509651SAndreas.Sandberg@ARM.com * simulation ticks. The timer allows scaling of the host time to take 519651SAndreas.Sandberg@ARM.com * performance differences between the simulated and real CPU into 529651SAndreas.Sandberg@ARM.com * account. 539651SAndreas.Sandberg@ARM.com * 549651SAndreas.Sandberg@ARM.com * The performance scaling factor is ratio between the target's CPI 559651SAndreas.Sandberg@ARM.com * and the host's CPI. It is larger than 1 if the host is faster than 569651SAndreas.Sandberg@ARM.com * the target and lower than 1 if it is slower. 579651SAndreas.Sandberg@ARM.com * 589651SAndreas.Sandberg@ARM.com * When the timer times out, it sends a signal to the thread that 599651SAndreas.Sandberg@ARM.com * started the timer. The signal forces KVM to drop out of the system 609651SAndreas.Sandberg@ARM.com * call that started the guest and hands control to gem5. 619651SAndreas.Sandberg@ARM.com */ 629651SAndreas.Sandberg@ARM.comclass BaseKvmTimer 639651SAndreas.Sandberg@ARM.com{ 649651SAndreas.Sandberg@ARM.com public: 659651SAndreas.Sandberg@ARM.com /** 669651SAndreas.Sandberg@ARM.com * Setup basic timer functionality shared by all timer 679651SAndreas.Sandberg@ARM.com * implementations. 689651SAndreas.Sandberg@ARM.com * 699651SAndreas.Sandberg@ARM.com * @param signo Signal to deliver 709651SAndreas.Sandberg@ARM.com * @param hostFactor Performance scaling factor 719651SAndreas.Sandberg@ARM.com * @param hostFreq Clock frequency of the host 729651SAndreas.Sandberg@ARM.com */ 739651SAndreas.Sandberg@ARM.com BaseKvmTimer(int signo, float hostFactor, Tick hostFreq) 749651SAndreas.Sandberg@ARM.com : signo(signo), _resolution(0), 759651SAndreas.Sandberg@ARM.com hostFactor(hostFactor), hostFreq(hostFreq) {}; 769651SAndreas.Sandberg@ARM.com virtual ~BaseKvmTimer() {}; 779651SAndreas.Sandberg@ARM.com 789651SAndreas.Sandberg@ARM.com /** 799651SAndreas.Sandberg@ARM.com * Arm the timer so that it fires after a certain number of ticks. 809651SAndreas.Sandberg@ARM.com * 819651SAndreas.Sandberg@ARM.com * @note A timer implementation is free to convert between 829651SAndreas.Sandberg@ARM.com * simulation ticks and virtualized time using any method it 839651SAndreas.Sandberg@ARM.com * chooses. The accuracy of the timer therefore depends on what it 849651SAndreas.Sandberg@ARM.com * measures, an accurate timer implementation should measure the 859651SAndreas.Sandberg@ARM.com * number of cycles or instructions executed in the guest. If such 869651SAndreas.Sandberg@ARM.com * counters are unavailable, it may fallback to wall clock time. 879651SAndreas.Sandberg@ARM.com * 889651SAndreas.Sandberg@ARM.com * @param ticks Number of ticks until the timer fires 899651SAndreas.Sandberg@ARM.com */ 909651SAndreas.Sandberg@ARM.com virtual void arm(Tick ticks) = 0; 919651SAndreas.Sandberg@ARM.com /** 929651SAndreas.Sandberg@ARM.com * Disarm the timer. 939651SAndreas.Sandberg@ARM.com * 949651SAndreas.Sandberg@ARM.com * When this method has returned, the timer may no longer deliver 959651SAndreas.Sandberg@ARM.com * signals upon timeout. 969651SAndreas.Sandberg@ARM.com */ 979651SAndreas.Sandberg@ARM.com virtual void disarm() = 0; 989651SAndreas.Sandberg@ARM.com 999651SAndreas.Sandberg@ARM.com /** 1009651SAndreas.Sandberg@ARM.com * Determine the resolution of the timer in ticks. This method is 1019651SAndreas.Sandberg@ARM.com * mainly used to determine the smallest number of ticks the timer 1029651SAndreas.Sandberg@ARM.com * can wait before triggering a signal. 1039651SAndreas.Sandberg@ARM.com * 1049651SAndreas.Sandberg@ARM.com * @return Minimum number of ticks the timer can resolve 1059651SAndreas.Sandberg@ARM.com */ 1069651SAndreas.Sandberg@ARM.com Tick resolution() { 1079651SAndreas.Sandberg@ARM.com if (_resolution == 0) 1089651SAndreas.Sandberg@ARM.com _resolution = calcResolution(); 1099651SAndreas.Sandberg@ARM.com return _resolution; 1109651SAndreas.Sandberg@ARM.com } 1119651SAndreas.Sandberg@ARM.com 1129651SAndreas.Sandberg@ARM.com /** 1139651SAndreas.Sandberg@ARM.com * Convert cycles executed on the host into Ticks executed in the 1149651SAndreas.Sandberg@ARM.com * simulator. Scales the results using the hostFactor to take CPU 1159651SAndreas.Sandberg@ARM.com * performance differences into account. 1169651SAndreas.Sandberg@ARM.com * 1179651SAndreas.Sandberg@ARM.com * @return Host cycles executed in VM converted to simulation ticks 1189651SAndreas.Sandberg@ARM.com */ 1199651SAndreas.Sandberg@ARM.com Tick ticksFromHostCycles(uint64_t cycles) { 1209651SAndreas.Sandberg@ARM.com return cycles * hostFactor * hostFreq; 1219651SAndreas.Sandberg@ARM.com } 1229651SAndreas.Sandberg@ARM.com 1239651SAndreas.Sandberg@ARM.com /** 1249651SAndreas.Sandberg@ARM.com * Convert nanoseconds executed on the host into Ticks executed in 1259651SAndreas.Sandberg@ARM.com * the simulator. Scales the results using the hostFactor to take 1269651SAndreas.Sandberg@ARM.com * CPU performance differences into account. 1279651SAndreas.Sandberg@ARM.com * 1289651SAndreas.Sandberg@ARM.com * @return Nanoseconds executed in VM converted to simulation ticks 1299651SAndreas.Sandberg@ARM.com */ 1309651SAndreas.Sandberg@ARM.com Tick ticksFromHostNs(uint64_t ns) { 1319651SAndreas.Sandberg@ARM.com return ns * hostFactor * SimClock::Float::ns; 1329651SAndreas.Sandberg@ARM.com } 1339651SAndreas.Sandberg@ARM.com 1349651SAndreas.Sandberg@ARM.com protected: 1359651SAndreas.Sandberg@ARM.com /** 1369651SAndreas.Sandberg@ARM.com * Calculate the timer resolution, used by resolution() which 1379651SAndreas.Sandberg@ARM.com * caches the result. 1389651SAndreas.Sandberg@ARM.com * 1399651SAndreas.Sandberg@ARM.com * @return Minimum number of ticks the timer can resolve 1409651SAndreas.Sandberg@ARM.com */ 1419651SAndreas.Sandberg@ARM.com virtual Tick calcResolution() = 0; 1429651SAndreas.Sandberg@ARM.com 1439651SAndreas.Sandberg@ARM.com /** 1449651SAndreas.Sandberg@ARM.com * Convert a time in simulator ticks to host nanoseconds. 1459651SAndreas.Sandberg@ARM.com * 1469651SAndreas.Sandberg@ARM.com * @return Simulation ticks converted into nanoseconds on the host 1479651SAndreas.Sandberg@ARM.com */ 1489651SAndreas.Sandberg@ARM.com uint64_t hostNs(Tick ticks) { 1499651SAndreas.Sandberg@ARM.com return ticks / (SimClock::Float::ns * hostFactor); 1509651SAndreas.Sandberg@ARM.com } 1519651SAndreas.Sandberg@ARM.com 1529651SAndreas.Sandberg@ARM.com /** 1539651SAndreas.Sandberg@ARM.com * Convert a time in simulator ticks to host cycles 1549651SAndreas.Sandberg@ARM.com * 1559651SAndreas.Sandberg@ARM.com * 1569651SAndreas.Sandberg@ARM.com * @return Simulation ticks converted into CPU cycles on the host 1579651SAndreas.Sandberg@ARM.com */ 1589651SAndreas.Sandberg@ARM.com uint64_t hostCycles(Tick ticks) { 1599651SAndreas.Sandberg@ARM.com return ticks / (hostFreq * hostFactor); 1609651SAndreas.Sandberg@ARM.com } 1619651SAndreas.Sandberg@ARM.com 1629651SAndreas.Sandberg@ARM.com /** Signal to deliver when the timer times out */ 1639651SAndreas.Sandberg@ARM.com int signo; 1649651SAndreas.Sandberg@ARM.com 1659651SAndreas.Sandberg@ARM.com private: 1669651SAndreas.Sandberg@ARM.com /** Cached resolution */ 1679651SAndreas.Sandberg@ARM.com mutable Tick _resolution; 1689651SAndreas.Sandberg@ARM.com 1699651SAndreas.Sandberg@ARM.com /** Performance scaling factor */ 1709651SAndreas.Sandberg@ARM.com float hostFactor; 1719651SAndreas.Sandberg@ARM.com /** Host frequency */ 1729651SAndreas.Sandberg@ARM.com Tick hostFreq; 1739651SAndreas.Sandberg@ARM.com}; 1749651SAndreas.Sandberg@ARM.com 1759651SAndreas.Sandberg@ARM.com/** 1769651SAndreas.Sandberg@ARM.com * Timer based on standard POSIX timers. The POSIX timer API supports 1779651SAndreas.Sandberg@ARM.com * several different clock with different characteristics. 1789651SAndreas.Sandberg@ARM.com * 1799651SAndreas.Sandberg@ARM.com * @note It might be tempting to use 1809651SAndreas.Sandberg@ARM.com * CLOCK_(THREAD|PROCESS)_CPUTIME_ID, however, this clock usually has 1819651SAndreas.Sandberg@ARM.com * much lower resolution than the real-time clocks. 1829651SAndreas.Sandberg@ARM.com */ 1839651SAndreas.Sandberg@ARM.comclass PosixKvmTimer : public BaseKvmTimer 1849651SAndreas.Sandberg@ARM.com{ 1859651SAndreas.Sandberg@ARM.com public: 1869651SAndreas.Sandberg@ARM.com /** 1879651SAndreas.Sandberg@ARM.com * @param signo Signal to deliver 1889651SAndreas.Sandberg@ARM.com * @param clockID ID of the clock to use 1899651SAndreas.Sandberg@ARM.com * @param hostFactor Performance scaling factor 1909651SAndreas.Sandberg@ARM.com * @param hostFreq Clock frequency of the host 1919651SAndreas.Sandberg@ARM.com */ 1929651SAndreas.Sandberg@ARM.com PosixKvmTimer(int signo, clockid_t clockID, 1939651SAndreas.Sandberg@ARM.com float hostFactor, Tick hostFreq); 1949651SAndreas.Sandberg@ARM.com ~PosixKvmTimer(); 1959651SAndreas.Sandberg@ARM.com 1969651SAndreas.Sandberg@ARM.com void arm(Tick ticks); 1979651SAndreas.Sandberg@ARM.com void disarm(); 1989651SAndreas.Sandberg@ARM.com 1999651SAndreas.Sandberg@ARM.com protected: 2009651SAndreas.Sandberg@ARM.com Tick calcResolution(); 2019651SAndreas.Sandberg@ARM.com 2029651SAndreas.Sandberg@ARM.com private: 2039651SAndreas.Sandberg@ARM.com clockid_t clockID; 2049651SAndreas.Sandberg@ARM.com timer_t timer; 2059651SAndreas.Sandberg@ARM.com}; 2069651SAndreas.Sandberg@ARM.com 2079655SAndreas.Sandberg@ARM.com/** 2089655SAndreas.Sandberg@ARM.com * PerfEvent based timer using the host's CPU cycle counter. 2099655SAndreas.Sandberg@ARM.com * 2109655SAndreas.Sandberg@ARM.com * @warning There is a known problem in some versions of the PerfEvent 2119655SAndreas.Sandberg@ARM.com * API that prevents the counter overflow period from being updated 2129655SAndreas.Sandberg@ARM.com * reliably, which might break this timer. See PerfKvmCounter::period() 2139655SAndreas.Sandberg@ARM.com * for details. 2149655SAndreas.Sandberg@ARM.com */ 2159655SAndreas.Sandberg@ARM.comclass PerfKvmTimer : public BaseKvmTimer 2169655SAndreas.Sandberg@ARM.com{ 2179655SAndreas.Sandberg@ARM.com public: 2189655SAndreas.Sandberg@ARM.com /** 2199655SAndreas.Sandberg@ARM.com * Create a timer that uses an existing hardware cycle counter. 2209655SAndreas.Sandberg@ARM.com * 2219655SAndreas.Sandberg@ARM.com * @note The performance counter must be configured for overflow 2229655SAndreas.Sandberg@ARM.com * sampling, which in practice means that it must have a non-zero 2239655SAndreas.Sandberg@ARM.com * sample period. The initial sample period is ignored since 2249655SAndreas.Sandberg@ARM.com * period will be updated when arm() is called. 2259655SAndreas.Sandberg@ARM.com * 2269655SAndreas.Sandberg@ARM.com * @param ctr Attached performance counter configured for overflow 2279655SAndreas.Sandberg@ARM.com * reporting. 2289655SAndreas.Sandberg@ARM.com * @param signo Signal to deliver 2299655SAndreas.Sandberg@ARM.com * @param hostFactor Performance scaling factor 2309655SAndreas.Sandberg@ARM.com * @param hostFreq Clock frequency of the host 2319655SAndreas.Sandberg@ARM.com */ 2329655SAndreas.Sandberg@ARM.com PerfKvmTimer(PerfKvmCounter &ctr, 2339655SAndreas.Sandberg@ARM.com int signo, 2349655SAndreas.Sandberg@ARM.com float hostFactor, Tick hostFreq); 2359655SAndreas.Sandberg@ARM.com ~PerfKvmTimer(); 2369655SAndreas.Sandberg@ARM.com 2379655SAndreas.Sandberg@ARM.com void arm(Tick ticks); 2389655SAndreas.Sandberg@ARM.com void disarm(); 2399655SAndreas.Sandberg@ARM.com 2409655SAndreas.Sandberg@ARM.com protected: 2419655SAndreas.Sandberg@ARM.com Tick calcResolution(); 2429655SAndreas.Sandberg@ARM.com 2439655SAndreas.Sandberg@ARM.com private: 2449655SAndreas.Sandberg@ARM.com PerfKvmCounter &hwOverflow; 2459655SAndreas.Sandberg@ARM.com}; 2469655SAndreas.Sandberg@ARM.com 2479651SAndreas.Sandberg@ARM.com#endif 248