xref: /qemu/hw/hppa/machine.c (revision ed35afcb331a972210816435d6b1b5de17fc7d4f)
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"
252ed4faa0SHelge Deller #include "hw/usb.h"
26134ba73fSMark Cave-Ayland #include "hw/pci/pci.h"
277df6f751SHelge Deller #include "hw/pci/pci_device.h"
282ed4faa0SHelge Deller #include "hw/pci-host/astro.h"
290db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
3045f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
31148da670SMark Cave-Ayland #include "hppa_hardware.h"
32c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
33813dff13SHelge Deller #include "qapi/error.h"
34852c27e2SPaolo Bonzini #include "net/net.h"
35691cbbadSRichard Henderson #include "qemu/log.h"
36813dff13SHelge Deller 
37f88131d9SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
3828b71a2eSHelge Deller 
39*ed35afcbSHelge Deller #define HPA_POWER_BUTTON        (FIRMWARE_END - 0x10)
40*ed35afcbSHelge Deller static hwaddr soft_power_reg;
41b28c4a64SHelge Deller 
42932befaaSMark Cave-Ayland #define enable_lasi_lan()       0
43932befaaSMark Cave-Ayland 
447df6f751SHelge Deller static DeviceState *lasi_dev;
45932befaaSMark Cave-Ayland 
46b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
47b28c4a64SHelge Deller {
48b28c4a64SHelge Deller     uint32_t val;
49b28c4a64SHelge Deller 
50b28c4a64SHelge Deller     val = ldl_be_phys(&address_space_memory, soft_power_reg);
51b28c4a64SHelge Deller     if ((val >> 8) == 0) {
52b28c4a64SHelge Deller         /* immediately shut down when under hardware control */
53b28c4a64SHelge Deller         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
54b28c4a64SHelge Deller         return;
55b28c4a64SHelge Deller     }
56b28c4a64SHelge Deller 
57b28c4a64SHelge Deller     /* clear bit 31 to indicate that the power switch was pressed. */
58b28c4a64SHelge Deller     val &= ~1;
59b28c4a64SHelge Deller     stl_be_phys(&address_space_memory, soft_power_reg, val);
60b28c4a64SHelge Deller }
61b28c4a64SHelge Deller 
62b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
63b28c4a64SHelge Deller     .notify = hppa_powerdown_req
64b28c4a64SHelge Deller };
65b28c4a64SHelge Deller 
6628f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
6728f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
6828f5332aSMark Cave-Ayland {
6928f5332aSMark Cave-Ayland     return 0;
7028f5332aSMark Cave-Ayland }
7128f5332aSMark Cave-Ayland 
7228f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
7328f5332aSMark Cave-Ayland {
7428f5332aSMark Cave-Ayland }
7528f5332aSMark Cave-Ayland 
7628f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7728f5332aSMark Cave-Ayland     .read = ignore_read,
7828f5332aSMark Cave-Ayland     .write = ignore_write,
7928f5332aSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
8028f5332aSMark Cave-Ayland     .valid = {
8128f5332aSMark Cave-Ayland         .min_access_size = 1,
8228f5332aSMark Cave-Ayland         .max_access_size = 8,
8328f5332aSMark Cave-Ayland     },
8428f5332aSMark Cave-Ayland     .impl = {
8528f5332aSMark Cave-Ayland         .min_access_size = 1,
8628f5332aSMark Cave-Ayland         .max_access_size = 8,
8728f5332aSMark Cave-Ayland     },
8828f5332aSMark Cave-Ayland };
89b28c4a64SHelge Deller 
90f386a16eSRichard Henderson static ISABus *hppa_isa_bus(hwaddr addr)
91a72bd606SHelge Deller {
92a72bd606SHelge Deller     ISABus *isa_bus;
93a72bd606SHelge Deller     qemu_irq *isa_irqs;
94a72bd606SHelge Deller     MemoryRegion *isa_region;
95a72bd606SHelge Deller 
96a72bd606SHelge Deller     isa_region = g_new(MemoryRegion, 1);
97a72bd606SHelge Deller     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
98a72bd606SHelge Deller                           NULL, "isa-io", 0x800);
99f386a16eSRichard Henderson     memory_region_add_subregion(get_system_memory(), addr, isa_region);
100a72bd606SHelge Deller 
101a72bd606SHelge Deller     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
102a72bd606SHelge Deller                           &error_abort);
103a536f564SHelge Deller     isa_irqs = i8259_init(isa_bus, NULL);
1047067887eSPhilippe Mathieu-Daudé     isa_bus_register_input_irqs(isa_bus, isa_irqs);
105a72bd606SHelge Deller 
106a72bd606SHelge Deller     return isa_bus;
107a72bd606SHelge Deller }
108a72bd606SHelge Deller 
109e2c41ee5SHelge Deller /*
110e2c41ee5SHelge Deller  * Helper functions to emulate RTC clock and DebugOutputPort
111e2c41ee5SHelge Deller  */
112e2c41ee5SHelge Deller static time_t rtc_ref;
113e2c41ee5SHelge Deller 
114e2c41ee5SHelge Deller static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
115e2c41ee5SHelge Deller {
116e2c41ee5SHelge Deller     uint64_t val = 0;
117e2c41ee5SHelge Deller 
118e2c41ee5SHelge Deller     switch (addr) {
119e2c41ee5SHelge Deller     case 0:             /* RTC clock */
120e2c41ee5SHelge Deller         val = time(NULL);
121e2c41ee5SHelge Deller         val += rtc_ref;
122e2c41ee5SHelge Deller         break;
123e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
124e2c41ee5SHelge Deller         return 0xe9;    /* readback */
125e2c41ee5SHelge Deller     }
126e2c41ee5SHelge Deller     return val;
127e2c41ee5SHelge Deller }
128e2c41ee5SHelge Deller 
129e2c41ee5SHelge Deller static void io_cpu_write(void *opaque, hwaddr addr,
130e2c41ee5SHelge Deller                          uint64_t val, unsigned size)
131e2c41ee5SHelge Deller {
132e2c41ee5SHelge Deller     unsigned char ch;
133e2c41ee5SHelge Deller     Chardev *debugout;
134e2c41ee5SHelge Deller 
135e2c41ee5SHelge Deller     switch (addr) {
136e2c41ee5SHelge Deller     case 0:             /* RTC clock */
137e2c41ee5SHelge Deller         rtc_ref = val - time(NULL);
138e2c41ee5SHelge Deller         break;
139e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
140e2c41ee5SHelge Deller         ch = val;
141e2c41ee5SHelge Deller         debugout = serial_hd(0);
142e2c41ee5SHelge Deller         if (debugout) {
143e2c41ee5SHelge Deller             qemu_chr_fe_write_all(debugout->be, &ch, 1);
144e2c41ee5SHelge Deller         } else {
145e2c41ee5SHelge Deller             fprintf(stderr, "%c", ch);
146e2c41ee5SHelge Deller         }
147e2c41ee5SHelge Deller         break;
148e2c41ee5SHelge Deller     }
149e2c41ee5SHelge Deller }
150e2c41ee5SHelge Deller 
151e2c41ee5SHelge Deller static const MemoryRegionOps hppa_io_helper_ops = {
152e2c41ee5SHelge Deller     .read = io_cpu_read,
153e2c41ee5SHelge Deller     .write = io_cpu_write,
154e2c41ee5SHelge Deller     .endianness = DEVICE_BIG_ENDIAN,
155e2c41ee5SHelge Deller     .valid = {
156e2c41ee5SHelge Deller         .min_access_size = 1,
157e2c41ee5SHelge Deller         .max_access_size = 8,
158e2c41ee5SHelge Deller     },
159e2c41ee5SHelge Deller     .impl = {
160e2c41ee5SHelge Deller         .min_access_size = 1,
161e2c41ee5SHelge Deller         .max_access_size = 8,
162e2c41ee5SHelge Deller     },
163e2c41ee5SHelge Deller };
164e2c41ee5SHelge Deller 
165f386a16eSRichard Henderson typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
166e2c41ee5SHelge Deller 
167f386a16eSRichard Henderson static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
168a72bd606SHelge Deller {
169a72bd606SHelge Deller     addr &= (0x10000000 - 1);
170a72bd606SHelge Deller     return addr;
171a72bd606SHelge Deller }
172a72bd606SHelge Deller 
173f386a16eSRichard Henderson static uint64_t translate_pa10(void *dummy, uint64_t addr)
174f386a16eSRichard Henderson {
175f386a16eSRichard Henderson     return (uint32_t)addr;
176f386a16eSRichard Henderson }
177f386a16eSRichard Henderson 
178f386a16eSRichard Henderson static uint64_t translate_pa20(void *dummy, uint64_t addr)
179f386a16eSRichard Henderson {
180f386a16eSRichard Henderson     return hppa_abs_to_phys_pa2_w0(addr);
181f386a16eSRichard Henderson }
182f386a16eSRichard Henderson 
183a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
184a72bd606SHelge Deller static uint64_t firmware_entry;
185813dff13SHelge Deller 
18632ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
18732ff8bf2SHelge Deller                             Error **errp)
18832ff8bf2SHelge Deller {
18932ff8bf2SHelge Deller     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
19032ff8bf2SHelge Deller }
19132ff8bf2SHelge Deller 
192f386a16eSRichard Henderson static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
193f386a16eSRichard Henderson                                  hwaddr addr)
19428b71a2eSHelge Deller {
19528b71a2eSHelge Deller     FWCfgState *fw_cfg;
19628b71a2eSHelge Deller     uint64_t val;
197069d2966SHelge Deller     const char qemu_version[] = QEMU_VERSION;
198bcd4dd4cSHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(ms);
1999cf2112bSRichard Henderson     int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
200bcd4dd4cSHelge Deller     int len;
20128b71a2eSHelge Deller 
202f386a16eSRichard Henderson     fw_cfg = fw_cfg_init_mem(addr, addr + 4);
20328b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
20428b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
205bfdf22bcSPaolo Bonzini     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
20628b71a2eSHelge Deller 
20728b71a2eSHelge Deller     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
20828b71a2eSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
20928b71a2eSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
21028b71a2eSHelge Deller 
2119cf2112bSRichard Henderson     val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
212df5c6a50SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
213df5c6a50SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
214df5c6a50SHelge Deller 
2159cf2112bSRichard Henderson     val = cpu_to_le64(btlb_entries);
216bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
217bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
218bcd4dd4cSHelge Deller 
219bcd4dd4cSHelge Deller     len = strlen(mc->name) + 1;
220bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
221bcd4dd4cSHelge Deller                     g_memdup(mc->name, len), len);
222bcd4dd4cSHelge Deller 
223*ed35afcbSHelge Deller     val = cpu_to_le64(soft_power_reg);
224bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
225bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
226bcd4dd4cSHelge Deller 
227e2c41ee5SHelge Deller     val = cpu_to_le64(CPU_HPA + 16);
228e2c41ee5SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
229e2c41ee5SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
230e2c41ee5SHelge Deller 
231bcd4dd4cSHelge Deller     val = cpu_to_le64(CPU_HPA + 24);
232bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
233b28c4a64SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
234b28c4a64SHelge Deller 
23597ec4d21SPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
23632ff8bf2SHelge Deller     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
23732ff8bf2SHelge Deller 
238069d2966SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
239069d2966SHelge Deller                     g_memdup(qemu_version, sizeof(qemu_version)),
240069d2966SHelge Deller                     sizeof(qemu_version));
241069d2966SHelge Deller 
242bcd4dd4cSHelge Deller     fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
243bcd4dd4cSHelge Deller 
24428b71a2eSHelge Deller     return fw_cfg;
24528b71a2eSHelge Deller }
24628b71a2eSHelge Deller 
247e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
248e881e3c8SMark Cave-Ayland {
249e881e3c8SMark Cave-Ayland     DeviceState *dev;
250e881e3c8SMark Cave-Ayland 
251e881e3c8SMark Cave-Ayland     dev = qdev_new(TYPE_LASI_CHIP);
252e881e3c8SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
253e881e3c8SMark Cave-Ayland 
254e881e3c8SMark Cave-Ayland     return LASI_CHIP(dev);
255e881e3c8SMark Cave-Ayland }
256e881e3c8SMark Cave-Ayland 
2570d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
2580d068996SMark Cave-Ayland {
2590d068996SMark Cave-Ayland     DeviceState *dev;
2600d068996SMark Cave-Ayland 
2610d068996SMark Cave-Ayland     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
2620d068996SMark Cave-Ayland     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
2630d068996SMark Cave-Ayland                              &error_fatal);
2640d068996SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2650d068996SMark Cave-Ayland 
2660d068996SMark Cave-Ayland     return DINO_PCI_HOST_BRIDGE(dev);
2670d068996SMark Cave-Ayland }
2680d068996SMark Cave-Ayland 
2697df6f751SHelge Deller /*
2707df6f751SHelge Deller  * Step 1: Create CPUs and Memory
2717df6f751SHelge Deller  */
272f386a16eSRichard Henderson static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
273813dff13SHelge Deller {
274a72bd606SHelge Deller     MemoryRegion *addr_space = get_system_memory();
27533decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
276f386a16eSRichard Henderson     TranslateFn *translate;
277f386a16eSRichard Henderson     MemoryRegion *cpu_region;
27892039f61SHelge Deller     uint64_t ram_max;
279a72bd606SHelge Deller 
280a72bd606SHelge Deller     /* Create CPUs.  */
281f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
282a72bd606SHelge Deller         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
283f386a16eSRichard Henderson     }
284f386a16eSRichard Henderson 
285f386a16eSRichard Henderson     /*
286f386a16eSRichard Henderson      * For now, treat address layout as if PSW_W is clear.
287f386a16eSRichard Henderson      * TODO: create a proper hppa64 board model and load elf64 firmware.
288f386a16eSRichard Henderson      */
289f386a16eSRichard Henderson     if (hppa_is_pa20(&cpu[0]->env)) {
290f386a16eSRichard Henderson         translate = translate_pa20;
29192039f61SHelge Deller         ram_max = 0xf0000000;      /* 3.75 GB (limited by 32-bit firmware) */
292f386a16eSRichard Henderson     } else {
293f386a16eSRichard Henderson         translate = translate_pa10;
29492039f61SHelge Deller         ram_max = 0xf0000000;      /* 3.75 GB (32-bit CPU) */
295f386a16eSRichard Henderson     }
296f386a16eSRichard Henderson 
297*ed35afcbSHelge Deller     soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
298*ed35afcbSHelge Deller 
299f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
300f386a16eSRichard Henderson         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
301a72bd606SHelge Deller 
302a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
303a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
304266a880eSPaolo Bonzini                               cpu[i], name, 4);
305f386a16eSRichard Henderson         memory_region_add_subregion(addr_space,
306f386a16eSRichard Henderson                                     translate(NULL, CPU_HPA + i * 0x1000),
307a72bd606SHelge Deller                                     cpu_region);
308813dff13SHelge Deller     }
309813dff13SHelge Deller 
310e2c41ee5SHelge Deller     /* RTC and DebugOutputPort on CPU #0 */
311e2c41ee5SHelge Deller     cpu_region = g_new(MemoryRegion, 1);
312e2c41ee5SHelge Deller     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
313e2c41ee5SHelge Deller                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
314f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
315f386a16eSRichard Henderson                                 cpu_region);
316e2c41ee5SHelge Deller 
317a72bd606SHelge Deller     /* Main memory region. */
31892039f61SHelge Deller     if (machine->ram_size > ram_max) {
31992039f61SHelge Deller         info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
32092039f61SHelge Deller         machine->ram_size = ram_max;
321b7746b11SPhilippe Mathieu-Daudé     }
3227c59c1e0SIgor Mammedov     memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
323f386a16eSRichard Henderson 
324f386a16eSRichard Henderson     return translate;
3257df6f751SHelge Deller }
3267c59c1e0SIgor Mammedov 
3277df6f751SHelge Deller /*
3287df6f751SHelge Deller  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
3297df6f751SHelge Deller  */
330f386a16eSRichard Henderson static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
331f386a16eSRichard Henderson                                         TranslateFn *translate)
3327df6f751SHelge Deller {
3337df6f751SHelge Deller     const char *kernel_filename = machine->kernel_filename;
3347df6f751SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
3357df6f751SHelge Deller     const char *initrd_filename = machine->initrd_filename;
3367df6f751SHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(machine);
3377df6f751SHelge Deller     DeviceState *dev;
3382ed4faa0SHelge Deller     PCIDevice *pci_dev;
3397df6f751SHelge Deller     char *firmware_filename;
3407df6f751SHelge Deller     uint64_t firmware_low, firmware_high;
3417df6f751SHelge Deller     long size;
3427df6f751SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
3437df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
3447df6f751SHelge Deller     MemoryRegion *rom_region;
3457df6f751SHelge Deller     long i;
3467df6f751SHelge Deller     unsigned int smp_cpus = machine->smp.cpus;
3477df6f751SHelge Deller     SysBusDevice *s;
34828b71a2eSHelge Deller 
349a72bd606SHelge Deller     /* SCSI disk setup. */
350d8a32200SHelge Deller     if (drive_get_max_bus(IF_SCSI) >= 0) {
351877eb21dSMark Cave-Ayland         dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
352877eb21dSMark Cave-Ayland         lsi53c8xx_handle_legacy_cmdline(dev);
353d8a32200SHelge Deller     }
354a72bd606SHelge Deller 
3554765384cSSven Schnelle     /* Graphics setup. */
3564765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
357f9bcb2d6SGautam Agrawal         vga_interface_created = true;
3583e80f690SMarkus Armbruster         dev = qdev_new("artist");
3594765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
3603c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
361f386a16eSRichard Henderson         sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
362f386a16eSRichard Henderson         sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
3634765384cSSven Schnelle     }
3644765384cSSven Schnelle 
3650e6de551SHelge Deller     /* Network setup. */
366d8a32200SHelge Deller     if (nd_table[0].used && enable_lasi_lan()) {
367f386a16eSRichard Henderson         lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
368c3c3fe47SMark Cave-Ayland                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
369c3c3fe47SMark Cave-Ayland     }
370c3c3fe47SMark Cave-Ayland 
371a72bd606SHelge Deller     for (i = 0; i < nb_nics; i++) {
372376b8519SHelge Deller         if (!enable_lasi_lan()) {
3739f8981a9SThomas Huth             pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL);
374a72bd606SHelge Deller         }
375376b8519SHelge Deller     }
376a72bd606SHelge Deller 
3772ed4faa0SHelge Deller     /* BMC board: HP Powerbar SP2 Diva (with console only) */
3782ed4faa0SHelge Deller     pci_dev = pci_new(-1, "pci-serial");
3792ed4faa0SHelge Deller     if (!lasi_dev) {
3802ed4faa0SHelge Deller         /* bind default keyboard/serial to Diva card */
3812ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0));
3822ed4faa0SHelge Deller     }
3832ed4faa0SHelge Deller     qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0);
3842ed4faa0SHelge Deller     pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3852ed4faa0SHelge Deller     pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP);
3862ed4faa0SHelge Deller     pci_config_set_device_id(pci_dev->config, 0x1048);
3872ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP);
3882ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
3892ed4faa0SHelge Deller 
3902ed4faa0SHelge Deller     /* create a second serial PCI card when running Astro */
391d8a32200SHelge Deller     if (serial_hd(1) && !lasi_dev) {
3922ed4faa0SHelge Deller         pci_dev = pci_new(-1, "pci-serial-4x");
3932ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
3942ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
3952ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3));
3962ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4));
3972ed4faa0SHelge Deller         pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3982ed4faa0SHelge Deller     }
3992ed4faa0SHelge Deller 
4002ed4faa0SHelge Deller     /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
4012ed4faa0SHelge Deller     if (!lasi_dev && machine->enable_graphics) {
4022ed4faa0SHelge Deller         pci_create_simple(pci_bus, -1, "pci-ohci");
4032ed4faa0SHelge Deller         usb_create_simple(usb_bus_find(-1), "usb-kbd");
4042ed4faa0SHelge Deller         usb_create_simple(usb_bus_find(-1), "usb-mouse");
4052ed4faa0SHelge Deller     }
4062ed4faa0SHelge Deller 
407b28c4a64SHelge Deller     /* register power switch emulation */
408b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
409b28c4a64SHelge Deller 
4107df6f751SHelge Deller     /* fw_cfg configuration interface */
411f386a16eSRichard Henderson     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
4127df6f751SHelge Deller 
413a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
414a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
415a72bd606SHelge Deller        well load it directly from an ELF image.  */
416a72bd606SHelge Deller     firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
417b57e3e97SPaolo Bonzini                                        machine->firmware ?: "hppa-firmware.img");
418a72bd606SHelge Deller     if (firmware_filename == NULL) {
419a72bd606SHelge Deller         error_report("no firmware provided");
420a72bd606SHelge Deller         exit(1);
421a72bd606SHelge Deller     }
422a72bd606SHelge Deller 
423f386a16eSRichard Henderson     size = load_elf(firmware_filename, NULL, translate, NULL,
4246cdda0ffSAleksandar Markovic                     &firmware_entry, &firmware_low, &firmware_high, NULL,
425a72bd606SHelge Deller                     true, EM_PARISC, 0, 0);
426a72bd606SHelge Deller 
427a72bd606SHelge Deller     if (size < 0) {
428a72bd606SHelge Deller         error_report("could not load firmware '%s'", firmware_filename);
429a72bd606SHelge Deller         exit(1);
430a72bd606SHelge Deller     }
431691cbbadSRichard Henderson     qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
432691cbbadSRichard Henderson                   "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
433a72bd606SHelge Deller                   firmware_low, firmware_high, firmware_entry);
434f386a16eSRichard Henderson     if (firmware_low < translate(NULL, FIRMWARE_START) ||
435f386a16eSRichard Henderson         firmware_high >= translate(NULL, FIRMWARE_END)) {
436a72bd606SHelge Deller         error_report("Firmware overlaps with memory or IO space");
437a72bd606SHelge Deller         exit(1);
438a72bd606SHelge Deller     }
439a72bd606SHelge Deller     g_free(firmware_filename);
440a72bd606SHelge Deller 
441a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
4426a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
4436a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
444f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
445f386a16eSRichard Henderson                                 translate(NULL, FIRMWARE_START), rom_region);
446a72bd606SHelge Deller 
447a72bd606SHelge Deller     /* Load kernel */
448a72bd606SHelge Deller     if (kernel_filename) {
449f386a16eSRichard Henderson         size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
4506cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
451a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
452a72bd606SHelge Deller 
453f386a16eSRichard Henderson         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
454a72bd606SHelge Deller 
455a72bd606SHelge Deller         if (size < 0) {
456a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
457a72bd606SHelge Deller             exit(1);
458a72bd606SHelge Deller         }
459691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
460691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
461c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
462c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
463a72bd606SHelge Deller 
464a72bd606SHelge Deller         if (kernel_cmdline) {
465a72bd606SHelge Deller             cpu[0]->env.gr[24] = 0x4000;
466a72bd606SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
467a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
468a72bd606SHelge Deller         }
469a72bd606SHelge Deller 
470a72bd606SHelge Deller         if (initrd_filename) {
471a72bd606SHelge Deller             ram_addr_t initrd_base;
472f3839fdaSLi Zhijian             int64_t initrd_size;
473a72bd606SHelge Deller 
474a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
475a72bd606SHelge Deller             if (initrd_size < 0) {
476a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
477a72bd606SHelge Deller                              initrd_filename);
478a72bd606SHelge Deller                 exit(1);
479a72bd606SHelge Deller             }
480a72bd606SHelge Deller 
481a72bd606SHelge Deller             /* Load the initrd image high in memory.
482a72bd606SHelge Deller                Mirror the algorithm used by palo:
483a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
484a72bd606SHelge Deller                put the initrd no higher than 1G.
485a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
486bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
487c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
488a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
489a72bd606SHelge Deller 
490a72bd606SHelge Deller             if (initrd_base < kernel_high) {
491a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
492a72bd606SHelge Deller                 exit(1);
493a72bd606SHelge Deller             }
494a72bd606SHelge Deller 
495a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
496a72bd606SHelge Deller             cpu[0]->env.gr[23] = initrd_base;
497a72bd606SHelge Deller             cpu[0]->env.gr[22] = initrd_base + initrd_size;
498a72bd606SHelge Deller         }
499a72bd606SHelge Deller     }
500a72bd606SHelge Deller 
501a72bd606SHelge Deller     if (!kernel_entry) {
502a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
503a72bd606SHelge Deller          * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
504a72bd606SHelge Deller          * or hard disc * (gr[24]='c').
505a72bd606SHelge Deller          */
50697ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
50797ec4d21SPaolo Bonzini         cpu[0]->env.gr[24] = machine->boot_config.order[0];
508a72bd606SHelge Deller     }
509a72bd606SHelge Deller 
510a72bd606SHelge Deller     /* We jump to the firmware entry routine and pass the
511a72bd606SHelge Deller      * various parameters in registers. After firmware initialization,
512a72bd606SHelge Deller      * firmware will start the Linux kernel with ramdisk and cmdline.
513a72bd606SHelge Deller      */
514bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = machine->ram_size;
515a72bd606SHelge Deller     cpu[0]->env.gr[25] = kernel_entry;
516a72bd606SHelge Deller 
517a72bd606SHelge Deller     /* tell firmware how many SMP CPUs to present in inventory table */
518a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
51924576007SHelge Deller 
52024576007SHelge Deller     /* tell firmware fw_cfg port */
52124576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
522a72bd606SHelge Deller }
523a72bd606SHelge Deller 
5247df6f751SHelge Deller /*
5257df6f751SHelge Deller  * Create HP B160L workstation
5267df6f751SHelge Deller  */
5277df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
5287df6f751SHelge Deller {
5297df6f751SHelge Deller     DeviceState *dev, *dino_dev;
5307df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
531f386a16eSRichard Henderson     TranslateFn *translate;
5327df6f751SHelge Deller     ISABus *isa_bus;
5337df6f751SHelge Deller     PCIBus *pci_bus;
5347df6f751SHelge Deller 
5357df6f751SHelge Deller     /* Create CPUs and RAM.  */
536f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
5377df6f751SHelge Deller 
5383d1611bfSHelge Deller     if (hppa_is_pa20(&cpu[0]->env)) {
5393d1611bfSHelge Deller         error_report("The HP B160L workstation requires a 32-bit "
5403d1611bfSHelge Deller                      "CPU. Use '-machine C3700' instead.");
5413d1611bfSHelge Deller         exit(1);
5423d1611bfSHelge Deller     }
5433d1611bfSHelge Deller 
5447df6f751SHelge Deller     /* Init Lasi chip */
5457df6f751SHelge Deller     lasi_dev = DEVICE(lasi_init());
546f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
5477df6f751SHelge Deller                                 sysbus_mmio_get_region(
5487df6f751SHelge Deller                                     SYS_BUS_DEVICE(lasi_dev), 0));
5497df6f751SHelge Deller 
5507df6f751SHelge Deller     /* Init Dino (PCI host bus chip).  */
5517df6f751SHelge Deller     dino_dev = DEVICE(dino_init(addr_space));
552f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
5537df6f751SHelge Deller                                 sysbus_mmio_get_region(
5547df6f751SHelge Deller                                     SYS_BUS_DEVICE(dino_dev), 0));
5557df6f751SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
5567df6f751SHelge Deller     assert(pci_bus);
5577df6f751SHelge Deller 
5587df6f751SHelge Deller     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
559f386a16eSRichard Henderson     isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
5607df6f751SHelge Deller     assert(isa_bus);
5617df6f751SHelge Deller 
5627df6f751SHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
563f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
5647df6f751SHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
5657df6f751SHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
5667df6f751SHelge Deller 
567f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
5687df6f751SHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
5697df6f751SHelge Deller         serial_hd(1), DEVICE_BIG_ENDIAN);
5707df6f751SHelge Deller 
5717df6f751SHelge Deller     /* Parallel port */
572f386a16eSRichard Henderson     parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
5737df6f751SHelge Deller                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
5747df6f751SHelge Deller                      parallel_hds[0]);
5757df6f751SHelge Deller 
5767df6f751SHelge Deller     /* PS/2 Keyboard/Mouse */
5777df6f751SHelge Deller     dev = qdev_new(TYPE_LASIPS2);
5787df6f751SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5797df6f751SHelge Deller     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
5807df6f751SHelge Deller                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
581f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
582f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA),
5837df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5847df6f751SHelge Deller                                                        0));
585f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
586f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA + 0x100),
5877df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5887df6f751SHelge Deller                                                        1));
5897df6f751SHelge Deller 
5907df6f751SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
591f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
5927df6f751SHelge Deller }
5937df6f751SHelge Deller 
5942ed4faa0SHelge Deller static AstroState *astro_init(void)
5952ed4faa0SHelge Deller {
5962ed4faa0SHelge Deller     DeviceState *dev;
5972ed4faa0SHelge Deller 
5982ed4faa0SHelge Deller     dev = qdev_new(TYPE_ASTRO_CHIP);
5992ed4faa0SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
6002ed4faa0SHelge Deller 
6012ed4faa0SHelge Deller     return ASTRO_CHIP(dev);
6022ed4faa0SHelge Deller }
6032ed4faa0SHelge Deller 
6042ed4faa0SHelge Deller /*
6052ed4faa0SHelge Deller  * Create HP C3700 workstation
6062ed4faa0SHelge Deller  */
6072ed4faa0SHelge Deller static void machine_HP_C3700_init(MachineState *machine)
6082ed4faa0SHelge Deller {
6092ed4faa0SHelge Deller     PCIBus *pci_bus;
6102ed4faa0SHelge Deller     AstroState *astro;
6112ed4faa0SHelge Deller     DeviceState *astro_dev;
6122ed4faa0SHelge Deller     MemoryRegion *addr_space = get_system_memory();
613f386a16eSRichard Henderson     TranslateFn *translate;
6142ed4faa0SHelge Deller 
6152ed4faa0SHelge Deller     /* Create CPUs and RAM.  */
616f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
6172ed4faa0SHelge Deller 
6183d1611bfSHelge Deller     if (!hppa_is_pa20(&cpu[0]->env)) {
6193d1611bfSHelge Deller         error_report("The HP C3000 workstation requires a 64-bit CPU. "
6203d1611bfSHelge Deller                      "Use '-machine B160L' instead.");
6213d1611bfSHelge Deller         exit(1);
6223d1611bfSHelge Deller     }
6233d1611bfSHelge Deller 
6242ed4faa0SHelge Deller     /* Init Astro and the Elroys (PCI host bus chips).  */
6252ed4faa0SHelge Deller     astro = astro_init();
6262ed4faa0SHelge Deller     astro_dev = DEVICE(astro);
627f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
6282ed4faa0SHelge Deller                                 sysbus_mmio_get_region(
6292ed4faa0SHelge Deller                                     SYS_BUS_DEVICE(astro_dev), 0));
6302ed4faa0SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
6312ed4faa0SHelge Deller     assert(pci_bus);
6322ed4faa0SHelge Deller 
6332ed4faa0SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
634f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
6352ed4faa0SHelge Deller }
6362ed4faa0SHelge Deller 
6377966d70fSJason A. Donenfeld static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
638a72bd606SHelge Deller {
63933decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
640a72bd606SHelge Deller     int i;
641a72bd606SHelge Deller 
6427966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
643a72bd606SHelge Deller 
644a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
645a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
64650ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
647a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
64850ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
64950ba97e9SHelge Deller 
65050ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
65150ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
652a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
65350ba97e9SHelge Deller 
65450ba97e9SHelge Deller         cs->exception_index = -1;
65550ba97e9SHelge Deller         cs->halted = 0;
656a72bd606SHelge Deller     }
657a72bd606SHelge Deller 
658a72bd606SHelge Deller     /* already initialized by machine_hppa_init()? */
659bfdf22bcSPaolo Bonzini     if (cpu[0]->env.gr[26] == ms->ram_size) {
660a72bd606SHelge Deller         return;
661a72bd606SHelge Deller     }
662a72bd606SHelge Deller 
663bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
664a72bd606SHelge Deller     cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
665a72bd606SHelge Deller     cpu[0]->env.gr[24] = 'c';
666a72bd606SHelge Deller     /* gr22/gr23 unused, no initrd while reboot. */
667a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
66824576007SHelge Deller     /* tell firmware fw_cfg port */
66924576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
670a72bd606SHelge Deller }
671a72bd606SHelge Deller 
6724a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
6734a4554c6SHelge Deller {
6744a4554c6SHelge Deller     CPUState *cs;
6754a4554c6SHelge Deller 
6764a4554c6SHelge Deller     CPU_FOREACH(cs) {
6774a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
6784a4554c6SHelge Deller     }
6794a4554c6SHelge Deller }
680a72bd606SHelge Deller 
681790a4428SGavin Shan static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
682790a4428SGavin Shan {
683790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
6843d1611bfSHelge Deller         TYPE_HPPA_CPU,
6853d1611bfSHelge Deller         NULL
6863d1611bfSHelge Deller     };
68742cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
68842cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
68942cc2bf6SMark Cave-Ayland 
6907df6f751SHelge Deller     mc->desc = "HP B160L workstation";
691a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
692790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
6937df6f751SHelge Deller     mc->init = machine_HP_B160L_init;
694a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
695813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
696a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
697a72bd606SHelge Deller     mc->default_cpus = 1;
698ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
699d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
700813dff13SHelge Deller     mc->default_boot_order = "cd";
7017c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
7029f8981a9SThomas Huth     mc->default_nic = "tulip";
703813dff13SHelge Deller 
7044a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7054a4554c6SHelge Deller }
7064a4554c6SHelge Deller 
7077df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
7087df6f751SHelge Deller     .name = MACHINE_TYPE_NAME("B160L"),
709c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
7107df6f751SHelge Deller     .class_init = HP_B160L_machine_init_class_init,
7114a4554c6SHelge Deller     .interfaces = (InterfaceInfo[]) {
7124a4554c6SHelge Deller         { TYPE_NMI },
7134a4554c6SHelge Deller         { }
7144a4554c6SHelge Deller     },
7154a4554c6SHelge Deller };
7164a4554c6SHelge Deller 
717790a4428SGavin Shan static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
718790a4428SGavin Shan {
719790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
7203d1611bfSHelge Deller         TYPE_HPPA64_CPU,
7213d1611bfSHelge Deller         NULL
7223d1611bfSHelge Deller     };
7232ed4faa0SHelge Deller     MachineClass *mc = MACHINE_CLASS(oc);
7242ed4faa0SHelge Deller     NMIClass *nc = NMI_CLASS(oc);
7252ed4faa0SHelge Deller 
7262ed4faa0SHelge Deller     mc->desc = "HP C3700 workstation";
727fd9b04bfSHelge Deller     mc->default_cpu_type = TYPE_HPPA64_CPU;
728790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
7292ed4faa0SHelge Deller     mc->init = machine_HP_C3700_init;
7302ed4faa0SHelge Deller     mc->reset = hppa_machine_reset;
7312ed4faa0SHelge Deller     mc->block_default_type = IF_SCSI;
7322ed4faa0SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
7332ed4faa0SHelge Deller     mc->default_cpus = 1;
7342ed4faa0SHelge Deller     mc->is_default = false;
7352ed4faa0SHelge Deller     mc->default_ram_size = 1024 * MiB;
7362ed4faa0SHelge Deller     mc->default_boot_order = "cd";
7372ed4faa0SHelge Deller     mc->default_ram_id = "ram";
7382ed4faa0SHelge Deller     mc->default_nic = "tulip";
7392ed4faa0SHelge Deller 
7402ed4faa0SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7412ed4faa0SHelge Deller }
7422ed4faa0SHelge Deller 
7432ed4faa0SHelge Deller static const TypeInfo HP_C3700_machine_init_typeinfo = {
7442ed4faa0SHelge Deller     .name = MACHINE_TYPE_NAME("C3700"),
7452ed4faa0SHelge Deller     .parent = TYPE_MACHINE,
7462ed4faa0SHelge Deller     .class_init = HP_C3700_machine_init_class_init,
7472ed4faa0SHelge Deller     .interfaces = (InterfaceInfo[]) {
7482ed4faa0SHelge Deller         { TYPE_NMI },
7492ed4faa0SHelge Deller         { }
7502ed4faa0SHelge Deller     },
7512ed4faa0SHelge Deller };
7522ed4faa0SHelge Deller 
753297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
7544a4554c6SHelge Deller {
7557df6f751SHelge Deller     type_register_static(&HP_B160L_machine_init_typeinfo);
7562ed4faa0SHelge Deller     type_register_static(&HP_C3700_machine_init_typeinfo);
7574a4554c6SHelge Deller }
7584a4554c6SHelge Deller 
759297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
760