timer.hh revision 9651:f551c8ad12a5
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 "sim/core.hh"
46
47/**
48 * Timer functions to interrupt VM execution after a number of
49 * simulation ticks. The timer allows scaling of the host time to take
50 * performance differences between the simulated and real CPU into
51 * account.
52 *
53 * The performance scaling factor is ratio between the target's CPI
54 * and the host's CPI. It is larger than 1 if the host is faster than
55 * the target and lower than 1 if it is slower.
56 *
57 * When the timer times out, it sends a signal to the thread that
58 * started the timer. The signal forces KVM to drop out of the system
59 * call that started the guest and hands control to gem5.
60 */
61class BaseKvmTimer
62{
63  public:
64    /**
65     * Setup basic timer functionality shared by all timer
66     * implementations.
67     *
68     * @param signo Signal to deliver
69     * @param hostFactor Performance scaling factor
70     * @param hostFreq Clock frequency of the host
71     */
72    BaseKvmTimer(int signo, float hostFactor, Tick hostFreq)
73        : signo(signo), _resolution(0),
74          hostFactor(hostFactor), hostFreq(hostFreq) {};
75    virtual ~BaseKvmTimer() {};
76
77    /**
78     * Arm the timer so that it fires after a certain number of ticks.
79     *
80     * @note A timer implementation is free to convert between
81     * simulation ticks and virtualized time using any method it
82     * chooses. The accuracy of the timer therefore depends on what it
83     * measures, an accurate timer implementation should measure the
84     * number of cycles or instructions executed in the guest. If such
85     * counters are unavailable, it may fallback to wall clock time.
86     *
87     * @param ticks Number of ticks until the timer fires
88     */
89    virtual void arm(Tick ticks) = 0;
90    /**
91     * Disarm the timer.
92     *
93     * When this method has returned, the timer may no longer deliver
94     * signals upon timeout.
95     */
96    virtual void disarm() = 0;
97
98    /**
99     * Determine the resolution of the timer in ticks. This method is
100     * mainly used to determine the smallest number of ticks the timer
101     * can wait before triggering a signal.
102     *
103     * @return Minimum number of ticks the timer can resolve
104     */
105    Tick resolution() {
106        if (_resolution == 0)
107            _resolution = calcResolution();
108        return _resolution;
109    }
110
111    /**
112     * Convert cycles executed on the host into Ticks executed in the
113     * simulator. Scales the results using the hostFactor to take CPU
114     * performance differences into account.
115     *
116     * @return Host cycles executed in VM converted to simulation ticks
117     */
118    Tick ticksFromHostCycles(uint64_t cycles) {
119        return cycles * hostFactor * hostFreq;
120    }
121
122    /**
123     * Convert nanoseconds executed on the host into Ticks executed in
124     * the simulator. Scales the results using the hostFactor to take
125     * CPU performance differences into account.
126     *
127     * @return Nanoseconds executed in VM converted to simulation ticks
128     */
129    Tick ticksFromHostNs(uint64_t ns) {
130        return ns * hostFactor * SimClock::Float::ns;
131    }
132
133  protected:
134    /**
135     * Calculate the timer resolution, used by resolution() which
136     * caches the result.
137     *
138     * @return Minimum number of ticks the timer can resolve
139     */
140    virtual Tick calcResolution() = 0;
141
142    /**
143     * Convert a time in simulator ticks to host nanoseconds.
144     *
145     * @return Simulation ticks converted into nanoseconds on the host
146     */
147    uint64_t hostNs(Tick ticks) {
148        return ticks / (SimClock::Float::ns * hostFactor);
149    }
150
151    /**
152     * Convert a time in simulator ticks to host cycles
153     *
154     *
155     * @return Simulation ticks converted into CPU cycles on the host
156     */
157    uint64_t hostCycles(Tick ticks) {
158        return ticks / (hostFreq * hostFactor);
159    }
160
161    /** Signal to deliver when the timer times out */
162    int signo;
163
164  private:
165    /** Cached resolution */
166    mutable Tick _resolution;
167
168    /** Performance scaling factor */
169    float hostFactor;
170    /** Host frequency */
171    Tick hostFreq;
172};
173
174/**
175 * Timer based on standard POSIX timers. The POSIX timer API supports
176 * several different clock with different characteristics.
177 *
178 * @note It might be tempting to use
179 * CLOCK_(THREAD|PROCESS)_CPUTIME_ID, however, this clock usually has
180 * much lower resolution than the real-time clocks.
181 */
182class PosixKvmTimer : public BaseKvmTimer
183{
184  public:
185    /**
186     * @param signo Signal to deliver
187     * @param clockID ID of the clock to use
188     * @param hostFactor Performance scaling factor
189     * @param hostFreq Clock frequency of the host
190     */
191    PosixKvmTimer(int signo, clockid_t clockID,
192                  float hostFactor, Tick hostFreq);
193    ~PosixKvmTimer();
194
195    void arm(Tick ticks);
196    void disarm();
197
198  protected:
199    Tick calcResolution();
200
201  private:
202    clockid_t clockID;
203    timer_t timer;
204};
205
206#endif
207