1/* 2 * Copyright (c) 2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andreas Sandberg 38 */ 39 40#ifndef __CPU_KVM_TIMER_HH__ 41#define __CPU_KVM_TIMER_HH__ 42 43#include <ctime> 44 45#include "cpu/kvm/perfevent.hh" 46#include "sim/core.hh" 47 48/** 49 * Timer functions to interrupt VM execution after a number of 50 * simulation ticks. The timer allows scaling of the host time to take 51 * performance differences between the simulated and real CPU into 52 * account. 53 * 54 * The performance scaling factor is ratio between the target's CPI 55 * and the host's CPI. It is larger than 1 if the host is faster than 56 * the target and lower than 1 if it is slower. 57 * 58 * When the timer times out, it sends a signal to the thread that 59 * started the timer. The signal forces KVM to drop out of the system 60 * call that started the guest and hands control to gem5. 61 */ 62class BaseKvmTimer 63{ 64 public: 65 /** 66 * Setup basic timer functionality shared by all timer 67 * implementations. 68 * 69 * @param signo Signal to deliver 70 * @param hostFactor Performance scaling factor 71 * @param hostFreq Clock frequency of the host 72 */ 73 BaseKvmTimer(int signo, float hostFactor, Tick hostFreq) 74 : signo(signo), _resolution(0), 75 hostFactor(hostFactor), hostFreq(hostFreq) {}; 76 virtual ~BaseKvmTimer() {}; 77 78 /** 79 * Arm the timer so that it fires after a certain number of ticks. 80 * 81 * @note A timer implementation is free to convert between 82 * simulation ticks and virtualized time using any method it 83 * chooses. The accuracy of the timer therefore depends on what it 84 * measures, an accurate timer implementation should measure the 85 * number of cycles or instructions executed in the guest. If such 86 * counters are unavailable, it may fallback to wall clock time. 87 * 88 * @param ticks Number of ticks until the timer fires 89 */ 90 virtual void arm(Tick ticks) = 0; 91 /** 92 * Disarm the timer. 93 * 94 * When this method has returned, the timer may no longer deliver 95 * signals upon timeout. 96 */ 97 virtual void disarm() = 0; 98 99 /** 100 * Determine the resolution of the timer in ticks. This method is 101 * mainly used to determine the smallest number of ticks the timer 102 * can wait before triggering a signal. 103 * 104 * @return Minimum number of ticks the timer can resolve 105 */ 106 Tick resolution() { 107 if (_resolution == 0) 108 _resolution = calcResolution(); 109 return _resolution; 110 } 111 112 /** 113 * Convert cycles executed on the host into Ticks executed in the 114 * simulator. Scales the results using the hostFactor to take CPU 115 * performance differences into account. 116 * 117 * @return Host cycles executed in VM converted to simulation ticks 118 */ 119 Tick ticksFromHostCycles(uint64_t cycles) { 120 return cycles * hostFactor * hostFreq; 121 } 122 123 /** 124 * Convert nanoseconds executed on the host into Ticks executed in 125 * the simulator. Scales the results using the hostFactor to take 126 * CPU performance differences into account. 127 * 128 * @return Nanoseconds executed in VM converted to simulation ticks 129 */ 130 Tick ticksFromHostNs(uint64_t ns) { 131 return ns * hostFactor * SimClock::Float::ns; 132 } 133 134 protected: 135 /** 136 * Calculate the timer resolution, used by resolution() which 137 * caches the result. 138 * 139 * @return Minimum number of ticks the timer can resolve 140 */ 141 virtual Tick calcResolution() = 0; 142 143 /** 144 * Convert a time in simulator ticks to host nanoseconds. 145 * 146 * @return Simulation ticks converted into nanoseconds on the host 147 */ 148 uint64_t hostNs(Tick ticks) { 149 return ticks / (SimClock::Float::ns * hostFactor); 150 } 151 152 /** 153 * Convert a time in simulator ticks to host cycles 154 * 155 * 156 * @return Simulation ticks converted into CPU cycles on the host 157 */ 158 uint64_t hostCycles(Tick ticks) { 159 return ticks / (hostFreq * hostFactor); 160 } 161 162 /** Signal to deliver when the timer times out */ 163 int signo; 164 165 private: 166 /** Cached resolution */ 167 mutable Tick _resolution; 168 169 /** Performance scaling factor */ 170 float hostFactor; 171 /** Host frequency */ 172 Tick hostFreq; 173}; 174 175/** 176 * Timer based on standard POSIX timers. The POSIX timer API supports 177 * several different clock with different characteristics. 178 * 179 * @note It might be tempting to use 180 * CLOCK_(THREAD|PROCESS)_CPUTIME_ID, however, this clock usually has 181 * much lower resolution than the real-time clocks. 182 */ 183class PosixKvmTimer : public BaseKvmTimer 184{ 185 public: 186 /** 187 * @param signo Signal to deliver 188 * @param clockID ID of the clock to use 189 * @param hostFactor Performance scaling factor 190 * @param hostFreq Clock frequency of the host 191 */ 192 PosixKvmTimer(int signo, clockid_t clockID, 193 float hostFactor, Tick hostFreq); 194 ~PosixKvmTimer(); 195 196 void arm(Tick ticks); 197 void disarm(); 198 199 protected: 200 Tick calcResolution(); 201 202 private: 203 clockid_t clockID; 204 timer_t timer; 205}; 206 207/** 208 * PerfEvent based timer using the host's CPU cycle counter. 209 * 210 * @warning There is a known problem in some versions of the PerfEvent 211 * API that prevents the counter overflow period from being updated 212 * reliably, which might break this timer. See PerfKvmCounter::period() 213 * for details. 214 */ 215class PerfKvmTimer : public BaseKvmTimer 216{ 217 public: 218 /** 219 * Create a timer that uses an existing hardware cycle counter. 220 * 221 * @note The performance counter must be configured for overflow 222 * sampling, which in practice means that it must have a non-zero 223 * sample period. The initial sample period is ignored since 224 * period will be updated when arm() is called. 225 * 226 * @param ctr Attached performance counter configured for overflow 227 * reporting. 228 * @param signo Signal to deliver 229 * @param hostFactor Performance scaling factor 230 * @param hostFreq Clock frequency of the host 231 */ 232 PerfKvmTimer(PerfKvmCounter &ctr, 233 int signo, 234 float hostFactor, Tick hostFreq); 235 ~PerfKvmTimer(); 236 237 void arm(Tick ticks); 238 void disarm(); 239 240 protected: 241 Tick calcResolution(); 242 243 private: 244 PerfKvmCounter &hwOverflow; 245}; 246 247#endif 248