|
|
1.1 ! root 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: * Copyright (c) 2007 Thiemo Seufer ! 8: * ! 9: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 10: * of this software and associated documentation files (the "Software"), to deal ! 11: * in the Software without restriction, including without limitation the rights ! 12: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 13: * copies of the Software, and to permit persons to whom the Software is ! 14: * furnished to do so, subject to the following conditions: ! 15: * ! 16: * The above copyright notice and this permission notice shall be included in ! 17: * all copies or substantial portions of the Software. ! 18: * ! 19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 22: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 24: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 25: * THE SOFTWARE. ! 26: */ ! 27: #include "hw.h" ! 28: #include "mips.h" ! 29: #include "pc.h" ! 30: #include "isa.h" ! 31: #include "net.h" ! 32: #include "sysemu.h" ! 33: #include "boards.h" ! 34: ! 35: #ifdef TARGET_WORDS_BIGENDIAN ! 36: #define BIOS_FILENAME "mips_bios.bin" ! 37: #else ! 38: #define BIOS_FILENAME "mipsel_bios.bin" ! 39: #endif ! 40: ! 41: #ifdef TARGET_MIPS64 ! 42: #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL) ! 43: #else ! 44: #define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU) ! 45: #endif ! 46: ! 47: #define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000)) ! 48: ! 49: static struct _loaderparams { ! 50: int ram_size; ! 51: const char *kernel_filename; ! 52: const char *kernel_cmdline; ! 53: const char *initrd_filename; ! 54: } loaderparams; ! 55: ! 56: static void load_kernel (CPUState *env) ! 57: { ! 58: int64_t entry, kernel_low, kernel_high; ! 59: long kernel_size; ! 60: long initrd_size; ! 61: ram_addr_t initrd_offset; ! 62: ! 63: kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, ! 64: &entry, &kernel_low, &kernel_high); ! 65: if (kernel_size >= 0) { ! 66: if ((entry & ~0x7fffffffULL) == 0x80000000) ! 67: entry = (int32_t)entry; ! 68: env->PC[env->current_tc] = entry; ! 69: } else { ! 70: fprintf(stderr, "qemu: could not load kernel '%s'\n", ! 71: loaderparams.kernel_filename); ! 72: exit(1); ! 73: } ! 74: ! 75: /* load initrd */ ! 76: initrd_size = 0; ! 77: initrd_offset = 0; ! 78: if (loaderparams.initrd_filename) { ! 79: initrd_size = get_image_size (loaderparams.initrd_filename); ! 80: if (initrd_size > 0) { ! 81: initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; ! 82: if (initrd_offset + initrd_size > loaderparams.ram_size) { ! 83: fprintf(stderr, ! 84: "qemu: memory too small for initial ram disk '%s'\n", ! 85: loaderparams.initrd_filename); ! 86: exit(1); ! 87: } ! 88: initrd_size = load_image(loaderparams.initrd_filename, ! 89: phys_ram_base + initrd_offset); ! 90: } ! 91: if (initrd_size == (target_ulong) -1) { ! 92: fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", ! 93: loaderparams.initrd_filename); ! 94: exit(1); ! 95: } ! 96: } ! 97: } ! 98: ! 99: static void main_cpu_reset(void *opaque) ! 100: { ! 101: CPUState *env = opaque; ! 102: cpu_reset(env); ! 103: ! 104: if (loaderparams.kernel_filename) ! 105: load_kernel (env); ! 106: } ! 107: ! 108: static void ! 109: mips_mipssim_init (int ram_size, int vga_ram_size, ! 110: const char *boot_device, DisplayState *ds, ! 111: const char *kernel_filename, const char *kernel_cmdline, ! 112: const char *initrd_filename, const char *cpu_model) ! 113: { ! 114: char buf[1024]; ! 115: unsigned long bios_offset; ! 116: CPUState *env; ! 117: int bios_size; ! 118: ! 119: /* Init CPUs. */ ! 120: if (cpu_model == NULL) { ! 121: #ifdef TARGET_MIPS64 ! 122: cpu_model = "5Kf"; ! 123: #else ! 124: cpu_model = "24Kf"; ! 125: #endif ! 126: } ! 127: env = cpu_init(cpu_model); ! 128: if (!env) { ! 129: fprintf(stderr, "Unable to find CPU definition\n"); ! 130: exit(1); ! 131: } ! 132: register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); ! 133: qemu_register_reset(main_cpu_reset, env); ! 134: ! 135: /* Allocate RAM. */ ! 136: cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); ! 137: ! 138: /* Load a BIOS / boot exception handler image. */ ! 139: bios_offset = ram_size + vga_ram_size; ! 140: if (bios_name == NULL) ! 141: bios_name = BIOS_FILENAME; ! 142: snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name); ! 143: bios_size = load_image(buf, phys_ram_base + bios_offset); ! 144: if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename) { ! 145: /* Bail out if we have neither a kernel image nor boot vector code. */ ! 146: fprintf(stderr, ! 147: "qemu: Could not load MIPS bios '%s', and no -kernel argument was specified\n", ! 148: buf); ! 149: exit(1); ! 150: } else { ! 151: /* Map the BIOS / boot exception handler. */ ! 152: cpu_register_physical_memory(0x1fc00000LL, ! 153: bios_size, bios_offset | IO_MEM_ROM); ! 154: /* We have a boot vector start address. */ ! 155: env->PC[env->current_tc] = (target_long)(int32_t)0xbfc00000; ! 156: } ! 157: ! 158: if (kernel_filename) { ! 159: loaderparams.ram_size = ram_size; ! 160: loaderparams.kernel_filename = kernel_filename; ! 161: loaderparams.kernel_cmdline = kernel_cmdline; ! 162: loaderparams.initrd_filename = initrd_filename; ! 163: load_kernel(env); ! 164: } ! 165: ! 166: /* Init CPU internal devices. */ ! 167: cpu_mips_irq_init_cpu(env); ! 168: cpu_mips_clock_init(env); ! 169: cpu_mips_irqctrl_init(); ! 170: ! 171: /* Register 64 KB of ISA IO space at 0x1fd00000. */ ! 172: isa_mmio_init(0x1fd00000, 0x00010000); ! 173: ! 174: /* A single 16450 sits at offset 0x3f8. It is attached to ! 175: MIPS CPU INT2, which is interrupt 4. */ ! 176: if (serial_hds[0]) ! 177: serial_init(0x3f8, env->irq[4], serial_hds[0]); ! 178: ! 179: if (nd_table[0].vlan) { ! 180: if (nd_table[0].model == NULL ! 181: || strcmp(nd_table[0].model, "mipsnet") == 0) { ! 182: /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */ ! 183: mipsnet_init(0x4200, env->irq[2], &nd_table[0]); ! 184: } else if (strcmp(nd_table[0].model, "?") == 0) { ! 185: fprintf(stderr, "qemu: Supported NICs: mipsnet\n"); ! 186: exit (1); ! 187: } else { ! 188: fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model); ! 189: exit (1); ! 190: } ! 191: } ! 192: } ! 193: ! 194: QEMUMachine mips_mipssim_machine = { ! 195: "mipssim", ! 196: "MIPS MIPSsim platform", ! 197: mips_mipssim_init, ! 198: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.