1 /* 2 * QEMU Alpha DP264/CLIPPER hardware system emulator. 3 * 4 * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK 5 * variants because CLIPPER doesn't have an SMC669 SuperIO controller 6 * that we need to emulate as well. 7 */ 8 9 #include "qemu/osdep.h" 10 #include "qemu-common.h" 11 #include "cpu.h" 12 #include "hw/hw.h" 13 #include "elf.h" 14 #include "hw/loader.h" 15 #include "hw/boards.h" 16 #include "alpha_sys.h" 17 #include "qemu/error-report.h" 18 #include "sysemu/sysemu.h" 19 #include "hw/timer/mc146818rtc.h" 20 #include "hw/ide.h" 21 #include "hw/timer/i8254.h" 22 #include "hw/char/serial.h" 23 #include "qemu/cutils.h" 24 25 #define MAX_IDE_BUS 2 26 27 static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) 28 { 29 if (((addr >> 41) & 3) == 2) { 30 addr &= 0xffffffffffull; 31 } 32 return addr; 33 } 34 35 /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. 36 (0) The dev_irq_n lines into the cpu, which we totally ignore, 37 (1) The DRIR lines in the typhoon chipset, 38 (2) The "vector" aka mangled interrupt number reported by SRM PALcode, 39 (3) The interrupt number assigned by the kernel. 40 The following function is concerned with (1) only. */ 41 42 static int clipper_pci_map_irq(PCIDevice *d, int irq_num) 43 { 44 int slot = d->devfn >> 3; 45 46 assert(irq_num >= 0 && irq_num <= 3); 47 48 return (slot + 1) * 4 + irq_num; 49 } 50 51 static void clipper_init(MachineState *machine) 52 { 53 ram_addr_t ram_size = machine->ram_size; 54 const char *cpu_model = machine->cpu_model ? machine->cpu_model : "ev67"; 55 const char *kernel_filename = machine->kernel_filename; 56 const char *kernel_cmdline = machine->kernel_cmdline; 57 const char *initrd_filename = machine->initrd_filename; 58 AlphaCPU *cpus[4]; 59 PCIBus *pci_bus; 60 ISABus *isa_bus; 61 qemu_irq rtc_irq; 62 long size, i; 63 char *palcode_filename; 64 uint64_t palcode_entry, palcode_low, palcode_high; 65 uint64_t kernel_entry, kernel_low, kernel_high; 66 67 /* Create up to 4 cpus. */ 68 memset(cpus, 0, sizeof(cpus)); 69 for (i = 0; i < smp_cpus; ++i) { 70 cpus[i] = ALPHA_CPU(cpu_generic_init(TYPE_ALPHA_CPU, cpu_model)); 71 if (!cpus[i]) { 72 error_report("Unable to find CPU definition"); 73 exit(1); 74 } 75 } 76 77 cpus[0]->env.trap_arg0 = ram_size; 78 cpus[0]->env.trap_arg1 = 0; 79 cpus[0]->env.trap_arg2 = smp_cpus; 80 81 /* Init the chipset. */ 82 pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, 83 clipper_pci_map_irq); 84 85 /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ 86 rtc_init(isa_bus, 1900, rtc_irq); 87 88 pit_init(isa_bus, 0x40, 0, NULL); 89 isa_create_simple(isa_bus, "i8042"); 90 91 /* VGA setup. Don't bother loading the bios. */ 92 pci_vga_init(pci_bus); 93 94 /* Serial code setup. */ 95 serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS); 96 97 /* Network setup. e1000 is good enough, failing Tulip support. */ 98 for (i = 0; i < nb_nics; i++) { 99 pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); 100 } 101 102 /* IDE disk setup. */ 103 { 104 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; 105 ide_drive_get(hd, ARRAY_SIZE(hd)); 106 107 pci_cmd646_ide_init(pci_bus, hd, 0); 108 } 109 110 /* Load PALcode. Given that this is not "real" cpu palcode, 111 but one explicitly written for the emulation, we might as 112 well load it directly from and ELF image. */ 113 palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, 114 bios_name ? bios_name : "palcode-clipper"); 115 if (palcode_filename == NULL) { 116 error_report("no palcode provided"); 117 exit(1); 118 } 119 size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys, 120 NULL, &palcode_entry, &palcode_low, &palcode_high, 121 0, EM_ALPHA, 0, 0); 122 if (size < 0) { 123 error_report("could not load palcode '%s'", palcode_filename); 124 exit(1); 125 } 126 g_free(palcode_filename); 127 128 /* Start all cpus at the PALcode RESET entry point. */ 129 for (i = 0; i < smp_cpus; ++i) { 130 cpus[i]->env.pc = palcode_entry; 131 cpus[i]->env.palbr = palcode_entry; 132 } 133 134 /* Load a kernel. */ 135 if (kernel_filename) { 136 uint64_t param_offset; 137 138 size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys, 139 NULL, &kernel_entry, &kernel_low, &kernel_high, 140 0, EM_ALPHA, 0, 0); 141 if (size < 0) { 142 error_report("could not load kernel '%s'", kernel_filename); 143 exit(1); 144 } 145 146 cpus[0]->env.trap_arg1 = kernel_entry; 147 148 param_offset = kernel_low - 0x6000; 149 150 if (kernel_cmdline) { 151 pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); 152 } 153 154 if (initrd_filename) { 155 long initrd_base, initrd_size; 156 157 initrd_size = get_image_size(initrd_filename); 158 if (initrd_size < 0) { 159 error_report("could not load initial ram disk '%s'", 160 initrd_filename); 161 exit(1); 162 } 163 164 /* Put the initrd image as high in memory as possible. */ 165 initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK; 166 load_image_targphys(initrd_filename, initrd_base, 167 ram_size - initrd_base); 168 169 address_space_stq(&address_space_memory, param_offset + 0x100, 170 initrd_base + 0xfffffc0000000000ULL, 171 MEMTXATTRS_UNSPECIFIED, 172 NULL); 173 address_space_stq(&address_space_memory, param_offset + 0x108, 174 initrd_size, MEMTXATTRS_UNSPECIFIED, NULL); 175 } 176 } 177 } 178 179 static void clipper_machine_init(MachineClass *mc) 180 { 181 mc->desc = "Alpha DP264/CLIPPER"; 182 mc->init = clipper_init; 183 mc->block_default_type = IF_IDE; 184 mc->max_cpus = 4; 185 mc->is_default = 1; 186 } 187 188 DEFINE_MACHINE("clipper", clipper_machine_init) 189