changeset 75df7a87be83 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=75df7a87be83
description:
        dev, arm: Add virtual timers to the generic timer model

        The generic timer model currently does not support virtual
        counters. Virtual and physical counters both tick with the same
        frequency. However, virtual timers allow a hypervisor to set an offset
        that is subtracted from the counter when it is read. This enables the
        hypervisor to present a time base that ticks with virtual time in the
        VM (i.e., doesn't tick when the VM isn't running). Modern Linux
        kernels generally assume that virtual counters exist and try to use
        them by default.

diffstat:

 src/arch/arm/miscregs.cc     |  12 +++++-----
 src/dev/arm/RealView.py      |   9 ++++---
 src/dev/arm/generic_timer.cc |  50 ++++++++++++++++++++++++++++++++++++-------
 src/dev/arm/generic_timer.hh |  19 ++++++++++++++-
 4 files changed, 69 insertions(+), 21 deletions(-)

diffs (265 lines):

diff -r 8551af601f75 -r 75df7a87be83 src/arch/arm/miscregs.cc
--- a/src/arch/arm/miscregs.cc  Sat May 23 13:46:52 2015 +0100
+++ b/src/arch/arm/miscregs.cc  Sat May 23 13:46:53 2015 +0100
@@ -715,9 +715,9 @@
     // MISCREG_CNTP_CTL_S
     bitset<NUM_MISCREG_INFOS>(string("00110011001111100000")),
     // MISCREG_CNTV_TVAL
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTV_CTL
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTHCTL
     bitset<NUM_MISCREG_INFOS>(string("01001000000000000000")),
     // MISCREG_CNTHP_TVAL
@@ -763,7 +763,7 @@
     // MISCREG_CNTP_CVAL_S
     bitset<NUM_MISCREG_INFOS>(string("00110011001111100000")),
     // MISCREG_CNTV_CVAL
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTVOFF
     bitset<NUM_MISCREG_INFOS>(string("11001100000000000001")),
     // MISCREG_CNTHP_CVAL
@@ -1259,11 +1259,11 @@
     // MISCREG_CNTP_CVAL_EL0
     bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTV_TVAL_EL0
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTV_CTL_EL0
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_CNTV_CVAL_EL0
-    bitset<NUM_MISCREG_INFOS>(string("01111000000000000000")),
+    bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_PMEVCNTR0_EL0
     bitset<NUM_MISCREG_INFOS>(string("11111111111111000001")),
     // MISCREG_PMEVCNTR1_EL0
diff -r 8551af601f75 -r 75df7a87be83 src/dev/arm/RealView.py
--- a/src/dev/arm/RealView.py   Sat May 23 13:46:52 2015 +0100
+++ b/src/dev/arm/RealView.py   Sat May 23 13:46:53 2015 +0100
@@ -136,9 +136,10 @@
     cxx_header = "dev/arm/generic_timer.hh"
     system = Param.System(Parent.any, "system")
     gic = Param.BaseGic(Parent.any, "GIC to use for interrupting")
-    int_phys = Param.UInt32("Interrupt number used per-cpu to GIC")
-    # @todo: for now only one timer per CPU is supported, which is the
-    # normal behaviour when Security and Virt. extensions are disabled.
+    # @todo: for now only two timers per CPU is supported, which is the
+    # normal behaviour when security extensions are disabled.
+    int_phys = Param.UInt32("Physical timer interrupt number")
+    int_virt = Param.UInt32("Virtual timer interrupt number")
 
 class PL031(AmbaIntDevice):
     type = 'PL031'
@@ -457,7 +458,7 @@
                                idreg=0x02250000, pio_addr=0x1C010000)
     gic = Pl390(dist_addr=0x2C001000, cpu_addr=0x2C002000)
     local_cpu_timer = CpuLocalTimer(int_num_timer=29, int_num_watchdog=30, 
pio_addr=0x2C080000)
-    generic_timer = GenericTimer(int_phys=29)
+    generic_timer = GenericTimer(int_phys=29, int_virt=27)
     timer0 = Sp804(int_num0=34, int_num1=34, pio_addr=0x1C110000, 
clock0='1MHz', clock1='1MHz')
     timer1 = Sp804(int_num0=35, int_num1=35, pio_addr=0x1C120000, 
clock0='1MHz', clock1='1MHz')
     clcd   = Pl111(pio_addr=0x1c1f0000, int_num=46)
diff -r 8551af601f75 -r 75df7a87be83 src/dev/arm/generic_timer.cc
--- a/src/dev/arm/generic_timer.cc      Sat May 23 13:46:52 2015 +0100
+++ b/src/dev/arm/generic_timer.cc      Sat May 23 13:46:53 2015 +0100
@@ -93,7 +93,7 @@
                      const Interrupt &interrupt)
     : _name(name), _parent(parent), _systemCounter(sysctr),
       _interrupt(interrupt),
-      _control(0), _counterLimit(0),
+      _control(0), _counterLimit(0), _offset(0),
       _counterLimitReachedEvent(this)
 {
 }
@@ -159,10 +159,17 @@
     _control.imask = new_ctl.imask;
 }
 
+void
+ArchTimer::setOffset(uint64_t val)
+{
+    _offset = val;
+    updateCounter();
+}
+
 uint64_t
 ArchTimer::value() const
 {
-    return _systemCounter.value();
+    return _systemCounter.value() - _offset;
 }
 
 void
@@ -170,6 +177,7 @@
 {
     paramOut(os, "control_serial", _control);
     SERIALIZE_SCALAR(_counterLimit);
+    SERIALIZE_SCALAR(_offset);
 
     const bool event_scheduled(_counterLimitReachedEvent.scheduled());
     SERIALIZE_SCALAR(event_scheduled);
@@ -184,6 +192,11 @@
                                          const std::string &section)
 {
     paramIn(cp, section, "control_serial", _control);
+    // We didn't serialize an offset before we added support for the
+    // virtual timer. Consider it optional to maintain backwards
+    // compatibility.
+    if (!UNSERIALIZE_OPT_SCALAR(_offset))
+        _offset = 0;
     bool event_scheduled;
     UNSERIALIZE_SCALAR(event_scheduled);
     if (event_scheduled) {
@@ -218,7 +231,8 @@
 GenericTimer::GenericTimer(GenericTimerParams *p)
     : SimObject(p),
       gic(p->gic),
-      irqPhys(p->int_phys)
+      irqPhys(p->int_phys),
+      irqVirt(p->int_virt)
 {
     dynamic_cast<ArmSystem &>(*p->system).setGenericTimer(this);
 }
@@ -236,6 +250,9 @@
 
         nameOut(os, core.phys.name());
         core.phys.serialize(os);
+
+        nameOut(os, core.virt.name());
+        core.virt.serialize(os);
     }
 }
 
@@ -260,6 +277,7 @@
         // This should really be phys_timerN, but we are stuck with
         // arch_timer for backwards compatibility.
         core.phys.unserialize(cp, csprintf("%s.arch_timer%d", section, i));
+        core.virt.unserialize(cp, csprintf("%s.virt_timer%d", section, i));
     }
 }
 
@@ -282,7 +300,7 @@
     timers.resize(cpus);
     for (unsigned i = old_cpu_count; i < cpus; ++i) {
         timers[i].reset(
-            new CoreTimers(*this, i, irqPhys));
+            new CoreTimers(*this, i, irqPhys, irqVirt));
     }
 }
 
@@ -334,13 +352,23 @@
       // Virtual timer
       case MISCREG_CNTVOFF:
       case MISCREG_CNTVOFF_EL2:
+        core.virt.setOffset(val);
+        return;
+
       case MISCREG_CNTV_CVAL:
       case MISCREG_CNTV_CVAL_EL0:
+        core.virt.setCompareValue(val);
+        return;
+
       case MISCREG_CNTV_TVAL:
       case MISCREG_CNTV_TVAL_EL0:
+        core.virt.setTimerValue(val);
+        return;
+
       case MISCREG_CNTV_CTL:
       case MISCREG_CNTV_CTL_EL0:
-        /* FALLTHROUGH */
+        core.virt.setControl(val);
+        return;
 
       // PL1 phys. timer, secure
       case MISCREG_CNTP_CTL_S:
@@ -405,19 +433,23 @@
       // Virtual timer
       case MISCREG_CNTVCT:
       case MISCREG_CNTVCT_EL0:
-        warn_once("Virtual timer not implemented, "
-                  "returning physical timer value\n");
-        return core.phys.value();
+        return core.virt.value();
 
       case MISCREG_CNTVOFF:
       case MISCREG_CNTVOFF_EL2:
+        return core.virt.offset();
+
       case MISCREG_CNTV_CVAL:
       case MISCREG_CNTV_CVAL_EL0:
+        return core.virt.compareValue();
+
       case MISCREG_CNTV_TVAL:
       case MISCREG_CNTV_TVAL_EL0:
+        return core.virt.timerValue();
+
       case MISCREG_CNTV_CTL:
       case MISCREG_CNTV_CTL_EL0:
-        /* FALLTHROUGH */
+        return core.virt.control();
 
       // PL1 phys. timer, secure
       case MISCREG_CNTP_CTL_S:
diff -r 8551af601f75 -r 75df7a87be83 src/dev/arm/generic_timer.hh
--- a/src/dev/arm/generic_timer.hh      Sat May 23 13:46:52 2015 +0100
+++ b/src/dev/arm/generic_timer.hh      Sat May 23 13:46:53 2015 +0100
@@ -145,6 +145,8 @@
     ArchTimerCtrl _control;
     /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
     uint64_t _counterLimit;
+    /// Offset relative to the physical timer (CNTVOFF)
+    uint64_t _offset;
 
     /**
      * Timer settings or the offset has changed, re-evaluate
@@ -180,6 +182,9 @@
     uint32_t control() const { return _control; }
     void setControl(uint32_t val);
 
+    uint64_t offset() const { return _offset; }
+    void setOffset(uint64_t val);
+
     /// Returns the value of the counter which this timer relies on.
     uint64_t value() const;
 
@@ -206,17 +211,24 @@
   protected:
     struct CoreTimers {
         CoreTimers(GenericTimer &parent, unsigned cpu,
-                   unsigned _irqPhys)
+                   unsigned _irqPhys, unsigned _irqVirt)
             : irqPhys(*parent.gic, _irqPhys, cpu),
+              irqVirt(*parent.gic, _irqVirt, cpu),
               // This should really be phys_timerN, but we are stuck with
               // arch_timer for backwards compatibility.
               phys(csprintf("%s.arch_timer%d", parent.name(), cpu),
                    parent, parent.systemCounter,
-                   irqPhys)
+                   irqPhys),
+              virt(csprintf("%s.virt_timer%d", parent.name(), cpu),
+                   parent, parent.systemCounter,
+                   irqVirt)
         {}
 
         ArchTimer::Interrupt irqPhys;
+        ArchTimer::Interrupt irqVirt;
+
         ArchTimer phys;
+        ArchTimer virt;
 
       private:
         // Disable copying
@@ -238,6 +250,9 @@
 
     /// Physical timer interrupt
     const unsigned irqPhys;
+
+    /// Virtual timer interrupt
+    const unsigned irqVirt;
 };
 
 class GenericTimerISA : public ArmISA::BaseISADevice
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to