2 * QEMU/mipssim emulation
4 * Emulates a very simple machine model similiar to the one use by the
5 * proprietary MIPS emulator.
9 #ifdef TARGET_WORDS_BIGENDIAN
10 #define BIOS_FILENAME "mips_bios.bin"
12 #define BIOS_FILENAME "mipsel_bios.bin"
16 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
18 #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
21 #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
23 static void load_kernel (CPUState
*env
)
25 int64_t entry
, kernel_low
, kernel_high
;
28 ram_addr_t initrd_offset
;
30 kernel_size
= load_elf(env
->kernel_filename
, VIRT_TO_PHYS_ADDEND
,
31 &entry
, &kernel_low
, &kernel_high
);
32 if (kernel_size
>= 0) {
33 if ((entry
& ~0x7fffffffULL
) == 0x80000000)
34 entry
= (int32_t)entry
;
35 env
->PC
[env
->current_tc
] = entry
;
37 fprintf(stderr
, "qemu: could not load kernel '%s'\n",
38 env
->kernel_filename
);
45 if (env
->initrd_filename
) {
46 initrd_size
= get_image_size (env
->initrd_filename
);
47 if (initrd_size
> 0) {
48 initrd_offset
= (kernel_high
+ ~TARGET_PAGE_MASK
) & TARGET_PAGE_MASK
;
49 if (initrd_offset
+ initrd_size
> env
->ram_size
) {
51 "qemu: memory too small for initial ram disk '%s'\n",
52 env
->initrd_filename
);
55 initrd_size
= load_image(env
->initrd_filename
,
56 phys_ram_base
+ initrd_offset
);
58 if (initrd_size
== (target_ulong
) -1) {
59 fprintf(stderr
, "qemu: could not load initial ram disk '%s'\n",
60 env
->initrd_filename
);
66 static void main_cpu_reset(void *opaque
)
68 CPUState
*env
= opaque
;
70 cpu_mips_register(env
, NULL
);
72 if (env
->kernel_filename
)
77 mips_mipssim_init (int ram_size
, int vga_ram_size
, const char *boot_device
,
78 DisplayState
*ds
, const char **fd_filename
, int snapshot
,
79 const char *kernel_filename
, const char *kernel_cmdline
,
80 const char *initrd_filename
, const char *cpu_model
)
83 unsigned long bios_offset
;
89 if (cpu_model
== NULL
) {
96 if (mips_find_by_name(cpu_model
, &def
) != 0)
99 cpu_mips_register(env
, def
);
100 register_savevm("cpu", 0, 3, cpu_save
, cpu_load
, env
);
101 qemu_register_reset(main_cpu_reset
, env
);
104 cpu_register_physical_memory(0, ram_size
, IO_MEM_RAM
);
106 /* Load a BIOS / boot exception handler image. */
107 bios_offset
= ram_size
+ vga_ram_size
;
108 if (bios_name
== NULL
)
109 bios_name
= BIOS_FILENAME
;
110 snprintf(buf
, sizeof(buf
), "%s/%s", bios_dir
, bios_name
);
111 bios_size
= load_image(buf
, phys_ram_base
+ bios_offset
);
112 if ((bios_size
< 0 || bios_size
> BIOS_SIZE
) && !kernel_filename
) {
113 /* Bail out if we have neither a kernel image nor boot vector code. */
115 "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
119 /* Map the BIOS / boot exception handler. */
120 cpu_register_physical_memory(0x1fc00000LL
,
121 bios_size
, bios_offset
| IO_MEM_ROM
);
122 /* We have a boot vector start address. */
123 env
->PC
[env
->current_tc
] = (target_long
)(int32_t)0xbfc00000;
126 if (kernel_filename
) {
127 env
->ram_size
= ram_size
;
128 env
->kernel_filename
= kernel_filename
;
129 env
->kernel_cmdline
= kernel_cmdline
;
130 env
->initrd_filename
= initrd_filename
;
134 /* Init CPU internal devices. */
135 cpu_mips_irq_init_cpu(env
);
136 cpu_mips_clock_init(env
);
137 cpu_mips_irqctrl_init();
139 /* Register 64 KB of ISA IO space at 0x1fd00000. */
140 isa_mmio_init(0x1fd00000, 0x00010000);
142 /* A single 16450 sits at offset 0x3f8. It is attached to
143 MIPS CPU INT2, which is interrupt 4. */
145 serial_init(0x3f8, env
->irq
[4], serial_hds
[0]);
147 if (nd_table
[0].vlan
) {
148 if (nd_table
[0].model
== NULL
149 || strcmp(nd_table
[0].model
, "mipsnet") == 0) {
150 /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
151 mipsnet_init(0x4200, env
->irq
[2], &nd_table
[0]);
152 } else if (strcmp(nd_table
[0].model
, "?") == 0) {
153 fprintf(stderr
, "qemu: Supported NICs: mipsnet\n");
156 fprintf(stderr
, "qemu: Unsupported NIC: %s\n", nd_table
[0].model
);
162 QEMUMachine mips_mipssim_machine
= {
164 "MIPS MIPSsim platform",