xref: /qemu/hw/hppa/machine.c (revision bcd4dd4c22f2df17def72668c75cdf01fb47b6ff)
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"
260db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
2745f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
28148da670SMark Cave-Ayland #include "hppa_hardware.h"
29c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
30813dff13SHelge Deller #include "qapi/error.h"
31852c27e2SPaolo Bonzini #include "net/net.h"
32691cbbadSRichard Henderson #include "qemu/log.h"
33813dff13SHelge Deller 
34a536f564SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 10 /* require at least this fw version */
3528b71a2eSHelge Deller 
36b28c4a64SHelge Deller #define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
37b28c4a64SHelge Deller 
38932befaaSMark Cave-Ayland #define enable_lasi_lan()       0
39932befaaSMark Cave-Ayland 
40932befaaSMark Cave-Ayland 
41b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
42b28c4a64SHelge Deller {
43b28c4a64SHelge Deller     hwaddr soft_power_reg = HPA_POWER_BUTTON;
44b28c4a64SHelge Deller     uint32_t val;
45b28c4a64SHelge Deller 
46b28c4a64SHelge Deller     val = ldl_be_phys(&address_space_memory, soft_power_reg);
47b28c4a64SHelge Deller     if ((val >> 8) == 0) {
48b28c4a64SHelge Deller         /* immediately shut down when under hardware control */
49b28c4a64SHelge Deller         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
50b28c4a64SHelge Deller         return;
51b28c4a64SHelge Deller     }
52b28c4a64SHelge Deller 
53b28c4a64SHelge Deller     /* clear bit 31 to indicate that the power switch was pressed. */
54b28c4a64SHelge Deller     val &= ~1;
55b28c4a64SHelge Deller     stl_be_phys(&address_space_memory, soft_power_reg, val);
56b28c4a64SHelge Deller }
57b28c4a64SHelge Deller 
58b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
59b28c4a64SHelge Deller     .notify = hppa_powerdown_req
60b28c4a64SHelge Deller };
61b28c4a64SHelge Deller 
6228f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
6328f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
6428f5332aSMark Cave-Ayland {
6528f5332aSMark Cave-Ayland     return 0;
6628f5332aSMark Cave-Ayland }
6728f5332aSMark Cave-Ayland 
6828f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
6928f5332aSMark Cave-Ayland {
7028f5332aSMark Cave-Ayland }
7128f5332aSMark Cave-Ayland 
7228f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7328f5332aSMark Cave-Ayland     .read = ignore_read,
7428f5332aSMark Cave-Ayland     .write = ignore_write,
7528f5332aSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
7628f5332aSMark Cave-Ayland     .valid = {
7728f5332aSMark Cave-Ayland         .min_access_size = 1,
7828f5332aSMark Cave-Ayland         .max_access_size = 8,
7928f5332aSMark Cave-Ayland     },
8028f5332aSMark Cave-Ayland     .impl = {
8128f5332aSMark Cave-Ayland         .min_access_size = 1,
8228f5332aSMark Cave-Ayland         .max_access_size = 8,
8328f5332aSMark Cave-Ayland     },
8428f5332aSMark Cave-Ayland };
85b28c4a64SHelge Deller 
86a72bd606SHelge Deller static ISABus *hppa_isa_bus(void)
87a72bd606SHelge Deller {
88a72bd606SHelge Deller     ISABus *isa_bus;
89a72bd606SHelge Deller     qemu_irq *isa_irqs;
90a72bd606SHelge Deller     MemoryRegion *isa_region;
91a72bd606SHelge Deller 
92a72bd606SHelge Deller     isa_region = g_new(MemoryRegion, 1);
93a72bd606SHelge Deller     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
94a72bd606SHelge Deller                           NULL, "isa-io", 0x800);
95a72bd606SHelge Deller     memory_region_add_subregion(get_system_memory(), IDE_HPA,
96a72bd606SHelge Deller                                 isa_region);
97a72bd606SHelge Deller 
98a72bd606SHelge Deller     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
99a72bd606SHelge Deller                           &error_abort);
100a536f564SHelge Deller     isa_irqs = i8259_init(isa_bus, NULL);
1017067887eSPhilippe Mathieu-Daudé     isa_bus_register_input_irqs(isa_bus, isa_irqs);
102a72bd606SHelge Deller 
103a72bd606SHelge Deller     return isa_bus;
104a72bd606SHelge Deller }
105a72bd606SHelge Deller 
106a72bd606SHelge Deller static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr)
107a72bd606SHelge Deller {
108a72bd606SHelge Deller     addr &= (0x10000000 - 1);
109a72bd606SHelge Deller     return addr;
110a72bd606SHelge Deller }
111a72bd606SHelge Deller 
112a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
113a72bd606SHelge Deller static uint64_t firmware_entry;
114813dff13SHelge Deller 
11532ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
11632ff8bf2SHelge Deller                             Error **errp)
11732ff8bf2SHelge Deller {
11832ff8bf2SHelge Deller     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
11932ff8bf2SHelge Deller }
12032ff8bf2SHelge Deller 
121*bcd4dd4cSHelge Deller static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus)
12228b71a2eSHelge Deller {
12328b71a2eSHelge Deller     FWCfgState *fw_cfg;
12428b71a2eSHelge Deller     uint64_t val;
125069d2966SHelge Deller     const char qemu_version[] = QEMU_VERSION;
126*bcd4dd4cSHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(ms);
127*bcd4dd4cSHelge Deller     int len;
12828b71a2eSHelge Deller 
12924576007SHelge Deller     fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4);
13028b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
13128b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
132bfdf22bcSPaolo Bonzini     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
13328b71a2eSHelge Deller 
13428b71a2eSHelge Deller     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
13528b71a2eSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
13628b71a2eSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
13728b71a2eSHelge Deller 
1386d1ef68cSHelge Deller     val = cpu_to_le64(HPPA_TLB_ENTRIES - HPPA_BTLB_ENTRIES);
139df5c6a50SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
140df5c6a50SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
141df5c6a50SHelge Deller 
142*bcd4dd4cSHelge Deller     val = cpu_to_le64(HPPA_BTLB_ENTRIES);
143*bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
144*bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
145*bcd4dd4cSHelge Deller 
146*bcd4dd4cSHelge Deller     len = strlen(mc->name) + 1;
147*bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
148*bcd4dd4cSHelge Deller                     g_memdup(mc->name, len), len);
149*bcd4dd4cSHelge Deller 
150b28c4a64SHelge Deller     val = cpu_to_le64(HPA_POWER_BUTTON);
151*bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
152*bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
153*bcd4dd4cSHelge Deller 
154*bcd4dd4cSHelge Deller     val = cpu_to_le64(CPU_HPA + 24);
155*bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
156b28c4a64SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
157b28c4a64SHelge Deller 
15897ec4d21SPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
15932ff8bf2SHelge Deller     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
16032ff8bf2SHelge Deller 
161069d2966SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
162069d2966SHelge Deller                     g_memdup(qemu_version, sizeof(qemu_version)),
163069d2966SHelge Deller                     sizeof(qemu_version));
164069d2966SHelge Deller 
165*bcd4dd4cSHelge Deller     fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
166*bcd4dd4cSHelge Deller 
16728b71a2eSHelge Deller     return fw_cfg;
16828b71a2eSHelge Deller }
16928b71a2eSHelge Deller 
170e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
171e881e3c8SMark Cave-Ayland {
172e881e3c8SMark Cave-Ayland     DeviceState *dev;
173e881e3c8SMark Cave-Ayland 
174e881e3c8SMark Cave-Ayland     dev = qdev_new(TYPE_LASI_CHIP);
175e881e3c8SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
176e881e3c8SMark Cave-Ayland 
177e881e3c8SMark Cave-Ayland     return LASI_CHIP(dev);
178e881e3c8SMark Cave-Ayland }
179e881e3c8SMark Cave-Ayland 
1800d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
1810d068996SMark Cave-Ayland {
1820d068996SMark Cave-Ayland     DeviceState *dev;
1830d068996SMark Cave-Ayland 
1840d068996SMark Cave-Ayland     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
1850d068996SMark Cave-Ayland     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
1860d068996SMark Cave-Ayland                              &error_fatal);
1870d068996SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1880d068996SMark Cave-Ayland 
1890d068996SMark Cave-Ayland     return DINO_PCI_HOST_BRIDGE(dev);
1900d068996SMark Cave-Ayland }
1910d068996SMark Cave-Ayland 
192813dff13SHelge Deller static void machine_hppa_init(MachineState *machine)
193813dff13SHelge Deller {
194a72bd606SHelge Deller     const char *kernel_filename = machine->kernel_filename;
195a72bd606SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
196a72bd606SHelge Deller     const char *initrd_filename = machine->initrd_filename;
1979f8981a9SThomas Huth     MachineClass *mc = MACHINE_GET_CLASS(machine);
1982683758cSMark Cave-Ayland     DeviceState *dev, *dino_dev, *lasi_dev;
199a72bd606SHelge Deller     PCIBus *pci_bus;
200a72bd606SHelge Deller     ISABus *isa_bus;
201a72bd606SHelge Deller     char *firmware_filename;
202a72bd606SHelge Deller     uint64_t firmware_low, firmware_high;
203a72bd606SHelge Deller     long size;
204a72bd606SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
205a72bd606SHelge Deller     MemoryRegion *addr_space = get_system_memory();
206a72bd606SHelge Deller     MemoryRegion *rom_region;
207a72bd606SHelge Deller     MemoryRegion *cpu_region;
208a72bd606SHelge Deller     long i;
20933decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
2104765384cSSven Schnelle     SysBusDevice *s;
211a72bd606SHelge Deller 
212a72bd606SHelge Deller     /* Create CPUs.  */
213a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
214266a880eSPaolo Bonzini         char *name = g_strdup_printf("cpu%ld-io-eir", i);
215a72bd606SHelge Deller         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
216a72bd606SHelge Deller 
217a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
218a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
219266a880eSPaolo Bonzini                               cpu[i], name, 4);
220a72bd606SHelge Deller         memory_region_add_subregion(addr_space, CPU_HPA + i * 0x1000,
221a72bd606SHelge Deller                                     cpu_region);
222266a880eSPaolo Bonzini         g_free(name);
223813dff13SHelge Deller     }
224813dff13SHelge Deller 
225a72bd606SHelge Deller     /* Main memory region. */
226b7746b11SPhilippe Mathieu-Daudé     if (machine->ram_size > 3 * GiB) {
227b7746b11SPhilippe Mathieu-Daudé         error_report("RAM size is currently restricted to 3GB");
228b7746b11SPhilippe Mathieu-Daudé         exit(EXIT_FAILURE);
229b7746b11SPhilippe Mathieu-Daudé     }
2307c59c1e0SIgor Mammedov     memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
2317c59c1e0SIgor Mammedov 
232a72bd606SHelge Deller 
233376b8519SHelge Deller     /* Init Lasi chip */
234e881e3c8SMark Cave-Ayland     lasi_dev = DEVICE(lasi_init());
2352683758cSMark Cave-Ayland     memory_region_add_subregion(addr_space, LASI_HPA,
2362683758cSMark Cave-Ayland                                 sysbus_mmio_get_region(
2372683758cSMark Cave-Ayland                                     SYS_BUS_DEVICE(lasi_dev), 0));
238376b8519SHelge Deller 
239a72bd606SHelge Deller     /* Init Dino (PCI host bus chip).  */
24036f9bbdbSMark Cave-Ayland     dino_dev = DEVICE(dino_init(addr_space));
241efdb3ce2SMark Cave-Ayland     memory_region_add_subregion(addr_space, DINO_HPA,
242efdb3ce2SMark Cave-Ayland                                 sysbus_mmio_get_region(
243efdb3ce2SMark Cave-Ayland                                     SYS_BUS_DEVICE(dino_dev), 0));
24405245dafSMark Cave-Ayland     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
245a72bd606SHelge Deller     assert(pci_bus);
246a72bd606SHelge Deller 
247a72bd606SHelge Deller     /* Create ISA bus. */
248a72bd606SHelge Deller     isa_bus = hppa_isa_bus();
249a72bd606SHelge Deller     assert(isa_bus);
250a72bd606SHelge Deller 
251a72bd606SHelge Deller     /* Realtime clock, used by firmware for PDC_TOD call. */
25236f9bbdbSMark Cave-Ayland     mc146818_rtc_init(isa_bus, 2000, NULL);
253a72bd606SHelge Deller 
2545079892dSHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
2552da547b8SMark Cave-Ayland     serial_mm_init(addr_space, LASI_UART_HPA + 0x800, 0,
2565079892dSHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
2575079892dSHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
2585079892dSHelge Deller 
2595079892dSHelge Deller     serial_mm_init(addr_space, DINO_UART_HPA + 0x800, 0,
2605079892dSHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
2612da547b8SMark Cave-Ayland         serial_hd(1), DEVICE_BIG_ENDIAN);
2622da547b8SMark Cave-Ayland 
2639701e569SMark Cave-Ayland     /* Parallel port */
2649701e569SMark Cave-Ayland     parallel_mm_init(addr_space, LASI_LPT_HPA + 0x800, 0,
2659701e569SMark Cave-Ayland                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
2669701e569SMark Cave-Ayland                      parallel_hds[0]);
2679701e569SMark Cave-Ayland 
26828b71a2eSHelge Deller     /* fw_cfg configuration interface */
269*bcd4dd4cSHelge Deller     create_fw_cfg(machine, pci_bus);
27028b71a2eSHelge Deller 
271a72bd606SHelge Deller     /* SCSI disk setup. */
272877eb21dSMark Cave-Ayland     dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
273877eb21dSMark Cave-Ayland     lsi53c8xx_handle_legacy_cmdline(dev);
274a72bd606SHelge Deller 
2754765384cSSven Schnelle     /* Graphics setup. */
2764765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
277f9bcb2d6SGautam Agrawal         vga_interface_created = true;
2783e80f690SMarkus Armbruster         dev = qdev_new("artist");
2794765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
2803c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
2814765384cSSven Schnelle         sysbus_mmio_map(s, 0, LASI_GFX_HPA);
2824765384cSSven Schnelle         sysbus_mmio_map(s, 1, ARTIST_FB_ADDR);
2834765384cSSven Schnelle     }
2844765384cSSven Schnelle 
2850e6de551SHelge Deller     /* Network setup. */
286c3c3fe47SMark Cave-Ayland     if (enable_lasi_lan()) {
287c3c3fe47SMark Cave-Ayland         lasi_82596_init(addr_space, LASI_LAN_HPA,
288c3c3fe47SMark Cave-Ayland                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
289c3c3fe47SMark Cave-Ayland     }
290c3c3fe47SMark Cave-Ayland 
291a72bd606SHelge Deller     for (i = 0; i < nb_nics; i++) {
292376b8519SHelge Deller         if (!enable_lasi_lan()) {
2939f8981a9SThomas Huth             pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL);
294a72bd606SHelge Deller         }
295376b8519SHelge Deller     }
296a72bd606SHelge Deller 
297d26c575cSMark Cave-Ayland     /* PS/2 Keyboard/Mouse */
29892bd278cSMark Cave-Ayland     dev = qdev_new(TYPE_LASIPS2);
29992bd278cSMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
30092bd278cSMark Cave-Ayland     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
30192bd278cSMark Cave-Ayland                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
3026479296fSMark Cave-Ayland     memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA,
3036479296fSMark Cave-Ayland                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
3046479296fSMark Cave-Ayland                                                        0));
3056479296fSMark Cave-Ayland     memory_region_add_subregion(addr_space, LASI_PS2KBD_HPA + 0x100,
3066479296fSMark Cave-Ayland                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
3076479296fSMark Cave-Ayland                                                        1));
308d26c575cSMark Cave-Ayland 
309b28c4a64SHelge Deller     /* register power switch emulation */
310b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
311b28c4a64SHelge Deller 
312a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
313a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
314a72bd606SHelge Deller        well load it directly from an ELF image.  */
315a72bd606SHelge Deller     firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
316b57e3e97SPaolo Bonzini                                        machine->firmware ?: "hppa-firmware.img");
317a72bd606SHelge Deller     if (firmware_filename == NULL) {
318a72bd606SHelge Deller         error_report("no firmware provided");
319a72bd606SHelge Deller         exit(1);
320a72bd606SHelge Deller     }
321a72bd606SHelge Deller 
3224366e1dbSLiam Merwick     size = load_elf(firmware_filename, NULL, NULL, NULL,
3236cdda0ffSAleksandar Markovic                     &firmware_entry, &firmware_low, &firmware_high, NULL,
324a72bd606SHelge Deller                     true, EM_PARISC, 0, 0);
325a72bd606SHelge Deller 
326a72bd606SHelge Deller     /* Unfortunately, load_elf sign-extends reading elf32.  */
327a72bd606SHelge Deller     firmware_entry = (target_ureg)firmware_entry;
328a72bd606SHelge Deller     firmware_low = (target_ureg)firmware_low;
329a72bd606SHelge Deller     firmware_high = (target_ureg)firmware_high;
330a72bd606SHelge Deller 
331a72bd606SHelge Deller     if (size < 0) {
332a72bd606SHelge Deller         error_report("could not load firmware '%s'", firmware_filename);
333a72bd606SHelge Deller         exit(1);
334a72bd606SHelge Deller     }
335691cbbadSRichard Henderson     qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
336691cbbadSRichard Henderson                   "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
337a72bd606SHelge Deller                   firmware_low, firmware_high, firmware_entry);
3388262863dSPhilippe Mathieu-Daudé     if (firmware_low < FIRMWARE_START || firmware_high >= FIRMWARE_END) {
339a72bd606SHelge Deller         error_report("Firmware overlaps with memory or IO space");
340a72bd606SHelge Deller         exit(1);
341a72bd606SHelge Deller     }
342a72bd606SHelge Deller     g_free(firmware_filename);
343a72bd606SHelge Deller 
344a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
3456a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
3466a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
347a72bd606SHelge Deller     memory_region_add_subregion(addr_space, FIRMWARE_START, rom_region);
348a72bd606SHelge Deller 
349a72bd606SHelge Deller     /* Load kernel */
350a72bd606SHelge Deller     if (kernel_filename) {
3514366e1dbSLiam Merwick         size = load_elf(kernel_filename, NULL, &cpu_hppa_to_phys,
3526cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
353a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
354a72bd606SHelge Deller 
355a72bd606SHelge Deller         /* Unfortunately, load_elf sign-extends reading elf32.  */
356a72bd606SHelge Deller         kernel_entry = (target_ureg) cpu_hppa_to_phys(NULL, kernel_entry);
357a72bd606SHelge Deller         kernel_low = (target_ureg)kernel_low;
358a72bd606SHelge Deller         kernel_high = (target_ureg)kernel_high;
359a72bd606SHelge Deller 
360a72bd606SHelge Deller         if (size < 0) {
361a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
362a72bd606SHelge Deller             exit(1);
363a72bd606SHelge Deller         }
364691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
365691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
366c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
367c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
368a72bd606SHelge Deller 
369a72bd606SHelge Deller         if (kernel_cmdline) {
370a72bd606SHelge Deller             cpu[0]->env.gr[24] = 0x4000;
371a72bd606SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
372a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
373a72bd606SHelge Deller         }
374a72bd606SHelge Deller 
375a72bd606SHelge Deller         if (initrd_filename) {
376a72bd606SHelge Deller             ram_addr_t initrd_base;
377f3839fdaSLi Zhijian             int64_t initrd_size;
378a72bd606SHelge Deller 
379a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
380a72bd606SHelge Deller             if (initrd_size < 0) {
381a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
382a72bd606SHelge Deller                              initrd_filename);
383a72bd606SHelge Deller                 exit(1);
384a72bd606SHelge Deller             }
385a72bd606SHelge Deller 
386a72bd606SHelge Deller             /* Load the initrd image high in memory.
387a72bd606SHelge Deller                Mirror the algorithm used by palo:
388a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
389a72bd606SHelge Deller                put the initrd no higher than 1G.
390a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
391bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
392c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
393a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
394a72bd606SHelge Deller 
395a72bd606SHelge Deller             if (initrd_base < kernel_high) {
396a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
397a72bd606SHelge Deller                 exit(1);
398a72bd606SHelge Deller             }
399a72bd606SHelge Deller 
400a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
401a72bd606SHelge Deller             cpu[0]->env.gr[23] = initrd_base;
402a72bd606SHelge Deller             cpu[0]->env.gr[22] = initrd_base + initrd_size;
403a72bd606SHelge Deller         }
404a72bd606SHelge Deller     }
405a72bd606SHelge Deller 
406a72bd606SHelge Deller     if (!kernel_entry) {
407a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
408a72bd606SHelge Deller          * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
409a72bd606SHelge Deller          * or hard disc * (gr[24]='c').
410a72bd606SHelge Deller          */
41197ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
41297ec4d21SPaolo Bonzini         cpu[0]->env.gr[24] = machine->boot_config.order[0];
413a72bd606SHelge Deller     }
414a72bd606SHelge Deller 
415a72bd606SHelge Deller     /* We jump to the firmware entry routine and pass the
416a72bd606SHelge Deller      * various parameters in registers. After firmware initialization,
417a72bd606SHelge Deller      * firmware will start the Linux kernel with ramdisk and cmdline.
418a72bd606SHelge Deller      */
419bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = machine->ram_size;
420a72bd606SHelge Deller     cpu[0]->env.gr[25] = kernel_entry;
421a72bd606SHelge Deller 
422a72bd606SHelge Deller     /* tell firmware how many SMP CPUs to present in inventory table */
423a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
42424576007SHelge Deller 
42524576007SHelge Deller     /* tell firmware fw_cfg port */
42624576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
427a72bd606SHelge Deller }
428a72bd606SHelge Deller 
4297966d70fSJason A. Donenfeld static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
430a72bd606SHelge Deller {
43133decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
432a72bd606SHelge Deller     int i;
433a72bd606SHelge Deller 
4347966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
435a72bd606SHelge Deller 
436a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
437a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
43850ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
439a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
44050ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
44150ba97e9SHelge Deller 
44250ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
44350ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
444a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
44550ba97e9SHelge Deller 
44650ba97e9SHelge Deller         cs->exception_index = -1;
44750ba97e9SHelge Deller         cs->halted = 0;
4486d1ef68cSHelge Deller 
4496d1ef68cSHelge Deller         /* clear any existing TLB and BTLB entries */
4506d1ef68cSHelge Deller         memset(cpu[i]->env.tlb, 0, sizeof(cpu[i]->env.tlb));
4516d1ef68cSHelge Deller         cpu[i]->env.tlb_last = HPPA_BTLB_ENTRIES;
452a72bd606SHelge Deller     }
453a72bd606SHelge Deller 
454a72bd606SHelge Deller     /* already initialized by machine_hppa_init()? */
455bfdf22bcSPaolo Bonzini     if (cpu[0]->env.gr[26] == ms->ram_size) {
456a72bd606SHelge Deller         return;
457a72bd606SHelge Deller     }
458a72bd606SHelge Deller 
459bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
460a72bd606SHelge Deller     cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
461a72bd606SHelge Deller     cpu[0]->env.gr[24] = 'c';
462a72bd606SHelge Deller     /* gr22/gr23 unused, no initrd while reboot. */
463a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
46424576007SHelge Deller     /* tell firmware fw_cfg port */
46524576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
466a72bd606SHelge Deller }
467a72bd606SHelge Deller 
4684a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
4694a4554c6SHelge Deller {
4704a4554c6SHelge Deller     CPUState *cs;
4714a4554c6SHelge Deller 
4724a4554c6SHelge Deller     CPU_FOREACH(cs) {
4734a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
4744a4554c6SHelge Deller     }
4754a4554c6SHelge Deller }
476a72bd606SHelge Deller 
477297d4103SMark Cave-Ayland static void hppa_machine_init_class_init(ObjectClass *oc, void *data)
478813dff13SHelge Deller {
47942cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
48042cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
48142cc2bf6SMark Cave-Ayland 
4820d98fbb5SMark Cave-Ayland     mc->desc = "HPPA B160L machine";
483a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
484813dff13SHelge Deller     mc->init = machine_hppa_init;
485a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
486813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
487a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
488a72bd606SHelge Deller     mc->default_cpus = 1;
489ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
490d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
491813dff13SHelge Deller     mc->default_boot_order = "cd";
4927c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
4939f8981a9SThomas Huth     mc->default_nic = "tulip";
494813dff13SHelge Deller 
4954a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
4964a4554c6SHelge Deller }
4974a4554c6SHelge Deller 
498297d4103SMark Cave-Ayland static const TypeInfo hppa_machine_init_typeinfo = {
499c165905cSMark Cave-Ayland     .name = MACHINE_TYPE_NAME("hppa"),
500c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
501297d4103SMark Cave-Ayland     .class_init = hppa_machine_init_class_init,
5024a4554c6SHelge Deller     .interfaces = (InterfaceInfo[]) {
5034a4554c6SHelge Deller         { TYPE_NMI },
5044a4554c6SHelge Deller         { }
5054a4554c6SHelge Deller     },
5064a4554c6SHelge Deller };
5074a4554c6SHelge Deller 
508297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
5094a4554c6SHelge Deller {
510297d4103SMark Cave-Ayland     type_register_static(&hppa_machine_init_typeinfo);
5114a4554c6SHelge Deller }
5124a4554c6SHelge Deller 
513297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
514