blob: 1017ecf330db5aa24bc2d9e5c0e6c38415d2447d [file] [log] [blame]
Richard Henderson80bb2ff2011-08-25 11:38:59 -10001/*
2 * QEMU Alpha DP264/CLIPPER hardware system emulator.
3 *
4 * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
Dong Xu Wang66a0a2c2011-11-29 16:52:39 +08005 * variants because CLIPPER doesn't have an SMC669 SuperIO controller
Richard Henderson80bb2ff2011-08-25 11:38:59 -10006 * that we need to emulate as well.
7 */
8
Peter Maydelle2e5e112016-01-26 18:17:04 +00009#include "qemu/osdep.h"
Paolo Bonzini4771d752016-01-19 21:51:44 +010010#include "qemu-common.h"
11#include "cpu.h"
Richard Henderson80bb2ff2011-08-25 11:38:59 -100012#include "elf.h"
Paolo Bonzini83c9f4c2013-02-04 15:40:22 +010013#include "hw/loader.h"
Paolo Bonzini47b43a12013-03-18 17:36:02 +010014#include "alpha_sys.h"
Markus Armbrusterc5254362015-12-17 17:35:09 +010015#include "qemu/error-report.h"
Philippe Mathieu-Daudébcdb9062019-10-04 01:03:53 +020016#include "hw/rtc/mc146818rtc.h"
Mark Cave-Ayland25297912020-03-07 09:13:12 +000017#include "hw/ide/pci.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010018#include "hw/timer/i8254.h"
Philippe Mathieu-Daudéa4cb7732018-03-08 23:39:45 +010019#include "hw/isa/superio.h"
Philippe Mathieu-Daudéf4564fc02018-03-08 23:39:44 +010020#include "hw/dma/i8257.h"
Paolo Bonzini852c27e2019-12-12 17:15:43 +010021#include "net/net.h"
Veronia Bahaaf348b6d2016-03-20 19:16:19 +020022#include "qemu/cutils.h"
Paolo Bonzini2c65db52020-10-28 07:36:57 -040023#include "qemu/datadir.h"
Philippe Mathieu-Daudéb58337f2020-02-28 12:46:39 +010024#include "net/net.h"
Richard Henderson80bb2ff2011-08-25 11:38:59 -100025
26#define MAX_IDE_BUS 2
27
28static 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
43static 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
Marcel Apfelbaum3ef96222014-05-07 17:42:57 +030052static void clipper_init(MachineState *machine)
Richard Henderson80bb2ff2011-08-25 11:38:59 -100053{
Marcel Apfelbaum3ef96222014-05-07 17:42:57 +030054 ram_addr_t ram_size = machine->ram_size;
Marcel Apfelbaum3ef96222014-05-07 17:42:57 +030055 const char *kernel_filename = machine->kernel_filename;
56 const char *kernel_cmdline = machine->kernel_cmdline;
57 const char *initrd_filename = machine->initrd_filename;
Andreas Färberad601172012-10-16 02:45:53 +020058 AlphaCPU *cpus[4];
Richard Henderson80bb2ff2011-08-25 11:38:59 -100059 PCIBus *pci_bus;
BALATON Zoltanbe1765f2020-03-17 16:05:37 +010060 PCIDevice *pci_dev;
Hervé Poussineau48a18b32011-12-15 22:09:51 +010061 ISABus *isa_bus;
Richard Henderson80bb2ff2011-08-25 11:38:59 -100062 qemu_irq rtc_irq;
63 long size, i;
Shannon Zhaoc18f8552015-05-28 20:39:42 +080064 char *palcode_filename;
BALATON Zoltan617160c2020-07-05 19:22:11 +020065 uint64_t palcode_entry;
66 uint64_t kernel_entry, kernel_low;
Like Xu33decbd2019-05-19 04:54:27 +080067 unsigned int smp_cpus = machine->smp.cpus;
Richard Henderson80bb2ff2011-08-25 11:38:59 -100068
69 /* Create up to 4 cpus. */
70 memset(cpus, 0, sizeof(cpus));
71 for (i = 0; i < smp_cpus; ++i) {
Igor Mammedovfb92da82017-10-05 15:50:39 +020072 cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
Richard Henderson80bb2ff2011-08-25 11:38:59 -100073 }
74
Andreas Färberad601172012-10-16 02:45:53 +020075 cpus[0]->env.trap_arg0 = ram_size;
76 cpus[0]->env.trap_arg1 = 0;
77 cpus[0]->env.trap_arg2 = smp_cpus;
Richard Henderson80bb2ff2011-08-25 11:38:59 -100078
79 /* Init the chipset. */
Igor Mammedovb844d822020-02-19 11:08:42 -050080 pci_bus = typhoon_init(machine->ram, &isa_bus, &rtc_irq, cpus,
Hervé Poussineau71baa302011-12-15 22:09:55 +010081 clipper_pci_map_irq);
Richard Henderson80bb2ff2011-08-25 11:38:59 -100082
Richard Hendersone605e962013-07-13 17:23:37 -070083 /* Since we have an SRM-compatible PALcode, use the SRM epoch. */
Philippe Mathieu-Daudé6c646a12017-10-17 13:44:16 -030084 mc146818_rtc_init(isa_bus, 1900, rtc_irq);
Richard Hendersone605e962013-07-13 17:23:37 -070085
Philippe Mathieu-Daudéacf695e2017-10-17 13:44:15 -030086 i8254_pit_init(isa_bus, 0x40, 0, NULL);
Richard Henderson80bb2ff2011-08-25 11:38:59 -100087
88 /* VGA setup. Don't bother loading the bios. */
Aurelien Jarno606f90c2012-09-08 12:16:28 +020089 pci_vga_init(pci_bus);
Richard Henderson80bb2ff2011-08-25 11:38:59 -100090
Richard Henderson80bb2ff2011-08-25 11:38:59 -100091 /* Network setup. e1000 is good enough, failing Tulip support. */
92 for (i = 0; i < nb_nics; i++) {
David Gibson29b358f2013-06-06 18:48:51 +100093 pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL);
Richard Henderson80bb2ff2011-08-25 11:38:59 -100094 }
95
Philippe Mathieu-Daudéf4564fc02018-03-08 23:39:44 +010096 /* 2 82C37 (dma) */
97 isa_create_simple(isa_bus, "i82374");
98
Philippe Mathieu-Daudéa4cb7732018-03-08 23:39:45 +010099 /* Super I/O */
100 isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
101
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000102 /* IDE disk setup. */
BALATON Zoltanbe1765f2020-03-17 16:05:37 +0100103 pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
104 pci_ide_create_devs(pci_dev);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000105
106 /* Load PALcode. Given that this is not "real" cpu palcode,
107 but one explicitly written for the emulation, we might as
108 well load it directly from and ELF image. */
Shannon Zhaoc18f8552015-05-28 20:39:42 +0800109 palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
Paolo Bonzini2c4a83e2020-10-26 10:30:14 -0400110 machine->firmware ?: "palcode-clipper");
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000111 if (palcode_filename == NULL) {
Markus Armbrusterc5254362015-12-17 17:35:09 +0100112 error_report("no palcode provided");
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000113 exit(1);
114 }
Liam Merwick4366e1d2019-01-15 12:18:03 +0000115 size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
BALATON Zoltan617160c2020-07-05 19:22:11 +0200116 NULL, &palcode_entry, NULL, NULL, NULL,
Peter Crosthwaite7ef295e2016-03-04 11:30:21 +0000117 0, EM_ALPHA, 0, 0);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000118 if (size < 0) {
Markus Armbrusterc5254362015-12-17 17:35:09 +0100119 error_report("could not load palcode '%s'", palcode_filename);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000120 exit(1);
121 }
Shannon Zhaoc18f8552015-05-28 20:39:42 +0800122 g_free(palcode_filename);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000123
124 /* Start all cpus at the PALcode RESET entry point. */
125 for (i = 0; i < smp_cpus; ++i) {
Andreas Färberad601172012-10-16 02:45:53 +0200126 cpus[i]->env.pc = palcode_entry;
127 cpus[i]->env.palbr = palcode_entry;
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000128 }
129
130 /* Load a kernel. */
131 if (kernel_filename) {
132 uint64_t param_offset;
133
Liam Merwick4366e1d2019-01-15 12:18:03 +0000134 size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
BALATON Zoltan617160c2020-07-05 19:22:11 +0200135 NULL, &kernel_entry, &kernel_low, NULL, NULL,
Peter Crosthwaite7ef295e2016-03-04 11:30:21 +0000136 0, EM_ALPHA, 0, 0);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000137 if (size < 0) {
Markus Armbrusterc5254362015-12-17 17:35:09 +0100138 error_report("could not load kernel '%s'", kernel_filename);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000139 exit(1);
140 }
141
Andreas Färberad601172012-10-16 02:45:53 +0200142 cpus[0]->env.trap_arg1 = kernel_entry;
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000143
144 param_offset = kernel_low - 0x6000;
145
146 if (kernel_cmdline) {
147 pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
148 }
149
150 if (initrd_filename) {
Li Zhijianf3839fd2018-09-13 18:07:13 +0800151 long initrd_base;
152 int64_t initrd_size;
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000153
154 initrd_size = get_image_size(initrd_filename);
155 if (initrd_size < 0) {
Markus Armbrusterc5254362015-12-17 17:35:09 +0100156 error_report("could not load initial ram disk '%s'",
157 initrd_filename);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000158 exit(1);
159 }
160
161 /* Put the initrd image as high in memory as possible. */
162 initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
163 load_image_targphys(initrd_filename, initrd_base,
164 ram_size - initrd_base);
165
Peter Maydell42874d32015-04-26 16:49:24 +0100166 address_space_stq(&address_space_memory, param_offset + 0x100,
167 initrd_base + 0xfffffc0000000000ULL,
168 MEMTXATTRS_UNSPECIFIED,
169 NULL);
170 address_space_stq(&address_space_memory, param_offset + 0x108,
171 initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000172 }
173 }
174}
175
Eduardo Habkoste264d292015-09-04 15:37:08 -0300176static void clipper_machine_init(MachineClass *mc)
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000177{
Eduardo Habkoste264d292015-09-04 15:37:08 -0300178 mc->desc = "Alpha DP264/CLIPPER";
179 mc->init = clipper_init;
Markus Armbruster20598392017-02-15 11:05:40 +0100180 mc->block_default_type = IF_IDE;
Eduardo Habkoste264d292015-09-04 15:37:08 -0300181 mc->max_cpus = 4;
Philippe Mathieu-Daudéea0ac7f2020-02-07 17:19:47 +0100182 mc->is_default = true;
Igor Mammedovfb92da82017-10-05 15:50:39 +0200183 mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
Igor Mammedovb844d822020-02-19 11:08:42 -0500184 mc->default_ram_id = "ram";
Richard Henderson80bb2ff2011-08-25 11:38:59 -1000185}
186
Eduardo Habkoste264d292015-09-04 15:37:08 -0300187DEFINE_MACHINE("clipper", clipper_machine_init)