114039Sstacze01@arm.com# Copyright (c) 2013, 2018-2019 ARM Limited
214039Sstacze01@arm.com# All rights reserved
314039Sstacze01@arm.com#
414039Sstacze01@arm.com# The license below extends only to copyright in the software and shall
514039Sstacze01@arm.com# not be construed as granting a license to any other intellectual
614039Sstacze01@arm.com# property including but not limited to intellectual property relating
714039Sstacze01@arm.com# to a hardware implementation of the functionality of the software
814039Sstacze01@arm.com# licensed hereunder.  You may use the software subject to the license
914039Sstacze01@arm.com# terms below provided that you ensure that this notice is replicated
1014039Sstacze01@arm.com# unmodified and in its entirety in all distributions of the software,
1114039Sstacze01@arm.com# modified or unmodified, in source code or in binary form.
1214039Sstacze01@arm.com#
1314039Sstacze01@arm.com# Redistribution and use in source and binary forms, with or without
1414039Sstacze01@arm.com# modification, are permitted provided that the following conditions are
1514039Sstacze01@arm.com# met: redistributions of source code must retain the above copyright
1614039Sstacze01@arm.com# notice, this list of conditions and the following disclaimer;
1714039Sstacze01@arm.com# redistributions in binary form must reproduce the above copyright
1814039Sstacze01@arm.com# notice, this list of conditions and the following disclaimer in the
1914039Sstacze01@arm.com# documentation and/or other materials provided with the distribution;
2014039Sstacze01@arm.com# neither the name of the copyright holders nor the names of its
2114039Sstacze01@arm.com# contributors may be used to endorse or promote products derived from
2214039Sstacze01@arm.com# this software without specific prior written permission.
2314039Sstacze01@arm.com#
2414039Sstacze01@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2514039Sstacze01@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2614039Sstacze01@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2714039Sstacze01@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2814039Sstacze01@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2914039Sstacze01@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3014039Sstacze01@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3114039Sstacze01@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3214039Sstacze01@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3314039Sstacze01@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3414039Sstacze01@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3514039Sstacze01@arm.com#
3614039Sstacze01@arm.com# Authors: Stan Czerniawski
3714039Sstacze01@arm.com#          Giacomo Travaglini
3814039Sstacze01@arm.com
3914039Sstacze01@arm.comfrom m5.params import *
4014039Sstacze01@arm.comfrom m5.proxy import *
4114039Sstacze01@arm.comfrom m5.util.fdthelper import *
4214039Sstacze01@arm.comfrom m5.SimObject import *
4314252Sgabeblack@google.comfrom m5.objects.ClockedObject import ClockedObject
4414039Sstacze01@arm.com
4514252Sgabeblack@google.comclass SMMUv3SlaveInterface(ClockedObject):
4614039Sstacze01@arm.com    type = 'SMMUv3SlaveInterface'
4714039Sstacze01@arm.com    cxx_header = 'dev/arm/smmu_v3_slaveifc.hh'
4814039Sstacze01@arm.com
4914039Sstacze01@arm.com    slave = SlavePort('Device port')
5014039Sstacze01@arm.com    ats_master = MasterPort('ATS master port')
5114039Sstacze01@arm.com    ats_slave  = SlavePort('ATS slave port')
5214039Sstacze01@arm.com
5314039Sstacze01@arm.com    port_width = Param.Unsigned(16, 'Port width in bytes (= 1 beat)')
5414039Sstacze01@arm.com    wrbuf_slots = Param.Unsigned(16, 'Write buffer size (in beats)')
5514039Sstacze01@arm.com    xlate_slots = Param.Unsigned(16, 'Translation slots')
5614039Sstacze01@arm.com
5714039Sstacze01@arm.com    utlb_entries = Param.Unsigned(32, 'Micro TLB size (entries)')
5814039Sstacze01@arm.com    utlb_assoc = Param.Unsigned(0, 'Micro TLB associativity (0=full)')
5914039Sstacze01@arm.com    utlb_policy = Param.String('rr', 'Micro TLB replacement policy')
6014039Sstacze01@arm.com    utlb_enable = Param.Bool(True, 'Micro TLB enable')
6114039Sstacze01@arm.com    utlb_lat = Param.Cycles(1, 'Micro TLB lookup latency')
6214039Sstacze01@arm.com    utlb_slots = Param.Cycles(1, 'Micro TLB lookup slots')
6314039Sstacze01@arm.com
6414039Sstacze01@arm.com    tlb_entries = Param.Unsigned(2048, 'Main TLB size (entries)')
6514039Sstacze01@arm.com    tlb_assoc = Param.Unsigned(4, 'Main TLB associativity (0=full)')
6614039Sstacze01@arm.com    tlb_policy = Param.String('rr', 'Main TLB replacement policy')
6714039Sstacze01@arm.com    tlb_enable = Param.Bool(True, 'Main TLB enable')
6814039Sstacze01@arm.com    tlb_lat = Param.Cycles(3, 'Main TLB lookup latency')
6914039Sstacze01@arm.com    tlb_slots = Param.Cycles(3, 'Main TLB lookup slots')
7014039Sstacze01@arm.com
7114039Sstacze01@arm.com    prefetch_enable = Param.Bool(False,
7214039Sstacze01@arm.com        'Enable prefetch')
7314039Sstacze01@arm.com    prefetch_reserve_last_way = Param.Bool(True,
7414039Sstacze01@arm.com        'Reserve last way of the main TLB for prefetched entries')
7514039Sstacze01@arm.com
7614252Sgabeblack@google.comclass SMMUv3(ClockedObject):
7714039Sstacze01@arm.com    type = 'SMMUv3'
7814039Sstacze01@arm.com    cxx_header = 'dev/arm/smmu_v3.hh'
7914039Sstacze01@arm.com
8014039Sstacze01@arm.com    master = MasterPort('Master port')
8114039Sstacze01@arm.com    master_walker = MasterPort(
8214039Sstacze01@arm.com        'Master port for SMMU initiated HWTW requests (optional)')
8314039Sstacze01@arm.com    control = SlavePort('Control port for accessing memory-mapped registers')
8414039Sstacze01@arm.com    sample_period = Param.Clock('10us', 'Stats sample period')
8514039Sstacze01@arm.com    reg_map = Param.AddrRange('Address range for control registers')
8614039Sstacze01@arm.com    system = Param.System(Parent.any, "System this device is part of")
8714039Sstacze01@arm.com
8814039Sstacze01@arm.com    slave_interfaces = VectorParam.SMMUv3SlaveInterface([], "Slave interfaces")
8914039Sstacze01@arm.com
9014039Sstacze01@arm.com    # SLAVE INTERFACE<->SMMU link parameters
9114039Sstacze01@arm.com    ifc_smmu_lat = Param.Cycles(8, 'IFC to SMMU communication latency')
9214039Sstacze01@arm.com    smmu_ifc_lat = Param.Cycles(8, 'SMMU to IFC communication latency')
9314039Sstacze01@arm.com
9414039Sstacze01@arm.com    # SMMU parameters
9514039Sstacze01@arm.com    xlate_slots = Param.Unsigned(64, 'SMMU translation slots')
9614039Sstacze01@arm.com    ptw_slots = Param.Unsigned(16, 'SMMU page table walk slots')
9714039Sstacze01@arm.com
9814039Sstacze01@arm.com    master_port_width = Param.Unsigned(16,
9914039Sstacze01@arm.com        'Master port width in bytes (= 1 beat)')
10014039Sstacze01@arm.com
10114039Sstacze01@arm.com    tlb_entries = Param.Unsigned(2048, 'TLB size (entries)')
10214039Sstacze01@arm.com    tlb_assoc = Param.Unsigned(4, 'TLB associativity (0=full)')
10314039Sstacze01@arm.com    tlb_policy = Param.String('rr', 'TLB replacement policy')
10414039Sstacze01@arm.com    tlb_enable = Param.Bool(False, 'TLB enable')
10514039Sstacze01@arm.com    tlb_lat = Param.Cycles(3, 'TLB lookup latency')
10614039Sstacze01@arm.com    tlb_slots = Param.Cycles(3, 'TLB lookup slots')
10714039Sstacze01@arm.com
10814039Sstacze01@arm.com    cfg_entries = Param.Unsigned(64, 'Config cache size (entries)')
10914039Sstacze01@arm.com    cfg_assoc = Param.Unsigned(4, 'Config cache associativity (0=full)')
11014039Sstacze01@arm.com    cfg_policy = Param.String('rr', 'Config cache replacement policy')
11114039Sstacze01@arm.com    cfg_enable = Param.Bool(True, 'Config cache enable')
11214039Sstacze01@arm.com    cfg_lat = Param.Cycles(3, 'Config cache lookup latency')
11314039Sstacze01@arm.com    cfg_slots = Param.Cycles(3, 'Config cache lookup slots')
11414039Sstacze01@arm.com
11514039Sstacze01@arm.com    ipa_entries = Param.Unsigned(128, 'IPA cache size (entries)')
11614039Sstacze01@arm.com    ipa_assoc = Param.Unsigned(4, 'IPA cache associativity (0=full)')
11714039Sstacze01@arm.com    ipa_policy = Param.String('rr', 'IPA cache replacement policy')
11814039Sstacze01@arm.com    ipa_enable = Param.Bool(False, 'IPA cache enable')
11914039Sstacze01@arm.com    ipa_lat = Param.Cycles(3, 'IPA cache lookup lantency')
12014039Sstacze01@arm.com    ipa_slots = Param.Cycles(3, 'IPA cache lookup slots')
12114039Sstacze01@arm.com
12214039Sstacze01@arm.com    walk_S1L0 = Param.Unsigned(4, 'Walk cache S1L0 size (entries)')
12314039Sstacze01@arm.com    walk_S1L1 = Param.Unsigned(28, 'Walk cache S1L1 size (entries)')
12414039Sstacze01@arm.com    walk_S1L2 = Param.Unsigned(348, 'Walk cache S1L2 size (entries)')
12514039Sstacze01@arm.com    walk_S1L3 = Param.Unsigned(4, 'Walk cache S1L3 size (entries)')
12614039Sstacze01@arm.com    walk_S2L0 = Param.Unsigned(4, 'Walk cache S2L0 size (entries)')
12714039Sstacze01@arm.com    walk_S2L1 = Param.Unsigned(28, 'Walk cache S2L1 size (entries)')
12814039Sstacze01@arm.com    walk_S2L2 = Param.Unsigned(92, 'Walk cache S2L2 size (entries)')
12914039Sstacze01@arm.com    walk_S2L3 = Param.Unsigned(4, 'Walk cache S2L3 size (entries)')
13014039Sstacze01@arm.com    walk_assoc = Param.Unsigned(4, 'Walk cache associativity (0=full)')
13114039Sstacze01@arm.com    walk_policy = Param.String('rr', 'Walk cache replacement policy')
13214039Sstacze01@arm.com    walk_enable = Param.Bool(True, 'Walk cache enable')
13314039Sstacze01@arm.com    wc_nonfinal_enable = Param.Bool(False,
13414039Sstacze01@arm.com        'Nonfinal translations use walk cache')
13514039Sstacze01@arm.com    wc_s1_levels = Param.Unsigned(7,
13614039Sstacze01@arm.com        'S1 PT levels cached in walk cache (bit 0 is L0, bit 1 is L1, etc)')
13714039Sstacze01@arm.com    wc_s2_levels = Param.Unsigned(7,
13814039Sstacze01@arm.com        'S2 PT levels cached in walk cache (bit 0 is L0, bit 1 is L1, etc)')
13914039Sstacze01@arm.com
14014039Sstacze01@arm.com    walk_lat   = Param.Cycles(4, 'Walk cache lookup latency')
14114039Sstacze01@arm.com    walk_slots = Param.Cycles(4, 'Walk cache lookup slots')
14214039Sstacze01@arm.com
14314039Sstacze01@arm.com    # [28:27] ST_LEVEL = 0b01, 2-level Stream Table supported in addition
14414039Sstacze01@arm.com    # to Linear Stream table.
14514039Sstacze01@arm.com    # [25:24] STALL_MODEL = 0b01, Stall is not supported, all faults
14614039Sstacze01@arm.com    # terminate transaction.
14714039Sstacze01@arm.com    # [22:21] TTENDIAN = 0b10, Endianness support for translation table walks
14814039Sstacze01@arm.com    # (0b10 = Little-endian).
14914039Sstacze01@arm.com    # [19] CD2L = 0b1, 2-level CD table supported.
15014039Sstacze01@arm.com    # [18] VMID16 = 0b1, 16-bit VMID supported.
15114039Sstacze01@arm.com    # [12] ASID16 = 0b1, 16-bit ASID supported.
15214039Sstacze01@arm.com    # [3:2] TTF = 0b10, Translation Table Formats (Stage 1/2)
15314039Sstacze01@arm.com    # (0b10 = AArch64).
15414039Sstacze01@arm.com    # [1] S1P = 0b1, Stage 1 translation supported.
15514039Sstacze01@arm.com    # [0] S2P = 0b1, Stage 2 translation supported.
15614039Sstacze01@arm.com    smmu_idr0 = Param.UInt32(0x094C100F, "SMMU_IDR0 register");
15714039Sstacze01@arm.com
15814039Sstacze01@arm.com    # [25:21] CMDQS = 0b00101, Maximum number of Command queue entries
15914039Sstacze01@arm.com    # as log 2 (entries) (0b00101 = 32 entries).
16014039Sstacze01@arm.com    smmu_idr1 = Param.UInt32(0x00A00000, "SMMU_IDR1 register");
16114039Sstacze01@arm.com
16214039Sstacze01@arm.com    smmu_idr2 = Param.UInt32(0, "SMMU_IDR2 register");
16314039Sstacze01@arm.com    smmu_idr3 = Param.UInt32(0, "SMMU_IDR3 register");
16414039Sstacze01@arm.com    smmu_idr4 = Param.UInt32(0, "SMMU_IDR4 register");
16514039Sstacze01@arm.com
16614039Sstacze01@arm.com    # [6] GRAN64K = 0b1, 64KB translation granule supported.
16714039Sstacze01@arm.com    # [4] GRAN4K = 0b1, 4KB translation granule supported.
16814039Sstacze01@arm.com    # [2:0] OAS = 0b101, Output Address Size (0b101 = 48-bit).
16914039Sstacze01@arm.com    smmu_idr5 = Param.UInt32(0x55, "SMMU_IDR5 register");
17014039Sstacze01@arm.com    smmu_iidr = Param.UInt32(0, "SMMU_IIDR register");
17114039Sstacze01@arm.com
17214039Sstacze01@arm.com    # [7:0] (0 = SMMUv3.0) (1 = SMMUv3.1)
17314039Sstacze01@arm.com    smmu_aidr = Param.UInt32(0, "SMMU_AIDR register");
17414039Sstacze01@arm.com
17514039Sstacze01@arm.com    def generateDeviceTree(self, state):
17614039Sstacze01@arm.com        reg_addr = self.reg_map.start
17714039Sstacze01@arm.com        reg_size = self.reg_map.size()
17814039Sstacze01@arm.com        node = FdtNode("smmuv3@%x" % long(reg_addr))
17914039Sstacze01@arm.com        node.appendCompatible("arm,smmu-v3")
18014039Sstacze01@arm.com        node.append(FdtPropertyWords("reg",
18114039Sstacze01@arm.com            state.addrCells(reg_addr) +
18214039Sstacze01@arm.com            state.sizeCells(reg_size)))
18314039Sstacze01@arm.com        node.append(FdtPropertyWords("#iommu-cells", [1]))
18414039Sstacze01@arm.com
18514039Sstacze01@arm.com        node.appendPhandle(self)
18614039Sstacze01@arm.com        yield node
18714039Sstacze01@arm.com
18814039Sstacze01@arm.com    def connect(self, device, bus):
18914039Sstacze01@arm.com        """
19014039Sstacze01@arm.com        Helper method used to connect the SMMU. The master could
19114039Sstacze01@arm.com        be either a dma port (if the SMMU is attached directly to a
19214039Sstacze01@arm.com        dma device), or to a master port (this is the case where the SMMU
19314039Sstacze01@arm.com        is attached to a bridge).
19414039Sstacze01@arm.com        """
19514039Sstacze01@arm.com
19614039Sstacze01@arm.com        self.master = bus.slave
19714039Sstacze01@arm.com        self.control = bus.master
19814039Sstacze01@arm.com
19914039Sstacze01@arm.com        slave_interface = SMMUv3SlaveInterface()
20014039Sstacze01@arm.com
20114039Sstacze01@arm.com        if hasattr(device, "master"):
20214039Sstacze01@arm.com            slave_interface.slave = device.master
20314039Sstacze01@arm.com        elif hasattr(device, "dma"):
20414039Sstacze01@arm.com            slave_interface.slave = device.dma
20514039Sstacze01@arm.com        else:
20614039Sstacze01@arm.com            print("Unable to attach SMMUv3\n")
20714039Sstacze01@arm.com            sys.exit(1)
20814039Sstacze01@arm.com
20914039Sstacze01@arm.com        self.slave_interfaces.append(slave_interface)
21014273Sgiacomo.travaglini@arm.com
21114273Sgiacomo.travaglini@arm.com        # Storing a reference to the smmu to be used when generating
21214273Sgiacomo.travaglini@arm.com        # the binding in the device DTB.
21314273Sgiacomo.travaglini@arm.com        device._iommu = self
214