1
/*
2
* QEMU Sun4u / Sun4v System Emulator
ths
authored
18 years ago
3
*
4
* Copyright ( c ) 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
26
27
28
29
30
31
32
# include "hw.h"
# include "pci.h"
# include "pc.h"
# include "nvram.h"
# include "fdc.h"
# include "net.h"
# include "qemu-timer.h"
# include "sysemu.h"
# include "boards.h"
33
# include "firmware_abi.h"
34
35
36
37
# define KERNEL_LOAD_ADDR 0x00404000
# define CMDLINE_ADDR 0x003ff000
# define INITRD_LOAD_ADDR 0x00300000
38
# define PROM_SIZE_MAX ( 4 * 1024 * 1024 )
39
40
# define PROM_ADDR 0x1fff0000000ULL
# define PROM_VADDR 0x000ffd00000ULL
41
# define APB_SPECIAL_BASE 0x1fe00000000ULL
42
43
44
# define APB_MEM_BASE 0x1ff00000000ULL
# define VGA_BASE ( APB_MEM_BASE + 0x400000ULL )
# define PROM_FILENAME "openbios-sparc64"
45
# define NVRAM_SIZE 0x2000
ths
authored
17 years ago
46
# define MAX_IDE_BUS 2
47
48
49
50
51
struct hwdef {
const char * const default_cpu_model ;
};
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
int DMA_get_channel_mode ( int nchan )
{
return 0 ;
}
int DMA_read_memory ( int nchan , void * buf , int pos , int size )
{
return 0 ;
}
int DMA_write_memory ( int nchan , void * buf , int pos , int size )
{
return 0 ;
}
void DMA_hold_DREQ ( int nchan ) {}
void DMA_release_DREQ ( int nchan ) {}
void DMA_schedule ( int nchan ) {}
void DMA_run ( void ) {}
void DMA_init ( int high_page_enable ) {}
void DMA_register_channel ( int nchan ,
DMA_transfer_handler transfer_handler ,
void * opaque )
{
}
75
76
77
78
79
80
81
82
83
84
static int nvram_boot_set ( void * opaque , const char * boot_device )
{
unsigned int i ;
uint8_t image [ sizeof ( ohwcfg_v3_t )];
ohwcfg_v3_t * header = ( ohwcfg_v3_t * ) & image ;
m48t59_t * nvram = ( m48t59_t * ) opaque ;
for ( i = 0 ; i < sizeof ( image ); i ++ )
image [ i ] = m48t59_read ( nvram , i ) & 0xff ;
85
strcpy (( char * ) header -> boot_devices , boot_device );
86
87
88
89
90
91
92
93
94
header -> nboot_devices = strlen ( boot_device ) & 0xff ;
header -> crc = cpu_to_be16 ( OHW_compute_crc ( header , 0x00 , 0xF8 ));
for ( i = 0 ; i < sizeof ( image ); i ++ )
m48t59_write ( nvram , i , image [ i ]);
return 0 ;
}
95
96
extern int nographic ;
97
static int sun4u_NVRAM_set_params ( m48t59_t * nvram , uint16_t NVRAM_size ,
98
const char * arch ,
99
100
ram_addr_t RAM_size ,
const char * boot_devices ,
101
102
103
104
uint32_t kernel_image , uint32_t kernel_size ,
const char * cmdline ,
uint32_t initrd_image , uint32_t initrd_size ,
uint32_t NVRAM_image ,
105
106
int width , int height , int depth ,
const uint8_t * macaddr )
107
{
108
109
unsigned int i ;
uint32_t start , end ;
110
111
112
113
114
115
116
117
uint8_t image [ 0x1ff0 ];
ohwcfg_v3_t * header = ( ohwcfg_v3_t * ) & image ;
struct sparc_arch_cfg * sparc_header ;
struct OpenBIOS_nvpart_v1 * part_header ;
memset ( image , '\0' , sizeof ( image ));
// Try to match PPC NVRAM
118
strcpy (( char * ) header -> struct_ident , "QEMU_BIOS" );
119
120
121
122
123
header -> struct_version = cpu_to_be32 ( 3 ); /* structure v3 */
header -> nvram_size = cpu_to_be16 ( NVRAM_size );
header -> nvram_arch_ptr = cpu_to_be16 ( sizeof ( ohwcfg_v3_t ));
header -> nvram_arch_size = cpu_to_be16 ( sizeof ( struct sparc_arch_cfg ));
124
strcpy (( char * ) header -> arch , arch );
125
126
127
header -> nb_cpus = smp_cpus & 0xff ;
header -> RAM0_base = 0 ;
header -> RAM0_size = cpu_to_be64 (( uint64_t ) RAM_size );
128
strcpy (( char * ) header -> boot_devices , boot_devices );
129
130
131
header -> nboot_devices = strlen ( boot_devices ) & 0xff ;
header -> kernel_image = cpu_to_be64 (( uint64_t ) kernel_image );
header -> kernel_size = cpu_to_be64 (( uint64_t ) kernel_size );
132
if ( cmdline ) {
133
pstrcpy_targphys ( CMDLINE_ADDR , TARGET_PAGE_SIZE , cmdline );
134
135
header -> cmdline = cpu_to_be64 (( uint64_t ) CMDLINE_ADDR );
header -> cmdline_size = cpu_to_be64 (( uint64_t ) strlen ( cmdline ));
136
}
137
138
139
140
141
142
143
144
145
header -> initrd_image = cpu_to_be64 (( uint64_t ) initrd_image );
header -> initrd_size = cpu_to_be64 (( uint64_t ) initrd_size );
header -> NVRAM_image = cpu_to_be64 (( uint64_t ) NVRAM_image );
header -> width = cpu_to_be16 ( width );
header -> height = cpu_to_be16 ( height );
header -> depth = cpu_to_be16 ( depth );
if ( nographic )
header -> graphic_flags = cpu_to_be16 ( OHW_GF_NOGRAPHICS );
146
147
148
149
150
151
152
153
header -> crc = cpu_to_be16 ( OHW_compute_crc ( header , 0x00 , 0xF8 ));
// Architecture specific header
start = sizeof ( ohwcfg_v3_t );
sparc_header = ( struct sparc_arch_cfg * ) & image [ start ];
sparc_header -> valid = 0 ;
start += sizeof ( struct sparc_arch_cfg );
154
155
156
// OpenBIOS nvram variables
// Variable partition
157
158
159
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_SYSTEM ;
strcpy ( part_header -> name , "system" );
160
161
end = start + sizeof ( struct OpenBIOS_nvpart_v1 );
162
for ( i = 0 ; i < nb_prom_envs ; i ++ )
163
164
165
166
end = OpenBIOS_set_var ( image , end , prom_envs [ i ]);
// End marker
image [ end ++ ] = '\0' ;
167
168
end = start + (( end - start + 15 ) & ~ 15 );
169
OpenBIOS_finish_partition ( part_header , end - start );
170
171
172
// free partition
start = end ;
173
174
175
part_header = ( struct OpenBIOS_nvpart_v1 * ) & image [ start ];
part_header -> signature = OPENBIOS_PART_FREE ;
strcpy ( part_header -> name , "free" );
176
177
end = 0x1fd0 ;
178
179
OpenBIOS_finish_partition ( part_header , end - start );
180
181
Sun_init_header (( struct Sun_nvram * ) & image [ 0x1fd8 ], macaddr , 0x80 );
182
183
for ( i = 0 ; i < sizeof ( image ); i ++ )
m48t59_write ( nvram , i , image [ i ]);
184
185
186
qemu_register_boot_set ( nvram_boot_set , nvram );
187
return 0 ;
188
189
}
190
void pic_info ( void )
191
192
193
{
}
194
void irq_info ( void )
195
196
197
{
}
198
void qemu_system_powerdown ( void )
199
200
201
{
}
202
203
204
static void main_cpu_reset ( void * opaque )
{
CPUState * env = opaque ;
205
206
cpu_reset ( env );
207
208
209
210
211
212
213
214
ptimer_set_limit ( env -> tick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> tick , 0 );
ptimer_set_limit ( env -> stick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> stick , 0 );
ptimer_set_limit ( env -> hstick , 0x7fffffffffffffffULL , 1 );
ptimer_run ( env -> hstick , 0 );
}
215
static void tick_irq ( void * opaque )
216
217
218
219
220
221
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
222
static void stick_irq ( void * opaque )
223
224
225
226
227
228
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
}
229
static void hstick_irq ( void * opaque )
230
231
232
233
{
CPUState * env = opaque ;
cpu_interrupt ( env , CPU_INTERRUPT_TIMER );
234
235
}
236
237
238
239
static void dummy_cpu_set_irq ( void * opaque , int irq , int level )
{
}
240
241
242
static const int ide_iobase [ 2 ] = { 0x1f0 , 0x170 };
static const int ide_iobase2 [ 2 ] = { 0x3f6 , 0x376 };
static const int ide_irq [ 2 ] = { 14 , 15 };
243
244
245
246
247
248
249
250
static const int serial_io [ MAX_SERIAL_PORTS ] = { 0x3f8 , 0x2f8 , 0x3e8 , 0x2e8 };
static const int serial_irq [ MAX_SERIAL_PORTS ] = { 4 , 3 , 4 , 3 };
static const int parallel_io [ MAX_PARALLEL_PORTS ] = { 0x378 , 0x278 , 0x3bc };
static const int parallel_irq [ MAX_PARALLEL_PORTS ] = { 7 , 7 , 7 };
static fdctrl_t * floppy_controller ;
251
252
253
254
255
256
static void sun4uv_init ( ram_addr_t RAM_size , int vga_ram_size ,
const char * boot_devices , DisplayState * ds ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model ,
const struct hwdef * hwdef )
257
{
258
CPUState * env ;
259
char buf [ 1024 ];
260
m48t59_t * nvram ;
261
262
int ret , linux_boot ;
unsigned int i ;
263
264
long prom_offset , initrd_size , kernel_size ;
PCIBus * pci_bus ;
265
QEMUBH * bh ;
266
qemu_irq * irq ;
267
int drive_index ;
ths
authored
17 years ago
268
269
BlockDriverState * hd [ MAX_IDE_BUS * MAX_IDE_DEVS ];
BlockDriverState * fd [ MAX_FD ];
270
271
272
linux_boot = ( kernel_filename != NULL );
273
/* init CPUs */
274
275
276
if ( ! cpu_model )
cpu_model = hwdef -> default_cpu_model ;
277
278
env = cpu_init ( cpu_model );
if ( ! env ) {
279
280
281
fprintf ( stderr , "Unable to find Sparc CPU definition \n " );
exit ( 1 );
}
282
283
284
285
286
287
288
289
290
291
292
bh = qemu_bh_new ( tick_irq , env );
env -> tick = ptimer_init ( bh );
ptimer_set_period ( env -> tick , 1ULL );
bh = qemu_bh_new ( stick_irq , env );
env -> stick = ptimer_init ( bh );
ptimer_set_period ( env -> stick , 1ULL );
bh = qemu_bh_new ( hstick_irq , env );
env -> hstick = ptimer_init ( bh );
ptimer_set_period ( env -> hstick , 1ULL );
293
qemu_register_reset ( main_cpu_reset , env );
294
main_cpu_reset ( env );
295
296
/* allocate RAM */
297
cpu_register_physical_memory ( 0 , RAM_size , 0 );
298
299
prom_offset = RAM_size + vga_ram_size ;
ths
authored
18 years ago
300
cpu_register_physical_memory ( PROM_ADDR ,
301
302
( PROM_SIZE_MAX + TARGET_PAGE_SIZE ) &
TARGET_PAGE_MASK ,
303
prom_offset | IO_MEM_ROM );
304
305
306
307
if ( bios_name == NULL )
bios_name = PROM_FILENAME ;
snprintf ( buf , sizeof ( buf ), "%s/%s" , bios_dir , bios_name );
308
ret = load_elf ( buf , PROM_ADDR - PROM_VADDR , NULL , NULL , NULL );
309
if ( ret < 0 ) {
310
311
312
fprintf ( stderr , "qemu: could not load prom '%s' \n " ,
buf );
exit ( 1 );
313
314
315
}
kernel_size = 0 ;
316
initrd_size = 0 ;
317
if ( linux_boot ) {
318
/* XXX: put correct offset */
ths
authored
18 years ago
319
kernel_size = load_elf ( kernel_filename , 0 , NULL , NULL , NULL );
320
if ( kernel_size < 0 )
321
322
kernel_size = load_aout ( kernel_filename , KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
323
if ( kernel_size < 0 )
324
325
326
kernel_size = load_image_targphys ( kernel_filename ,
KERNEL_LOAD_ADDR ,
ram_size - KERNEL_LOAD_ADDR );
327
if ( kernel_size < 0 ) {
ths
authored
18 years ago
328
fprintf ( stderr , "qemu: could not load kernel '%s' \n " ,
329
kernel_filename );
330
exit ( 1 );
331
332
333
334
}
/* load initrd */
if ( initrd_filename ) {
335
336
337
initrd_size = load_image_targphys ( initrd_filename ,
INITRD_LOAD_ADDR ,
ram_size - INITRD_LOAD_ADDR );
338
if ( initrd_size < 0 ) {
ths
authored
18 years ago
339
fprintf ( stderr , "qemu: could not load initial ram disk '%s' \n " ,
340
341
342
343
344
initrd_filename );
exit ( 1 );
}
}
if ( initrd_size > 0 ) {
345
for ( i = 0 ; i < 64 * TARGET_PAGE_SIZE ; i += TARGET_PAGE_SIZE ) {
346
347
348
if ( ldl_phys ( KERNEL_LOAD_ADDR + i ) == 0x48647253 ) { // HdrS
stl_phys ( KERNEL_LOAD_ADDR + i + 16 , INITRD_LOAD_ADDR );
stl_phys ( KERNEL_LOAD_ADDR + i + 20 , initrd_size );
349
350
351
break ;
}
}
352
353
}
}
354
pci_bus = pci_apb_init ( APB_SPECIAL_BASE , APB_MEM_BASE , NULL );
355
isa_mem_base = VGA_BASE ;
356
357
pci_cirrus_vga_init ( pci_bus , ds , phys_ram_base + RAM_size , RAM_size ,
vga_ram_size );
358
359
360
for ( i = 0 ; i < MAX_SERIAL_PORTS ; i ++ ) {
if ( serial_hds [ i ]) {
361
362
serial_init ( serial_io [ i ], NULL /*serial_irq[i]*/ , 115200 ,
serial_hds [ i ]);
363
364
365
366
367
}
}
for ( i = 0 ; i < MAX_PARALLEL_PORTS ; i ++ ) {
if ( parallel_hds [ i ]) {
368
369
parallel_init ( parallel_io [ i ], NULL /*parallel_irq[i]*/ ,
parallel_hds [ i ]);
370
371
372
373
}
}
for ( i = 0 ; i < nb_nics ; i ++ ) {
374
375
if ( ! nd_table [ i ]. model )
nd_table [ i ]. model = "ne2k_pci" ;
376
pci_nic_init ( pci_bus , & nd_table [ i ], - 1 );
377
378
}
379
irq = qemu_allocate_irqs ( dummy_cpu_set_irq , NULL , 32 );
ths
authored
17 years ago
380
381
382
383
384
if ( drive_get_max_bus ( IF_IDE ) >= MAX_IDE_BUS ) {
fprintf ( stderr , "qemu: too many IDE bus \n " );
exit ( 1 );
}
for ( i = 0 ; i < MAX_IDE_BUS * MAX_IDE_DEVS ; i ++ ) {
385
386
387
388
drive_index = drive_get_index ( IF_IDE , i / MAX_IDE_DEVS ,
i % MAX_IDE_DEVS );
if ( drive_index != - 1 )
hd [ i ] = drives_table [ drive_index ]. bdrv ;
ths
authored
17 years ago
389
390
391
392
393
394
else
hd [ i ] = NULL ;
}
// XXX pci_cmd646_ide_init ( pci_bus , hd , 1 );
pci_piix3_ide_init ( pci_bus , hd , - 1 , irq );
395
396
/* FIXME: wire up interrupts. */
i8042_init ( NULL /*1*/ , NULL /*12*/ , 0x60 );
ths
authored
17 years ago
397
for ( i = 0 ; i < MAX_FD ; i ++ ) {
398
399
400
drive_index = drive_get_index ( IF_FLOPPY , 0 , i );
if ( drive_index != - 1 )
fd [ i ] = drives_table [ drive_index ]. bdrv ;
ths
authored
17 years ago
401
402
403
404
else
fd [ i ] = NULL ;
}
floppy_controller = fdctrl_init ( NULL /*6*/ , 2 , 0 , 0x3f0 , fd );
405
nvram = m48t59_init ( NULL /*8*/ , 0 , 0x0074 , NVRAM_SIZE , 59 );
406
sun4u_NVRAM_set_params ( nvram , NVRAM_SIZE , "Sun4u" , RAM_size , boot_devices ,
407
408
409
410
411
412
413
KERNEL_LOAD_ADDR , kernel_size ,
kernel_cmdline ,
INITRD_LOAD_ADDR , initrd_size ,
/* XXX: need an option to load a NVRAM image */
0 ,
graphic_width , graphic_height , graphic_depth ,
( uint8_t * ) & nd_table [ 0 ]. macaddr );
414
415
416
}
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
static const struct hwdef hwdefs [] = {
/* Sun4u generic PC-like machine */
{
. default_cpu_model = "TI UltraSparc II" ,
},
/* Sun4v generic PC-like machine */
{
. default_cpu_model = "Sun UltraSparc T1" ,
},
};
/* Sun4u hardware initialisation */
static void sun4u_init ( ram_addr_t RAM_size , int vga_ram_size ,
const char * boot_devices , DisplayState * ds ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
{
sun4uv_init ( RAM_size , vga_ram_size , boot_devices , ds , kernel_filename ,
kernel_cmdline , initrd_filename , cpu_model , & hwdefs [ 0 ]);
}
/* Sun4v hardware initialisation */
static void sun4v_init ( ram_addr_t RAM_size , int vga_ram_size ,
const char * boot_devices , DisplayState * ds ,
const char * kernel_filename , const char * kernel_cmdline ,
const char * initrd_filename , const char * cpu_model )
{
sun4uv_init ( RAM_size , vga_ram_size , boot_devices , ds , kernel_filename ,
kernel_cmdline , initrd_filename , cpu_model , & hwdefs [ 1 ]);
}
448
QEMUMachine sun4u_machine = {
449
450
451
452
. name = "sun4u" ,
. desc = "Sun4u platform" ,
. init = sun4u_init ,
. ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE ,
453
. nodisk_ok = 1 ,
454
};
455
456
QEMUMachine sun4v_machine = {
457
458
459
460
. name = "sun4v" ,
. desc = "Sun4v platform" ,
. init = sun4v_init ,
. ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE ,
461
. nodisk_ok = 1 ,
462
};