1/* 2 * Copyright (c) 2013, 2015, 2017-2018 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: Giacomo Gabrielli 38 * Andreas Sandberg 39 */ 40 41#ifndef __DEV_ARM_GENERIC_TIMER_HH__ 42#define __DEV_ARM_GENERIC_TIMER_HH__ 43 44#include "arch/arm/isa_device.hh" 45#include "arch/arm/system.hh" 46#include "base/bitunion.hh" 47#include "dev/arm/base_gic.hh" 48#include "sim/core.hh" 49#include "sim/sim_object.hh" 50 51/// @file 52/// This module implements the global system counter and the local per-CPU 53/// architected timers as specified by the ARM Generic Timer extension (ARM 54/// ARM, Issue C, Chapter 17). 55 56class Checkpoint; 57class GenericTimerParams; 58class GenericTimerMemParams; 59 60/// Global system counter. It is shared by the architected timers. 61/// @todo: implement memory-mapped controls 62class SystemCounter : public Serializable 63{ 64 protected: 65 /// Counter frequency (as specified by CNTFRQ). 66 uint64_t _freq; 67 /// Cached copy of the counter period (inverse of the frequency). 68 Tick _period; 69 /// Tick when the counter was reset. 70 Tick _resetTick; 71 72 /// Kernel event stream control register 73 uint32_t _regCntkctl; 74 /// Hypervisor event stream control register 75 uint32_t _regCnthctl; 76 77 public: 78 SystemCounter(); 79 80 /// Returns the current value of the physical counter. 81 uint64_t value() const 82 { 83 if (_freq == 0) 84 return 0; // Counter is still off. 85 return (curTick() - _resetTick) / _period; 86 } 87 88 /// Returns the counter frequency. 89 uint64_t freq() const { return _freq; } 90 /// Sets the counter frequency. 91 /// @param freq frequency in Hz. 92 void setFreq(uint32_t freq); 93 94 /// Returns the counter period. 95 Tick period() const { return _period; } 96 97 void setKernelControl(uint32_t val) { _regCntkctl = val; } 98 uint32_t getKernelControl() { return _regCntkctl; } 99 100 void setHypControl(uint32_t val) { _regCnthctl = val; } 101 uint32_t getHypControl() { return _regCnthctl; } 102 103 void serialize(CheckpointOut &cp) const override; 104 void unserialize(CheckpointIn &cp) override; 105 106 private: 107 // Disable copying 108 SystemCounter(const SystemCounter &c); 109}; 110 111/// Per-CPU architected timer. 112class ArchTimer : public Serializable, public Drainable 113{ 114 protected: 115 /// Control register. 116 BitUnion32(ArchTimerCtrl) 117 Bitfield<0> enable; 118 Bitfield<1> imask; 119 Bitfield<2> istatus; 120 EndBitUnion(ArchTimerCtrl) 121 122 /// Name of this timer. 123 const std::string _name; 124 125 /// Pointer to parent class. 126 SimObject &_parent; 127 128 SystemCounter &_systemCounter; 129 130 ArmInterruptPin * const _interrupt; 131 132 /// Value of the control register ({CNTP/CNTHP/CNTV}_CTL). 133 ArchTimerCtrl _control; 134 /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL). 135 uint64_t _counterLimit; 136 /// Offset relative to the physical timer (CNTVOFF) 137 uint64_t _offset; 138 139 /** 140 * Timer settings or the offset has changed, re-evaluate 141 * trigger condition and raise interrupt if necessary. 142 */ 143 void updateCounter(); 144 145 /// Called when the upcounter reaches the programmed value. 146 void counterLimitReached(); 147 EventFunctionWrapper _counterLimitReachedEvent; 148 149 virtual bool scheduleEvents() { return true; } 150 151 public: 152 ArchTimer(const std::string &name, 153 SimObject &parent, 154 SystemCounter &sysctr, 155 ArmInterruptPin *interrupt); 156 157 /// Returns the timer name. 158 std::string name() const { return _name; } 159 160 /// Returns the CompareValue view of the timer. 161 uint64_t compareValue() const { return _counterLimit; } 162 /// Sets the CompareValue view of the timer. 163 void setCompareValue(uint64_t val); 164 165 /// Returns the TimerValue view of the timer. 166 uint32_t timerValue() const { return _counterLimit - value(); } 167 /// Sets the TimerValue view of the timer. 168 void setTimerValue(uint32_t val); 169 170 /// Sets the control register. 171 uint32_t control() const { return _control; } 172 void setControl(uint32_t val); 173 174 uint64_t offset() const { return _offset; } 175 void setOffset(uint64_t val); 176 177 /// Returns the value of the counter which this timer relies on. 178 uint64_t value() const; 179 180 // Serializable 181 void serialize(CheckpointOut &cp) const override; 182 void unserialize(CheckpointIn &cp) override; 183 184 // Drainable 185 DrainState drain() override; 186 void drainResume() override; 187 188 private: 189 // Disable copying 190 ArchTimer(const ArchTimer &t); 191}; 192 193class ArchTimerKvm : public ArchTimer 194{ 195 private: 196 ArmSystem &system; 197 198 public: 199 ArchTimerKvm(const std::string &name, 200 ArmSystem &system, 201 SimObject &parent, 202 SystemCounter &sysctr, 203 ArmInterruptPin *interrupt) 204 : ArchTimer(name, parent, sysctr, interrupt), system(system) {} 205 206 protected: 207 // For ArchTimer's in a GenericTimerISA with Kvm execution about 208 // to begin, skip rescheduling the event. 209 // Otherwise, we should reschedule the event (if necessary). 210 bool scheduleEvents() override { 211 return !system.validKvmEnvironment(); 212 } 213}; 214 215class GenericTimer : public ClockedObject 216{ 217 public: 218 const GenericTimerParams * params() const; 219 220 GenericTimer(GenericTimerParams *p); 221 222 void serialize(CheckpointOut &cp) const override; 223 void unserialize(CheckpointIn &cp) override; 224 225 public: 226 void setMiscReg(int misc_reg, unsigned cpu, RegVal val); 227 RegVal readMiscReg(int misc_reg, unsigned cpu); 228 229 protected: 230 struct CoreTimers { 231 CoreTimers(GenericTimer &parent, ArmSystem &system, unsigned cpu, 232 ArmInterruptPin *_irqPhysS, ArmInterruptPin *_irqPhysNS, 233 ArmInterruptPin *_irqVirt, ArmInterruptPin *_irqHyp) 234 : irqPhysS(_irqPhysS), 235 irqPhysNS(_irqPhysNS), 236 irqVirt(_irqVirt), 237 irqHyp(_irqHyp), 238 physS(csprintf("%s.phys_s_timer%d", parent.name(), cpu), 239 system, parent, parent.systemCounter, 240 _irqPhysS), 241 // This should really be phys_timerN, but we are stuck with 242 // arch_timer for backwards compatibility. 243 physNS(csprintf("%s.arch_timer%d", parent.name(), cpu), 244 system, parent, parent.systemCounter, 245 _irqPhysNS), 246 virt(csprintf("%s.virt_timer%d", parent.name(), cpu), 247 system, parent, parent.systemCounter, 248 _irqVirt), 249 hyp(csprintf("%s.hyp_timer%d", parent.name(), cpu), 250 system, parent, parent.systemCounter, 251 _irqHyp) 252 {} 253 254 ArmInterruptPin const *irqPhysS; 255 ArmInterruptPin const *irqPhysNS; 256 ArmInterruptPin const *irqVirt; 257 ArmInterruptPin const *irqHyp; 258 259 ArchTimerKvm physS; 260 ArchTimerKvm physNS; 261 ArchTimerKvm virt; 262 ArchTimerKvm hyp; 263 264 private: 265 // Disable copying 266 CoreTimers(const CoreTimers &c); 267 }; 268 269 CoreTimers &getTimers(int cpu_id); 270 void createTimers(unsigned cpus); 271 272 /// System counter. 273 SystemCounter systemCounter; 274 275 /// Per-CPU physical architected timers. 276 std::vector<std::unique_ptr<CoreTimers>> timers; 277 278 protected: // Configuration 279 /// ARM system containing this timer 280 ArmSystem &system; 281}; 282 283class GenericTimerISA : public ArmISA::BaseISADevice 284{ 285 public: 286 GenericTimerISA(GenericTimer &_parent, unsigned _cpu) 287 : parent(_parent), cpu(_cpu) {} 288 289 void setMiscReg(int misc_reg, RegVal val) override; 290 RegVal readMiscReg(int misc_reg) override; 291 292 protected: 293 GenericTimer &parent; 294 unsigned cpu; 295}; 296 297class GenericTimerMem : public PioDevice 298{ 299 public: 300 GenericTimerMem(GenericTimerMemParams *p); 301 302 void serialize(CheckpointOut &cp) const override; 303 void unserialize(CheckpointIn &cp) override; 304 305 public: // PioDevice 306 AddrRangeList getAddrRanges() const override { return addrRanges; } 307 Tick read(PacketPtr pkt) override; 308 Tick write(PacketPtr pkt) override; 309 310 protected: 311 uint64_t ctrlRead(Addr addr, size_t size) const; 312 void ctrlWrite(Addr addr, size_t size, uint64_t value); 313 314 uint64_t timerRead(Addr addr, size_t size) const; 315 void timerWrite(Addr addr, size_t size, uint64_t value); 316 317 protected: // Registers 318 static const Addr CTRL_CNTFRQ = 0x000; 319 static const Addr CTRL_CNTNSAR = 0x004; 320 static const Addr CTRL_CNTTIDR = 0x008; 321 static const Addr CTRL_CNTACR_BASE = 0x040; 322 static const Addr CTRL_CNTVOFF_LO_BASE = 0x080; 323 static const Addr CTRL_CNTVOFF_HI_BASE = 0x084; 324 325 static const Addr TIMER_CNTPCT_LO = 0x000; 326 static const Addr TIMER_CNTPCT_HI = 0x004; 327 static const Addr TIMER_CNTVCT_LO = 0x008; 328 static const Addr TIMER_CNTVCT_HI = 0x00C; 329 static const Addr TIMER_CNTFRQ = 0x010; 330 static const Addr TIMER_CNTEL0ACR = 0x014; 331 static const Addr TIMER_CNTVOFF_LO = 0x018; 332 static const Addr TIMER_CNTVOFF_HI = 0x01C; 333 static const Addr TIMER_CNTP_CVAL_LO = 0x020; 334 static const Addr TIMER_CNTP_CVAL_HI = 0x024; 335 static const Addr TIMER_CNTP_TVAL = 0x028; 336 static const Addr TIMER_CNTP_CTL = 0x02C; 337 static const Addr TIMER_CNTV_CVAL_LO = 0x030; 338 static const Addr TIMER_CNTV_CVAL_HI = 0x034; 339 static const Addr TIMER_CNTV_TVAL = 0x038; 340 static const Addr TIMER_CNTV_CTL = 0x03C; 341 342 protected: // Params 343 const AddrRange ctrlRange; 344 const AddrRange timerRange; 345 const AddrRangeList addrRanges; 346 347 protected: 348 /// System counter. 349 SystemCounter systemCounter; 350 ArchTimer physTimer; 351 ArchTimer virtTimer; 352}; 353 354#endif // __DEV_ARM_GENERIC_TIMER_HH__ 355