Statistics
| Branch: | Revision:

root / hw / mips_mipssim.c @ a47b8d38

History | View | Annotate | Download (5.1 kB)

1
/*
2
 * QEMU/mipssim emulation
3
 *
4
 * Emulates a very simple machine model similiar to the one use by the
5
 * proprietary MIPS emulator.
6
 */
7
#include "vl.h"
8

    
9
#ifdef TARGET_WORDS_BIGENDIAN
10
#define BIOS_FILENAME "mips_bios.bin"
11
#else
12
#define BIOS_FILENAME "mipsel_bios.bin"
13
#endif
14

    
15
#ifdef TARGET_MIPS64
16
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
17
#else
18
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
19
#endif
20

    
21
#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
22

    
23
static void load_kernel (CPUState *env)
24
{
25
    int64_t entry, kernel_low, kernel_high;
26
    long kernel_size;
27
    long initrd_size;
28
    ram_addr_t initrd_offset;
29

    
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;
36
    } else {
37
        fprintf(stderr, "qemu: could not load kernel '%s'\n",
38
                env->kernel_filename);
39
        exit(1);
40
    }
41

    
42
    /* load initrd */
43
    initrd_size = 0;
44
    initrd_offset = 0;
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) {
50
                fprintf(stderr,
51
                        "qemu: memory too small for initial ram disk '%s'\n",
52
                        env->initrd_filename);
53
                exit(1);
54
            }
55
            initrd_size = load_image(env->initrd_filename,
56
                                     phys_ram_base + initrd_offset);
57
        }
58
        if (initrd_size == (target_ulong) -1) {
59
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
60
                    env->initrd_filename);
61
            exit(1);
62
        }
63
    }
64
}
65

    
66
static void main_cpu_reset(void *opaque)
67
{
68
    CPUState *env = opaque;
69
    cpu_reset(env);
70
    cpu_mips_register(env, NULL);
71

    
72
    if (env->kernel_filename)
73
        load_kernel (env);
74
}
75

    
76
static void
77
mips_mipssim_init (int ram_size, int vga_ram_size, int 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)
81
{
82
    char buf[1024];
83
    unsigned long bios_offset;
84
    CPUState *env;
85
    int bios_size;
86
    mips_def_t *def;
87

    
88
    /* Init CPUs. */
89
    if (cpu_model == NULL) {
90
#ifdef TARGET_MIPS64
91
        cpu_model = "5Kf";
92
#else
93
        cpu_model = "24Kf";
94
#endif
95
    }
96
    if (mips_find_by_name(cpu_model, &def) != 0)
97
        def = NULL;
98
    env = cpu_init();
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);
102

    
103
    /* Allocate RAM. */
104
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
105

    
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. */
114
        fprintf(stderr,
115
                "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n",
116
                buf);
117
        exit(1);
118
    } else {
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;
124
    }
125

    
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;
131
        load_kernel(env);
132
    }
133

    
134
    /* Init CPU internal devices. */
135
    cpu_mips_irq_init_cpu(env);
136
    cpu_mips_clock_init(env);
137
    cpu_mips_irqctrl_init();
138

    
139
    /* Register 64 KB of ISA IO space at 0x1fd00000. */
140
    isa_mmio_init(0x1fd00000, 0x00010000);
141

    
142
    /* A single 16450 sits at offset 0x3f8. It is attached to
143
       MIPS CPU INT2, which is interrupt 4. */
144
    if (serial_hds[0])
145
        serial_init(0x3f8, env->irq[4], serial_hds[0]);
146

    
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");
154
            exit (1);
155
        } else {
156
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
157
            exit (1);
158
        }
159
    }
160
}
161

    
162
QEMUMachine mips_mipssim_machine = {
163
    "mipssim",
164
    "MIPS MIPSsim platform",
165
    mips_mipssim_init,
166
};