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