Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / ilu_peu / vera / N2fc / N2fcIommuMgr.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2fcIommuMgr.vr
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35#include <vera_defines.vrh>
36
37// model some of the NCU/PIU CSRs
38//extern N2fcPiuShadowRegs PiuCsrs;
39
40// This is for accessing MEMORY
41//#include "niu_mem.vrh"
42//extern CSparseMem SparseMem;
43
44class N2fcIommuMgr {
45
46 // bits in the MMU CONTROL reg
47 bit process_disable = 0;
48 bit snoop_en = 0;
49 bit [1:0] cache_mode = 0;
50 bit busid_sel = 0;
51 bit sun4v_en = 0;
52 bit bypass_en = 0;
53 bit translation_en = 0;
54
55 bit tsb_valid = 0;
56 bit [38:0] tsb_pa = 0;
57 bit [26:0] tsb_offset = 0;
58 bit [2:0] tsb_pgsz = 0;
59 bit [3:0] tsb_tblsz = 0;
60
61
62 bit iotte_valid = 0;
63 bit iotte_write = 0;
64 bit iotte_keyvld = 0;
65 bit [38:0] iotte_datapa = 0;
66 bit [2:0] iotte_fnm = 0;
67 bit [15:0] iotte_devkey = 0;
68
69
70 bit msi = 0;
71
72 // ******************************************************************
73 // Methods
74 // ******************************************************************
75
76 public task new ();
77
78 function bit get_physical_address(bit [63:0] va, var bit [39:0] pa, bit [7:0] busid, bit dmawr);
79 function bit get_sun4v_pa (bit [63:0] va, var bit [39:0] pa, bit [7:0] busid, bit dmawr);
80
81 // helper functions
82 function bit is_bypass_mode(bit [63:0] va);
83 function bit is_sun4u_mode(bit [63:0] va);
84 function bit is_sun4v_mode(bit [63:0] va);
85
86 task get_mmu_cntl_reg();
87 function bit [ 4:0] get_iotsb_no(bit [7:0] busid, bit va_bit63 );
88 function bit [63:0] get_sun4v_tsb(bit [4:0] iotsb_no );
89 function bit [63:0] get_iotte(bit [38:0] iotte_pa );
90
91 task set_msi(bit a_msi ) { msi = a_msi; }
92
93}
94
95//--------------------------------------------------------------------
96// Method Name: new()
97// Description: initialize iommu mgr
98//--------------------------------------------------------------------
99task N2fcIommuMgr::new()
100{
101 get_mmu_cntl_reg();
102}
103
104
105//--------------------------------------------------------------------
106// Method Name: get_mmu_cntl_reg()
107// Description: initialize iommu control bits
108//--------------------------------------------------------------------
109task N2fcIommuMgr::get_mmu_cntl_reg()
110{
111 // load up the control bits from the MMU CONTROL reg
112 process_disable = PiuCsrs.IoMmuControl[12];
113 snoop_en = PiuCsrs.IoMmuControl[10];
114 cache_mode = PiuCsrs.IoMmuControl[9:8];
115 busid_sel = PiuCsrs.IoMmuControl[3];
116 sun4v_en = PiuCsrs.IoMmuControl[2];
117 bypass_en = PiuCsrs.IoMmuControl[1];
118 translation_en = PiuCsrs.IoMmuControl[0];
119}
120
121
122//--------------------------------------------------------------------
123// Method Name: get_physical_address
124// Description: return physical address, and whether it is valid
125//--------------------------------------------------------------------
126function bit N2fcIommuMgr::get_physical_address( bit [63:0] va,
127 var bit [39:0] pa,
128 bit [7:0] busid,
129 bit dmawr )
130{
131 get_physical_address = 0;
132 if (is_bypass_mode(va)) {
133 pa = va[39:0];
134 get_physical_address = 1;
135 }
136 else if (is_sun4u_mode(va)) {
137 printf("N2fcIommuMgr::get_physical_address sun4u mode support not ready yet, assumming V==R %0h\n", va);
138 pa = va[39:0];
139 get_physical_address = 1;
140 }
141 else if (is_sun4v_mode(va)) {
142 get_physical_address = get_sun4v_pa(va, pa, busid, dmawr);
143 }
144 else {
145 printf("N2fcIommuMgr::get_physical_address %0h is not bypass, sun4u or sun4v. Probably an error.\n", va);
146 }
147}
148
149//--------------------------------------------------------------------
150// Method Name: get_sun4v_pa
151// Description: perform sun4v translation to get physical address
152//--------------------------------------------------------------------
153function bit N2fcIommuMgr::get_sun4v_pa( bit [63:0] va,
154 var bit [39:0] pa,
155 bit [7:0] busid,
156 bit dmawr)
157{
158 bit [4:0] iotsb_no = get_iotsb_no(busid, va[63]);
159 bit [63:0] tsb;
160 bit [38:0] iotte_pa;
161 bit [38:0] num_pages;
162 bit [63:0] iotte;
163 bit [38:0] byte_offset, byte_offset_mask;
164
165 get_sun4v_pa = 0;
166 tsb = get_sun4v_tsb(iotsb_no);
167
168 if (!tsb_valid) {
169 printf("N2fcIommuMgr::get_sun4v_pa tsb valid bit is 0. tsb is %h\n", tsb);
170 return;
171 }
172
173 if ((tsb_pgsz == 3'b010) || (tsb_pgsz == 3'b100) || (tsb_pgsz == 3'b110) || (tsb_pgsz == 3'b111) ) {
174 printf("N2fcIommuMgr::get_sun4v_pa invalid page size (%h) specified. tsb is %h\n", tsb_pgsz, tsb);
175 return;
176 }
177
178 // calculate the iotte address
179 iotte_pa = va[39:0] >> (13 + 3*tsb_pgsz);
180 if ( iotte_pa < tsb_offset ) {
181 printf("N2fcIommuMgr::get_sun4v_pa underflow subtracting offset %h from iotte_pa %h\n", tsb_offset, iotte_pa);
182 return;
183 }
184 iotte_pa = iotte_pa - tsb_offset; // this is the Adjusted Page Number
185
186 num_pages = 32'h400 << tsb_tblsz; // 11'b100_0000_0000 << tsb_tblsz;
187 if ( iotte_pa > num_pages) {
188 printf("N2fcIommuMgr::get_sun4v_pa adjusted page number (%h) out of range: num pages %h\n", iotte_pa, num_pages);
189 return;
190 }
191
192 iotte_pa = (iotte_pa << 3) + tsb_pa;
193
194 // get the iotte from dram memory
195 iotte = get_iotte(iotte_pa);
196
197 if ( !iotte_valid ) {
198 printf("N2fcIommuMgr::get_sun4v_pa iotte valid bit is not 1. iotte is %h @ %h\n", iotte, iotte_pa);
199 return;
200 }
201
202 if ( !iotte_write && dmawr ) {
203 printf("N2fcIommuMgr::get_sun4v_pa write bit is 0 for dma write. iotte is %h @ %h\n", iotte, iotte_pa);
204 return;
205 }
206
207 if ( iotte_keyvld ) {
208 printf("N2fcIommuMgr::get_sun4v_pa KEY_VLD not supportted yet. iotte is %h @ %h\n", iotte, iotte_pa);
209 //return;
210 }
211
212 // or the lower bits of the va with the iotte_datapa, and we're done!
213 byte_offset_mask = (1 << (13 + 3*tsb_pgsz)) - 1;
214 byte_offset = va & byte_offset_mask;
215 pa = iotte_datapa | byte_offset;
216 printf("N2fcIommuMgr::get_sun4v_pa va %0h => pa %0h\n", va, pa);
217 get_sun4v_pa = 1;
218}
219
220//--------------------------------------------------------------------
221// Method Name: is_bypass_mode
222// Description: return 1 if va is a bypass address and bypass is enabled
223// If this is an MSI address, then
224// bypass does not have to be enabled).
225//--------------------------------------------------------------------
226function bit N2fcIommuMgr::is_bypass_mode(bit [63:0] va)
227{
228 if ((bypass_en || msi) && (va[63:39] == 25'h1fff800))
229 is_bypass_mode = 1;
230 else
231 is_bypass_mode = 0;
232}
233
234//--------------------------------------------------------------------
235// Method Name: is_sun4u_mode
236// Description: return 1 if va is a virtual address and sun4u is enabled
237//--------------------------------------------------------------------
238function bit N2fcIommuMgr::is_sun4u_mode(bit [63:0] va)
239{
240 if (translation_en && !sun4v_en && (va[63:32] == 32'h0))
241 is_sun4u_mode = 1;
242 else
243 is_sun4u_mode = 0;
244}
245
246//--------------------------------------------------------------------
247// Method Name: is_sun4v_mode
248// Description: return 1 if va is a virtual address and sun4v is enabled
249//--------------------------------------------------------------------
250function bit N2fcIommuMgr::is_sun4v_mode(bit [63:0] va)
251{
252 if (translation_en && sun4v_en && (va[62:40] == 23'h000000))
253 is_sun4v_mode = 1;
254 else
255 is_sun4v_mode = 0;
256}
257
258
259//--------------------------------------------------------------------
260// Method Name: get_iotsb_no
261// Description: return the sunv4 iotsb number based on the busid select,
262// the busid, and VA[63]
263//--------------------------------------------------------------------
264function bit [4:0] N2fcIommuMgr::get_iotsb_no(bit [7:0] busid,
265 bit va_bit63 )
266{
267 bit [ 3:0] dev2iotsb_reg_no = 0;
268 bit [ 2:0] iotsb_no = 0;
269 bit [63:0] temp_dev2iotsb_reg;
270
271 if (busid_sel) {
272 '{dev2iotsb_reg_no,iotsb_no} = {va_bit63,busid[5:0]};
273 }
274 else {
275 '{dev2iotsb_reg_no,iotsb_no} = {va_bit63,busid[6:1]};
276 }
277
278 temp_dev2iotsb_reg = PiuCsrs.IoMmuDev2Iotsb[dev2iotsb_reg_no];
279 get_iotsb_no = temp_dev2iotsb_reg[((iotsb_no+1)*8)-4:(iotsb_no*8)];
280}
281
282
283//--------------------------------------------------------------------
284// Method Name: get_sun4v_tsb
285// Description: return the sunv4 tsb, also break it up into fields
286//--------------------------------------------------------------------
287function bit [63:0] N2fcIommuMgr::get_sun4v_tsb(bit [4:0] iotsb_no )
288{
289 bit [63:0] tsb = PiuCsrs.IoMmuIoTsbDesc[iotsb_no];
290
291 tsb_valid = tsb[63];
292 tsb_pa = {tsb[59:34],13'b0};
293 tsb_offset = tsb[33:7];
294 tsb_pgsz = tsb[6:4];
295 tsb_tblsz = tsb[3:0];
296
297 get_sun4v_tsb = tsb;
298}
299
300//--------------------------------------------------------------------
301// Method Name: get_iotte
302// Description: return the iotte, also break it up into fields
303//--------------------------------------------------------------------
304function bit [63:0] N2fcIommuMgr::get_iotte(bit [38:0] iotte_pa )
305{
306 //bit [63:0] iotte = gMem.read_mem(iotte_pa);
307 bit [63:0] iottele, iotte;
308 SparseMem.ReadMem(iotte_pa, iottele, 8'hff);
309 // ReadMem returns data in little endian format, so do byte swap
310 // so that it maskes sense
311 iotte = {iottele[7:0],iottele[15:8],iottele[23:16],iottele[31:24],
312 iottele[39:32],iottele[47:40],iottele[55:48],iottele[63:56]};
313 iotte_valid = iotte[0];
314 iotte_write = iotte[1];
315 iotte_datapa = {iotte[38:13],13'b0};
316 iotte_fnm = iotte[5:3];
317 iotte_devkey = iotte[63:48];
318 iotte_keyvld = iotte[2];
319
320 get_iotte = iotte;
321}
322