From 1fc48cc45471be63a6c7cb4eb2e3a2c13f8f9bf3 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Thu, 22 Feb 2018 18:45:30 +0000 Subject: dev, arm: Add support for HYP & secure timers Change-Id: I1a4849283f9bd5b1856e1378f7cefc33fc14eebd Signed-off-by: Andreas Sandberg Reviewed-by: Curtis Dunham Reviewed-on: https://gem5-review.googlesource.com/10023 Reviewed-by: Giacomo Travaglini Maintainer: Giacomo Travaglini --- src/dev/arm/RealView.py | 21 ++++---- src/dev/arm/generic_timer.cc | 112 +++++++++++++++++++++++++++---------------- src/dev/arm/generic_timer.hh | 44 +++++++++++++---- 3 files changed, 119 insertions(+), 58 deletions(-) (limited to 'src/dev') diff --git a/src/dev/arm/RealView.py b/src/dev/arm/RealView.py index 9b91f4609..308de18af 100644 --- a/src/dev/arm/RealView.py +++ b/src/dev/arm/RealView.py @@ -418,10 +418,10 @@ class GenericTimer(ClockedObject): cxx_header = "dev/arm/generic_timer.hh" system = Param.ArmSystem(Parent.any, "system") gic = Param.BaseGic(Parent.any, "GIC to use for interrupting") - # @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_phys_s = Param.UInt32("Physical (S) timer interrupt number") + int_phys_ns = Param.UInt32("Physical (NS) timer interrupt number") int_virt = Param.UInt32("Virtual timer interrupt number") + int_hyp = Param.UInt32("Hypervisor timer interrupt number") def generateDeviceTree(self, state): node = FdtNode("timer") @@ -429,9 +429,12 @@ class GenericTimer(ClockedObject): node.appendCompatible(["arm,cortex-a15-timer", "arm,armv7-timer", "arm,armv8-timer"]) - node.append(FdtPropertyWords("interrupts", - [1, int(self.int_phys) - 16, 0xf08, - 1, int(self.int_virt) - 16, 0xf08])) + node.append(FdtPropertyWords("interrupts", [ + 1, int(self.int_phys_s) - 16, 0xf08, + 1, int(self.int_phys_ns) - 16, 0xf08, + 1, int(self.int_virt) - 16, 0xf08, + 1, int(self.int_hyp) - 16, 0xf08, + ])) clock = state.phandle(self.clk_domain.unproxy(self)) node.append(FdtPropertyWords("clocks", clock)) @@ -900,7 +903,8 @@ class VExpress_EMM(RealView): conf_base=0x30000000, conf_size='256MB', conf_device_bits=16, pci_pio_base=0) - generic_timer = GenericTimer(int_phys=29, int_virt=27) + generic_timer = GenericTimer(int_phys_s=29, int_phys_ns=30, + int_virt=27, int_hyp=26) 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) @@ -1118,7 +1122,8 @@ Interrupts: Gicv2mFrame(spi_base=256, spi_len=64, addr=0x2c1c0000), ] - generic_timer = GenericTimer(int_phys=29, int_virt=27) + generic_timer = GenericTimer(int_phys_s=29, int_phys_ns=30, + int_virt=27, int_hyp=26) hdlcd = HDLcd(pxl_clk=dcc.osc_pxl, pio_addr=0x2b000000, int_num=95) diff --git a/src/dev/arm/generic_timer.cc b/src/dev/arm/generic_timer.cc index 73e4f9143..1d5e8bb00 100644 --- a/src/dev/arm/generic_timer.cc +++ b/src/dev/arm/generic_timer.cc @@ -69,6 +69,7 @@ void SystemCounter::serialize(CheckpointOut &cp) const { SERIALIZE_SCALAR(_regCntkctl); + SERIALIZE_SCALAR(_regCnthctl); SERIALIZE_SCALAR(_freq); SERIALIZE_SCALAR(_period); SERIALIZE_SCALAR(_resetTick); @@ -81,6 +82,8 @@ SystemCounter::unserialize(CheckpointIn &cp) // if it isn't present. if (!UNSERIALIZE_OPT_SCALAR(_regCntkctl)) _regCntkctl = 0; + if (!UNSERIALIZE_OPT_SCALAR(_regCnthctl)) + _regCnthctl = 0; UNSERIALIZE_SCALAR(_freq); UNSERIALIZE_SCALAR(_period); UNSERIALIZE_SCALAR(_resetTick); @@ -242,8 +245,10 @@ GenericTimer::GenericTimer(GenericTimerParams *p) : ClockedObject(p), system(*p->system), gic(p->gic), - irqPhys(p->int_phys), - irqVirt(p->int_virt) + irqPhysS(p->int_phys_s), + irqPhysNS(p->int_phys_ns), + irqVirt(p->int_virt), + irqHyp(p->int_hyp) { fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); system.setGenericTimer(this); @@ -261,8 +266,10 @@ GenericTimer::serialize(CheckpointOut &cp) const // This should really be phys_timerN, but we are stuck with // arch_timer for backwards compatibility. - core.phys.serializeSection(cp, csprintf("arch_timer%d", i)); + core.physNS.serializeSection(cp, csprintf("arch_timer%d", i)); + core.physS.serializeSection(cp, csprintf("phys_s_timer%d", i)); core.virt.serializeSection(cp, csprintf("virt_timer%d", i)); + core.hyp.serializeSection(cp, csprintf("hyp_timer%d", i)); } } @@ -286,8 +293,10 @@ GenericTimer::unserialize(CheckpointIn &cp) CoreTimers &core(getTimers(i)); // This should really be phys_timerN, but we are stuck with // arch_timer for backwards compatibility. - core.phys.unserializeSection(cp, csprintf("arch_timer%d", i)); + core.physNS.unserializeSection(cp, csprintf("arch_timer%d", i)); + core.physS.unserializeSection(cp, csprintf("phys_s_timer%d", i)); core.virt.unserializeSection(cp, csprintf("virt_timer%d", i)); + core.hyp.unserializeSection(cp, csprintf("hyp_timer%d", i)); } } @@ -310,7 +319,8 @@ GenericTimer::createTimers(unsigned cpus) timers.resize(cpus); for (unsigned i = old_cpu_count; i < cpus; ++i) { timers[i].reset( - new CoreTimers(*this, system, i, irqPhys, irqVirt)); + new CoreTimers(*this, system, i, + irqPhysS, irqPhysNS, irqVirt, irqHyp)); } } @@ -331,23 +341,25 @@ GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) systemCounter.setKernelControl(val); return; - // Physical timer - case MISCREG_CNTP_CVAL: + case MISCREG_CNTHCTL: + case MISCREG_CNTHCTL_EL2: + systemCounter.setHypControl(val); + return; + + // Physical timer (NS) case MISCREG_CNTP_CVAL_NS: case MISCREG_CNTP_CVAL_EL0: - core.phys.setCompareValue(val); + core.physNS.setCompareValue(val); return; - case MISCREG_CNTP_TVAL: case MISCREG_CNTP_TVAL_NS: case MISCREG_CNTP_TVAL_EL0: - core.phys.setTimerValue(val); + core.physNS.setTimerValue(val); return; - case MISCREG_CNTP_CTL: case MISCREG_CNTP_CTL_NS: case MISCREG_CNTP_CTL_EL0: - core.phys.setControl(val); + core.physNS.setControl(val); return; // Count registers @@ -380,24 +392,36 @@ GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val) core.virt.setControl(val); return; - // PL1 phys. timer, secure + // Physical timer (S) case MISCREG_CNTP_CTL_S: + case MISCREG_CNTPS_CTL_EL1: + core.physS.setControl(val); + return; + + case MISCREG_CNTP_CVAL_S: case MISCREG_CNTPS_CVAL_EL1: + core.physS.setCompareValue(val); + return; + + case MISCREG_CNTP_TVAL_S: case MISCREG_CNTPS_TVAL_EL1: - case MISCREG_CNTPS_CTL_EL1: - M5_FALLTHROUGH; + core.physS.setTimerValue(val); + return; + + // Hyp phys. timer, non-secure + case MISCREG_CNTHP_CTL: + case MISCREG_CNTHP_CTL_EL2: + core.hyp.setControl(val); + return; - // PL2 phys. timer, non-secure - case MISCREG_CNTHCTL: - case MISCREG_CNTHCTL_EL2: case MISCREG_CNTHP_CVAL: case MISCREG_CNTHP_CVAL_EL2: + core.hyp.setCompareValue(val); + return; + case MISCREG_CNTHP_TVAL: case MISCREG_CNTHP_TVAL_EL2: - case MISCREG_CNTHP_CTL: - case MISCREG_CNTHP_CTL_EL2: - warn("Writing to unimplemented register: %s\n", - miscRegName[reg]); + core.hyp.setTimerValue(val); return; default: @@ -421,23 +445,26 @@ GenericTimer::readMiscReg(int reg, unsigned cpu) case MISCREG_CNTKCTL_EL1: return systemCounter.getKernelControl(); + case MISCREG_CNTHCTL: + case MISCREG_CNTHCTL_EL2: + return systemCounter.getHypControl(); + // Physical timer - case MISCREG_CNTP_CVAL: + case MISCREG_CNTP_CVAL_NS: case MISCREG_CNTP_CVAL_EL0: - return core.phys.compareValue(); + return core.physNS.compareValue(); - case MISCREG_CNTP_TVAL: + case MISCREG_CNTP_TVAL_NS: case MISCREG_CNTP_TVAL_EL0: - return core.phys.timerValue(); + return core.physNS.timerValue(); - case MISCREG_CNTP_CTL: case MISCREG_CNTP_CTL_EL0: case MISCREG_CNTP_CTL_NS: - return core.phys.control(); + return core.physNS.control(); case MISCREG_CNTPCT: case MISCREG_CNTPCT_EL0: - return core.phys.value(); + return core.physNS.value(); // Virtual timer @@ -463,24 +490,29 @@ GenericTimer::readMiscReg(int reg, unsigned cpu) // PL1 phys. timer, secure case MISCREG_CNTP_CTL_S: + case MISCREG_CNTPS_CTL_EL1: + return core.physS.control(); + + case MISCREG_CNTP_CVAL_S: case MISCREG_CNTPS_CVAL_EL1: + return core.physS.compareValue(); + + case MISCREG_CNTP_TVAL_S: case MISCREG_CNTPS_TVAL_EL1: - case MISCREG_CNTPS_CTL_EL1: - M5_FALLTHROUGH; + return core.physS.timerValue(); + + // HYP phys. timer (NS) + case MISCREG_CNTHP_CTL: + case MISCREG_CNTHP_CTL_EL2: + return core.hyp.control(); - // PL2 phys. timer, non-secure - case MISCREG_CNTHCTL: - case MISCREG_CNTHCTL_EL2: case MISCREG_CNTHP_CVAL: case MISCREG_CNTHP_CVAL_EL2: + return core.hyp.compareValue(); + case MISCREG_CNTHP_TVAL: case MISCREG_CNTHP_TVAL_EL2: - case MISCREG_CNTHP_CTL: - case MISCREG_CNTHP_CTL_EL2: - warn("Reading from unimplemented register: %s\n", - miscRegName[reg]); - return 0; - + return core.hyp.timerValue(); default: warn("Reading from unknown register: %s\n", miscRegName[reg]); diff --git a/src/dev/arm/generic_timer.hh b/src/dev/arm/generic_timer.hh index c9cfb7497..2c5776590 100644 --- a/src/dev/arm/generic_timer.hh +++ b/src/dev/arm/generic_timer.hh @@ -69,7 +69,10 @@ class SystemCounter : public Serializable /// Tick when the counter was reset. Tick _resetTick; + /// Kernel event stream control register uint32_t _regCntkctl; + /// Hypervisor event stream control register + uint32_t _regCnthctl; public: SystemCounter(); @@ -94,6 +97,9 @@ class SystemCounter : public Serializable void setKernelControl(uint32_t val) { _regCntkctl = val; } uint32_t getKernelControl() { return _regCntkctl; } + void setHypControl(uint32_t val) { _regCnthctl = val; } + uint32_t getHypControl() { return _regCnthctl; } + void serialize(CheckpointOut &cp) const override; void unserialize(CheckpointIn &cp) override; @@ -241,24 +247,37 @@ class GenericTimer : public ClockedObject protected: struct CoreTimers { CoreTimers(GenericTimer &parent, ArmSystem &system, unsigned cpu, - unsigned _irqPhys, unsigned _irqVirt) - : irqPhys(*parent.gic, _irqPhys, cpu), + unsigned _irqPhysS, unsigned _irqPhysNS, + unsigned _irqVirt, unsigned _irqHyp) + : irqPhysS(*parent.gic, _irqPhysS, cpu), + irqPhysNS(*parent.gic, _irqPhysNS, cpu), irqVirt(*parent.gic, _irqVirt, cpu), + irqHyp(*parent.gic, _irqHyp, cpu), + physS(csprintf("%s.phys_s_timer%d", parent.name(), cpu), + system, parent, parent.systemCounter, + irqPhysS), // 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), - system, parent, parent.systemCounter, - irqPhys), + physNS(csprintf("%s.arch_timer%d", parent.name(), cpu), + system, parent, parent.systemCounter, + irqPhysNS), virt(csprintf("%s.virt_timer%d", parent.name(), cpu), system, parent, parent.systemCounter, - irqVirt) + irqVirt), + hyp(csprintf("%s.hyp_timer%d", parent.name(), cpu), + system, parent, parent.systemCounter, + irqHyp) {} - ArchTimer::Interrupt irqPhys; + ArchTimer::Interrupt irqPhysS; + ArchTimer::Interrupt irqPhysNS; ArchTimer::Interrupt irqVirt; + ArchTimer::Interrupt irqHyp; - ArchTimerKvm phys; + ArchTimerKvm physS; + ArchTimerKvm physNS; ArchTimerKvm virt; + ArchTimerKvm hyp; private: // Disable copying @@ -281,11 +300,16 @@ class GenericTimer : public ClockedObject /// Pointer to the GIC, needed to trigger timer interrupts. BaseGic *const gic; - /// Physical timer interrupt - const unsigned irqPhys; + /// Physical timer interrupt (S) + const unsigned irqPhysS; + /// Physical timer interrupt (NS) + const unsigned irqPhysNS; /// Virtual timer interrupt const unsigned irqVirt; + + /// Hypervisor timer interrupt + const unsigned irqHyp; }; class GenericTimerISA : public ArmISA::BaseISADevice -- cgit v1.2.3