diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2018-02-22 18:45:30 +0000 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2018-06-06 13:54:57 +0000 |
commit | 1fc48cc45471be63a6c7cb4eb2e3a2c13f8f9bf3 (patch) | |
tree | aa73ba7664e05fa40baf2497985cd02f63a4e524 /src | |
parent | a9b78bcee79a9228d0590091c5f6dfc265e59300 (diff) | |
download | gem5-1fc48cc45471be63a6c7cb4eb2e3a2c13f8f9bf3.tar.xz |
dev, arm: Add support for HYP & secure timers
Change-Id: I1a4849283f9bd5b1856e1378f7cefc33fc14eebd
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/10023
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/miscregs.cc | 29 | ||||
-rw-r--r-- | src/dev/arm/RealView.py | 21 | ||||
-rw-r--r-- | src/dev/arm/generic_timer.cc | 112 | ||||
-rw-r--r-- | src/dev/arm/generic_timer.hh | 44 |
4 files changed, 126 insertions, 80 deletions
diff --git a/src/arch/arm/miscregs.cc b/src/arch/arm/miscregs.cc index 8dd56c791..89caa1455 100644 --- a/src/arch/arm/miscregs.cc +++ b/src/arch/arm/miscregs.cc @@ -3176,7 +3176,6 @@ ISA::initializeMiscRegMetadata() .privSecure(!aarch32EL3) .monSecure(0); InitReg(MISCREG_CNTP_TVAL_S) - .unimplemented() .bankedChild() .secure().user(1); InitReg(MISCREG_CNTP_CTL) @@ -3187,7 +3186,6 @@ ISA::initializeMiscRegMetadata() .privSecure(!aarch32EL3) .monSecure(0); InitReg(MISCREG_CNTP_CTL_S) - .unimplemented() .bankedChild() .secure().user(1); InitReg(MISCREG_CNTV_TVAL) @@ -3195,13 +3193,10 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_CNTV_CTL) .allPrivileges(); InitReg(MISCREG_CNTHCTL) - .unimplemented() .hypWrite().monNonSecureRead(); InitReg(MISCREG_CNTHP_TVAL) - .unimplemented() .hypWrite().monNonSecureRead(); InitReg(MISCREG_CNTHP_CTL) - .unimplemented() .hypWrite().monNonSecureRead(); InitReg(MISCREG_IL1DATA0) .unimplemented() @@ -3256,7 +3251,6 @@ ISA::initializeMiscRegMetadata() .privSecure(!aarch32EL3) .monSecure(0); InitReg(MISCREG_CNTP_CVAL_S) - .unimplemented() .bankedChild() .secure().user(1); InitReg(MISCREG_CNTV_CVAL) @@ -3264,7 +3258,6 @@ ISA::initializeMiscRegMetadata() InitReg(MISCREG_CNTVOFF) .hyp().monNonSecure(); InitReg(MISCREG_CNTHP_CVAL) - .unimplemented() .hypWrite().monNonSecureRead(); InitReg(MISCREG_CPUMERRSR) .unimplemented() @@ -3936,31 +3929,23 @@ ISA::initializeMiscRegMetadata() .hyp().mon() .mapsTo(MISCREG_CNTVOFF); /* 64b */ InitReg(MISCREG_CNTHCTL_EL2) - .unimplemented() - .warnNotFail() - .mon().monNonSecureWrite(0).hypWrite() + .mon().hyp() .mapsTo(MISCREG_CNTHCTL); InitReg(MISCREG_CNTHP_TVAL_EL2) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite() + .mon().hyp() .mapsTo(MISCREG_CNTHP_TVAL); InitReg(MISCREG_CNTHP_CTL_EL2) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite() + .mon().hyp() .mapsTo(MISCREG_CNTHP_CTL); InitReg(MISCREG_CNTHP_CVAL_EL2) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite() + .mon().hyp() .mapsTo(MISCREG_CNTHP_CVAL); /* 64b */ InitReg(MISCREG_CNTPS_TVAL_EL1) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite(); + .mon().privSecure(); InitReg(MISCREG_CNTPS_CTL_EL1) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite(); + .mon().privSecure(); InitReg(MISCREG_CNTPS_CVAL_EL1) - .unimplemented() - .mon().monNonSecureWrite(0).hypWrite(); + .mon().privSecure(); InitReg(MISCREG_IL1DATA0_EL1) .allPrivileges().exceptUserMode(); InitReg(MISCREG_IL1DATA1_EL1) 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 |