xref: /openbmc/qemu/hw/hppa/machine.c (revision 7df6f7511769af63c209d2fdcd6c7638f680e35a)
1813dff13SHelge Deller /*
2813dff13SHelge Deller  * QEMU HPPA hardware system emulator.
3a536f564SHelge Deller  * (C) Copyright 2018-2023 Helge Deller <deller@gmx.de>
4a536f564SHelge Deller  *
5a536f564SHelge Deller  * This work is licensed under the GNU GPL license version 2 or later.
6813dff13SHelge Deller  */
7813dff13SHelge Deller 
8813dff13SHelge Deller #include "qemu/osdep.h"
92c65db5eSPaolo Bonzini #include "qemu/datadir.h"
10813dff13SHelge Deller #include "cpu.h"
11813dff13SHelge Deller #include "elf.h"
12813dff13SHelge Deller #include "hw/loader.h"
13813dff13SHelge Deller #include "qemu/error-report.h"
1471e8a915SMarkus Armbruster #include "sysemu/reset.h"
15813dff13SHelge Deller #include "sysemu/sysemu.h"
16b28c4a64SHelge Deller #include "sysemu/runstate.h"
17bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
18813dff13SHelge Deller #include "hw/timer/i8254.h"
19813dff13SHelge Deller #include "hw/char/serial.h"
209701e569SMark Cave-Ayland #include "hw/char/parallel.h"
21134ba73fSMark Cave-Ayland #include "hw/intc/i8259.h"
22d26c575cSMark Cave-Ayland #include "hw/input/lasips2.h"
23376b8519SHelge Deller #include "hw/net/lasi_82596.h"
244a4554c6SHelge Deller #include "hw/nmi.h"
25134ba73fSMark Cave-Ayland #include "hw/pci/pci.h"
26*7df6f751SHelge Deller #include "hw/pci/pci_device.h"
270db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
2845f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
29148da670SMark Cave-Ayland #include "hppa_hardware.h"
30c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
31813dff13SHelge Deller #include "qapi/error.h"
32852c27e2SPaolo Bonzini #include "net/net.h"
33691cbbadSRichard Henderson #include "qemu/log.h"
34813dff13SHelge Deller 
35a536f564SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 10 /* require at least this fw version */
3628b71a2eSHelge Deller 
37b28c4a64SHelge Deller #define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
38b28c4a64SHelge Deller 
39932befaaSMark Cave-Ayland #define enable_lasi_lan()       0
40932befaaSMark Cave-Ayland 
41*7df6f751SHelge Deller static DeviceState *lasi_dev;
42932befaaSMark Cave-Ayland 
43b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
44b28c4a64SHelge Deller {
45b28c4a64SHelge Deller     hwaddr soft_power_reg = HPA_POWER_BUTTON;
46b28c4a64SHelge Deller     uint32_t val;
47b28c4a64SHelge Deller 
48b28c4a64SHelge Deller     val = ldl_be_phys(&address_space_memory, soft_power_reg);
49b28c4a64SHelge Deller     if ((val >> 8) == 0) {
50b28c4a64SHelge Deller         /* immediately shut down when under hardware control */
51b28c4a64SHelge Deller         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
52b28c4a64SHelge Deller         return;
53b28c4a64SHelge Deller     }
54b28c4a64SHelge Deller 
55b28c4a64SHelge Deller     /* clear bit 31 to indicate that the power switch was pressed. */
56b28c4a64SHelge Deller     val &= ~1;
57b28c4a64SHelge Deller     stl_be_phys(&address_space_memory, soft_power_reg, val);
58b28c4a64SHelge Deller }
59b28c4a64SHelge Deller 
60b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
61b28c4a64SHelge Deller     .notify = hppa_powerdown_req
62b28c4a64SHelge Deller };
63b28c4a64SHelge Deller 
6428f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
6528f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
6628f5332aSMark Cave-Ayland {
6728f5332aSMark Cave-Ayland     return 0;
6828f5332aSMark Cave-Ayland }
6928f5332aSMark Cave-Ayland 
7028f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
7128f5332aSMark Cave-Ayland {
7228f5332aSMark Cave-Ayland }
7328f5332aSMark Cave-Ayland 
7428f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7528f5332aSMark Cave-Ayland     .read = ignore_read,
7628f5332aSMark Cave-Ayland     .write = ignore_write,
7728f5332aSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
7828f5332aSMark Cave-Ayland     .valid = {
7928f5332aSMark Cave-Ayland         .min_access_size = 1,
8028f5332aSMark Cave-Ayland         .max_access_size = 8,
8128f5332aSMark Cave-Ayland     },
8228f5332aSMark Cave-Ayland     .impl = {
8328f5332aSMark Cave-Ayland         .min_access_size = 1,
8428f5332aSMark Cave-Ayland         .max_access_size = 8,
8528f5332aSMark Cave-Ayland     },
8628f5332aSMark Cave-Ayland };
87b28c4a64SHelge Deller 
88a72bd606SHelge Deller static ISABus *hppa_isa_bus(void)
89a72bd606SHelge Deller {
90a72bd606SHelge Deller     ISABus *isa_bus;
91a72bd606SHelge Deller     qemu_irq *isa_irqs;
92a72bd606SHelge Deller     MemoryRegion *isa_region;
93a72bd606SHelge Deller 
94a72bd606SHelge Deller     isa_region = g_new(MemoryRegion, 1);
95a72bd606SHelge Deller     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
96a72bd606SHelge Deller                           NULL, "isa-io", 0x800);
97a72bd606SHelge Deller     memory_region_add_subregion(get_system_memory(), IDE_HPA,
98a72bd606SHelge Deller                                 isa_region);
99a72bd606SHelge Deller 
100a72bd606SHelge Deller     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
101a72bd606SHelge Deller                           &error_abort);
102a536f564SHelge Deller     isa_irqs = i8259_init(isa_bus, NULL);
1037067887eSPhilippe Mathieu-Daudé     isa_bus_register_input_irqs(isa_bus, isa_irqs);
104a72bd606SHelge Deller 
105a72bd606SHelge Deller     return isa_bus;
106a72bd606SHelge Deller }
107a72bd606SHelge Deller 
108e2c41ee5SHelge Deller /*
109e2c41ee5SHelge Deller  * Helper functions to emulate RTC clock and DebugOutputPort
110e2c41ee5SHelge Deller  */
111e2c41ee5SHelge Deller static time_t rtc_ref;
112e2c41ee5SHelge Deller 
113e2c41ee5SHelge Deller static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
114e2c41ee5SHelge Deller {
115e2c41ee5SHelge Deller     uint64_t val = 0;
116e2c41ee5SHelge Deller 
117e2c41ee5SHelge Deller     switch (addr) {
118e2c41ee5SHelge Deller     case 0:             /* RTC clock */
119e2c41ee5SHelge Deller         val = time(NULL);
120e2c41ee5SHelge Deller         val += rtc_ref;
121e2c41ee5SHelge Deller         break;
122e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
123e2c41ee5SHelge Deller         return 0xe9;    /* readback */
124e2c41ee5SHelge Deller     }
125e2c41ee5SHelge Deller     return val;
126e2c41ee5SHelge Deller }
127e2c41ee5SHelge Deller 
128e2c41ee5SHelge Deller static void io_cpu_write(void *opaque, hwaddr addr,
129e2c41ee5SHelge Deller                          uint64_t val, unsigned size)
130e2c41ee5SHelge Deller {
131e2c41ee5SHelge Deller     unsigned char ch;
132e2c41ee5SHelge Deller     Chardev *debugout;
133e2c41ee5SHelge Deller 
134e2c41ee5SHelge Deller     switch (addr) {
135e2c41ee5SHelge Deller     case 0:             /* RTC clock */
136e2c41ee5SHelge Deller         rtc_ref = val - time(NULL);
137e2c41ee5SHelge Deller         break;
138e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
139e2c41ee5SHelge Deller         ch = val;
140e2c41ee5SHelge Deller         debugout = serial_hd(0);
141e2c41ee5SHelge Deller         if (debugout) {
142e2c41ee5SHelge Deller             qemu_chr_fe_write_all(debugout->be, &ch, 1);
143e2c41ee5SHelge Deller         } else {
144e2c41ee5SHelge Deller             fprintf(stderr, "%c", ch);
145e2c41ee5SHelge Deller         }
146e2c41ee5SHelge Deller         break;
147e2c41ee5SHelge Deller     }
148e2c41ee5SHelge Deller }
149e2c41ee5SHelge Deller 
150e2c41ee5SHelge Deller static const MemoryRegionOps hppa_io_helper_ops = {
151e2c41ee5SHelge Deller     .read = io_cpu_read,
152e2c41ee5SHelge Deller     .write = io_cpu_write,
153e2c41ee5SHelge Deller     .endianness = DEVICE_BIG_ENDIAN,
154e2c41ee5SHelge Deller     .valid = {
155e2c41ee5SHelge Deller         .min_access_size = 1,
156e2c41ee5SHelge Deller         .max_access_size = 8,
157e2c41ee5SHelge Deller     },
158e2c41ee5SHelge Deller     .impl = {
159e2c41ee5SHelge Deller         .min_access_size = 1,
160e2c41ee5SHelge Deller         .max_access_size = 8,
161e2c41ee5SHelge Deller     },
162e2c41ee5SHelge Deller };
163e2c41ee5SHelge Deller 
164e2c41ee5SHelge Deller 
165a72bd606SHelge Deller static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr)
166a72bd606SHelge Deller {
167a72bd606SHelge Deller     addr &= (0x10000000 - 1);
168a72bd606SHelge Deller     return addr;
169a72bd606SHelge Deller }
170a72bd606SHelge Deller 
171a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
172a72bd606SHelge Deller static uint64_t firmware_entry;
173813dff13SHelge Deller 
17432ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
17532ff8bf2SHelge Deller                             Error **errp)
17632ff8bf2SHelge Deller {
17732ff8bf2SHelge Deller     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
17832ff8bf2SHelge Deller }
17932ff8bf2SHelge Deller 
180bcd4dd4cSHelge Deller static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus)
18128b71a2eSHelge Deller {
18228b71a2eSHelge Deller     FWCfgState *fw_cfg;
18328b71a2eSHelge Deller     uint64_t val;
184069d2966SHelge Deller     const char qemu_version[] = QEMU_VERSION;
185bcd4dd4cSHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(ms);
186bcd4dd4cSHelge Deller     int len;
18728b71a2eSHelge Deller 
18824576007SHelge Deller     fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4);
18928b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
19028b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
191bfdf22bcSPaolo Bonzini     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
19228b71a2eSHelge Deller 
19328b71a2eSHelge Deller     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
19428b71a2eSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
19528b71a2eSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
19628b71a2eSHelge Deller 
1976d1ef68cSHelge Deller     val = cpu_to_le64(HPPA_TLB_ENTRIES - HPPA_BTLB_ENTRIES);
198df5c6a50SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
199df5c6a50SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
200df5c6a50SHelge Deller 
201bcd4dd4cSHelge Deller     val = cpu_to_le64(HPPA_BTLB_ENTRIES);
202bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
203bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
204bcd4dd4cSHelge Deller 
205bcd4dd4cSHelge Deller     len = strlen(mc->name) + 1;
206bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
207bcd4dd4cSHelge Deller                     g_memdup(mc->name, len), len);
208bcd4dd4cSHelge Deller 
209b28c4a64SHelge Deller     val = cpu_to_le64(HPA_POWER_BUTTON);
210bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
211bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
212bcd4dd4cSHelge Deller 
213e2c41ee5SHelge Deller     val = cpu_to_le64(CPU_HPA + 16);
214e2c41ee5SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
215e2c41ee5SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
216e2c41ee5SHelge Deller 
217bcd4dd4cSHelge Deller     val = cpu_to_le64(CPU_HPA + 24);
218bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
219b28c4a64SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
220b28c4a64SHelge Deller 
22197ec4d21SPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
22232ff8bf2SHelge Deller     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
22332ff8bf2SHelge Deller 
224069d2966SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
225069d2966SHelge Deller                     g_memdup(qemu_version, sizeof(qemu_version)),
226069d2966SHelge Deller                     sizeof(qemu_version));
227069d2966SHelge Deller 
228bcd4dd4cSHelge Deller     fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
229bcd4dd4cSHelge Deller 
23028b71a2eSHelge Deller     return fw_cfg;
23128b71a2eSHelge Deller }
23228b71a2eSHelge Deller 
233e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
234e881e3c8SMark Cave-Ayland {
235e881e3c8SMark Cave-Ayland     DeviceState *dev;
236e881e3c8SMark Cave-Ayland 
237e881e3c8SMark Cave-Ayland     dev = qdev_new(TYPE_LASI_CHIP);
238e881e3c8SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
239e881e3c8SMark Cave-Ayland 
240e881e3c8SMark Cave-Ayland     return LASI_CHIP(dev);
241e881e3c8SMark Cave-Ayland }
242e881e3c8SMark Cave-Ayland 
2430d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
2440d068996SMark Cave-Ayland {
2450d068996SMark Cave-Ayland     DeviceState *dev;
2460d068996SMark Cave-Ayland 
2470d068996SMark Cave-Ayland     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
2480d068996SMark Cave-Ayland     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
2490d068996SMark Cave-Ayland                              &error_fatal);
2500d068996SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2510d068996SMark Cave-Ayland 
2520d068996SMark Cave-Ayland     return DINO_PCI_HOST_BRIDGE(dev);
2530d068996SMark Cave-Ayland }
2540d068996SMark Cave-Ayland 
255*7df6f751SHelge Deller /*
256*7df6f751SHelge Deller  * Step 1: Create CPUs and Memory
257*7df6f751SHelge Deller  */
258*7df6f751SHelge Deller static void machine_HP_common_init_cpus(MachineState *machine)
259813dff13SHelge Deller {
260a72bd606SHelge Deller     MemoryRegion *addr_space = get_system_memory();
261a72bd606SHelge Deller     MemoryRegion *cpu_region;
262a72bd606SHelge Deller     long i;
26333decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
264*7df6f751SHelge Deller     char *name;
265a72bd606SHelge Deller 
266a72bd606SHelge Deller     /* Create CPUs.  */
267a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
268*7df6f751SHelge Deller         name = g_strdup_printf("cpu%ld-io-eir", i);
269a72bd606SHelge Deller         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
270a72bd606SHelge Deller 
271a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
272a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
273266a880eSPaolo Bonzini                               cpu[i], name, 4);
274a72bd606SHelge Deller         memory_region_add_subregion(addr_space, CPU_HPA + i * 0x1000,
275a72bd606SHelge Deller                                     cpu_region);
276266a880eSPaolo Bonzini         g_free(name);
277813dff13SHelge Deller     }
278813dff13SHelge Deller 
279e2c41ee5SHelge Deller     /* RTC and DebugOutputPort on CPU #0 */
280e2c41ee5SHelge Deller     cpu_region = g_new(MemoryRegion, 1);
281e2c41ee5SHelge Deller     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
282e2c41ee5SHelge Deller                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
283e2c41ee5SHelge Deller     memory_region_add_subregion(addr_space, CPU_HPA + 16, cpu_region);
284e2c41ee5SHelge Deller 
285a72bd606SHelge Deller     /* Main memory region. */
286b7746b11SPhilippe Mathieu-Daudé     if (machine->ram_size > 3 * GiB) {
287b7746b11SPhilippe Mathieu-Daudé         error_report("RAM size is currently restricted to 3GB");
288b7746b11SPhilippe Mathieu-Daudé         exit(EXIT_FAILURE);
289b7746b11SPhilippe Mathieu-Daudé     }
2907c59c1e0SIgor Mammedov     memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
291*7df6f751SHelge Deller }
2927c59c1e0SIgor Mammedov 
293*7df6f751SHelge Deller /*
294*7df6f751SHelge Deller  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
295*7df6f751SHelge Deller  */
296*7df6f751SHelge Deller static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus)
297*7df6f751SHelge Deller {
298*7df6f751SHelge Deller     const char *kernel_filename = machine->kernel_filename;
299*7df6f751SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
300*7df6f751SHelge Deller     const char *initrd_filename = machine->initrd_filename;
301*7df6f751SHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(machine);
302*7df6f751SHelge Deller     DeviceState *dev;
303*7df6f751SHelge Deller     char *firmware_filename;
304*7df6f751SHelge Deller     uint64_t firmware_low, firmware_high;
305*7df6f751SHelge Deller     long size;
306*7df6f751SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
307*7df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
308*7df6f751SHelge Deller     MemoryRegion *rom_region;
309*7df6f751SHelge Deller     long i;
310*7df6f751SHelge Deller     unsigned int smp_cpus = machine->smp.cpus;
311*7df6f751SHelge Deller     SysBusDevice *s;
31228b71a2eSHelge Deller 
313a72bd606SHelge Deller     /* SCSI disk setup. */
314877eb21dSMark Cave-Ayland     dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
315877eb21dSMark Cave-Ayland     lsi53c8xx_handle_legacy_cmdline(dev);
316a72bd606SHelge Deller 
3174765384cSSven Schnelle     /* Graphics setup. */
3184765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
319f9bcb2d6SGautam Agrawal         vga_interface_created = true;
3203e80f690SMarkus Armbruster         dev = qdev_new("artist");
3214765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
3223c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
3234765384cSSven Schnelle         sysbus_mmio_map(s, 0, LASI_GFX_HPA);
3244765384cSSven Schnelle         sysbus_mmio_map(s, 1, ARTIST_FB_ADDR);
3254765384cSSven Schnelle     }
3264765384cSSven Schnelle 
3270e6de551SHelge Deller     /* Network setup. */
328c3c3fe47SMark Cave-Ayland     if (enable_lasi_lan()) {
329c3c3fe47SMark Cave-Ayland         lasi_82596_init(addr_space, LASI_LAN_HPA,
330c3c3fe47SMark Cave-Ayland                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
331c3c3fe47SMark Cave-Ayland     }
332c3c3fe47SMark Cave-Ayland 
333a72bd606SHelge Deller     for (i = 0; i < nb_nics; i++) {
334376b8519SHelge Deller         if (!enable_lasi_lan()) {
3359f8981a9SThomas Huth             pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL);
336a72bd606SHelge Deller         }
337376b8519SHelge Deller     }
338a72bd606SHelge Deller 
339b28c4a64SHelge Deller     /* register power switch emulation */
340b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
341b28c4a64SHelge Deller 
342*7df6f751SHelge Deller     /* fw_cfg configuration interface */
343*7df6f751SHelge Deller     create_fw_cfg(machine, pci_bus);
344*7df6f751SHelge Deller 
345a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
346a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
347a72bd606SHelge Deller        well load it directly from an ELF image.  */
348a72bd606SHelge Deller     firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
349b57e3e97SPaolo Bonzini                                        machine->firmware ?: "hppa-firmware.img");
350a72bd606SHelge Deller     if (firmware_filename == NULL) {
351a72bd606SHelge Deller         error_report("no firmware provided");
352a72bd606SHelge Deller         exit(1);
353a72bd606SHelge Deller     }
354a72bd606SHelge Deller 
3554366e1dbSLiam Merwick     size = load_elf(firmware_filename, NULL, NULL, NULL,
3566cdda0ffSAleksandar Markovic                     &firmware_entry, &firmware_low, &firmware_high, NULL,
357a72bd606SHelge Deller                     true, EM_PARISC, 0, 0);
358a72bd606SHelge Deller 
359a72bd606SHelge Deller     /* Unfortunately, load_elf sign-extends reading elf32.  */
360a72bd606SHelge Deller     firmware_entry = (target_ureg)firmware_entry;
361a72bd606SHelge Deller     firmware_low = (target_ureg)firmware_low;
362a72bd606SHelge Deller     firmware_high = (target_ureg)firmware_high;
363a72bd606SHelge Deller 
364a72bd606SHelge Deller     if (size < 0) {
365a72bd606SHelge Deller         error_report("could not load firmware '%s'", firmware_filename);
366a72bd606SHelge Deller         exit(1);
367a72bd606SHelge Deller     }
368691cbbadSRichard Henderson     qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
369691cbbadSRichard Henderson                   "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
370a72bd606SHelge Deller                   firmware_low, firmware_high, firmware_entry);
3718262863dSPhilippe Mathieu-Daudé     if (firmware_low < FIRMWARE_START || firmware_high >= FIRMWARE_END) {
372a72bd606SHelge Deller         error_report("Firmware overlaps with memory or IO space");
373a72bd606SHelge Deller         exit(1);
374a72bd606SHelge Deller     }
375a72bd606SHelge Deller     g_free(firmware_filename);
376a72bd606SHelge Deller 
377a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
3786a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
3796a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
380a72bd606SHelge Deller     memory_region_add_subregion(addr_space, FIRMWARE_START, rom_region);
381a72bd606SHelge Deller 
382a72bd606SHelge Deller     /* Load kernel */
383a72bd606SHelge Deller     if (kernel_filename) {
3844366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
3856cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
386a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
387a72bd606SHelge Deller 
388a72bd606SHelge Deller         /* Unfortunately, load_elf sign-extends reading elf32.  */
389a72bd606SHelge Deller         kernel_entry = (target_ureg) cpu_hppa_to_phys(NULL, kernel_entry);
390a72bd606SHelge Deller         kernel_low = (target_ureg)kernel_low;
391a72bd606SHelge Deller         kernel_high = (target_ureg)kernel_high;
392a72bd606SHelge Deller 
393a72bd606SHelge Deller         if (size < 0) {
394a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
395a72bd606SHelge Deller             exit(1);
396a72bd606SHelge Deller         }
397691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
398691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
399c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
400c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
401a72bd606SHelge Deller 
402a72bd606SHelge Deller         if (kernel_cmdline) {
403a72bd606SHelge Deller             cpu[0]->env.gr[24] = 0x4000;
404a72bd606SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
405a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
406a72bd606SHelge Deller         }
407a72bd606SHelge Deller 
408a72bd606SHelge Deller         if (initrd_filename) {
409a72bd606SHelge Deller             ram_addr_t initrd_base;
410f3839fdaSLi Zhijian             int64_t initrd_size;
411a72bd606SHelge Deller 
412a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
413a72bd606SHelge Deller             if (initrd_size < 0) {
414a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
415a72bd606SHelge Deller                              initrd_filename);
416a72bd606SHelge Deller                 exit(1);
417a72bd606SHelge Deller             }
418a72bd606SHelge Deller 
419a72bd606SHelge Deller             /* Load the initrd image high in memory.
420a72bd606SHelge Deller                Mirror the algorithm used by palo:
421a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
422a72bd606SHelge Deller                put the initrd no higher than 1G.
423a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
424bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
425c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
426a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
427a72bd606SHelge Deller 
428a72bd606SHelge Deller             if (initrd_base < kernel_high) {
429a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
430a72bd606SHelge Deller                 exit(1);
431a72bd606SHelge Deller             }
432a72bd606SHelge Deller 
433a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
434a72bd606SHelge Deller             cpu[0]->env.gr[23] = initrd_base;
435a72bd606SHelge Deller             cpu[0]->env.gr[22] = initrd_base + initrd_size;
436a72bd606SHelge Deller         }
437a72bd606SHelge Deller     }
438a72bd606SHelge Deller 
439a72bd606SHelge Deller     if (!kernel_entry) {
440a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
441a72bd606SHelge Deller          * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
442a72bd606SHelge Deller          * or hard disc * (gr[24]='c').
443a72bd606SHelge Deller          */
44497ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
44597ec4d21SPaolo Bonzini         cpu[0]->env.gr[24] = machine->boot_config.order[0];
446a72bd606SHelge Deller     }
447a72bd606SHelge Deller 
448a72bd606SHelge Deller     /* We jump to the firmware entry routine and pass the
449a72bd606SHelge Deller      * various parameters in registers. After firmware initialization,
450a72bd606SHelge Deller      * firmware will start the Linux kernel with ramdisk and cmdline.
451a72bd606SHelge Deller      */
452bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = machine->ram_size;
453a72bd606SHelge Deller     cpu[0]->env.gr[25] = kernel_entry;
454a72bd606SHelge Deller 
455a72bd606SHelge Deller     /* tell firmware how many SMP CPUs to present in inventory table */
456a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
45724576007SHelge Deller 
45824576007SHelge Deller     /* tell firmware fw_cfg port */
45924576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
460a72bd606SHelge Deller }
461a72bd606SHelge Deller 
462*7df6f751SHelge Deller /*
463*7df6f751SHelge Deller  * Create HP B160L workstation
464*7df6f751SHelge Deller  */
465*7df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
466*7df6f751SHelge Deller {
467*7df6f751SHelge Deller     DeviceState *dev, *dino_dev;
468*7df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
469*7df6f751SHelge Deller     ISABus *isa_bus;
470*7df6f751SHelge Deller     PCIBus *pci_bus;
471*7df6f751SHelge Deller 
472*7df6f751SHelge Deller     /* Create CPUs and RAM.  */
473*7df6f751SHelge Deller     machine_HP_common_init_cpus(machine);
474*7df6f751SHelge Deller 
475*7df6f751SHelge Deller     /* Init Lasi chip */
476*7df6f751SHelge Deller     lasi_dev = DEVICE(lasi_init());
477*7df6f751SHelge Deller     memory_region_add_subregion(addr_space, LASI_HPA,
478*7df6f751SHelge Deller                                 sysbus_mmio_get_region(
479*7df6f751SHelge Deller                                     SYS_BUS_DEVICE(lasi_dev), 0));
480*7df6f751SHelge Deller 
481*7df6f751SHelge Deller     /* Init Dino (PCI host bus chip).  */
482*7df6f751SHelge Deller     dino_dev = DEVICE(dino_init(addr_space));
483*7df6f751SHelge Deller     memory_region_add_subregion(addr_space, DINO_HPA,
484*7df6f751SHelge Deller                                 sysbus_mmio_get_region(
485*7df6f751SHelge Deller                                     SYS_BUS_DEVICE(dino_dev), 0));
486*7df6f751SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
487*7df6f751SHelge Deller     assert(pci_bus);
488*7df6f751SHelge Deller 
489*7df6f751SHelge Deller     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
490*7df6f751SHelge Deller     isa_bus = hppa_isa_bus();
491*7df6f751SHelge Deller     assert(isa_bus);
492*7df6f751SHelge Deller 
493*7df6f751SHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
494*7df6f751SHelge Deller     serial_mm_init(addr_space, LASI_UART_HPA + 0x800, 0,
495*7df6f751SHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
496*7df6f751SHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
497*7df6f751SHelge Deller 
498*7df6f751SHelge Deller     serial_mm_init(addr_space, DINO_UART_HPA + 0x800, 0,
499*7df6f751SHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
500*7df6f751SHelge Deller         serial_hd(1), DEVICE_BIG_ENDIAN);
501*7df6f751SHelge Deller 
502*7df6f751SHelge Deller     /* Parallel port */
503*7df6f751SHelge Deller     parallel_mm_init(addr_space, LASI_LPT_HPA + 0x800, 0,
504*7df6f751SHelge Deller                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
505*7df6f751SHelge Deller                      parallel_hds[0]);
506*7df6f751SHelge Deller 
507*7df6f751SHelge Deller     /* PS/2 Keyboard/Mouse */
508*7df6f751SHelge Deller     dev = qdev_new(TYPE_LASIPS2);
509*7df6f751SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
510*7df6f751SHelge Deller     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
511*7df6f751SHelge Deller                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
512*7df6f751SHelge Deller     memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA,
513*7df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
514*7df6f751SHelge Deller                                                        0));
515*7df6f751SHelge Deller     memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA + 0x100,
516*7df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
517*7df6f751SHelge Deller                                                        1));
518*7df6f751SHelge Deller 
519*7df6f751SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
520*7df6f751SHelge Deller     machine_HP_common_init_tail(machine, pci_bus);
521*7df6f751SHelge Deller }
522*7df6f751SHelge Deller 
5237966d70fSJason A. Donenfeld static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
524a72bd606SHelge Deller {
52533decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
526a72bd606SHelge Deller     int i;
527a72bd606SHelge Deller 
5287966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
529a72bd606SHelge Deller 
530a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
531a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
53250ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
533a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
53450ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
53550ba97e9SHelge Deller 
53650ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
53750ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
538a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
53950ba97e9SHelge Deller 
54050ba97e9SHelge Deller         cs->exception_index = -1;
54150ba97e9SHelge Deller         cs->halted = 0;
5426d1ef68cSHelge Deller 
5436d1ef68cSHelge Deller         /* clear any existing TLB and BTLB entries */
5446d1ef68cSHelge Deller         memset(cpu[i]->env.tlb, 0, sizeof(cpu[i]->env.tlb));
5456d1ef68cSHelge Deller         cpu[i]->env.tlb_last = HPPA_BTLB_ENTRIES;
546a72bd606SHelge Deller     }
547a72bd606SHelge Deller 
548a72bd606SHelge Deller     /* already initialized by machine_hppa_init()? */
549bfdf22bcSPaolo Bonzini     if (cpu[0]->env.gr[26] == ms->ram_size) {
550a72bd606SHelge Deller         return;
551a72bd606SHelge Deller     }
552a72bd606SHelge Deller 
553bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
554a72bd606SHelge Deller     cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
555a72bd606SHelge Deller     cpu[0]->env.gr[24] = 'c';
556a72bd606SHelge Deller     /* gr22/gr23 unused, no initrd while reboot. */
557a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
55824576007SHelge Deller     /* tell firmware fw_cfg port */
55924576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
560a72bd606SHelge Deller }
561a72bd606SHelge Deller 
5624a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
5634a4554c6SHelge Deller {
5644a4554c6SHelge Deller     CPUState *cs;
5654a4554c6SHelge Deller 
5664a4554c6SHelge Deller     CPU_FOREACH(cs) {
5674a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
5684a4554c6SHelge Deller     }
5694a4554c6SHelge Deller }
570a72bd606SHelge Deller 
571*7df6f751SHelge Deller static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
572813dff13SHelge Deller {
57342cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
57442cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
57542cc2bf6SMark Cave-Ayland 
576*7df6f751SHelge Deller     mc->desc = "HP B160L workstation";
577a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
578*7df6f751SHelge Deller     mc->init = machine_HP_B160L_init;
579a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
580813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
581a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
582a72bd606SHelge Deller     mc->default_cpus = 1;
583ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
584d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
585813dff13SHelge Deller     mc->default_boot_order = "cd";
5867c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
5879f8981a9SThomas Huth     mc->default_nic = "tulip";
588813dff13SHelge Deller 
5894a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
5904a4554c6SHelge Deller }
5914a4554c6SHelge Deller 
592*7df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
593*7df6f751SHelge Deller     .name = MACHINE_TYPE_NAME("B160L"),
594c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
595*7df6f751SHelge Deller     .class_init = HP_B160L_machine_init_class_init,
5964a4554c6SHelge Deller     .interfaces = (InterfaceInfo[]) {
5974a4554c6SHelge Deller         { TYPE_NMI },
5984a4554c6SHelge Deller         { }
5994a4554c6SHelge Deller     },
6004a4554c6SHelge Deller };
6014a4554c6SHelge Deller 
602297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
6034a4554c6SHelge Deller {
604*7df6f751SHelge Deller     type_register_static(&HP_B160L_machine_init_typeinfo);
6054a4554c6SHelge Deller }
6064a4554c6SHelge Deller 
607297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
608