xref: /openbmc/qemu/hw/alpha/dp264.c (revision 29b008927ef6e3fbb70e6607b25d3fcae26a5190)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * QEMU Alpha DP264/CLIPPER hardware system emulator.
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
553018216SPaolo Bonzini  * variants because CLIPPER doesn't have an SMC669 SuperIO controller
653018216SPaolo Bonzini  * that we need to emulate as well.
753018216SPaolo Bonzini  */
853018216SPaolo Bonzini 
9e2e5e114SPeter Maydell #include "qemu/osdep.h"
104771d756SPaolo Bonzini #include "cpu.h"
1153018216SPaolo Bonzini #include "elf.h"
1253018216SPaolo Bonzini #include "hw/loader.h"
1347b43a1fSPaolo Bonzini #include "alpha_sys.h"
14c525436eSMarkus Armbruster #include "qemu/error-report.h"
15bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
1625297910SMark Cave-Ayland #include "hw/ide/pci.h"
17a4cb7739SPhilippe Mathieu-Daudé #include "hw/isa/superio.h"
18852c27e2SPaolo Bonzini #include "net/net.h"
19f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
202c65db5eSPaolo Bonzini #include "qemu/datadir.h"
2153018216SPaolo Bonzini 
cpu_alpha_superpage_to_phys(void * opaque,uint64_t addr)2253018216SPaolo Bonzini static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
2353018216SPaolo Bonzini {
2453018216SPaolo Bonzini     if (((addr >> 41) & 3) == 2) {
2553018216SPaolo Bonzini         addr &= 0xffffffffffull;
2653018216SPaolo Bonzini     }
2753018216SPaolo Bonzini     return addr;
2853018216SPaolo Bonzini }
2953018216SPaolo Bonzini 
3053018216SPaolo Bonzini /* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
3153018216SPaolo Bonzini     (0) The dev_irq_n lines into the cpu, which we totally ignore,
3253018216SPaolo Bonzini     (1) The DRIR lines in the typhoon chipset,
3353018216SPaolo Bonzini     (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
3453018216SPaolo Bonzini     (3) The interrupt number assigned by the kernel.
3553018216SPaolo Bonzini    The following function is concerned with (1) only.  */
3653018216SPaolo Bonzini 
clipper_pci_map_irq(PCIDevice * d,int irq_num)3753018216SPaolo Bonzini static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
3853018216SPaolo Bonzini {
3953018216SPaolo Bonzini     int slot = d->devfn >> 3;
4053018216SPaolo Bonzini 
4153018216SPaolo Bonzini     assert(irq_num >= 0 && irq_num <= 3);
4253018216SPaolo Bonzini 
4353018216SPaolo Bonzini     return (slot + 1) * 4 + irq_num;
4453018216SPaolo Bonzini }
4553018216SPaolo Bonzini 
clipper_init(MachineState * machine)463ef96221SMarcel Apfelbaum static void clipper_init(MachineState *machine)
4753018216SPaolo Bonzini {
483ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
493ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
503ef96221SMarcel Apfelbaum     const char *kernel_cmdline = machine->kernel_cmdline;
513ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
52cdd684b8SThomas Huth     MachineClass *mc = MACHINE_GET_CLASS(machine);
5353018216SPaolo Bonzini     AlphaCPU *cpus[4];
5453018216SPaolo Bonzini     PCIBus *pci_bus;
55be1765f3SBALATON Zoltan     PCIDevice *pci_dev;
565ec4f1d3SJason Thorpe     DeviceState *i82378_dev;
5753018216SPaolo Bonzini     ISABus *isa_bus;
5853018216SPaolo Bonzini     qemu_irq rtc_irq;
595ec4f1d3SJason Thorpe     qemu_irq isa_irq;
6053018216SPaolo Bonzini     long size, i;
61c18f8556SShannon Zhao     char *palcode_filename;
62617160c9SBALATON Zoltan     uint64_t palcode_entry;
63617160c9SBALATON Zoltan     uint64_t kernel_entry, kernel_low;
6433decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
6553018216SPaolo Bonzini 
6653018216SPaolo Bonzini     /* Create up to 4 cpus.  */
6753018216SPaolo Bonzini     memset(cpus, 0, sizeof(cpus));
6853018216SPaolo Bonzini     for (i = 0; i < smp_cpus; ++i) {
69fb92da84SIgor Mammedov         cpus[i] = ALPHA_CPU(cpu_create(machine->cpu_type));
7053018216SPaolo Bonzini     }
7153018216SPaolo Bonzini 
72387a1dcbSJason Thorpe     /*
73387a1dcbSJason Thorpe      * arg0 -> memory size
74387a1dcbSJason Thorpe      * arg1 -> kernel entry point
75387a1dcbSJason Thorpe      * arg2 -> config word
76387a1dcbSJason Thorpe      *
77387a1dcbSJason Thorpe      * Config word: bits 0-5 -> ncpus
78387a1dcbSJason Thorpe      *              bit  6   -> nographics option (for HWRPB CTB)
79387a1dcbSJason Thorpe      *
80387a1dcbSJason Thorpe      * See init_hwrpb() in the PALcode.
81387a1dcbSJason Thorpe      */
8253018216SPaolo Bonzini     cpus[0]->env.trap_arg0 = ram_size;
8353018216SPaolo Bonzini     cpus[0]->env.trap_arg1 = 0;
84387a1dcbSJason Thorpe     cpus[0]->env.trap_arg2 = smp_cpus | (!machine->enable_graphics << 6);
8553018216SPaolo Bonzini 
863a8233dcSJason Thorpe     /*
873a8233dcSJason Thorpe      * Init the chipset.  Because we're using CLIPPER IRQ mappings,
883a8233dcSJason Thorpe      * the minimum PCI device IdSel is 1.
893a8233dcSJason Thorpe      */
905ec4f1d3SJason Thorpe     pci_bus = typhoon_init(machine->ram, &isa_irq, &rtc_irq, cpus,
913a8233dcSJason Thorpe                            clipper_pci_map_irq, PCI_DEVFN(1, 0));
9253018216SPaolo Bonzini 
935ec4f1d3SJason Thorpe     /*
945ec4f1d3SJason Thorpe      * Init the PCI -> ISA bridge.
955ec4f1d3SJason Thorpe      *
965ec4f1d3SJason Thorpe      * Technically, PCI-based Alphas shipped with one of three different
975ec4f1d3SJason Thorpe      * PCI-ISA bridges:
985ec4f1d3SJason Thorpe      *
995ec4f1d3SJason Thorpe      * - Intel i82378 SIO
1005ec4f1d3SJason Thorpe      * - Cypress CY82c693UB
1015ec4f1d3SJason Thorpe      * - ALI M1533
1025ec4f1d3SJason Thorpe      *
1035ec4f1d3SJason Thorpe      * (An Intel i82375 PCI-EISA bridge was also used on some models.)
1045ec4f1d3SJason Thorpe      *
1055ec4f1d3SJason Thorpe      * For simplicity, we model an i82378 here, even though it wouldn't
1065ec4f1d3SJason Thorpe      * have been on any Tsunami/Typhoon systems; it's close enough, and
1075ec4f1d3SJason Thorpe      * we don't want to deal with modelling the CY82c693UB (which has
1085ec4f1d3SJason Thorpe      * incompatible edge/level control registers, plus other peripherals
1095ec4f1d3SJason Thorpe      * like IDE and USB) or the M1533 (which also has IDE and USB).
1105ec4f1d3SJason Thorpe      *
1115ec4f1d3SJason Thorpe      * Importantly, we need to provide a PCI device node for it, otherwise
1125ec4f1d3SJason Thorpe      * some operating systems won't notice there's an ISA bus to configure.
1135ec4f1d3SJason Thorpe      */
1145ec4f1d3SJason Thorpe     i82378_dev = DEVICE(pci_create_simple(pci_bus, PCI_DEVFN(7, 0), "i82378"));
1155ec4f1d3SJason Thorpe     isa_bus = ISA_BUS(qdev_get_child_bus(i82378_dev, "isa.0"));
1165ec4f1d3SJason Thorpe 
1175ec4f1d3SJason Thorpe     /* Connect the ISA PIC to the Typhoon IRQ used for ISA interrupts. */
1185ec4f1d3SJason Thorpe     qdev_connect_gpio_out(i82378_dev, 0, isa_irq);
1195ec4f1d3SJason Thorpe 
120e605e969SRichard Henderson     /* Since we have an SRM-compatible PALcode, use the SRM epoch.  */
1216c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(isa_bus, 1900, rtc_irq);
122e605e969SRichard Henderson 
12353018216SPaolo Bonzini     /* VGA setup.  Don't bother loading the bios.  */
12453018216SPaolo Bonzini     pci_vga_init(pci_bus);
12553018216SPaolo Bonzini 
12653018216SPaolo Bonzini     /* Network setup.  e1000 is good enough, failing Tulip support.  */
127*861bbc88SDavid Woodhouse     pci_init_nic_devices(pci_bus, mc->default_nic);
12853018216SPaolo Bonzini 
129a4cb7739SPhilippe Mathieu-Daudé     /* Super I/O */
130a4cb7739SPhilippe Mathieu-Daudé     isa_create_simple(isa_bus, TYPE_SMC37C669_SUPERIO);
131a4cb7739SPhilippe Mathieu-Daudé 
13253018216SPaolo Bonzini     /* IDE disk setup.  */
13325297910SMark Cave-Ayland     pci_dev = pci_create_simple(pci_bus, -1, "cmd646-ide");
134be1765f3SBALATON Zoltan     pci_ide_create_devs(pci_dev);
13553018216SPaolo Bonzini 
13653018216SPaolo Bonzini     /* Load PALcode.  Given that this is not "real" cpu palcode,
13753018216SPaolo Bonzini        but one explicitly written for the emulation, we might as
13853018216SPaolo Bonzini        well load it directly from and ELF image.  */
139c18f8556SShannon Zhao     palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
1402c4a83ebSPaolo Bonzini                                       machine->firmware ?: "palcode-clipper");
14153018216SPaolo Bonzini     if (palcode_filename == NULL) {
142c525436eSMarkus Armbruster         error_report("no palcode provided");
14353018216SPaolo Bonzini         exit(1);
14453018216SPaolo Bonzini     }
1454366e1dbSLiam Merwick     size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
146617160c9SBALATON Zoltan                     NULL, &palcode_entry, NULL, NULL, NULL,
1477ef295eaSPeter Crosthwaite                     0, EM_ALPHA, 0, 0);
14853018216SPaolo Bonzini     if (size < 0) {
149c525436eSMarkus Armbruster         error_report("could not load palcode '%s'", palcode_filename);
15053018216SPaolo Bonzini         exit(1);
15153018216SPaolo Bonzini     }
152c18f8556SShannon Zhao     g_free(palcode_filename);
15353018216SPaolo Bonzini 
15453018216SPaolo Bonzini     /* Start all cpus at the PALcode RESET entry point.  */
15553018216SPaolo Bonzini     for (i = 0; i < smp_cpus; ++i) {
15653018216SPaolo Bonzini         cpus[i]->env.pc = palcode_entry;
15753018216SPaolo Bonzini         cpus[i]->env.palbr = palcode_entry;
15853018216SPaolo Bonzini     }
15953018216SPaolo Bonzini 
16053018216SPaolo Bonzini     /* Load a kernel.  */
16153018216SPaolo Bonzini     if (kernel_filename) {
16253018216SPaolo Bonzini         uint64_t param_offset;
16353018216SPaolo Bonzini 
1644366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
165617160c9SBALATON Zoltan                         NULL, &kernel_entry, &kernel_low, NULL, NULL,
1667ef295eaSPeter Crosthwaite                         0, EM_ALPHA, 0, 0);
16753018216SPaolo Bonzini         if (size < 0) {
168c525436eSMarkus Armbruster             error_report("could not load kernel '%s'", kernel_filename);
16953018216SPaolo Bonzini             exit(1);
17053018216SPaolo Bonzini         }
17153018216SPaolo Bonzini 
17253018216SPaolo Bonzini         cpus[0]->env.trap_arg1 = kernel_entry;
17353018216SPaolo Bonzini 
17453018216SPaolo Bonzini         param_offset = kernel_low - 0x6000;
17553018216SPaolo Bonzini 
17653018216SPaolo Bonzini         if (kernel_cmdline) {
17753018216SPaolo Bonzini             pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
17853018216SPaolo Bonzini         }
17953018216SPaolo Bonzini 
18053018216SPaolo Bonzini         if (initrd_filename) {
181f3839fdaSLi Zhijian             long initrd_base;
182f3839fdaSLi Zhijian             int64_t initrd_size;
18353018216SPaolo Bonzini 
18453018216SPaolo Bonzini             initrd_size = get_image_size(initrd_filename);
18553018216SPaolo Bonzini             if (initrd_size < 0) {
186c525436eSMarkus Armbruster                 error_report("could not load initial ram disk '%s'",
18753018216SPaolo Bonzini                              initrd_filename);
18853018216SPaolo Bonzini                 exit(1);
18953018216SPaolo Bonzini             }
19053018216SPaolo Bonzini 
19153018216SPaolo Bonzini             /* Put the initrd image as high in memory as possible.  */
19253018216SPaolo Bonzini             initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
19353018216SPaolo Bonzini             load_image_targphys(initrd_filename, initrd_base,
19453018216SPaolo Bonzini                                 ram_size - initrd_base);
19553018216SPaolo Bonzini 
19642874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x100,
19742874d3aSPeter Maydell                               initrd_base + 0xfffffc0000000000ULL,
19842874d3aSPeter Maydell                               MEMTXATTRS_UNSPECIFIED,
19942874d3aSPeter Maydell                               NULL);
20042874d3aSPeter Maydell             address_space_stq(&address_space_memory, param_offset + 0x108,
20142874d3aSPeter Maydell                               initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
20253018216SPaolo Bonzini         }
20353018216SPaolo Bonzini     }
20453018216SPaolo Bonzini }
20553018216SPaolo Bonzini 
clipper_machine_init(MachineClass * mc)206e264d29dSEduardo Habkost static void clipper_machine_init(MachineClass *mc)
20753018216SPaolo Bonzini {
208e264d29dSEduardo Habkost     mc->desc = "Alpha DP264/CLIPPER";
209e264d29dSEduardo Habkost     mc->init = clipper_init;
2102059839bSMarkus Armbruster     mc->block_default_type = IF_IDE;
211e264d29dSEduardo Habkost     mc->max_cpus = 4;
212ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
213fb92da84SIgor Mammedov     mc->default_cpu_type = ALPHA_CPU_TYPE_NAME("ev67");
214b844d822SIgor Mammedov     mc->default_ram_id = "ram";
215cdd684b8SThomas Huth     mc->default_nic = "e1000";
21653018216SPaolo Bonzini }
21753018216SPaolo Bonzini 
218e264d29dSEduardo Habkost DEFINE_MACHINE("clipper", clipper_machine_init)
219