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 "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
# 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 */
85
86
# define IOMMU_SBCFG_SAB30 0x00010000 /* Phys - address bit 30 when
bypass enabled */
87
88
89
# 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
90
produced by this device as pure
91
92
93
94
95
96
physical . */
# define IOMMU_SBCFG_MASK 0x00010003
# define IOMMU_ARBEN ( 0x2000 >> 2 ) /* SBUS arbitration enable */
# define IOMMU_ARBEN_MASK 0x001f0000
# define IOMMU_MID 0x00000008
97
98
99
100
101
102
103
# 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 */
104
/* The format of an iopte in the page tables */
105
# define IOPTE_PAGE 0xffffff00 /* Physical page number (PA[35:12]) */
106
107
# define IOPTE_CACHE 0x00000080 /* Cached ( in vme IOCACHE or
Viking / MXCC ) */
108
109
110
111
# define IOPTE_WRITE 0x00000004 /* Writeable */
# define IOPTE_VALID 0x00000002 /* IOPTE is valid */
# define IOPTE_WAZ 0x00000001 /* Write as zeros */
112
113
114
# define IOMMU_PAGE_SHIFT 12
# define IOMMU_PAGE_SIZE ( 1 << IOMMU_PAGE_SHIFT )
# define IOMMU_PAGE_MASK ~ ( IOMMU_PAGE_SIZE - 1 )
115
116
typedef struct IOMMUState {
117
uint32_t regs [ IOMMU_NREGS ];
118
target_phys_addr_t iostart ;
119
uint32_t version ;
120
qemu_irq irq ;
121
122
} IOMMUState ;
123
static uint32_t iommu_mem_readl ( void * opaque , target_phys_addr_t addr )
124
125
{
IOMMUState * s = opaque ;
126
target_phys_addr_t saddr ;
127
uint32_t ret ;
128
129
saddr = addr >> 2 ;
130
131
switch ( saddr ) {
default :
132
133
134
135
136
137
ret = s -> regs [ saddr ];
break ;
case IOMMU_AFAR :
case IOMMU_AFSR :
ret = s -> regs [ saddr ];
qemu_irq_lower ( s -> irq );
138
break ;
139
}
140
141
DPRINTF ( "read reg[%d] = %x \n " , ( int ) saddr , ret );
return ret ;
142
143
}
144
static void iommu_mem_writel ( void * opaque , target_phys_addr_t addr ,
145
uint32_t val )
146
147
{
IOMMUState * s = opaque ;
148
target_phys_addr_t saddr ;
149
150
saddr = addr >> 2 ;
151
DPRINTF ( "write reg[%d] = %x \n " , ( int ) saddr , val );
152
switch ( saddr ) {
153
case IOMMU_CTRL :
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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 );
182
s -> regs [ saddr ] = (( val & IOMMU_CTRL_MASK ) | s -> version );
183
break ;
184
case IOMMU_BASE :
185
186
s -> regs [ saddr ] = val & IOMMU_BASE_MASK ;
break ;
187
case IOMMU_TLBFLUSH :
188
189
190
DPRINTF ( "tlb flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_TLBFLUSH_MASK ;
break ;
191
case IOMMU_PGFLUSH :
192
193
194
DPRINTF ( "page flush %x \n " , val );
s -> regs [ saddr ] = val & IOMMU_PGFLUSH_MASK ;
break ;
195
196
197
198
case IOMMU_AFAR :
s -> regs [ saddr ] = val ;
qemu_irq_lower ( s -> irq );
break ;
199
200
case IOMMU_AFSR :
s -> regs [ saddr ] = ( val & IOMMU_AFSR_MASK ) | IOMMU_AFSR_RESV ;
201
qemu_irq_lower ( s -> irq );
202
break ;
203
204
205
206
case IOMMU_SBCFG0 :
case IOMMU_SBCFG1 :
case IOMMU_SBCFG2 :
case IOMMU_SBCFG3 :
207
208
s -> regs [ saddr ] = val & IOMMU_SBCFG_MASK ;
break ;
209
210
211
case IOMMU_ARBEN :
// XXX implement SBus probing : fault when reading unmapped
// addresses , fault cause and address stored to MMU / IOMMU
212
213
s -> regs [ saddr ] = ( val & IOMMU_ARBEN_MASK ) | IOMMU_MID ;
break ;
214
215
216
case IOMMU_MASK_ID :
s -> regs [ saddr ] |= val & IOMMU_MASK_ID_MASK ;
break ;
217
default :
218
219
s -> regs [ saddr ] = val ;
break ;
220
221
222
223
}
}
static CPUReadMemoryFunc * iommu_mem_read [ 3 ] = {
224
225
226
NULL ,
NULL ,
iommu_mem_readl ,
227
228
229
};
static CPUWriteMemoryFunc * iommu_mem_write [ 3 ] = {
230
231
232
NULL ,
NULL ,
iommu_mem_writel ,
233
234
};
235
static uint32_t iommu_page_get_flags ( IOMMUState * s , target_phys_addr_t addr )
236
{
237
238
uint32_t ret ;
target_phys_addr_t iopte ;
239
240
241
# ifdef DEBUG_IOMMU
target_phys_addr_t pa = addr ;
# endif
242
243
iopte = s -> regs [ IOMMU_BASE ] << 4 ;
244
addr &= ~ s -> iostart ;
245
iopte += ( addr >> ( IOMMU_PAGE_SHIFT - 2 )) & ~ 3 ;
246
cpu_physical_memory_read ( iopte , ( uint8_t * ) & ret , 4 );
247
tswap32s ( & ret );
248
249
DPRINTF ( "get flags addr " TARGET_FMT_plx " => pte " TARGET_FMT_plx
", *pte = %x \n " , pa , iopte , ret );
250
251
return ret ;
252
253
}
254
static target_phys_addr_t iommu_translate_pa ( target_phys_addr_t addr ,
255
uint32_t pte )
256
257
{
uint32_t tmppte ;
258
259
260
target_phys_addr_t pa ;
tmppte = pte ;
261
pa = (( pte & IOPTE_PAGE ) << 4 ) + ( addr & ~ IOMMU_PAGE_MASK );
262
263
DPRINTF ( "xlate dva " TARGET_FMT_plx " => pa " TARGET_FMT_plx
" (iopte = %x) \n " , addr , pa , tmppte );
264
265
return pa ;
266
267
}
268
269
static void iommu_bad_addr ( IOMMUState * s , target_phys_addr_t addr ,
int is_write )
270
271
{
DPRINTF ( "bad addr " TARGET_FMT_plx " \n " , addr );
272
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_ERR | IOMMU_AFSR_LE | IOMMU_AFSR_RESV |
273
274
275
276
IOMMU_AFSR_FAV ;
if ( ! is_write )
s -> regs [ IOMMU_AFSR ] |= IOMMU_AFSR_RD ;
s -> regs [ IOMMU_AFAR ] = addr ;
277
qemu_irq_raise ( s -> irq );
278
279
}
280
281
void sparc_iommu_memory_rw ( void * opaque , target_phys_addr_t addr ,
uint8_t * buf , int len , int is_write )
282
{
283
284
285
int l ;
uint32_t flags ;
target_phys_addr_t page , phys_addr ;
286
287
while ( len > 0 ) {
288
289
page = addr & IOMMU_PAGE_MASK ;
l = ( page + IOMMU_PAGE_SIZE ) - addr ;
290
291
292
if ( l > len )
l = len ;
flags = iommu_page_get_flags ( opaque , page );
293
294
if ( ! ( flags & IOPTE_VALID )) {
iommu_bad_addr ( opaque , page , is_write );
295
return ;
296
}
297
phys_addr = iommu_translate_pa ( addr , flags );
298
if ( is_write ) {
299
300
if ( ! ( flags & IOPTE_WRITE )) {
iommu_bad_addr ( opaque , page , is_write );
301
return ;
302
}
303
cpu_physical_memory_write ( phys_addr , buf , l );
304
} else {
305
cpu_physical_memory_read ( phys_addr , buf , l );
306
307
308
309
310
311
312
}
len -= l ;
buf += l ;
addr += l ;
}
}
313
314
315
316
static void iommu_save ( QEMUFile * f , void * opaque )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
18 years ago
317
318
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
319
qemu_put_be32s ( f , & s -> regs [ i ]);
320
qemu_put_be64s ( f , & s -> iostart );
321
322
323
324
325
326
}
static int iommu_load ( QEMUFile * f , void * opaque , int version_id )
{
IOMMUState * s = opaque ;
int i ;
ths
authored
18 years ago
327
328
if ( version_id != 2 )
329
330
return - EINVAL ;
331
for ( i = 0 ; i < IOMMU_NREGS ; i ++ )
332
qemu_get_be32s ( f , & s -> regs [ i ]);
333
qemu_get_be64s ( f , & s -> iostart );
334
335
336
337
338
339
340
341
return 0 ;
}
static void iommu_reset ( void * opaque )
{
IOMMUState * s = opaque ;
342
memset ( s -> regs , 0 , IOMMU_NREGS * 4 );
343
s -> iostart = 0 ;
344
345
s -> regs [ IOMMU_CTRL ] = s -> version ;
s -> regs [ IOMMU_ARBEN ] = IOMMU_MID ;
346
s -> regs [ IOMMU_AFSR ] = IOMMU_AFSR_RESV ;
347
s -> regs [ IOMMU_MASK_ID ] = IOMMU_TS_MASK ;
348
qemu_irq_lower ( s -> irq );
349
350
}
351
void * iommu_init ( target_phys_addr_t addr , uint32_t version , qemu_irq irq )
352
353
{
IOMMUState * s ;
354
int iommu_io_memory ;
355
356
357
s = qemu_mallocz ( sizeof ( IOMMUState ));
if ( ! s )
358
return NULL ;
359
360
s -> version = version ;
361
s -> irq = irq ;
362
363
364
iommu_io_memory = cpu_register_io_memory ( 0 , iommu_mem_read ,
iommu_mem_write , s );
365
cpu_register_physical_memory ( addr , IOMMU_NREGS * 4 , iommu_io_memory );
ths
authored
18 years ago
366
367
register_savevm ( "iommu" , addr , 2 , iommu_save , iommu_load , s );
368
qemu_register_reset ( iommu_reset , s );
369
iommu_reset ( s );
370
return s ;
371
}