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