|
|
1.1 ! root 1: /* ! 2: * QEMU Leon3 System Emulator ! 3: * ! 4: * Copyright (c) 2010-2011 AdaCore ! 5: * ! 6: * Permission is hereby granted, free of charge, to any person obtaining a copy ! 7: * of this software and associated documentation files (the "Software"), to deal ! 8: * in the Software without restriction, including without limitation the rights ! 9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ! 10: * copies of the Software, and to permit persons to whom the Software is ! 11: * furnished to do so, subject to the following conditions: ! 12: * ! 13: * The above copyright notice and this permission notice shall be included in ! 14: * all copies or substantial portions of the Software. ! 15: * ! 16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ! 17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ! 19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ! 20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ! 21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ! 22: * THE SOFTWARE. ! 23: */ ! 24: #include "hw.h" ! 25: #include "qemu-timer.h" ! 26: #include "qemu-char.h" ! 27: #include "sysemu.h" ! 28: #include "boards.h" ! 29: #include "loader.h" ! 30: #include "elf.h" ! 31: #include "trace.h" ! 32: ! 33: #include "grlib.h" ! 34: ! 35: /* Default system clock. */ ! 36: #define CPU_CLK (40 * 1000 * 1000) ! 37: ! 38: #define PROM_FILENAME "u-boot.bin" ! 39: ! 40: #define MAX_PILS 16 ! 41: ! 42: typedef struct ResetData { ! 43: CPUState *env; ! 44: uint32_t entry; /* save kernel entry in case of reset */ ! 45: } ResetData; ! 46: ! 47: static void main_cpu_reset(void *opaque) ! 48: { ! 49: ResetData *s = (ResetData *)opaque; ! 50: CPUState *env = s->env; ! 51: ! 52: cpu_reset(env); ! 53: ! 54: env->halted = 0; ! 55: env->pc = s->entry; ! 56: env->npc = s->entry + 4; ! 57: } ! 58: ! 59: void leon3_irq_ack(void *irq_manager, int intno) ! 60: { ! 61: grlib_irqmp_ack((DeviceState *)irq_manager, intno); ! 62: } ! 63: ! 64: static void leon3_set_pil_in(void *opaque, uint32_t pil_in) ! 65: { ! 66: CPUState *env = (CPUState *)opaque; ! 67: ! 68: assert(env != NULL); ! 69: ! 70: env->pil_in = pil_in; ! 71: ! 72: if (env->pil_in && (env->interrupt_index == 0 || ! 73: (env->interrupt_index & ~15) == TT_EXTINT)) { ! 74: unsigned int i; ! 75: ! 76: for (i = 15; i > 0; i--) { ! 77: if (env->pil_in & (1 << i)) { ! 78: int old_interrupt = env->interrupt_index; ! 79: ! 80: env->interrupt_index = TT_EXTINT | i; ! 81: if (old_interrupt != env->interrupt_index) { ! 82: trace_leon3_set_irq(i); ! 83: cpu_interrupt(env, CPU_INTERRUPT_HARD); ! 84: } ! 85: break; ! 86: } ! 87: } ! 88: } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) { ! 89: trace_leon3_reset_irq(env->interrupt_index & 15); ! 90: env->interrupt_index = 0; ! 91: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); ! 92: } ! 93: } ! 94: ! 95: static void leon3_generic_hw_init(ram_addr_t ram_size, ! 96: const char *boot_device, ! 97: const char *kernel_filename, ! 98: const char *kernel_cmdline, ! 99: const char *initrd_filename, ! 100: const char *cpu_model) ! 101: { ! 102: CPUState *env; ! 103: ram_addr_t ram_offset, prom_offset; ! 104: int ret; ! 105: char *filename; ! 106: qemu_irq *cpu_irqs = NULL; ! 107: int bios_size; ! 108: int prom_size; ! 109: ResetData *reset_info; ! 110: ! 111: /* Init CPU */ ! 112: if (!cpu_model) { ! 113: cpu_model = "LEON3"; ! 114: } ! 115: ! 116: env = cpu_init(cpu_model); ! 117: if (!env) { ! 118: fprintf(stderr, "qemu: Unable to find Sparc CPU definition\n"); ! 119: exit(1); ! 120: } ! 121: ! 122: cpu_sparc_set_id(env, 0); ! 123: ! 124: /* Reset data */ ! 125: reset_info = qemu_mallocz(sizeof(ResetData)); ! 126: reset_info->env = env; ! 127: qemu_register_reset(main_cpu_reset, reset_info); ! 128: ! 129: /* Allocate IRQ manager */ ! 130: grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in); ! 131: ! 132: env->qemu_irq_ack = leon3_irq_manager; ! 133: ! 134: /* Allocate RAM */ ! 135: if ((uint64_t)ram_size > (1UL << 30)) { ! 136: fprintf(stderr, ! 137: "qemu: Too much memory for this machine: %d, maximum 1G\n", ! 138: (unsigned int)(ram_size / (1024 * 1024))); ! 139: exit(1); ! 140: } ! 141: ! 142: ram_offset = qemu_ram_alloc(NULL, "leon3.ram", ram_size); ! 143: cpu_register_physical_memory(0x40000000, ram_size, ram_offset | IO_MEM_RAM); ! 144: ! 145: /* Allocate BIOS */ ! 146: prom_size = 8 * 1024 * 1024; /* 8Mb */ ! 147: prom_offset = qemu_ram_alloc(NULL, "Leon3.bios", prom_size); ! 148: cpu_register_physical_memory(0x00000000, prom_size, ! 149: prom_offset | IO_MEM_ROM); ! 150: ! 151: /* Load boot prom */ ! 152: if (bios_name == NULL) { ! 153: bios_name = PROM_FILENAME; ! 154: } ! 155: filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); ! 156: ! 157: bios_size = get_image_size(filename); ! 158: ! 159: if (bios_size > prom_size) { ! 160: fprintf(stderr, "qemu: could not load prom '%s': file too big\n", ! 161: filename); ! 162: exit(1); ! 163: } ! 164: ! 165: if (bios_size > 0) { ! 166: ret = load_image_targphys(filename, 0x00000000, bios_size); ! 167: if (ret < 0 || ret > prom_size) { ! 168: fprintf(stderr, "qemu: could not load prom '%s'\n", filename); ! 169: exit(1); ! 170: } ! 171: } else if (kernel_filename == NULL) { ! 172: fprintf(stderr, "Can't read bios image %s\n", filename); ! 173: exit(1); ! 174: } ! 175: ! 176: /* Can directly load an application. */ ! 177: if (kernel_filename != NULL) { ! 178: long kernel_size; ! 179: uint64_t entry; ! 180: ! 181: kernel_size = load_elf(kernel_filename, NULL, NULL, &entry, NULL, NULL, ! 182: 1 /* big endian */, ELF_MACHINE, 0); ! 183: if (kernel_size < 0) { ! 184: fprintf(stderr, "qemu: could not load kernel '%s'\n", ! 185: kernel_filename); ! 186: exit(1); ! 187: } ! 188: if (bios_size <= 0) { ! 189: /* If there is no bios/monitor, start the application. */ ! 190: env->pc = entry; ! 191: env->npc = entry + 4; ! 192: reset_info->entry = entry; ! 193: } ! 194: } ! 195: ! 196: /* Allocate timers */ ! 197: grlib_gptimer_create(0x80000300, 2, CPU_CLK, cpu_irqs, 6); ! 198: ! 199: /* Allocate uart */ ! 200: if (serial_hds[0]) { ! 201: grlib_apbuart_create(0x80000100, serial_hds[0], cpu_irqs[3]); ! 202: } ! 203: } ! 204: ! 205: QEMUMachine leon3_generic_machine = { ! 206: .name = "leon3_generic", ! 207: .desc = "Leon-3 generic", ! 208: .init = leon3_generic_hw_init, ! 209: .use_scsi = 0, ! 210: }; ! 211: ! 212: static void leon3_machine_init(void) ! 213: { ! 214: qemu_register_machine(&leon3_generic_machine); ! 215: } ! 216: ! 217: machine_init(leon3_machine_init);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.