xref: /openbmc/qemu/hw/hppa/machine.c (revision 790a4428f2e2a32944f3cefc4753ab3c71611453)
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 
39e274d2a7SHelge Deller /* Power button address at &PAGE0->pad[4] */
40e274d2a7SHelge Deller #define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t))
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     hwaddr soft_power_reg = HPA_POWER_BUTTON;
49b28c4a64SHelge Deller     uint32_t val;
50b28c4a64SHelge Deller 
51b28c4a64SHelge Deller     val = ldl_be_phys(&address_space_memory, soft_power_reg);
52b28c4a64SHelge Deller     if ((val >> 8) == 0) {
53b28c4a64SHelge Deller         /* immediately shut down when under hardware control */
54b28c4a64SHelge Deller         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
55b28c4a64SHelge Deller         return;
56b28c4a64SHelge Deller     }
57b28c4a64SHelge Deller 
58b28c4a64SHelge Deller     /* clear bit 31 to indicate that the power switch was pressed. */
59b28c4a64SHelge Deller     val &= ~1;
60b28c4a64SHelge Deller     stl_be_phys(&address_space_memory, soft_power_reg, val);
61b28c4a64SHelge Deller }
62b28c4a64SHelge Deller 
63b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
64b28c4a64SHelge Deller     .notify = hppa_powerdown_req
65b28c4a64SHelge Deller };
66b28c4a64SHelge Deller 
6728f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
6828f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
6928f5332aSMark Cave-Ayland {
7028f5332aSMark Cave-Ayland     return 0;
7128f5332aSMark Cave-Ayland }
7228f5332aSMark Cave-Ayland 
7328f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
7428f5332aSMark Cave-Ayland {
7528f5332aSMark Cave-Ayland }
7628f5332aSMark Cave-Ayland 
7728f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7828f5332aSMark Cave-Ayland     .read = ignore_read,
7928f5332aSMark Cave-Ayland     .write = ignore_write,
8028f5332aSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
8128f5332aSMark Cave-Ayland     .valid = {
8228f5332aSMark Cave-Ayland         .min_access_size = 1,
8328f5332aSMark Cave-Ayland         .max_access_size = 8,
8428f5332aSMark Cave-Ayland     },
8528f5332aSMark Cave-Ayland     .impl = {
8628f5332aSMark Cave-Ayland         .min_access_size = 1,
8728f5332aSMark Cave-Ayland         .max_access_size = 8,
8828f5332aSMark Cave-Ayland     },
8928f5332aSMark Cave-Ayland };
90b28c4a64SHelge Deller 
91f386a16eSRichard Henderson static ISABus *hppa_isa_bus(hwaddr addr)
92a72bd606SHelge Deller {
93a72bd606SHelge Deller     ISABus *isa_bus;
94a72bd606SHelge Deller     qemu_irq *isa_irqs;
95a72bd606SHelge Deller     MemoryRegion *isa_region;
96a72bd606SHelge Deller 
97a72bd606SHelge Deller     isa_region = g_new(MemoryRegion, 1);
98a72bd606SHelge Deller     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
99a72bd606SHelge Deller                           NULL, "isa-io", 0x800);
100f386a16eSRichard Henderson     memory_region_add_subregion(get_system_memory(), addr, isa_region);
101a72bd606SHelge Deller 
102a72bd606SHelge Deller     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
103a72bd606SHelge Deller                           &error_abort);
104a536f564SHelge Deller     isa_irqs = i8259_init(isa_bus, NULL);
1057067887eSPhilippe Mathieu-Daudé     isa_bus_register_input_irqs(isa_bus, isa_irqs);
106a72bd606SHelge Deller 
107a72bd606SHelge Deller     return isa_bus;
108a72bd606SHelge Deller }
109a72bd606SHelge Deller 
110e2c41ee5SHelge Deller /*
111e2c41ee5SHelge Deller  * Helper functions to emulate RTC clock and DebugOutputPort
112e2c41ee5SHelge Deller  */
113e2c41ee5SHelge Deller static time_t rtc_ref;
114e2c41ee5SHelge Deller 
115e2c41ee5SHelge Deller static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
116e2c41ee5SHelge Deller {
117e2c41ee5SHelge Deller     uint64_t val = 0;
118e2c41ee5SHelge Deller 
119e2c41ee5SHelge Deller     switch (addr) {
120e2c41ee5SHelge Deller     case 0:             /* RTC clock */
121e2c41ee5SHelge Deller         val = time(NULL);
122e2c41ee5SHelge Deller         val += rtc_ref;
123e2c41ee5SHelge Deller         break;
124e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
125e2c41ee5SHelge Deller         return 0xe9;    /* readback */
126e2c41ee5SHelge Deller     }
127e2c41ee5SHelge Deller     return val;
128e2c41ee5SHelge Deller }
129e2c41ee5SHelge Deller 
130e2c41ee5SHelge Deller static void io_cpu_write(void *opaque, hwaddr addr,
131e2c41ee5SHelge Deller                          uint64_t val, unsigned size)
132e2c41ee5SHelge Deller {
133e2c41ee5SHelge Deller     unsigned char ch;
134e2c41ee5SHelge Deller     Chardev *debugout;
135e2c41ee5SHelge Deller 
136e2c41ee5SHelge Deller     switch (addr) {
137e2c41ee5SHelge Deller     case 0:             /* RTC clock */
138e2c41ee5SHelge Deller         rtc_ref = val - time(NULL);
139e2c41ee5SHelge Deller         break;
140e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
141e2c41ee5SHelge Deller         ch = val;
142e2c41ee5SHelge Deller         debugout = serial_hd(0);
143e2c41ee5SHelge Deller         if (debugout) {
144e2c41ee5SHelge Deller             qemu_chr_fe_write_all(debugout->be, &ch, 1);
145e2c41ee5SHelge Deller         } else {
146e2c41ee5SHelge Deller             fprintf(stderr, "%c", ch);
147e2c41ee5SHelge Deller         }
148e2c41ee5SHelge Deller         break;
149e2c41ee5SHelge Deller     }
150e2c41ee5SHelge Deller }
151e2c41ee5SHelge Deller 
152e2c41ee5SHelge Deller static const MemoryRegionOps hppa_io_helper_ops = {
153e2c41ee5SHelge Deller     .read = io_cpu_read,
154e2c41ee5SHelge Deller     .write = io_cpu_write,
155e2c41ee5SHelge Deller     .endianness = DEVICE_BIG_ENDIAN,
156e2c41ee5SHelge Deller     .valid = {
157e2c41ee5SHelge Deller         .min_access_size = 1,
158e2c41ee5SHelge Deller         .max_access_size = 8,
159e2c41ee5SHelge Deller     },
160e2c41ee5SHelge Deller     .impl = {
161e2c41ee5SHelge Deller         .min_access_size = 1,
162e2c41ee5SHelge Deller         .max_access_size = 8,
163e2c41ee5SHelge Deller     },
164e2c41ee5SHelge Deller };
165e2c41ee5SHelge Deller 
166f386a16eSRichard Henderson typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
167e2c41ee5SHelge Deller 
168f386a16eSRichard Henderson static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
169a72bd606SHelge Deller {
170a72bd606SHelge Deller     addr &= (0x10000000 - 1);
171a72bd606SHelge Deller     return addr;
172a72bd606SHelge Deller }
173a72bd606SHelge Deller 
174f386a16eSRichard Henderson static uint64_t translate_pa10(void *dummy, uint64_t addr)
175f386a16eSRichard Henderson {
176f386a16eSRichard Henderson     return (uint32_t)addr;
177f386a16eSRichard Henderson }
178f386a16eSRichard Henderson 
179f386a16eSRichard Henderson static uint64_t translate_pa20(void *dummy, uint64_t addr)
180f386a16eSRichard Henderson {
181f386a16eSRichard Henderson     return hppa_abs_to_phys_pa2_w0(addr);
182f386a16eSRichard Henderson }
183f386a16eSRichard Henderson 
184a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
185a72bd606SHelge Deller static uint64_t firmware_entry;
186813dff13SHelge Deller 
18732ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
18832ff8bf2SHelge Deller                             Error **errp)
18932ff8bf2SHelge Deller {
19032ff8bf2SHelge Deller     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
19132ff8bf2SHelge Deller }
19232ff8bf2SHelge Deller 
193f386a16eSRichard Henderson static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
194f386a16eSRichard Henderson                                  hwaddr addr)
19528b71a2eSHelge Deller {
19628b71a2eSHelge Deller     FWCfgState *fw_cfg;
19728b71a2eSHelge Deller     uint64_t val;
198069d2966SHelge Deller     const char qemu_version[] = QEMU_VERSION;
199bcd4dd4cSHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(ms);
2009cf2112bSRichard Henderson     int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
201bcd4dd4cSHelge Deller     int len;
20228b71a2eSHelge Deller 
203f386a16eSRichard Henderson     fw_cfg = fw_cfg_init_mem(addr, addr + 4);
20428b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
20528b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
206bfdf22bcSPaolo Bonzini     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
20728b71a2eSHelge Deller 
20828b71a2eSHelge Deller     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
20928b71a2eSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
21028b71a2eSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
21128b71a2eSHelge Deller 
2129cf2112bSRichard Henderson     val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
213df5c6a50SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
214df5c6a50SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
215df5c6a50SHelge Deller 
2169cf2112bSRichard Henderson     val = cpu_to_le64(btlb_entries);
217bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
218bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
219bcd4dd4cSHelge Deller 
220bcd4dd4cSHelge Deller     len = strlen(mc->name) + 1;
221bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
222bcd4dd4cSHelge Deller                     g_memdup(mc->name, len), len);
223bcd4dd4cSHelge Deller 
224b28c4a64SHelge Deller     val = cpu_to_le64(HPA_POWER_BUTTON);
225bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
226bcd4dd4cSHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
227bcd4dd4cSHelge Deller 
228e2c41ee5SHelge Deller     val = cpu_to_le64(CPU_HPA + 16);
229e2c41ee5SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
230e2c41ee5SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
231e2c41ee5SHelge Deller 
232bcd4dd4cSHelge Deller     val = cpu_to_le64(CPU_HPA + 24);
233bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
234b28c4a64SHelge Deller                     g_memdup(&val, sizeof(val)), sizeof(val));
235b28c4a64SHelge Deller 
23697ec4d21SPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
23732ff8bf2SHelge Deller     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
23832ff8bf2SHelge Deller 
239069d2966SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
240069d2966SHelge Deller                     g_memdup(qemu_version, sizeof(qemu_version)),
241069d2966SHelge Deller                     sizeof(qemu_version));
242069d2966SHelge Deller 
243bcd4dd4cSHelge Deller     fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
244bcd4dd4cSHelge Deller 
24528b71a2eSHelge Deller     return fw_cfg;
24628b71a2eSHelge Deller }
24728b71a2eSHelge Deller 
248e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
249e881e3c8SMark Cave-Ayland {
250e881e3c8SMark Cave-Ayland     DeviceState *dev;
251e881e3c8SMark Cave-Ayland 
252e881e3c8SMark Cave-Ayland     dev = qdev_new(TYPE_LASI_CHIP);
253e881e3c8SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
254e881e3c8SMark Cave-Ayland 
255e881e3c8SMark Cave-Ayland     return LASI_CHIP(dev);
256e881e3c8SMark Cave-Ayland }
257e881e3c8SMark Cave-Ayland 
2580d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
2590d068996SMark Cave-Ayland {
2600d068996SMark Cave-Ayland     DeviceState *dev;
2610d068996SMark Cave-Ayland 
2620d068996SMark Cave-Ayland     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
2630d068996SMark Cave-Ayland     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
2640d068996SMark Cave-Ayland                              &error_fatal);
2650d068996SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2660d068996SMark Cave-Ayland 
2670d068996SMark Cave-Ayland     return DINO_PCI_HOST_BRIDGE(dev);
2680d068996SMark Cave-Ayland }
2690d068996SMark Cave-Ayland 
2707df6f751SHelge Deller /*
2717df6f751SHelge Deller  * Step 1: Create CPUs and Memory
2727df6f751SHelge Deller  */
273f386a16eSRichard Henderson static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
274813dff13SHelge Deller {
275a72bd606SHelge Deller     MemoryRegion *addr_space = get_system_memory();
27633decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
277f386a16eSRichard Henderson     TranslateFn *translate;
278f386a16eSRichard Henderson     MemoryRegion *cpu_region;
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;
291f386a16eSRichard Henderson     } else {
292f386a16eSRichard Henderson         translate = translate_pa10;
293f386a16eSRichard Henderson     }
294f386a16eSRichard Henderson 
295f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
296f386a16eSRichard Henderson         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
297a72bd606SHelge Deller 
298a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
299a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
300266a880eSPaolo Bonzini                               cpu[i], name, 4);
301f386a16eSRichard Henderson         memory_region_add_subregion(addr_space,
302f386a16eSRichard Henderson                                     translate(NULL, CPU_HPA + i * 0x1000),
303a72bd606SHelge Deller                                     cpu_region);
304813dff13SHelge Deller     }
305813dff13SHelge Deller 
306e2c41ee5SHelge Deller     /* RTC and DebugOutputPort on CPU #0 */
307e2c41ee5SHelge Deller     cpu_region = g_new(MemoryRegion, 1);
308e2c41ee5SHelge Deller     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
309e2c41ee5SHelge Deller                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
310f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
311f386a16eSRichard Henderson                                 cpu_region);
312e2c41ee5SHelge Deller 
313a72bd606SHelge Deller     /* Main memory region. */
314b7746b11SPhilippe Mathieu-Daudé     if (machine->ram_size > 3 * GiB) {
315b7746b11SPhilippe Mathieu-Daudé         error_report("RAM size is currently restricted to 3GB");
316b7746b11SPhilippe Mathieu-Daudé         exit(EXIT_FAILURE);
317b7746b11SPhilippe Mathieu-Daudé     }
3187c59c1e0SIgor Mammedov     memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
319f386a16eSRichard Henderson 
320f386a16eSRichard Henderson     return translate;
3217df6f751SHelge Deller }
3227c59c1e0SIgor Mammedov 
3237df6f751SHelge Deller /*
3247df6f751SHelge Deller  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
3257df6f751SHelge Deller  */
326f386a16eSRichard Henderson static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
327f386a16eSRichard Henderson                                         TranslateFn *translate)
3287df6f751SHelge Deller {
3297df6f751SHelge Deller     const char *kernel_filename = machine->kernel_filename;
3307df6f751SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
3317df6f751SHelge Deller     const char *initrd_filename = machine->initrd_filename;
3327df6f751SHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(machine);
3337df6f751SHelge Deller     DeviceState *dev;
3342ed4faa0SHelge Deller     PCIDevice *pci_dev;
3357df6f751SHelge Deller     char *firmware_filename;
3367df6f751SHelge Deller     uint64_t firmware_low, firmware_high;
3377df6f751SHelge Deller     long size;
3387df6f751SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
3397df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
3407df6f751SHelge Deller     MemoryRegion *rom_region;
3417df6f751SHelge Deller     long i;
3427df6f751SHelge Deller     unsigned int smp_cpus = machine->smp.cpus;
3437df6f751SHelge Deller     SysBusDevice *s;
34428b71a2eSHelge Deller 
345a72bd606SHelge Deller     /* SCSI disk setup. */
346877eb21dSMark Cave-Ayland     dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
347877eb21dSMark Cave-Ayland     lsi53c8xx_handle_legacy_cmdline(dev);
348a72bd606SHelge Deller 
3494765384cSSven Schnelle     /* Graphics setup. */
3504765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
351f9bcb2d6SGautam Agrawal         vga_interface_created = true;
3523e80f690SMarkus Armbruster         dev = qdev_new("artist");
3534765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
3543c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
355f386a16eSRichard Henderson         sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
356f386a16eSRichard Henderson         sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
3574765384cSSven Schnelle     }
3584765384cSSven Schnelle 
3590e6de551SHelge Deller     /* Network setup. */
360c3c3fe47SMark Cave-Ayland     if (enable_lasi_lan()) {
361f386a16eSRichard Henderson         lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
362c3c3fe47SMark Cave-Ayland                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA));
363c3c3fe47SMark Cave-Ayland     }
364c3c3fe47SMark Cave-Ayland 
365a72bd606SHelge Deller     for (i = 0; i < nb_nics; i++) {
366376b8519SHelge Deller         if (!enable_lasi_lan()) {
3679f8981a9SThomas Huth             pci_nic_init_nofail(&nd_table[i], pci_bus, mc->default_nic, NULL);
368a72bd606SHelge Deller         }
369376b8519SHelge Deller     }
370a72bd606SHelge Deller 
3712ed4faa0SHelge Deller     /* BMC board: HP Powerbar SP2 Diva (with console only) */
3722ed4faa0SHelge Deller     pci_dev = pci_new(-1, "pci-serial");
3732ed4faa0SHelge Deller     if (!lasi_dev) {
3742ed4faa0SHelge Deller         /* bind default keyboard/serial to Diva card */
3752ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0));
3762ed4faa0SHelge Deller     }
3772ed4faa0SHelge Deller     qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0);
3782ed4faa0SHelge Deller     pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3792ed4faa0SHelge Deller     pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP);
3802ed4faa0SHelge Deller     pci_config_set_device_id(pci_dev->config, 0x1048);
3812ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP);
3822ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
3832ed4faa0SHelge Deller 
3842ed4faa0SHelge Deller     /* create a second serial PCI card when running Astro */
3852ed4faa0SHelge Deller     if (!lasi_dev) {
3862ed4faa0SHelge Deller         pci_dev = pci_new(-1, "pci-serial-4x");
3872ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
3882ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
3892ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3));
3902ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4));
3912ed4faa0SHelge Deller         pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3922ed4faa0SHelge Deller     }
3932ed4faa0SHelge Deller 
3942ed4faa0SHelge Deller     /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
3952ed4faa0SHelge Deller     if (!lasi_dev && machine->enable_graphics) {
3962ed4faa0SHelge Deller         pci_create_simple(pci_bus, -1, "pci-ohci");
3972ed4faa0SHelge Deller         usb_create_simple(usb_bus_find(-1), "usb-kbd");
3982ed4faa0SHelge Deller         usb_create_simple(usb_bus_find(-1), "usb-mouse");
3992ed4faa0SHelge Deller     }
4002ed4faa0SHelge Deller 
401b28c4a64SHelge Deller     /* register power switch emulation */
402b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
403b28c4a64SHelge Deller 
4047df6f751SHelge Deller     /* fw_cfg configuration interface */
405f386a16eSRichard Henderson     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
4067df6f751SHelge Deller 
407a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
408a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
409a72bd606SHelge Deller        well load it directly from an ELF image.  */
410a72bd606SHelge Deller     firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
411b57e3e97SPaolo Bonzini                                        machine->firmware ?: "hppa-firmware.img");
412a72bd606SHelge Deller     if (firmware_filename == NULL) {
413a72bd606SHelge Deller         error_report("no firmware provided");
414a72bd606SHelge Deller         exit(1);
415a72bd606SHelge Deller     }
416a72bd606SHelge Deller 
417f386a16eSRichard Henderson     size = load_elf(firmware_filename, NULL, translate, NULL,
4186cdda0ffSAleksandar Markovic                     &firmware_entry, &firmware_low, &firmware_high, NULL,
419a72bd606SHelge Deller                     true, EM_PARISC, 0, 0);
420a72bd606SHelge Deller 
421a72bd606SHelge Deller     if (size < 0) {
422a72bd606SHelge Deller         error_report("could not load firmware '%s'", firmware_filename);
423a72bd606SHelge Deller         exit(1);
424a72bd606SHelge Deller     }
425691cbbadSRichard Henderson     qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
426691cbbadSRichard Henderson                   "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
427a72bd606SHelge Deller                   firmware_low, firmware_high, firmware_entry);
428f386a16eSRichard Henderson     if (firmware_low < translate(NULL, FIRMWARE_START) ||
429f386a16eSRichard Henderson         firmware_high >= translate(NULL, FIRMWARE_END)) {
430a72bd606SHelge Deller         error_report("Firmware overlaps with memory or IO space");
431a72bd606SHelge Deller         exit(1);
432a72bd606SHelge Deller     }
433a72bd606SHelge Deller     g_free(firmware_filename);
434a72bd606SHelge Deller 
435a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
4366a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
4376a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
438f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
439f386a16eSRichard Henderson                                 translate(NULL, FIRMWARE_START), rom_region);
440a72bd606SHelge Deller 
441a72bd606SHelge Deller     /* Load kernel */
442a72bd606SHelge Deller     if (kernel_filename) {
443f386a16eSRichard Henderson         size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
4446cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
445a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
446a72bd606SHelge Deller 
447f386a16eSRichard Henderson         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
448a72bd606SHelge Deller 
449a72bd606SHelge Deller         if (size < 0) {
450a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
451a72bd606SHelge Deller             exit(1);
452a72bd606SHelge Deller         }
453691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
454691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
455c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
456c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
457a72bd606SHelge Deller 
458a72bd606SHelge Deller         if (kernel_cmdline) {
459a72bd606SHelge Deller             cpu[0]->env.gr[24] = 0x4000;
460a72bd606SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
461a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
462a72bd606SHelge Deller         }
463a72bd606SHelge Deller 
464a72bd606SHelge Deller         if (initrd_filename) {
465a72bd606SHelge Deller             ram_addr_t initrd_base;
466f3839fdaSLi Zhijian             int64_t initrd_size;
467a72bd606SHelge Deller 
468a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
469a72bd606SHelge Deller             if (initrd_size < 0) {
470a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
471a72bd606SHelge Deller                              initrd_filename);
472a72bd606SHelge Deller                 exit(1);
473a72bd606SHelge Deller             }
474a72bd606SHelge Deller 
475a72bd606SHelge Deller             /* Load the initrd image high in memory.
476a72bd606SHelge Deller                Mirror the algorithm used by palo:
477a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
478a72bd606SHelge Deller                put the initrd no higher than 1G.
479a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
480bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
481c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
482a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
483a72bd606SHelge Deller 
484a72bd606SHelge Deller             if (initrd_base < kernel_high) {
485a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
486a72bd606SHelge Deller                 exit(1);
487a72bd606SHelge Deller             }
488a72bd606SHelge Deller 
489a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
490a72bd606SHelge Deller             cpu[0]->env.gr[23] = initrd_base;
491a72bd606SHelge Deller             cpu[0]->env.gr[22] = initrd_base + initrd_size;
492a72bd606SHelge Deller         }
493a72bd606SHelge Deller     }
494a72bd606SHelge Deller 
495a72bd606SHelge Deller     if (!kernel_entry) {
496a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
497a72bd606SHelge Deller          * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
498a72bd606SHelge Deller          * or hard disc * (gr[24]='c').
499a72bd606SHelge Deller          */
50097ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
50197ec4d21SPaolo Bonzini         cpu[0]->env.gr[24] = machine->boot_config.order[0];
502a72bd606SHelge Deller     }
503a72bd606SHelge Deller 
504a72bd606SHelge Deller     /* We jump to the firmware entry routine and pass the
505a72bd606SHelge Deller      * various parameters in registers. After firmware initialization,
506a72bd606SHelge Deller      * firmware will start the Linux kernel with ramdisk and cmdline.
507a72bd606SHelge Deller      */
508bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = machine->ram_size;
509a72bd606SHelge Deller     cpu[0]->env.gr[25] = kernel_entry;
510a72bd606SHelge Deller 
511a72bd606SHelge Deller     /* tell firmware how many SMP CPUs to present in inventory table */
512a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
51324576007SHelge Deller 
51424576007SHelge Deller     /* tell firmware fw_cfg port */
51524576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
516a72bd606SHelge Deller }
517a72bd606SHelge Deller 
5187df6f751SHelge Deller /*
5197df6f751SHelge Deller  * Create HP B160L workstation
5207df6f751SHelge Deller  */
5217df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
5227df6f751SHelge Deller {
5237df6f751SHelge Deller     DeviceState *dev, *dino_dev;
5247df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
525f386a16eSRichard Henderson     TranslateFn *translate;
5267df6f751SHelge Deller     ISABus *isa_bus;
5277df6f751SHelge Deller     PCIBus *pci_bus;
5287df6f751SHelge Deller 
5297df6f751SHelge Deller     /* Create CPUs and RAM.  */
530f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
5317df6f751SHelge Deller 
5323d1611bfSHelge Deller     if (hppa_is_pa20(&cpu[0]->env)) {
5333d1611bfSHelge Deller         error_report("The HP B160L workstation requires a 32-bit "
5343d1611bfSHelge Deller                      "CPU. Use '-machine C3700' instead.");
5353d1611bfSHelge Deller         exit(1);
5363d1611bfSHelge Deller     }
5373d1611bfSHelge Deller 
5387df6f751SHelge Deller     /* Init Lasi chip */
5397df6f751SHelge Deller     lasi_dev = DEVICE(lasi_init());
540f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
5417df6f751SHelge Deller                                 sysbus_mmio_get_region(
5427df6f751SHelge Deller                                     SYS_BUS_DEVICE(lasi_dev), 0));
5437df6f751SHelge Deller 
5447df6f751SHelge Deller     /* Init Dino (PCI host bus chip).  */
5457df6f751SHelge Deller     dino_dev = DEVICE(dino_init(addr_space));
546f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
5477df6f751SHelge Deller                                 sysbus_mmio_get_region(
5487df6f751SHelge Deller                                     SYS_BUS_DEVICE(dino_dev), 0));
5497df6f751SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
5507df6f751SHelge Deller     assert(pci_bus);
5517df6f751SHelge Deller 
5527df6f751SHelge Deller     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
553f386a16eSRichard Henderson     isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
5547df6f751SHelge Deller     assert(isa_bus);
5557df6f751SHelge Deller 
5567df6f751SHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
557f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
5587df6f751SHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
5597df6f751SHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
5607df6f751SHelge Deller 
561f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
5627df6f751SHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
5637df6f751SHelge Deller         serial_hd(1), DEVICE_BIG_ENDIAN);
5647df6f751SHelge Deller 
5657df6f751SHelge Deller     /* Parallel port */
566f386a16eSRichard Henderson     parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
5677df6f751SHelge Deller                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
5687df6f751SHelge Deller                      parallel_hds[0]);
5697df6f751SHelge Deller 
5707df6f751SHelge Deller     /* PS/2 Keyboard/Mouse */
5717df6f751SHelge Deller     dev = qdev_new(TYPE_LASIPS2);
5727df6f751SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5737df6f751SHelge Deller     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
5747df6f751SHelge Deller                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
575f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
576f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA),
5777df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5787df6f751SHelge Deller                                                        0));
579f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
580f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA + 0x100),
5817df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5827df6f751SHelge Deller                                                        1));
5837df6f751SHelge Deller 
5847df6f751SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
585f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
5867df6f751SHelge Deller }
5877df6f751SHelge Deller 
5882ed4faa0SHelge Deller static AstroState *astro_init(void)
5892ed4faa0SHelge Deller {
5902ed4faa0SHelge Deller     DeviceState *dev;
5912ed4faa0SHelge Deller 
5922ed4faa0SHelge Deller     dev = qdev_new(TYPE_ASTRO_CHIP);
5932ed4faa0SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5942ed4faa0SHelge Deller 
5952ed4faa0SHelge Deller     return ASTRO_CHIP(dev);
5962ed4faa0SHelge Deller }
5972ed4faa0SHelge Deller 
5982ed4faa0SHelge Deller /*
5992ed4faa0SHelge Deller  * Create HP C3700 workstation
6002ed4faa0SHelge Deller  */
6012ed4faa0SHelge Deller static void machine_HP_C3700_init(MachineState *machine)
6022ed4faa0SHelge Deller {
6032ed4faa0SHelge Deller     PCIBus *pci_bus;
6042ed4faa0SHelge Deller     AstroState *astro;
6052ed4faa0SHelge Deller     DeviceState *astro_dev;
6062ed4faa0SHelge Deller     MemoryRegion *addr_space = get_system_memory();
607f386a16eSRichard Henderson     TranslateFn *translate;
6082ed4faa0SHelge Deller 
6092ed4faa0SHelge Deller     /* Create CPUs and RAM.  */
610f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
6112ed4faa0SHelge Deller 
6123d1611bfSHelge Deller     if (!hppa_is_pa20(&cpu[0]->env)) {
6133d1611bfSHelge Deller         error_report("The HP C3000 workstation requires a 64-bit CPU. "
6143d1611bfSHelge Deller                      "Use '-machine B160L' instead.");
6153d1611bfSHelge Deller         exit(1);
6163d1611bfSHelge Deller     }
6173d1611bfSHelge Deller 
6182ed4faa0SHelge Deller     /* Init Astro and the Elroys (PCI host bus chips).  */
6192ed4faa0SHelge Deller     astro = astro_init();
6202ed4faa0SHelge Deller     astro_dev = DEVICE(astro);
621f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
6222ed4faa0SHelge Deller                                 sysbus_mmio_get_region(
6232ed4faa0SHelge Deller                                     SYS_BUS_DEVICE(astro_dev), 0));
6242ed4faa0SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
6252ed4faa0SHelge Deller     assert(pci_bus);
6262ed4faa0SHelge Deller 
6272ed4faa0SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
628f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
6292ed4faa0SHelge Deller }
6302ed4faa0SHelge Deller 
6317966d70fSJason A. Donenfeld static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
632a72bd606SHelge Deller {
63333decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
634a72bd606SHelge Deller     int i;
635a72bd606SHelge Deller 
6367966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
637a72bd606SHelge Deller 
638a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
639a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
64050ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
641a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
64250ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
64350ba97e9SHelge Deller 
64450ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
64550ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
646a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
64750ba97e9SHelge Deller 
64850ba97e9SHelge Deller         cs->exception_index = -1;
64950ba97e9SHelge Deller         cs->halted = 0;
650a72bd606SHelge Deller     }
651a72bd606SHelge Deller 
652a72bd606SHelge Deller     /* already initialized by machine_hppa_init()? */
653bfdf22bcSPaolo Bonzini     if (cpu[0]->env.gr[26] == ms->ram_size) {
654a72bd606SHelge Deller         return;
655a72bd606SHelge Deller     }
656a72bd606SHelge Deller 
657bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
658a72bd606SHelge Deller     cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
659a72bd606SHelge Deller     cpu[0]->env.gr[24] = 'c';
660a72bd606SHelge Deller     /* gr22/gr23 unused, no initrd while reboot. */
661a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
66224576007SHelge Deller     /* tell firmware fw_cfg port */
66324576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
664a72bd606SHelge Deller }
665a72bd606SHelge Deller 
6664a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
6674a4554c6SHelge Deller {
6684a4554c6SHelge Deller     CPUState *cs;
6694a4554c6SHelge Deller 
6704a4554c6SHelge Deller     CPU_FOREACH(cs) {
6714a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
6724a4554c6SHelge Deller     }
6734a4554c6SHelge Deller }
674a72bd606SHelge Deller 
675*790a4428SGavin Shan static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
676*790a4428SGavin Shan {
677*790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
6783d1611bfSHelge Deller         TYPE_HPPA_CPU,
6793d1611bfSHelge Deller         NULL
6803d1611bfSHelge Deller     };
68142cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
68242cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
68342cc2bf6SMark Cave-Ayland 
6847df6f751SHelge Deller     mc->desc = "HP B160L workstation";
685a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
686*790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
6877df6f751SHelge Deller     mc->init = machine_HP_B160L_init;
688a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
689813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
690a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
691a72bd606SHelge Deller     mc->default_cpus = 1;
692ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
693d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
694813dff13SHelge Deller     mc->default_boot_order = "cd";
6957c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
6969f8981a9SThomas Huth     mc->default_nic = "tulip";
697813dff13SHelge Deller 
6984a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
6994a4554c6SHelge Deller }
7004a4554c6SHelge Deller 
7017df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
7027df6f751SHelge Deller     .name = MACHINE_TYPE_NAME("B160L"),
703c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
7047df6f751SHelge Deller     .class_init = HP_B160L_machine_init_class_init,
7054a4554c6SHelge Deller     .interfaces = (InterfaceInfo[]) {
7064a4554c6SHelge Deller         { TYPE_NMI },
7074a4554c6SHelge Deller         { }
7084a4554c6SHelge Deller     },
7094a4554c6SHelge Deller };
7104a4554c6SHelge Deller 
711*790a4428SGavin Shan static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
712*790a4428SGavin Shan {
713*790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
7143d1611bfSHelge Deller         TYPE_HPPA64_CPU,
7153d1611bfSHelge Deller         NULL
7163d1611bfSHelge Deller     };
7172ed4faa0SHelge Deller     MachineClass *mc = MACHINE_CLASS(oc);
7182ed4faa0SHelge Deller     NMIClass *nc = NMI_CLASS(oc);
7192ed4faa0SHelge Deller 
7202ed4faa0SHelge Deller     mc->desc = "HP C3700 workstation";
721fd9b04bfSHelge Deller     mc->default_cpu_type = TYPE_HPPA64_CPU;
722*790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
7232ed4faa0SHelge Deller     mc->init = machine_HP_C3700_init;
7242ed4faa0SHelge Deller     mc->reset = hppa_machine_reset;
7252ed4faa0SHelge Deller     mc->block_default_type = IF_SCSI;
7262ed4faa0SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
7272ed4faa0SHelge Deller     mc->default_cpus = 1;
7282ed4faa0SHelge Deller     mc->is_default = false;
7292ed4faa0SHelge Deller     mc->default_ram_size = 1024 * MiB;
7302ed4faa0SHelge Deller     mc->default_boot_order = "cd";
7312ed4faa0SHelge Deller     mc->default_ram_id = "ram";
7322ed4faa0SHelge Deller     mc->default_nic = "tulip";
7332ed4faa0SHelge Deller 
7342ed4faa0SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7352ed4faa0SHelge Deller }
7362ed4faa0SHelge Deller 
7372ed4faa0SHelge Deller static const TypeInfo HP_C3700_machine_init_typeinfo = {
7382ed4faa0SHelge Deller     .name = MACHINE_TYPE_NAME("C3700"),
7392ed4faa0SHelge Deller     .parent = TYPE_MACHINE,
7402ed4faa0SHelge Deller     .class_init = HP_C3700_machine_init_class_init,
7412ed4faa0SHelge Deller     .interfaces = (InterfaceInfo[]) {
7422ed4faa0SHelge Deller         { TYPE_NMI },
7432ed4faa0SHelge Deller         { }
7442ed4faa0SHelge Deller     },
7452ed4faa0SHelge Deller };
7462ed4faa0SHelge Deller 
747297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
7484a4554c6SHelge Deller {
7497df6f751SHelge Deller     type_register_static(&HP_B160L_machine_init_typeinfo);
7502ed4faa0SHelge Deller     type_register_static(&HP_C3700_machine_init_typeinfo);
7514a4554c6SHelge Deller }
7524a4554c6SHelge Deller 
753297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
754