1
2
3
/*
* QEMU SPARC iommu emulation
*
4
* Copyright ( c ) 2003 - 2005 Fabrice Bellard
ths
authored
17 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 "hw.h"
# include "sun4m.h"
26
27
28
29
/* debug iommu */
// # define DEBUG_IOMMU
30
31
32
33
34
35
# ifdef DEBUG_IOMMU
# define DPRINTF ( fmt , args ...) \
do { printf ( "IOMMU: " fmt , ## args ); } while ( 0 )
# else
# define DPRINTF ( fmt , args ...)
# endif
36
37
# define IOMMU_NREGS ( 4 * 4096 / 4 )
38
# define IOMMU_CTRL ( 0x0000 >> 2 )
39
40
41
42
43
44
45
46
47
48
49
50
# 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 */
51
52
53
54
55
56
57
58
59
60
61
# 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
62
63
# define IOMMU_AFSR ( 0x1000 >> 2 )
# define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
64
65
66
67
68
69
# 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 */
70
71
# define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
# define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
72
73
# define IOMMU_AFSR_RESV 0x00800000 /* Reserved , forced to 0x8 by
hardware */
74
75
76
# 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 */
77
# define IOMMU_AFSR_MASK 0xff0fffff
78
79
80
# define IOMMU_AFAR ( 0x1004 >> 2 )
81
82
83
84
85
86
87
88
89
90
91
92
93
# 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
94
95
96
97
# 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 */
98
99
# define IOMMU_SBCFG_SAB30 0x00010000 /* Phys - address bit 30 when
bypass enabled */
100
101
102
# 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
103
produced by this device as pure
104
105
106
107
108
109
physical . */
# define IOMMU_SBCFG_MASK 0x00010003
# define IOMMU_ARBEN ( 0x2000 >> 2 ) /* SBUS arbitration enable */
# define IOMMU_ARBEN_MASK 0x001f0000
# define IOMMU_MID 0x00000008
110
111
112
113
114
115
116
# 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 */
117
/* The format of an iopte in the page tables */
118
# define IOPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
119
120
# define IOPTE_CACHE 0x00000080 /* Cached ( in vme IOCACHE or
Viking / MXCC ) */
121
122
123
124
# define IOPTE_WRITE 0x00000004 /* Writeable */
# define IOPTE_VALID 0x00000002 /* IOPTE is valid */
# define IOPTE_WAZ 0x00000001 /* Write as zeros */
125
126
127
# define IOMMU_PAGE_SHIFT 12
# define IOMMU_PAGE_SIZE ( 1 << IOMMU_PAGE_SHIFT )
# define IOMMU_PAGE_MASK ~ ( IOMMU_PAGE_SIZE - 1 )
128
129
typedef struct IOMMUState {
130
uint32_t regs [ IOMMU_NREGS ];
131
target_phys_addr_t iostart ;
132
uint32_t version ;
133
qemu_irq irq ;
134
135
} IOMMUState ;
136
static uint32_t iommu_mem_readl ( void * opaque , target_phys_addr_t addr )
137
138
{
IOMMUState * s = opaque ;
139
target_phys_addr_t saddr ;
140
uint32_t ret ;
141
142
saddr = addr >> 2 ;
143
144
switch ( saddr ) {
default :
145
146
147
148
149
150
ret = s -> regs [ saddr ];
break ;
case IOMMU_AFAR :
case IOMMU_AFSR :
ret = s -> regs [ saddr ];
qemu_irq_lower ( s -> irq );
151
break ;
152
}
153
154
DPRINTF ( "read reg[%d] = %x \n " , ( int ) saddr , ret );
return ret ;
155
156
}
157
static void iommu_mem_writel ( void * opaque , target_phys_addr_t addr ,
158
uint32_t val )
159
160
{
IOMMUState * s = opaque ;
161
target_phys_addr_t saddr ;
162
163
saddr = addr >> 2 ;
164
DPRINTF ( "write reg[%d] = %x \n " , ( int ) saddr , val );
165
switch ( saddr ) {
166
case IOMMU_CTRL :
167
168
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
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 );
195
s -> regs [ saddr ] = (( val & IOMMU_CTRL_MASK ) | s -> version );
196
break ;
197
case IOMMU_BASE :
198
199
s -> regs [ saddr ] = val & IOMMU_BASE_MASK ;
break ;
200
case IOMMU_TLBFLUSH :
201
202
203
DPRINTF ( "tlb flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_TLBFLUSH_MASK ;
break ;
204
case IOMMU_PGFLUSH :
205
206
207
DPRINTF ( "page flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_PGFLUSH_MASK ;
break ;
208
209
210
211
case IOMMU_AFAR :
s -> regs [ saddr ] = val ;
qemu_irq_lower ( s -> irq );
break ;
212
213
214
case IOMMU_AER :
s -> regs [ saddr ] = ( val & IOMMU_AER_MASK ) | IOMMU_AER_EN_P0_ARB ;
break ;
215
216
case IOMMU_AFSR :
s -> regs [ saddr ] = ( val & IOMMU_AFSR_MASK ) | IOMMU_AFSR_RESV ;
217
qemu_irq_lower ( s -> irq );
218
break ;
219
220
221
222
case IOMMU_SBCFG0 :
case IOMMU_SBCFG1 :
case IOMMU_SBCFG2 :
case IOMMU_SBCFG3 :
223
224
s -> regs [ saddr ] = val & IOMMU_SBCFG_MASK ;
break ;
225
226
227
case IOMMU_ARBEN :
// XXX implement SBus probing : fault when reading unmapped
// addresses , fault cause and address stored to MMU / IOMMU
228
229
s -> regs [ saddr ] = ( val & IOMMU_ARBEN_MASK ) | IOMMU_MID ;
break ;
230
231
232
case IOMMU_MASK_ID :
s -> regs [ saddr ] |= val & IOMMU_MASK_ID_MASK ;
break ;
233
default :
234
235
s -> regs [ saddr ] = val ;
break ;
236
237
238
239
}
}
static CPUReadMemoryFunc * iommu_mem_read [ 3 ] = {
240
241
242
NULL ,
NULL ,
iommu_mem_readl ,
243
244
245
};
static CPUWriteMemoryFunc * iommu_mem_write [ 3 ] = {
246
247
248
NULL ,
NULL ,
iommu_mem_writel ,
249
250
};
251
static uint32_t iommu_page_get_flags ( IOMMUState * s , target_phys_addr_t addr )
252
{
253
254
uint32_t ret ;
target_phys_addr_t iopte ;
255
256
257
# ifdef DEBUG_IOMMU
target_phys_addr_t pa = addr ;
# endif
258
259
iopte = s -> regs [ IOMMU_BASE ] << 4 ;
260
addr &= ~ s -> iostart ;
261
iopte += ( addr >> ( IOMMU_PAGE_SHIFT - 2 )) & ~ 3 ;
262
cpu_physical_memory_read ( iopte , ( uint8_t * ) & ret , 4 );
263
tswap32s ( & ret );
264
265
DPRINTF ( "get flags addr " TARGET_FMT_plx " => pte " TARGET_FMT_plx
", *pte = %x \n " , pa , iopte , ret );
266
267
return ret ;
268
269
}
270
static target_phys_addr_t iommu_translate_pa ( target_phys_addr_t addr ,
271
uint32_t pte )
272
273
{
uint32_t tmppte ;
274
275
276
target_phys_addr_t pa ;
tmppte = pte ;
277
pa = (( pte & IOPTE_PAGE ) << 4 ) + ( addr & ~ IOMMU_PAGE_MASK );
278
279
DPRINTF ( "xlate dva " TARGET_FMT_plx " => pa " TARGET_FMT_plx
" (iopte = %x) \n " , addr , pa , tmppte );
280
281
return pa ;
282
283
}
284
285
static void iommu_bad_addr ( IOMMUState * s , target_phys_addr_t addr ,
int is_write )
286
287
{
DPRINTF ( "bad addr " TARGET_FMT_plx " \n " , addr );
288
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_ERR | IOMMU_AFSR_LE | IOMMU_AFSR_RESV |
289
290
291
292
IOMMU_AFSR_FAV ;
if ( ! is_write )
s -> regs [ IOMMU_AFSR ] |= IOMMU_AFSR_RD ;
s -> regs [ IOMMU_AFAR ] = addr ;
293
qemu_irq_raise ( s -> irq );
294
295
}
296
297
void sparc_iommu_memory_rw ( void * opaque , target_phys_addr_t addr ,
uint8_t * buf , int len , int is_write )
298
{
299
300
301
int l ;
uint32_t flags ;
target_phys_addr_t page , phys_addr ;
302
303
while ( len > 0 ) {
304
305
page = addr & IOMMU_PAGE_MASK ;
l = ( page + IOMMU_PAGE_SIZE ) - addr ;
306
307
308
if ( l > len )
l = len ;
flags = iommu_page_get_flags ( opaque , page );
309
310
if ( ! ( flags & IOPTE_VALID )) {
iommu_bad_addr ( opaque , page , is_write );
311
return ;
312
}
313
phys_addr = iommu_translate_pa ( addr , flags );
314
if ( is_write ) {
315
316
if ( ! ( flags & IOPTE_WRITE )) {
iommu_bad_addr ( opaque , page , is_write );
317
return ;
318
}
319
cpu_physical_memory_write ( phys_addr , buf , l );
320
} else {
321
cpu_physical_memory_read ( phys_addr , buf , l );
322
323
324
325
326
327
328
}
len -= l ;
buf += l ;
addr += l ;
}
}
329
330
331
332
static void iommu_save ( QEMUFile * f , void * opaque )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
17 years ago
333
334
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
335
qemu_put_be32s ( f , & s -> regs [ i ]);
336
qemu_put_be64s ( f , & s -> iostart );
337
338
339
340
341
342
}
static int iommu_load ( QEMUFile * f , void * opaque , int version_id )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
17 years ago
343
344
if ( version_id != 2 )
345
346
return - EINVAL ;
347
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
348
qemu_get_be32s ( f , & s -> regs [ i ]);
349
qemu_get_be64s ( f , & s -> iostart );
350
351
352
353
354
355
356
357
return 0 ;
}
static void iommu_reset ( void * opaque )
{
IOMMUState * s = opaque ;
358
memset ( s -> regs , 0 , IOMMU_NREGS * 4 );
359
s -> iostart = 0 ;
360
361
s -> regs [ IOMMU_CTRL ] = s -> version ;
s -> regs [ IOMMU_ARBEN ] = IOMMU_MID ;
362
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_RESV ;
363
s -> regs [ IOMMU_AER ] = IOMMU_AER_EN_P0_ARB | IOMMU_AER_EN_P1_ARB ;
364
s -> regs [ IOMMU_MASK_ID ] = IOMMU_TS_MASK ;
365
qemu_irq_lower ( s -> irq );
366
367
}
368
void * iommu_init ( target_phys_addr_t addr , uint32_t version , qemu_irq irq )
369
370
{
IOMMUState * s ;
371
int iommu_io_memory ;
372
373
374
s = qemu_mallocz ( sizeof ( IOMMUState ));
375
s -> version = version ;
376
s -> irq = irq ;
377
378
379
iommu_io_memory = cpu_register_io_memory ( 0 , iommu_mem_read ,
iommu_mem_write , s );
380
cpu_register_physical_memory ( addr , IOMMU_NREGS * 4 , iommu_io_memory );
ths
authored
17 years ago
381
382
register_savevm ( "iommu" , addr , 2 , iommu_save , iommu_load , s );
383
qemu_register_reset ( iommu_reset , s );
384
iommu_reset ( s );
385
return s ;
386
}