Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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