1
2
3
/*
* QEMU SPARC iommu emulation
*
4
* Copyright ( c ) 2003 - 2005 Fabrice Bellard
ths
authored
18 years ago
5
*
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the "Software" ), to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
24
25
# include "sun4m.h"
26
# include "sysbus.h"
27
28
29
30
/* debug iommu */
// # define DEBUG_IOMMU
31
# ifdef DEBUG_IOMMU
32
33
# define DPRINTF ( fmt , ...) \
do { printf ( "IOMMU: " fmt , ## __VA_ARGS__ ); } while ( 0 )
34
# else
35
# define DPRINTF ( fmt , ...)
36
# endif
37
38
# define IOMMU_NREGS ( 4 * 4096 / 4 )
39
# define IOMMU_CTRL ( 0x0000 >> 2 )
40
41
42
43
44
45
46
47
48
49
50
51
# define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
# define IOMMU_CTRL_VERS 0x0f000000 /* Version */
# define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
# define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
# define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
# define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
# define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
# define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
# define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
# define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
# define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
# define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
52
53
54
55
56
57
58
59
60
61
62
# define IOMMU_CTRL_MASK 0x0000001d
# define IOMMU_BASE ( 0x0004 >> 2 )
# define IOMMU_BASE_MASK 0x07fffc00
# define IOMMU_TLBFLUSH ( 0x0014 >> 2 )
# define IOMMU_TLBFLUSH_MASK 0xffffffff
# define IOMMU_PGFLUSH ( 0x0018 >> 2 )
# define IOMMU_PGFLUSH_MASK 0xffffffff
63
64
# define IOMMU_AFSR ( 0x1000 >> 2 )
# define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
65
66
67
68
69
70
# define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after
transaction */
# define IOMMU_AFSR_TO 0x20000000 /* Write access took more than
12 . 8 us . */
# define IOMMU_AFSR_BE 0x10000000 /* Write access received error
acknowledge */
71
72
# define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
# define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
73
74
# define IOMMU_AFSR_RESV 0x00800000 /* Reserved , forced to 0x8 by
hardware */
75
76
77
# define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
# define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
# define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
78
# define IOMMU_AFSR_MASK 0xff0fffff
79
80
81
# define IOMMU_AFAR ( 0x1004 >> 2 )
82
83
84
85
86
87
88
89
90
91
92
93
94
# define IOMMU_AER ( 0x1008 >> 2 ) /* Arbiter Enable Register */
# define IOMMU_AER_EN_P0_ARB 0x00000001 /* MBus master 0x8 (Always 1) */
# define IOMMU_AER_EN_P1_ARB 0x00000002 /* MBus master 0x9 */
# define IOMMU_AER_EN_P2_ARB 0x00000004 /* MBus master 0xa */
# define IOMMU_AER_EN_P3_ARB 0x00000008 /* MBus master 0xb */
# define IOMMU_AER_EN_0 0x00010000 /* SBus slot 0 */
# define IOMMU_AER_EN_1 0x00020000 /* SBus slot 1 */
# define IOMMU_AER_EN_2 0x00040000 /* SBus slot 2 */
# define IOMMU_AER_EN_3 0x00080000 /* SBus slot 3 */
# define IOMMU_AER_EN_F 0x00100000 /* SBus on-board */
# define IOMMU_AER_SBW 0x80000000 /* S-to-M asynchronous writes */
# define IOMMU_AER_MASK 0x801f000f
95
96
97
98
# define IOMMU_SBCFG0 ( 0x1010 >> 2 ) /* SBUS configration per-slot */
# define IOMMU_SBCFG1 ( 0x1014 >> 2 ) /* SBUS configration per-slot */
# define IOMMU_SBCFG2 ( 0x1018 >> 2 ) /* SBUS configration per-slot */
# define IOMMU_SBCFG3 ( 0x101c >> 2 ) /* SBUS configration per-slot */
99
100
# define IOMMU_SBCFG_SAB30 0x00010000 /* Phys - address bit 30 when
bypass enabled */
101
102
103
# define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
# define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
# define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU , treat all addresses
104
produced by this device as pure
105
106
107
108
109
110
physical . */
# define IOMMU_SBCFG_MASK 0x00010003
# define IOMMU_ARBEN ( 0x2000 >> 2 ) /* SBUS arbitration enable */
# define IOMMU_ARBEN_MASK 0x001f0000
# define IOMMU_MID 0x00000008
111
112
113
114
115
116
117
# define IOMMU_MASK_ID ( 0x3018 >> 2 ) /* Mask ID */
# define IOMMU_MASK_ID_MASK 0x00ffffff
# define IOMMU_MSII_MASK 0x26000000 /* microSPARC II mask number */
# define IOMMU_TS_MASK 0x23000000 /* turboSPARC mask number */
118
/* The format of an iopte in the page tables */
119
# define IOPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
120
121
# define IOPTE_CACHE 0x00000080 /* Cached ( in vme IOCACHE or
Viking / MXCC ) */
122
123
124
125
# define IOPTE_WRITE 0x00000004 /* Writeable */
# define IOPTE_VALID 0x00000002 /* IOPTE is valid */
# define IOPTE_WAZ 0x00000001 /* Write as zeros */
126
127
128
# define IOMMU_PAGE_SHIFT 12
# define IOMMU_PAGE_SIZE ( 1 << IOMMU_PAGE_SHIFT )
# define IOMMU_PAGE_MASK ~ ( IOMMU_PAGE_SIZE - 1 )
129
130
typedef struct IOMMUState {
131
SysBusDevice busdev ;
132
uint32_t regs [ IOMMU_NREGS ];
133
target_phys_addr_t iostart ;
134
uint32_t version ;
135
qemu_irq irq ;
136
137
} IOMMUState ;
138
static uint32_t iommu_mem_readl ( void * opaque , target_phys_addr_t addr )
139
140
{
IOMMUState * s = opaque ;
141
target_phys_addr_t saddr ;
142
uint32_t ret ;
143
144
saddr = addr >> 2 ;
145
146
switch ( saddr ) {
default :
147
148
149
150
151
152
ret = s -> regs [ saddr ];
break ;
case IOMMU_AFAR :
case IOMMU_AFSR :
ret = s -> regs [ saddr ];
qemu_irq_lower ( s -> irq );
153
break ;
154
}
155
156
DPRINTF ( "read reg[%d] = %x \n " , ( int ) saddr , ret );
return ret ;
157
158
}
159
static void iommu_mem_writel ( void * opaque , target_phys_addr_t addr ,
160
uint32_t val )
161
162
{
IOMMUState * s = opaque ;
163
target_phys_addr_t saddr ;
164
165
saddr = addr >> 2 ;
166
DPRINTF ( "write reg[%d] = %x \n " , ( int ) saddr , val );
167
switch ( saddr ) {
168
case IOMMU_CTRL :
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
switch ( val & IOMMU_CTRL_RNGE ) {
case IOMMU_RNGE_16MB :
s -> iostart = 0xffffffffff000000ULL ;
break ;
case IOMMU_RNGE_32MB :
s -> iostart = 0xfffffffffe000000ULL ;
break ;
case IOMMU_RNGE_64MB :
s -> iostart = 0xfffffffffc000000ULL ;
break ;
case IOMMU_RNGE_128MB :
s -> iostart = 0xfffffffff8000000ULL ;
break ;
case IOMMU_RNGE_256MB :
s -> iostart = 0xfffffffff0000000ULL ;
break ;
case IOMMU_RNGE_512MB :
s -> iostart = 0xffffffffe0000000ULL ;
break ;
case IOMMU_RNGE_1GB :
s -> iostart = 0xffffffffc0000000ULL ;
break ;
default :
case IOMMU_RNGE_2GB :
s -> iostart = 0xffffffff80000000ULL ;
break ;
}
DPRINTF ( "iostart = " TARGET_FMT_plx " \n " , s -> iostart );
197
s -> regs [ saddr ] = (( val & IOMMU_CTRL_MASK ) | s -> version );
198
break ;
199
case IOMMU_BASE :
200
201
s -> regs [ saddr ] = val & IOMMU_BASE_MASK ;
break ;
202
case IOMMU_TLBFLUSH :
203
204
205
DPRINTF ( "tlb flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_TLBFLUSH_MASK ;
break ;
206
case IOMMU_PGFLUSH :
207
208
209
DPRINTF ( "page flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_PGFLUSH_MASK ;
break ;
210
211
212
213
case IOMMU_AFAR :
s -> regs [ saddr ] = val ;
qemu_irq_lower ( s -> irq );
break ;
214
215
216
case IOMMU_AER :
s -> regs [ saddr ] = ( val & IOMMU_AER_MASK ) | IOMMU_AER_EN_P0_ARB ;
break ;
217
218
case IOMMU_AFSR :
s -> regs [ saddr ] = ( val & IOMMU_AFSR_MASK ) | IOMMU_AFSR_RESV ;
219
qemu_irq_lower ( s -> irq );
220
break ;
221
222
223
224
case IOMMU_SBCFG0 :
case IOMMU_SBCFG1 :
case IOMMU_SBCFG2 :
case IOMMU_SBCFG3 :
225
226
s -> regs [ saddr ] = val & IOMMU_SBCFG_MASK ;
break ;
227
228
229
case IOMMU_ARBEN :
// XXX implement SBus probing : fault when reading unmapped
// addresses , fault cause and address stored to MMU / IOMMU
230
231
s -> regs [ saddr ] = ( val & IOMMU_ARBEN_MASK ) | IOMMU_MID ;
break ;
232
233
234
case IOMMU_MASK_ID :
s -> regs [ saddr ] |= val & IOMMU_MASK_ID_MASK ;
break ;
235
default :
236
237
s -> regs [ saddr ] = val ;
break ;
238
239
240
241
}
}
static CPUReadMemoryFunc * iommu_mem_read [ 3 ] = {
242
243
244
NULL ,
NULL ,
iommu_mem_readl ,
245
246
247
};
static CPUWriteMemoryFunc * iommu_mem_write [ 3 ] = {
248
249
250
NULL ,
NULL ,
iommu_mem_writel ,
251
252
};
253
static uint32_t iommu_page_get_flags ( IOMMUState * s , target_phys_addr_t addr )
254
{
255
256
uint32_t ret ;
target_phys_addr_t iopte ;
257
258
259
# ifdef DEBUG_IOMMU
target_phys_addr_t pa = addr ;
# endif
260
261
iopte = s -> regs [ IOMMU_BASE ] << 4 ;
262
addr &= ~ s -> iostart ;
263
iopte += ( addr >> ( IOMMU_PAGE_SHIFT - 2 )) & ~ 3 ;
264
cpu_physical_memory_read ( iopte , ( uint8_t * ) & ret , 4 );
265
tswap32s ( & ret );
266
267
DPRINTF ( "get flags addr " TARGET_FMT_plx " => pte " TARGET_FMT_plx
", *pte = %x \n " , pa , iopte , ret );
268
269
return ret ;
270
271
}
272
static target_phys_addr_t iommu_translate_pa ( target_phys_addr_t addr ,
273
uint32_t pte )
274
275
{
uint32_t tmppte ;
276
277
278
target_phys_addr_t pa ;
tmppte = pte ;
279
pa = (( pte & IOPTE_PAGE ) << 4 ) + ( addr & ~ IOMMU_PAGE_MASK );
280
281
DPRINTF ( "xlate dva " TARGET_FMT_plx " => pa " TARGET_FMT_plx
" (iopte = %x) \n " , addr , pa , tmppte );
282
283
return pa ;
284
285
}
286
287
static void iommu_bad_addr ( IOMMUState * s , target_phys_addr_t addr ,
int is_write )
288
289
{
DPRINTF ( "bad addr " TARGET_FMT_plx " \n " , addr );
290
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_ERR | IOMMU_AFSR_LE | IOMMU_AFSR_RESV |
291
292
293
294
IOMMU_AFSR_FAV ;
if ( ! is_write )
s -> regs [ IOMMU_AFSR ] |= IOMMU_AFSR_RD ;
s -> regs [ IOMMU_AFAR ] = addr ;
295
qemu_irq_raise ( s -> irq );
296
297
}
298
299
void sparc_iommu_memory_rw ( void * opaque , target_phys_addr_t addr ,
uint8_t * buf , int len , int is_write )
300
{
301
302
303
int l ;
uint32_t flags ;
target_phys_addr_t page , phys_addr ;
304
305
while ( len > 0 ) {
306
307
page = addr & IOMMU_PAGE_MASK ;
l = ( page + IOMMU_PAGE_SIZE ) - addr ;
308
309
310
if ( l > len )
l = len ;
flags = iommu_page_get_flags ( opaque , page );
311
312
if ( ! ( flags & IOPTE_VALID )) {
iommu_bad_addr ( opaque , page , is_write );
313
return ;
314
}
315
phys_addr = iommu_translate_pa ( addr , flags );
316
if ( is_write ) {
317
318
if ( ! ( flags & IOPTE_WRITE )) {
iommu_bad_addr ( opaque , page , is_write );
319
return ;
320
}
321
cpu_physical_memory_write ( phys_addr , buf , l );
322
} else {
323
cpu_physical_memory_read ( phys_addr , buf , l );
324
325
326
327
328
329
330
}
len -= l ;
buf += l ;
addr += l ;
}
}
331
332
333
334
static void iommu_save ( QEMUFile * f , void * opaque )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
18 years ago
335
336
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
337
qemu_put_be32s ( f , & s -> regs [ i ]);
338
qemu_put_be64s ( f , & s -> iostart );
339
340
341
342
343
344
}
static int iommu_load ( QEMUFile * f , void * opaque , int version_id )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
18 years ago
345
346
if ( version_id != 2 )
347
348
return - EINVAL ;
349
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
350
qemu_get_be32s ( f , & s -> regs [ i ]);
351
qemu_get_be64s ( f , & s -> iostart );
352
353
354
355
356
357
358
359
return 0 ;
}
static void iommu_reset ( void * opaque )
{
IOMMUState * s = opaque ;
360
memset ( s -> regs , 0 , IOMMU_NREGS * 4 );
361
s -> iostart = 0 ;
362
363
s -> regs [ IOMMU_CTRL ] = s -> version ;
s -> regs [ IOMMU_ARBEN ] = IOMMU_MID ;
364
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_RESV ;
365
s -> regs [ IOMMU_AER ] = IOMMU_AER_EN_P0_ARB | IOMMU_AER_EN_P1_ARB ;
366
s -> regs [ IOMMU_MASK_ID ] = IOMMU_TS_MASK ;
367
368
}
369
void * iommu_init ( target_phys_addr_t addr , uint32_t version , qemu_irq irq )
370
{
371
372
373
374
375
DeviceState * dev ;
SysBusDevice * s ;
IOMMUState * d ;
dev = qdev_create ( NULL , "iommu" );
376
qdev_prop_set_uint32 ( dev , "version" , version );
377
378
379
380
381
382
383
384
385
386
387
388
389
390
qdev_init ( dev );
s = sysbus_from_qdev ( dev );
sysbus_connect_irq ( s , 0 , irq );
sysbus_mmio_map ( s , 0 , addr );
d = FROM_SYSBUS ( IOMMUState , s );
return d ;
}
static void iommu_init1 ( SysBusDevice * dev )
{
IOMMUState * s = FROM_SYSBUS ( IOMMUState , dev );
int io ;
391
392
sysbus_init_irq ( dev , & s -> irq );
393
394
395
io = cpu_register_io_memory ( iommu_mem_read , iommu_mem_write , s );
sysbus_init_mmio ( dev , IOMMU_NREGS * sizeof ( uint32_t ), io );
ths
authored
18 years ago
396
397
register_savevm ( "iommu" , - 1 , 2 , iommu_save , iommu_load , s );
398
qemu_register_reset ( iommu_reset , s );
399
iommu_reset ( s );
400
}
401
402
403
404
405
static SysBusDeviceInfo iommu_info = {
. init = iommu_init1 ,
. qdev . name = "iommu" ,
. qdev . size = sizeof ( IOMMUState ),
406
407
408
. qdev . props = ( Property []) {
{
. name = "version" ,
409
. info = & qdev_prop_hex32 ,
410
411
412
. offset = offsetof ( IOMMUState , version ),
},
{ /* end of property list */ }
413
414
415
416
417
418
419
420
421
}
};
static void iommu_register_devices ( void )
{
sysbus_register_withprop ( & iommu_info );
}
device_init ( iommu_register_devices )