1# Copyright (c) 2013, 2018-2019 ARM Limited
2# All rights reserved
3#
4# The license below extends only to copyright in the software and shall
5# not be construed as granting a license to any other intellectual
6# property including but not limited to intellectual property relating
7# to a hardware implementation of the functionality of the software
8# licensed hereunder.  You may use the software subject to the license
9# terms below provided that you ensure that this notice is replicated
10# unmodified and in its entirety in all distributions of the software,
11# modified or unmodified, in source code or in binary form.
12#
13# Redistribution and use in source and binary forms, with or without
14# modification, are permitted provided that the following conditions are
15# met: redistributions of source code must retain the above copyright
16# notice, this list of conditions and the following disclaimer;
17# redistributions in binary form must reproduce the above copyright
18# notice, this list of conditions and the following disclaimer in the
19# documentation and/or other materials provided with the distribution;
20# neither the name of the copyright holders nor the names of its
21# contributors may be used to endorse or promote products derived from
22# this software without specific prior written permission.
23#
24# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35#
36# Authors: Stan Czerniawski
37#          Giacomo Travaglini
38
39from m5.params import *
40from m5.proxy import *
41from m5.util.fdthelper import *
42from m5.SimObject import *
43from m5.objects.ClockedObject import ClockedObject
44
45class SMMUv3SlaveInterface(ClockedObject):
46    type = 'SMMUv3SlaveInterface'
47    cxx_header = 'dev/arm/smmu_v3_slaveifc.hh'
48
49    slave = SlavePort('Device port')
50    ats_master = MasterPort('ATS master port')
51    ats_slave  = SlavePort('ATS slave port')
52
53    port_width = Param.Unsigned(16, 'Port width in bytes (= 1 beat)')
54    wrbuf_slots = Param.Unsigned(16, 'Write buffer size (in beats)')
55    xlate_slots = Param.Unsigned(16, 'Translation slots')
56
57    utlb_entries = Param.Unsigned(32, 'Micro TLB size (entries)')
58    utlb_assoc = Param.Unsigned(0, 'Micro TLB associativity (0=full)')
59    utlb_policy = Param.String('rr', 'Micro TLB replacement policy')
60    utlb_enable = Param.Bool(True, 'Micro TLB enable')
61    utlb_lat = Param.Cycles(1, 'Micro TLB lookup latency')
62    utlb_slots = Param.Cycles(1, 'Micro TLB lookup slots')
63
64    tlb_entries = Param.Unsigned(2048, 'Main TLB size (entries)')
65    tlb_assoc = Param.Unsigned(4, 'Main TLB associativity (0=full)')
66    tlb_policy = Param.String('rr', 'Main TLB replacement policy')
67    tlb_enable = Param.Bool(True, 'Main TLB enable')
68    tlb_lat = Param.Cycles(3, 'Main TLB lookup latency')
69    tlb_slots = Param.Cycles(3, 'Main TLB lookup slots')
70
71    prefetch_enable = Param.Bool(False,
72        'Enable prefetch')
73    prefetch_reserve_last_way = Param.Bool(True,
74        'Reserve last way of the main TLB for prefetched entries')
75
76class SMMUv3(ClockedObject):
77    type = 'SMMUv3'
78    cxx_header = 'dev/arm/smmu_v3.hh'
79
80    master = MasterPort('Master port')
81    master_walker = MasterPort(
82        'Master port for SMMU initiated HWTW requests (optional)')
83    control = SlavePort('Control port for accessing memory-mapped registers')
84    sample_period = Param.Clock('10us', 'Stats sample period')
85    reg_map = Param.AddrRange('Address range for control registers')
86    system = Param.System(Parent.any, "System this device is part of")
87
88    slave_interfaces = VectorParam.SMMUv3SlaveInterface([], "Slave interfaces")
89
90    # SLAVE INTERFACE<->SMMU link parameters
91    ifc_smmu_lat = Param.Cycles(8, 'IFC to SMMU communication latency')
92    smmu_ifc_lat = Param.Cycles(8, 'SMMU to IFC communication latency')
93
94    # SMMU parameters
95    xlate_slots = Param.Unsigned(64, 'SMMU translation slots')
96    ptw_slots = Param.Unsigned(16, 'SMMU page table walk slots')
97
98    master_port_width = Param.Unsigned(16,
99        'Master port width in bytes (= 1 beat)')
100
101    tlb_entries = Param.Unsigned(2048, 'TLB size (entries)')
102    tlb_assoc = Param.Unsigned(4, 'TLB associativity (0=full)')
103    tlb_policy = Param.String('rr', 'TLB replacement policy')
104    tlb_enable = Param.Bool(False, 'TLB enable')
105    tlb_lat = Param.Cycles(3, 'TLB lookup latency')
106    tlb_slots = Param.Cycles(3, 'TLB lookup slots')
107
108    cfg_entries = Param.Unsigned(64, 'Config cache size (entries)')
109    cfg_assoc = Param.Unsigned(4, 'Config cache associativity (0=full)')
110    cfg_policy = Param.String('rr', 'Config cache replacement policy')
111    cfg_enable = Param.Bool(True, 'Config cache enable')
112    cfg_lat = Param.Cycles(3, 'Config cache lookup latency')
113    cfg_slots = Param.Cycles(3, 'Config cache lookup slots')
114
115    ipa_entries = Param.Unsigned(128, 'IPA cache size (entries)')
116    ipa_assoc = Param.Unsigned(4, 'IPA cache associativity (0=full)')
117    ipa_policy = Param.String('rr', 'IPA cache replacement policy')
118    ipa_enable = Param.Bool(False, 'IPA cache enable')
119    ipa_lat = Param.Cycles(3, 'IPA cache lookup lantency')
120    ipa_slots = Param.Cycles(3, 'IPA cache lookup slots')
121
122    walk_S1L0 = Param.Unsigned(4, 'Walk cache S1L0 size (entries)')
123    walk_S1L1 = Param.Unsigned(28, 'Walk cache S1L1 size (entries)')
124    walk_S1L2 = Param.Unsigned(348, 'Walk cache S1L2 size (entries)')
125    walk_S1L3 = Param.Unsigned(4, 'Walk cache S1L3 size (entries)')
126    walk_S2L0 = Param.Unsigned(4, 'Walk cache S2L0 size (entries)')
127    walk_S2L1 = Param.Unsigned(28, 'Walk cache S2L1 size (entries)')
128    walk_S2L2 = Param.Unsigned(92, 'Walk cache S2L2 size (entries)')
129    walk_S2L3 = Param.Unsigned(4, 'Walk cache S2L3 size (entries)')
130    walk_assoc = Param.Unsigned(4, 'Walk cache associativity (0=full)')
131    walk_policy = Param.String('rr', 'Walk cache replacement policy')
132    walk_enable = Param.Bool(True, 'Walk cache enable')
133    wc_nonfinal_enable = Param.Bool(False,
134        'Nonfinal translations use walk cache')
135    wc_s1_levels = Param.Unsigned(7,
136        'S1 PT levels cached in walk cache (bit 0 is L0, bit 1 is L1, etc)')
137    wc_s2_levels = Param.Unsigned(7,
138        'S2 PT levels cached in walk cache (bit 0 is L0, bit 1 is L1, etc)')
139
140    walk_lat   = Param.Cycles(4, 'Walk cache lookup latency')
141    walk_slots = Param.Cycles(4, 'Walk cache lookup slots')
142
143    # [28:27] ST_LEVEL = 0b01, 2-level Stream Table supported in addition
144    # to Linear Stream table.
145    # [25:24] STALL_MODEL = 0b01, Stall is not supported, all faults
146    # terminate transaction.
147    # [22:21] TTENDIAN = 0b10, Endianness support for translation table walks
148    # (0b10 = Little-endian).
149    # [19] CD2L = 0b1, 2-level CD table supported.
150    # [18] VMID16 = 0b1, 16-bit VMID supported.
151    # [12] ASID16 = 0b1, 16-bit ASID supported.
152    # [3:2] TTF = 0b10, Translation Table Formats (Stage 1/2)
153    # (0b10 = AArch64).
154    # [1] S1P = 0b1, Stage 1 translation supported.
155    # [0] S2P = 0b1, Stage 2 translation supported.
156    smmu_idr0 = Param.UInt32(0x094C100F, "SMMU_IDR0 register");
157
158    # [25:21] CMDQS = 0b00101, Maximum number of Command queue entries
159    # as log 2 (entries) (0b00101 = 32 entries).
160    smmu_idr1 = Param.UInt32(0x00A00000, "SMMU_IDR1 register");
161
162    smmu_idr2 = Param.UInt32(0, "SMMU_IDR2 register");
163    smmu_idr3 = Param.UInt32(0, "SMMU_IDR3 register");
164    smmu_idr4 = Param.UInt32(0, "SMMU_IDR4 register");
165
166    # [6] GRAN64K = 0b1, 64KB translation granule supported.
167    # [4] GRAN4K = 0b1, 4KB translation granule supported.
168    # [2:0] OAS = 0b101, Output Address Size (0b101 = 48-bit).
169    smmu_idr5 = Param.UInt32(0x55, "SMMU_IDR5 register");
170    smmu_iidr = Param.UInt32(0, "SMMU_IIDR register");
171
172    # [7:0] (0 = SMMUv3.0) (1 = SMMUv3.1)
173    smmu_aidr = Param.UInt32(0, "SMMU_AIDR register");
174
175    def generateDeviceTree(self, state):
176        reg_addr = self.reg_map.start
177        reg_size = self.reg_map.size()
178        node = FdtNode("smmuv3@%x" % long(reg_addr))
179        node.appendCompatible("arm,smmu-v3")
180        node.append(FdtPropertyWords("reg",
181            state.addrCells(reg_addr) +
182            state.sizeCells(reg_size)))
183        node.append(FdtPropertyWords("#iommu-cells", [1]))
184
185        node.appendPhandle(self)
186        yield node
187
188    def connect(self, device, bus):
189        """
190        Helper method used to connect the SMMU. The master could
191        be either a dma port (if the SMMU is attached directly to a
192        dma device), or to a master port (this is the case where the SMMU
193        is attached to a bridge).
194        """
195
196        self.master = bus.slave
197        self.control = bus.master
198
199        slave_interface = SMMUv3SlaveInterface()
200
201        if hasattr(device, "master"):
202            slave_interface.slave = device.master
203        elif hasattr(device, "dma"):
204            slave_interface.slave = device.dma
205        else:
206            print("Unable to attach SMMUv3\n")
207            sys.exit(1)
208
209        self.slave_interfaces.append(slave_interface)
210
211        # Storing a reference to the smmu to be used when generating
212        # the binding in the device DTB.
213        device._iommu = self
214