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/isa/superio.h" 23 #include "hw/dma/i8257.h" 24 #include "qemu/cutils.h" 25 26 #define MAX_IDE_BUS 2 27 28 static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr) 29 { 30 if (((addr >> 41) & 3) == 2) { 31 addr &= 0xffffffffffull; 32 } 33 return addr; 34 } 35 36 /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems. 37 (0) The dev_irq_n lines into the cpu, which we totally ignore, 38 (1) The DRIR lines in the typhoon chipset, 39 (2) The "vector" aka mangled interrupt number reported by SRM PALcode, 40 (3) The interrupt number assigned by the kernel. 41 The following function is concerned with (1) only. */ 42 43 static int clipper_pci_map_irq(PCIDevice *d, int irq_num) 44 { 45 int slot = d->devfn >> 3; 46 47 assert(irq_num >= 0 && irq_num <= 3); 48 49 return (slot + 1) * 4 + irq_num; 50 } 51 52 static void clipper_init(MachineState *machine) 53 { 54 ram_addr_t ram_size = machine->ram_size; 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 unsigned int smp_cpus = machine->smp.cpus; 67 68 /* Create up to 4 cpus. */ 69 memset(cpus, 0, sizeof(cpus)); 70 for (i = 0; i < smp_cpus; ++i) { 71 cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type)); 72 } 73 74 cpus[0]->env.trap_arg0 = ram_size; 75 cpus[0]->env.trap_arg1 = 0; 76 cpus[0]->env.trap_arg2 = smp_cpus; 77 78 /* Init the chipset. */ 79 pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, 80 clipper_pci_map_irq); 81 82 /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ 83 mc146818_rtc_init(isa_bus, 1900, rtc_irq); 84 85 i8254_pit_init(isa_bus, 0x40, 0, NULL); 86 87 /* VGA setup. Don't bother loading the bios. */ 88 pci_vga_init(pci_bus); 89 90 /* Network setup. e1000 is good enough, failing Tulip support. */ 91 for (i = 0; i < nb_nics; i++) { 92 pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); 93 } 94 95 /* 2 82C37 (dma) */ 96 isa_create_simple(isa_bus, "i82374"); 97 98 /* Super I/O */ 99 isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO); 100 101 /* IDE disk setup. */ 102 { 103 DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; 104 ide_drive_get(hd, ARRAY_SIZE(hd)); 105 106 pci_cmd646_ide_init(pci_bus, hd, 0); 107 } 108 109 /* Load PALcode. Given that this is not "real" cpu palcode, 110 but one explicitly written for the emulation, we might as 111 well load it directly from and ELF image. */ 112 palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, 113 bios_name ? bios_name : "palcode-clipper"); 114 if (palcode_filename == NULL) { 115 error_report("no palcode provided"); 116 exit(1); 117 } 118 size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys, 119 NULL, &palcode_entry, &palcode_low, &palcode_high, 120 0, EM_ALPHA, 0, 0); 121 if (size < 0) { 122 error_report("could not load palcode '%s'", palcode_filename); 123 exit(1); 124 } 125 g_free(palcode_filename); 126 127 /* Start all cpus at the PALcode RESET entry point. */ 128 for (i = 0; i < smp_cpus; ++i) { 129 cpus[i]->env.pc = palcode_entry; 130 cpus[i]->env.palbr = palcode_entry; 131 } 132 133 /* Load a kernel. */ 134 if (kernel_filename) { 135 uint64_t param_offset; 136 137 size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys, 138 NULL, &kernel_entry, &kernel_low, &kernel_high, 139 0, EM_ALPHA, 0, 0); 140 if (size < 0) { 141 error_report("could not load kernel '%s'", kernel_filename); 142 exit(1); 143 } 144 145 cpus[0]->env.trap_arg1 = kernel_entry; 146 147 param_offset = kernel_low - 0x6000; 148 149 if (kernel_cmdline) { 150 pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline); 151 } 152 153 if (initrd_filename) { 154 long initrd_base; 155 int64_t 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 mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67"); 187 } 188 189 DEFINE_MACHINE("clipper", clipper_machine_init) 190