180bb2ff7SRichard Henderson /*
280bb2ff7SRichard Henderson * QEMU Alpha DP264/CLIPPER hardware system emulator.
380bb2ff7SRichard Henderson *
480bb2ff7SRichard Henderson * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
566a0a2cbSDong Xu Wang * variants because CLIPPER doesn't have an SMC669 SuperIO controller
680bb2ff7SRichard Henderson * that we need to emulate as well.
780bb2ff7SRichard Henderson */
880bb2ff7SRichard Henderson
9e2e5e114SPeter Maydell #include "qemu/osdep.h"
104771d756SPaolo Bonzini #include "cpu.h"
11*9c2ff9cdSPierrick Bouvier #include "exec/target_page.h"
1280bb2ff7SRichard Henderson #include "elf.h"
1383c9f4caSPaolo Bonzini #include "hw/loader.h"
1447b43a1fSPaolo Bonzini #include "alpha_sys.h"
15c525436eSMarkus Armbruster #include "qemu/error-report.h"
16bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
1725297910SMark Cave-Ayland #include "hw/ide/pci.h"
18a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h"
19852c27e2SPaolo Bonzini #include "net/net.h"
20f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
212c65db5eSPaolo Bonzini #include "qemu/datadir.h"
2280bb2ff7SRichard Henderson
cpu_alpha_superpage_to_phys(void * opaque,uint64_t addr)2380bb2ff7SRichard Henderson static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
2480bb2ff7SRichard Henderson {
2580bb2ff7SRichard Henderson if (((addr >> 41) & 3) == 2) {
2680bb2ff7SRichard Henderson addr &= 0xffffffffffull;
2780bb2ff7SRichard Henderson }
2880bb2ff7SRichard Henderson return addr;
2980bb2ff7SRichard Henderson }
3080bb2ff7SRichard Henderson
3180bb2ff7SRichard Henderson /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
3280bb2ff7SRichard Henderson (0) The dev_irq_n lines into the cpu, which we totally ignore,
3380bb2ff7SRichard Henderson (1) The DRIR lines in the typhoon chipset,
3480bb2ff7SRichard Henderson (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
3580bb2ff7SRichard Henderson (3) The interrupt number assigned by the kernel.
3680bb2ff7SRichard Henderson The following function is concerned with (1) only. */
3780bb2ff7SRichard Henderson
clipper_pci_map_irq(PCIDevice * d,int irq_num)3880bb2ff7SRichard Henderson static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
3980bb2ff7SRichard Henderson {
4080bb2ff7SRichard Henderson int slot = d->devfn >> 3;
4180bb2ff7SRichard Henderson
4280bb2ff7SRichard Henderson assert(irq_num >= 0 && irq_num <= 3);
4380bb2ff7SRichard Henderson
4480bb2ff7SRichard Henderson return (slot + 1) * 4 + irq_num;
4580bb2ff7SRichard Henderson }
4680bb2ff7SRichard Henderson
clipper_init(MachineState * machine)473ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine)
4880bb2ff7SRichard Henderson {
493ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size;
503ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename;
513ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline;
523ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename;
53cdd684b8SThomas Huth MachineClass *mc = MACHINE_GET_CLASS(machine);
54ad601177SAndreas Färber AlphaCPU *cpus[4];
5580bb2ff7SRichard Henderson PCIBus *pci_bus;
56be1765f3SBALATON Zoltan PCIDevice *pci_dev;
575ec4f1d3SJason Thorpe DeviceState *i82378_dev;
5848a18b3cSHervé Poussineau ISABus *isa_bus;
5980bb2ff7SRichard Henderson qemu_irq rtc_irq;
605ec4f1d3SJason Thorpe qemu_irq isa_irq;
6180bb2ff7SRichard Henderson long size, i;
62c18f8556SShannon Zhao char *palcode_filename;
63617160c9SBALATON Zoltan uint64_t palcode_entry;
64617160c9SBALATON Zoltan uint64_t kernel_entry, kernel_low;
6533decbd2SLike Xu unsigned int smp_cpus = machine->smp.cpus;
6680bb2ff7SRichard Henderson
6780bb2ff7SRichard Henderson /* Create up to 4 cpus. */
6880bb2ff7SRichard Henderson memset(cpus, 0, sizeof(cpus));
6980bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) {
70fb92da84SIgor Mammedov cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
7180bb2ff7SRichard Henderson }
7280bb2ff7SRichard Henderson
73387a1dcbSJason Thorpe /*
74387a1dcbSJason Thorpe * arg0 -> memory size
75387a1dcbSJason Thorpe * arg1 -> kernel entry point
76387a1dcbSJason Thorpe * arg2 -> config word
77387a1dcbSJason Thorpe *
78387a1dcbSJason Thorpe * Config word: bits 0-5 -> ncpus
79387a1dcbSJason Thorpe * bit 6 -> nographics option (for HWRPB CTB)
80387a1dcbSJason Thorpe *
81387a1dcbSJason Thorpe * See init_hwrpb() in the PALcode.
82387a1dcbSJason Thorpe */
83ad601177SAndreas Färber cpus[0]->env.trap_arg0 = ram_size;
84ad601177SAndreas Färber cpus[0]->env.trap_arg1 = 0;
85387a1dcbSJason Thorpe cpus[0]->env.trap_arg2 = smp_cpus | (!machine->enable_graphics << 6);
8680bb2ff7SRichard Henderson
873a8233dcSJason Thorpe /*
883a8233dcSJason Thorpe * Init the chipset. Because we're using CLIPPER IRQ mappings,
893a8233dcSJason Thorpe * the minimum PCI device IdSel is 1.
903a8233dcSJason Thorpe */
915ec4f1d3SJason Thorpe pci_bus = typhoon_init(machine->ram, &isa_irq, &rtc_irq, cpus,
923a8233dcSJason Thorpe clipper_pci_map_irq, PCI_DEVFN(1, 0));
9380bb2ff7SRichard Henderson
945ec4f1d3SJason Thorpe /*
955ec4f1d3SJason Thorpe * Init the PCI -> ISA bridge.
965ec4f1d3SJason Thorpe *
975ec4f1d3SJason Thorpe * Technically, PCI-based Alphas shipped with one of three different
985ec4f1d3SJason Thorpe * PCI-ISA bridges:
995ec4f1d3SJason Thorpe *
1005ec4f1d3SJason Thorpe * - Intel i82378 SIO
1015ec4f1d3SJason Thorpe * - Cypress CY82c693UB
1025ec4f1d3SJason Thorpe * - ALI M1533
1035ec4f1d3SJason Thorpe *
1045ec4f1d3SJason Thorpe * (An Intel i82375 PCI-EISA bridge was also used on some models.)
1055ec4f1d3SJason Thorpe *
1065ec4f1d3SJason Thorpe * For simplicity, we model an i82378 here, even though it wouldn't
1075ec4f1d3SJason Thorpe * have been on any Tsunami/Typhoon systems; it's close enough, and
1085ec4f1d3SJason Thorpe * we don't want to deal with modelling the CY82c693UB (which has
1095ec4f1d3SJason Thorpe * incompatible edge/level control registers, plus other peripherals
1105ec4f1d3SJason Thorpe * like IDE and USB) or the M1533 (which also has IDE and USB).
1115ec4f1d3SJason Thorpe *
1125ec4f1d3SJason Thorpe * Importantly, we need to provide a PCI device node for it, otherwise
1135ec4f1d3SJason Thorpe * some operating systems won't notice there's an ISA bus to configure.
1145ec4f1d3SJason Thorpe */
1155ec4f1d3SJason Thorpe i82378_dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(7, 0), "i82378"));
1165ec4f1d3SJason Thorpe isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0"));
1175ec4f1d3SJason Thorpe
1185ec4f1d3SJason Thorpe /* Connect the ISA PIC to the Typhoon IRQ used for ISA interrupts. */
1195ec4f1d3SJason Thorpe qdev_connect_gpio_out(i82378_dev, 0, isa_irq);
1205ec4f1d3SJason Thorpe
121e605e969SRichard Henderson /* Since we have an SRM-compatible PALcode, use the SRM epoch. */
1226c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(isa_bus, 1900, rtc_irq);
123e605e969SRichard Henderson
12480bb2ff7SRichard Henderson /* VGA setup. Don't bother loading the bios. */
125606f90ccSAurelien Jarno pci_vga_init(pci_bus);
12680bb2ff7SRichard Henderson
12780bb2ff7SRichard Henderson /* Network setup. e1000 is good enough, failing Tulip support. */
128861bbc88SDavid Woodhouse pci_init_nic_devices(pci_bus, mc->default_nic);
12980bb2ff7SRichard Henderson
130a4cb7739SPhilippe Mathieu-Daudé /* Super I/O */
131a4cb7739SPhilippe Mathieu-Daudé isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
132a4cb7739SPhilippe Mathieu-Daudé
13380bb2ff7SRichard Henderson /* IDE disk setup. */
13425297910SMark Cave-Ayland pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
135be1765f3SBALATON Zoltan pci_ide_create_devs(pci_dev);
13680bb2ff7SRichard Henderson
13780bb2ff7SRichard Henderson /* Load PALcode. Given that this is not "real" cpu palcode,
13880bb2ff7SRichard Henderson but one explicitly written for the emulation, we might as
13980bb2ff7SRichard Henderson well load it directly from and ELF image. */
140c18f8556SShannon Zhao palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
1412c4a83ebSPaolo Bonzini machine->firmware ?: "palcode-clipper");
14280bb2ff7SRichard Henderson if (palcode_filename == NULL) {
143c525436eSMarkus Armbruster error_report("no palcode provided");
14480bb2ff7SRichard Henderson exit(1);
14580bb2ff7SRichard Henderson }
1464366e1dbSLiam Merwick size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
147617160c9SBALATON Zoltan NULL, &palcode_entry, NULL, NULL, NULL,
148adc1a4a2SPhilippe Mathieu-Daudé ELFDATA2LSB, EM_ALPHA, 0, 0);
14980bb2ff7SRichard Henderson if (size < 0) {
150c525436eSMarkus Armbruster error_report("could not load palcode '%s'", palcode_filename);
15180bb2ff7SRichard Henderson exit(1);
15280bb2ff7SRichard Henderson }
153c18f8556SShannon Zhao g_free(palcode_filename);
15480bb2ff7SRichard Henderson
15580bb2ff7SRichard Henderson /* Start all cpus at the PALcode RESET entry point. */
15680bb2ff7SRichard Henderson for (i = 0; i < smp_cpus; ++i) {
157ad601177SAndreas Färber cpus[i]->env.pc = palcode_entry;
158ad601177SAndreas Färber cpus[i]->env.palbr = palcode_entry;
15980bb2ff7SRichard Henderson }
16080bb2ff7SRichard Henderson
16180bb2ff7SRichard Henderson /* Load a kernel. */
16280bb2ff7SRichard Henderson if (kernel_filename) {
16380bb2ff7SRichard Henderson uint64_t param_offset;
16480bb2ff7SRichard Henderson
1654366e1dbSLiam Merwick size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
166617160c9SBALATON Zoltan NULL, &kernel_entry, &kernel_low, NULL, NULL,
167adc1a4a2SPhilippe Mathieu-Daudé ELFDATA2LSB, EM_ALPHA, 0, 0);
16880bb2ff7SRichard Henderson if (size < 0) {
169c525436eSMarkus Armbruster error_report("could not load kernel '%s'", kernel_filename);
17080bb2ff7SRichard Henderson exit(1);
17180bb2ff7SRichard Henderson }
17280bb2ff7SRichard Henderson
173ad601177SAndreas Färber cpus[0]->env.trap_arg1 = kernel_entry;
17480bb2ff7SRichard Henderson
17580bb2ff7SRichard Henderson param_offset = kernel_low - 0x6000;
17680bb2ff7SRichard Henderson
17780bb2ff7SRichard Henderson if (kernel_cmdline) {
17880bb2ff7SRichard Henderson pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
17980bb2ff7SRichard Henderson }
18080bb2ff7SRichard Henderson
18180bb2ff7SRichard Henderson if (initrd_filename) {
182f3839fdaSLi Zhijian long initrd_base;
183f3839fdaSLi Zhijian int64_t initrd_size;
18480bb2ff7SRichard Henderson
18580bb2ff7SRichard Henderson initrd_size = get_image_size(initrd_filename);
18680bb2ff7SRichard Henderson if (initrd_size < 0) {
187c525436eSMarkus Armbruster error_report("could not load initial ram disk '%s'",
18880bb2ff7SRichard Henderson initrd_filename);
18980bb2ff7SRichard Henderson exit(1);
19080bb2ff7SRichard Henderson }
19180bb2ff7SRichard Henderson
19280bb2ff7SRichard Henderson /* Put the initrd image as high in memory as possible. */
19380bb2ff7SRichard Henderson initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
19480bb2ff7SRichard Henderson load_image_targphys(initrd_filename, initrd_base,
19580bb2ff7SRichard Henderson ram_size - initrd_base);
19680bb2ff7SRichard Henderson
19742874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x100,
19842874d3aSPeter Maydell initrd_base + 0xfffffc0000000000ULL,
19942874d3aSPeter Maydell MEMTXATTRS_UNSPECIFIED,
20042874d3aSPeter Maydell NULL);
20142874d3aSPeter Maydell address_space_stq(&address_space_memory, param_offset + 0x108,
20242874d3aSPeter Maydell initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
20380bb2ff7SRichard Henderson }
20480bb2ff7SRichard Henderson }
20580bb2ff7SRichard Henderson }
20680bb2ff7SRichard Henderson
clipper_machine_init(MachineClass * mc)207e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
20880bb2ff7SRichard Henderson {
209e264d29dSEduardo Habkost mc->desc = "Alpha DP264/CLIPPER";
210e264d29dSEduardo Habkost mc->init = clipper_init;
2112059839bSMarkus Armbruster mc->block_default_type = IF_IDE;
212e264d29dSEduardo Habkost mc->max_cpus = 4;
213ea0ac7f6SPhilippe Mathieu-Daudé mc->is_default = true;
214fb92da84SIgor Mammedov mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
215b844d822SIgor Mammedov mc->default_ram_id = "ram";
216cdd684b8SThomas Huth mc->default_nic = "e1000";
21780bb2ff7SRichard Henderson }
21880bb2ff7SRichard Henderson
219e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
220