class GenericTimer(SimObject): """ Architected timers per PE in the system. Each of them provides a physical counter, a virtual counter and several timers accessible from different exception levels and security states. Reference: Arm ARM (ARM DDI 0487E.a) D11.2 - The AArch64 view of the Generic Timer G6.2 - The AArch32 view of the Generic Timer """ type = 'GenericTimer' cxx_header = "dev/arm/generic_timer.hh" cxx_class = 'gem5::GenericTimer' _freq_in_dtb = False system = Param.ArmSystem(Parent.any, "system") counter = Param.SystemCounter(Parent.any, "Global system counter") int_phys_s = Param.ArmPPI("Physical (S) timer interrupt") int_phys_ns = Param.ArmPPI("Physical (NS) timer interrupt") int_virt = Param.ArmPPI("Virtual timer interrupt") int_hyp = Param.ArmPPI("Hypervisor timer interrupt") # This value should be in theory initialized by the highest # priviledged software. We do this in gem5 to avoid KVM # complications (the gem5 firmware won't run at highest EL) # # PLEASE note: change this parameter only if using the gem5 bootloader # Another real world bootloader might be changing the CNTFRQ register # value, so this initial value will be discarded cntfrq = Param.UInt64(0x1800000, "Value for the CNTFRQ timer register") def generateDeviceTree(self, state): node = FdtNode("timer") node.appendCompatible( ["arm,cortex-a15-timer", "arm,armv7-timer", "arm,armv8-timer"]) gic = self._parent.unproxy(self).gic node.append( FdtPropertyWords( "interrupts", self.int_phys_s.generateFdtProperty(gic) + self.int_phys_ns.generateFdtProperty(gic) + self.int_virt.generateFdtProperty(gic) + self.int_hyp.generateFdtProperty(gic))) if self._freq_in_dtb: node.append(self.counter.unproxy(self).generateDtb()) yield node
class GenericTimerMem(PioDevice): """ System level implementation. It provides three main components: - Memory-mapped counter module: controls the system timer through the CNTControlBase frame, and provides its value through the CNTReadBase frame - Memory-mapped timer control module: controls the memory-mapped timers - Memory-mapped timers: implementations of the GenericTimer for system peripherals Reference: Arm ARM (ARM DDI 0487E.a) I2 - System Level Implementation of the Generic Timer """ type = 'GenericTimerMem' cxx_header = "dev/arm/generic_timer.hh" cxx_class = 'gem5::GenericTimerMem' _freq_in_dtb = False counter = Param.SystemCounter(Parent.any, "Global system counter") cnt_control_base = Param.Addr("CNTControlBase register frame base") cnt_read_base = Param.Addr("CNTReadBase register frame base") cnt_ctl_base = Param.Addr("CNTCTLBase register frame base") # Maximum of 8 timer frames frames = VectorParam.GenericTimerFrame([], "Memory-mapped timer frames") def generateDeviceTree(self, state): node = self.generateBasicPioDeviceNode(state, "timer", self.cnt_ctl_base, 0x1000) node.appendCompatible(["arm,armv7-timer-mem"]) node.append(state.addrCellsProperty()) node.append(state.sizeCellsProperty()) node.append(FdtProperty("ranges")) if self._freq_in_dtb: node.append(self.counter.unproxy(self).generateDtb()) gic = self._parent.unproxy(self).gic for i, frame in enumerate(self.frames): frame._frame_num = i node.append(frame.generateDeviceTree(state, gic)) yield node
class GenericTimerFrame(PioDevice): """ Memory-mapped timer frame implementation. Controlled from GenericTimerMem, may be used by peripherals without a system register interface. Reference: Arm ARM (ARM DDI 0487E.a) I2.3.2 - The CNTBaseN and CNTEL0BaseN frames """ type = 'GenericTimerFrame' cxx_header = "dev/arm/generic_timer.hh" cxx_class = 'gem5::GenericTimerFrame' _frame_num = 0 counter = Param.SystemCounter(Parent.any, "Global system counter") cnt_base = Param.Addr("CNTBase register frame base") cnt_el0_base = Param.Addr(MaxAddr, "CNTEL0Base register frame base") int_phys = Param.ArmSPI("Physical Interrupt") int_virt = Param.ArmSPI("Virtual Interrupt") def generateDeviceTree(self, state, gic): node = FdtNode("frame@{:08x}".format(self.cnt_base.value)) node.append(FdtPropertyWords("frame-number", self._frame_num)) ints = self.int_phys.generateFdtProperty(gic) if self.int_virt != NULL: ints.extend(self.int_virt.generateFdtProperty(gic)) node.append(FdtPropertyWords("interrupts", ints)) reg = state.addrCells(self.cnt_base) + state.sizeCells(0x1000) if self.cnt_el0_base.value != MaxAddr: reg.extend( state.addrCells(self.cnt_el0_base) + state.sizeCells(0x1000)) node.append(FdtPropertyWords("reg", reg)) return node