xref: /qemu/hw/hppa/machine.c (revision c656f293dfe31661e4252d78cfa6cab6372ad5ca)
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"
1432cad1ffSPhilippe Mathieu-Daudé #include "system/reset.h"
1532cad1ffSPhilippe Mathieu-Daudé #include "system/system.h"
1632cad1ffSPhilippe Mathieu-Daudé #include "system/qtest.h"
1732cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
18bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
19813dff13SHelge Deller #include "hw/timer/i8254.h"
207e6b5497SBernhard Beschow #include "hw/char/serial-mm.h"
219701e569SMark Cave-Ayland #include "hw/char/parallel.h"
22134ba73fSMark Cave-Ayland #include "hw/intc/i8259.h"
23d26c575cSMark Cave-Ayland #include "hw/input/lasips2.h"
24376b8519SHelge Deller #include "hw/net/lasi_82596.h"
254a4554c6SHelge Deller #include "hw/nmi.h"
262ed4faa0SHelge Deller #include "hw/usb.h"
27134ba73fSMark Cave-Ayland #include "hw/pci/pci.h"
287df6f751SHelge Deller #include "hw/pci/pci_device.h"
292ed4faa0SHelge Deller #include "hw/pci-host/astro.h"
300db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
3145f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
32148da670SMark Cave-Ayland #include "hppa_hardware.h"
33c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
34813dff13SHelge Deller #include "qapi/error.h"
35852c27e2SPaolo Bonzini #include "net/net.h"
36691cbbadSRichard Henderson #include "qemu/log.h"
37813dff13SHelge Deller 
38f88131d9SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
3928b71a2eSHelge Deller 
40ed35afcbSHelge Deller #define HPA_POWER_BUTTON        (FIRMWARE_END - 0x10)
41ed35afcbSHelge Deller static hwaddr soft_power_reg;
42b28c4a64SHelge Deller 
43932befaaSMark Cave-Ayland #define enable_lasi_lan()       0
44932befaaSMark Cave-Ayland 
457df6f751SHelge Deller static DeviceState *lasi_dev;
46932befaaSMark Cave-Ayland 
47b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
48b28c4a64SHelge Deller {
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",
2100572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2140572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2180572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2220572f011SPhilippe Mathieu-Daudé                     g_memdup2(mc->name, len), len);
223bcd4dd4cSHelge Deller 
224ed35afcbSHelge Deller     val = cpu_to_le64(soft_power_reg);
225bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
2260572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2300572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2340572f011SPhilippe Mathieu-Daudé                     g_memdup2(&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",
2400572f011SPhilippe Mathieu-Daudé                     g_memdup2(qemu_version, sizeof(qemu_version)),
241069d2966SHelge Deller                     sizeof(qemu_version));
242069d2966SHelge Deller 
243e5fd678aSPhilippe Mathieu-Daudé     pci_bus_add_fw_cfg_extra_pci_roots(fw_cfg, pci_bus, &error_abort);
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;
27992039f61SHelge Deller     uint64_t ram_max;
280a72bd606SHelge Deller 
281a72bd606SHelge Deller     /* Create CPUs.  */
282f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
283a72bd606SHelge Deller         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
284f386a16eSRichard Henderson     }
285f386a16eSRichard Henderson 
286d0ad4118SHelge Deller     /* Initialize memory */
287f386a16eSRichard Henderson     if (hppa_is_pa20(&cpu[0]->env)) {
288f386a16eSRichard Henderson         translate = translate_pa20;
289d0ad4118SHelge Deller         ram_max = 256 * GiB;       /* like HP rp8440 */
290f386a16eSRichard Henderson     } else {
291f386a16eSRichard Henderson         translate = translate_pa10;
292d0ad4118SHelge Deller         ram_max = FIRMWARE_START;  /* 3.75 GB (32-bit CPU) */
293f386a16eSRichard Henderson     }
294f386a16eSRichard Henderson 
295ed35afcbSHelge Deller     soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
296ed35afcbSHelge Deller 
297f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
298f386a16eSRichard Henderson         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
299a72bd606SHelge Deller 
300a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
301a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
302266a880eSPaolo Bonzini                               cpu[i], name, 4);
303f386a16eSRichard Henderson         memory_region_add_subregion(addr_space,
304f386a16eSRichard Henderson                                     translate(NULL, CPU_HPA + i * 0x1000),
305a72bd606SHelge Deller                                     cpu_region);
306813dff13SHelge Deller     }
307813dff13SHelge Deller 
308e2c41ee5SHelge Deller     /* RTC and DebugOutputPort on CPU #0 */
309e2c41ee5SHelge Deller     cpu_region = g_new(MemoryRegion, 1);
310e2c41ee5SHelge Deller     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
311e2c41ee5SHelge Deller                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
312f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
313f386a16eSRichard Henderson                                 cpu_region);
314e2c41ee5SHelge Deller 
315a72bd606SHelge Deller     /* Main memory region. */
31692039f61SHelge Deller     if (machine->ram_size > ram_max) {
31792039f61SHelge Deller         info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
31892039f61SHelge Deller         machine->ram_size = ram_max;
319b7746b11SPhilippe Mathieu-Daudé     }
320d0ad4118SHelge Deller     if (machine->ram_size <= FIRMWARE_START) {
321d0ad4118SHelge Deller         /* contiguous memory up to 3.75 GB RAM */
3227c59c1e0SIgor Mammedov         memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
323d0ad4118SHelge Deller     } else {
324d0ad4118SHelge Deller         /* non-contiguous: Memory above 3.75 GB is mapped at RAM_MAP_HIGH */
325d0ad4118SHelge Deller         MemoryRegion *mem_region;
326d0ad4118SHelge Deller         mem_region = g_new(MemoryRegion, 2);
327d0ad4118SHelge Deller         memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
328d0ad4118SHelge Deller                               "LowMem", machine->ram, 0, FIRMWARE_START);
329d0ad4118SHelge Deller         memory_region_init_alias(&mem_region[1], &addr_space->parent_obj,
330d0ad4118SHelge Deller                               "HighMem", machine->ram, FIRMWARE_START,
331d0ad4118SHelge Deller                               machine->ram_size - FIRMWARE_START);
332d0ad4118SHelge Deller         memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1);
333d0ad4118SHelge Deller         memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH,
334d0ad4118SHelge Deller                                             &mem_region[1], -1);
335d0ad4118SHelge Deller     }
336f386a16eSRichard Henderson 
337f386a16eSRichard Henderson     return translate;
3387df6f751SHelge Deller }
3397c59c1e0SIgor Mammedov 
3407df6f751SHelge Deller /*
3417df6f751SHelge Deller  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
3427df6f751SHelge Deller  */
343f386a16eSRichard Henderson static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
344f386a16eSRichard Henderson                                         TranslateFn *translate)
3457df6f751SHelge Deller {
3467df6f751SHelge Deller     const char *kernel_filename = machine->kernel_filename;
3477df6f751SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
3487df6f751SHelge Deller     const char *initrd_filename = machine->initrd_filename;
349a9314795SHelge Deller     const char *firmware = machine->firmware;
3507df6f751SHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(machine);
3517df6f751SHelge Deller     DeviceState *dev;
3522ed4faa0SHelge Deller     PCIDevice *pci_dev;
3537df6f751SHelge Deller     char *firmware_filename;
3547df6f751SHelge Deller     uint64_t firmware_low, firmware_high;
3557df6f751SHelge Deller     long size;
3567df6f751SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
3577df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
3587df6f751SHelge Deller     MemoryRegion *rom_region;
3597df6f751SHelge Deller     SysBusDevice *s;
36028b71a2eSHelge Deller 
361a72bd606SHelge Deller     /* SCSI disk setup. */
362d8a32200SHelge Deller     if (drive_get_max_bus(IF_SCSI) >= 0) {
363877eb21dSMark Cave-Ayland         dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
364877eb21dSMark Cave-Ayland         lsi53c8xx_handle_legacy_cmdline(dev);
365d8a32200SHelge Deller     }
366a72bd606SHelge Deller 
3674765384cSSven Schnelle     /* Graphics setup. */
3684765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
369f9bcb2d6SGautam Agrawal         vga_interface_created = true;
3703e80f690SMarkus Armbruster         dev = qdev_new("artist");
3714765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
3723c6ef471SMarkus Armbruster         sysbus_realize_and_unref(s, &error_fatal);
373f386a16eSRichard Henderson         sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
374f386a16eSRichard Henderson         sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
3754765384cSSven Schnelle     }
3764765384cSSven Schnelle 
3770e6de551SHelge Deller     /* Network setup. */
3782a98878fSDavid Woodhouse     if (lasi_dev) {
379f386a16eSRichard Henderson         lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
3802a98878fSDavid Woodhouse                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
3812a98878fSDavid Woodhouse                         enable_lasi_lan());
382c3c3fe47SMark Cave-Ayland     }
383c3c3fe47SMark Cave-Ayland 
3842dfe2f86SDavid Woodhouse     pci_init_nic_devices(pci_bus, mc->default_nic);
385a72bd606SHelge Deller 
3862ed4faa0SHelge Deller     /* BMC board: HP Powerbar SP2 Diva (with console only) */
3872ed4faa0SHelge Deller     pci_dev = pci_new(-1, "pci-serial");
3882ed4faa0SHelge Deller     if (!lasi_dev) {
3892ed4faa0SHelge Deller         /* bind default keyboard/serial to Diva card */
3902ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0));
3912ed4faa0SHelge Deller     }
3922ed4faa0SHelge Deller     qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0);
3932ed4faa0SHelge Deller     pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
3942ed4faa0SHelge Deller     pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP);
3952ed4faa0SHelge Deller     pci_config_set_device_id(pci_dev->config, 0x1048);
3962ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP);
3972ed4faa0SHelge Deller     pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
3982ed4faa0SHelge Deller 
3992ed4faa0SHelge Deller     /* create a second serial PCI card when running Astro */
400d8a32200SHelge Deller     if (serial_hd(1) && !lasi_dev) {
4012ed4faa0SHelge Deller         pci_dev = pci_new(-1, "pci-serial-4x");
4022ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
4032ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
4042ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3));
4052ed4faa0SHelge Deller         qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4));
4062ed4faa0SHelge Deller         pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
4072ed4faa0SHelge Deller     }
4082ed4faa0SHelge Deller 
4092ed4faa0SHelge Deller     /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
41082523f4aSPaolo Bonzini     if (!lasi_dev && machine->enable_graphics && defaults_enabled()) {
41182523f4aSPaolo Bonzini         USBBus *usb_bus;
41282523f4aSPaolo Bonzini 
4132ed4faa0SHelge Deller         pci_create_simple(pci_bus, -1, "pci-ohci");
41482523f4aSPaolo Bonzini         usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
41582523f4aSPaolo Bonzini                                                           &error_abort));
41682523f4aSPaolo Bonzini         usb_create_simple(usb_bus, "usb-kbd");
41782523f4aSPaolo Bonzini         usb_create_simple(usb_bus, "usb-mouse");
4182ed4faa0SHelge Deller     }
4192ed4faa0SHelge Deller 
420b28c4a64SHelge Deller     /* register power switch emulation */
421b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
422b28c4a64SHelge Deller 
4237df6f751SHelge Deller     /* fw_cfg configuration interface */
424f386a16eSRichard Henderson     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
4257df6f751SHelge Deller 
426a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
427a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
428a9314795SHelge Deller        well load it directly from an ELF image. Load the 64-bit
429a9314795SHelge Deller        firmware on 64-bit machines by default if not specified
430a9314795SHelge Deller        on command line. */
431a9314795SHelge Deller     if (!qtest_enabled()) {
432a9314795SHelge Deller         if (!firmware) {
433a9314795SHelge Deller             firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
434a9314795SHelge Deller         }
435a9314795SHelge Deller         firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
436a72bd606SHelge Deller         if (firmware_filename == NULL) {
437a72bd606SHelge Deller             error_report("no firmware provided");
438a72bd606SHelge Deller             exit(1);
439a72bd606SHelge Deller         }
440a72bd606SHelge Deller 
441f386a16eSRichard Henderson         size = load_elf(firmware_filename, NULL, translate, NULL,
4426cdda0ffSAleksandar Markovic                         &firmware_entry, &firmware_low, &firmware_high, NULL,
443a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
444a72bd606SHelge Deller 
445a72bd606SHelge Deller         if (size < 0) {
446a72bd606SHelge Deller             error_report("could not load firmware '%s'", firmware_filename);
447a72bd606SHelge Deller             exit(1);
448a72bd606SHelge Deller         }
449691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
450691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
451a72bd606SHelge Deller                       firmware_low, firmware_high, firmware_entry);
452f386a16eSRichard Henderson         if (firmware_low < translate(NULL, FIRMWARE_START) ||
453f386a16eSRichard Henderson             firmware_high >= translate(NULL, FIRMWARE_END)) {
454a72bd606SHelge Deller             error_report("Firmware overlaps with memory or IO space");
455a72bd606SHelge Deller             exit(1);
456a72bd606SHelge Deller         }
457a72bd606SHelge Deller         g_free(firmware_filename);
458a9314795SHelge Deller     }
459a72bd606SHelge Deller 
460a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
4616a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
4626a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
463f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
464f386a16eSRichard Henderson                                 translate(NULL, FIRMWARE_START), rom_region);
465a72bd606SHelge Deller 
466a72bd606SHelge Deller     /* Load kernel */
467a72bd606SHelge Deller     if (kernel_filename) {
468f386a16eSRichard Henderson         size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
4696cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
470a72bd606SHelge Deller                         true, EM_PARISC, 0, 0);
471a72bd606SHelge Deller 
472f386a16eSRichard Henderson         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
473a72bd606SHelge Deller 
474a72bd606SHelge Deller         if (size < 0) {
475a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
476a72bd606SHelge Deller             exit(1);
477a72bd606SHelge Deller         }
478691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
479691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
480c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
481c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
482a72bd606SHelge Deller 
483a72bd606SHelge Deller         if (kernel_cmdline) {
484*c656f293SHelge Deller             cpu[0]->env.cmdline_or_bootorder = 0x4000;
485*c656f293SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.cmdline_or_bootorder,
486a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
487a72bd606SHelge Deller         }
488a72bd606SHelge Deller 
489a72bd606SHelge Deller         if (initrd_filename) {
490a72bd606SHelge Deller             ram_addr_t initrd_base;
491f3839fdaSLi Zhijian             int64_t initrd_size;
492a72bd606SHelge Deller 
493a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
494a72bd606SHelge Deller             if (initrd_size < 0) {
495a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
496a72bd606SHelge Deller                              initrd_filename);
497a72bd606SHelge Deller                 exit(1);
498a72bd606SHelge Deller             }
499a72bd606SHelge Deller 
500a72bd606SHelge Deller             /* Load the initrd image high in memory.
501a72bd606SHelge Deller                Mirror the algorithm used by palo:
502a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
503a72bd606SHelge Deller                put the initrd no higher than 1G.
504a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
505bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
506c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
507a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
508a72bd606SHelge Deller 
509a72bd606SHelge Deller             if (initrd_base < kernel_high) {
510a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
511a72bd606SHelge Deller                 exit(1);
512a72bd606SHelge Deller             }
513a72bd606SHelge Deller 
514a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
515*c656f293SHelge Deller             cpu[0]->env.initrd_base = initrd_base;
516*c656f293SHelge Deller             cpu[0]->env.initrd_end  = initrd_base + initrd_size;
517a72bd606SHelge Deller         }
518a72bd606SHelge Deller     }
519a72bd606SHelge Deller 
520a72bd606SHelge Deller     if (!kernel_entry) {
521a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
522*c656f293SHelge Deller          * mode (kernel_entry=1), and to boot from CD (cmdline_or_bootorder='d')
523*c656f293SHelge Deller          * or hard disc (cmdline_or_bootorder='c').
524a72bd606SHelge Deller          */
52597ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
526*c656f293SHelge Deller         cpu[0]->env.cmdline_or_bootorder = machine->boot_config.order[0];
527a72bd606SHelge Deller     }
528a72bd606SHelge Deller 
529*c656f293SHelge Deller     /* Keep initial kernel_entry for first boot */
530*c656f293SHelge Deller     cpu[0]->env.kernel_entry = kernel_entry;
531a72bd606SHelge Deller }
532a72bd606SHelge Deller 
5337df6f751SHelge Deller /*
5347df6f751SHelge Deller  * Create HP B160L workstation
5357df6f751SHelge Deller  */
5367df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
5377df6f751SHelge Deller {
5387df6f751SHelge Deller     DeviceState *dev, *dino_dev;
5397df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
540f386a16eSRichard Henderson     TranslateFn *translate;
5417df6f751SHelge Deller     ISABus *isa_bus;
5427df6f751SHelge Deller     PCIBus *pci_bus;
5437df6f751SHelge Deller 
5447df6f751SHelge Deller     /* Create CPUs and RAM.  */
545f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
5467df6f751SHelge Deller 
5473d1611bfSHelge Deller     if (hppa_is_pa20(&cpu[0]->env)) {
5483d1611bfSHelge Deller         error_report("The HP B160L workstation requires a 32-bit "
5493d1611bfSHelge Deller                      "CPU. Use '-machine C3700' instead.");
5503d1611bfSHelge Deller         exit(1);
5513d1611bfSHelge Deller     }
5523d1611bfSHelge Deller 
5537df6f751SHelge Deller     /* Init Lasi chip */
5547df6f751SHelge Deller     lasi_dev = DEVICE(lasi_init());
555f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
5567df6f751SHelge Deller                                 sysbus_mmio_get_region(
5577df6f751SHelge Deller                                     SYS_BUS_DEVICE(lasi_dev), 0));
5587df6f751SHelge Deller 
5597df6f751SHelge Deller     /* Init Dino (PCI host bus chip).  */
5607df6f751SHelge Deller     dino_dev = DEVICE(dino_init(addr_space));
561f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
5627df6f751SHelge Deller                                 sysbus_mmio_get_region(
5637df6f751SHelge Deller                                     SYS_BUS_DEVICE(dino_dev), 0));
5647df6f751SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
5657df6f751SHelge Deller     assert(pci_bus);
5667df6f751SHelge Deller 
5677df6f751SHelge Deller     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
568f386a16eSRichard Henderson     isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
5697df6f751SHelge Deller     assert(isa_bus);
5707df6f751SHelge Deller 
5717df6f751SHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
572f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
5737df6f751SHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
5747df6f751SHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
5757df6f751SHelge Deller 
576f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
5777df6f751SHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
5787df6f751SHelge Deller         serial_hd(1), DEVICE_BIG_ENDIAN);
5797df6f751SHelge Deller 
5807df6f751SHelge Deller     /* Parallel port */
581f386a16eSRichard Henderson     parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
5827df6f751SHelge Deller                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
5837df6f751SHelge Deller                      parallel_hds[0]);
5847df6f751SHelge Deller 
5857df6f751SHelge Deller     /* PS/2 Keyboard/Mouse */
5867df6f751SHelge Deller     dev = qdev_new(TYPE_LASIPS2);
5877df6f751SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5887df6f751SHelge Deller     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
5897df6f751SHelge Deller                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
590f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
591f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA),
5927df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5937df6f751SHelge Deller                                                        0));
594f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
595f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA + 0x100),
5967df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5977df6f751SHelge Deller                                                        1));
5987df6f751SHelge Deller 
5997df6f751SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
600f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
6017df6f751SHelge Deller }
6027df6f751SHelge Deller 
6032ed4faa0SHelge Deller static AstroState *astro_init(void)
6042ed4faa0SHelge Deller {
6052ed4faa0SHelge Deller     DeviceState *dev;
6062ed4faa0SHelge Deller 
6072ed4faa0SHelge Deller     dev = qdev_new(TYPE_ASTRO_CHIP);
6082ed4faa0SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
6092ed4faa0SHelge Deller 
6102ed4faa0SHelge Deller     return ASTRO_CHIP(dev);
6112ed4faa0SHelge Deller }
6122ed4faa0SHelge Deller 
6132ed4faa0SHelge Deller /*
6142ed4faa0SHelge Deller  * Create HP C3700 workstation
6152ed4faa0SHelge Deller  */
6162ed4faa0SHelge Deller static void machine_HP_C3700_init(MachineState *machine)
6172ed4faa0SHelge Deller {
6182ed4faa0SHelge Deller     PCIBus *pci_bus;
6192ed4faa0SHelge Deller     AstroState *astro;
6202ed4faa0SHelge Deller     DeviceState *astro_dev;
6212ed4faa0SHelge Deller     MemoryRegion *addr_space = get_system_memory();
622f386a16eSRichard Henderson     TranslateFn *translate;
6232ed4faa0SHelge Deller 
6242ed4faa0SHelge Deller     /* Create CPUs and RAM.  */
625f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
6262ed4faa0SHelge Deller 
6273d1611bfSHelge Deller     if (!hppa_is_pa20(&cpu[0]->env)) {
6283d1611bfSHelge Deller         error_report("The HP C3000 workstation requires a 64-bit CPU. "
6293d1611bfSHelge Deller                      "Use '-machine B160L' instead.");
6303d1611bfSHelge Deller         exit(1);
6313d1611bfSHelge Deller     }
6323d1611bfSHelge Deller 
6332ed4faa0SHelge Deller     /* Init Astro and the Elroys (PCI host bus chips).  */
6342ed4faa0SHelge Deller     astro = astro_init();
6352ed4faa0SHelge Deller     astro_dev = DEVICE(astro);
636f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
6372ed4faa0SHelge Deller                                 sysbus_mmio_get_region(
6382ed4faa0SHelge Deller                                     SYS_BUS_DEVICE(astro_dev), 0));
6392ed4faa0SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
6402ed4faa0SHelge Deller     assert(pci_bus);
6412ed4faa0SHelge Deller 
6422ed4faa0SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
643f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
6442ed4faa0SHelge Deller }
6452ed4faa0SHelge Deller 
6461b063fe2SJuraj Marcin static void hppa_machine_reset(MachineState *ms, ResetType type)
647a72bd606SHelge Deller {
64833decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
649a72bd606SHelge Deller     int i;
650a72bd606SHelge Deller 
6511b063fe2SJuraj Marcin     qemu_devices_reset(type);
652a72bd606SHelge Deller 
653a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
654a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
65550ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
656a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
65750ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
65850ba97e9SHelge Deller 
65920f7b890SHelge Deller         /* reset CPU */
66020f7b890SHelge Deller         resettable_reset(OBJECT(cs), RESET_TYPE_COLD);
66120f7b890SHelge Deller 
66250ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
66350ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
664a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
665a72bd606SHelge Deller     }
666a72bd606SHelge Deller 
667bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
668*c656f293SHelge Deller     cpu[0]->env.gr[25] = cpu[0]->env.kernel_entry;
669*c656f293SHelge Deller     cpu[0]->env.gr[24] = cpu[0]->env.cmdline_or_bootorder;
670*c656f293SHelge Deller     cpu[0]->env.gr[23] = cpu[0]->env.initrd_base;
671*c656f293SHelge Deller     cpu[0]->env.gr[22] = cpu[0]->env.initrd_end;
672a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
67324576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
674*c656f293SHelge Deller 
675*c656f293SHelge Deller     /* reset static fields to avoid starting Linux kernel & initrd on reboot */
676*c656f293SHelge Deller     cpu[0]->env.kernel_entry = 0;
677*c656f293SHelge Deller     cpu[0]->env.initrd_base = 0;
678*c656f293SHelge Deller     cpu[0]->env.initrd_end = 0;
679*c656f293SHelge Deller     cpu[0]->env.cmdline_or_bootorder = 'c';
680a72bd606SHelge Deller }
681a72bd606SHelge Deller 
6824a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
6834a4554c6SHelge Deller {
6844a4554c6SHelge Deller     CPUState *cs;
6854a4554c6SHelge Deller 
6864a4554c6SHelge Deller     CPU_FOREACH(cs) {
6874a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
6884a4554c6SHelge Deller     }
6894a4554c6SHelge Deller }
690a72bd606SHelge Deller 
691790a4428SGavin Shan static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
692790a4428SGavin Shan {
693790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
6943d1611bfSHelge Deller         TYPE_HPPA_CPU,
6953d1611bfSHelge Deller         NULL
6963d1611bfSHelge Deller     };
69742cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
69842cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
69942cc2bf6SMark Cave-Ayland 
7007df6f751SHelge Deller     mc->desc = "HP B160L workstation";
701a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
702790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
7037df6f751SHelge Deller     mc->init = machine_HP_B160L_init;
704a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
705813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
706a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
707a72bd606SHelge Deller     mc->default_cpus = 1;
708ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
709d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
710813dff13SHelge Deller     mc->default_boot_order = "cd";
7117c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
7129f8981a9SThomas Huth     mc->default_nic = "tulip";
713813dff13SHelge Deller 
7144a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7154a4554c6SHelge Deller }
7164a4554c6SHelge Deller 
7177df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
7187df6f751SHelge Deller     .name = MACHINE_TYPE_NAME("B160L"),
719c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
7207df6f751SHelge Deller     .class_init = HP_B160L_machine_init_class_init,
7214a4554c6SHelge Deller     .interfaces = (InterfaceInfo[]) {
7224a4554c6SHelge Deller         { TYPE_NMI },
7234a4554c6SHelge Deller         { }
7244a4554c6SHelge Deller     },
7254a4554c6SHelge Deller };
7264a4554c6SHelge Deller 
727790a4428SGavin Shan static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
728790a4428SGavin Shan {
729790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
7303d1611bfSHelge Deller         TYPE_HPPA64_CPU,
7313d1611bfSHelge Deller         NULL
7323d1611bfSHelge Deller     };
7332ed4faa0SHelge Deller     MachineClass *mc = MACHINE_CLASS(oc);
7342ed4faa0SHelge Deller     NMIClass *nc = NMI_CLASS(oc);
7352ed4faa0SHelge Deller 
7362ed4faa0SHelge Deller     mc->desc = "HP C3700 workstation";
737fd9b04bfSHelge Deller     mc->default_cpu_type = TYPE_HPPA64_CPU;
738790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
7392ed4faa0SHelge Deller     mc->init = machine_HP_C3700_init;
7402ed4faa0SHelge Deller     mc->reset = hppa_machine_reset;
7412ed4faa0SHelge Deller     mc->block_default_type = IF_SCSI;
7422ed4faa0SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
7432ed4faa0SHelge Deller     mc->default_cpus = 1;
7442ed4faa0SHelge Deller     mc->is_default = false;
7452ed4faa0SHelge Deller     mc->default_ram_size = 1024 * MiB;
7462ed4faa0SHelge Deller     mc->default_boot_order = "cd";
7472ed4faa0SHelge Deller     mc->default_ram_id = "ram";
7482ed4faa0SHelge Deller     mc->default_nic = "tulip";
7492ed4faa0SHelge Deller 
7502ed4faa0SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7512ed4faa0SHelge Deller }
7522ed4faa0SHelge Deller 
7532ed4faa0SHelge Deller static const TypeInfo HP_C3700_machine_init_typeinfo = {
7542ed4faa0SHelge Deller     .name = MACHINE_TYPE_NAME("C3700"),
7552ed4faa0SHelge Deller     .parent = TYPE_MACHINE,
7562ed4faa0SHelge Deller     .class_init = HP_C3700_machine_init_class_init,
7572ed4faa0SHelge Deller     .interfaces = (InterfaceInfo[]) {
7582ed4faa0SHelge Deller         { TYPE_NMI },
7592ed4faa0SHelge Deller         { }
7602ed4faa0SHelge Deller     },
7612ed4faa0SHelge Deller };
7622ed4faa0SHelge Deller 
763297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
7644a4554c6SHelge Deller {
7657df6f751SHelge Deller     type_register_static(&HP_B160L_machine_init_typeinfo);
7662ed4faa0SHelge Deller     type_register_static(&HP_C3700_machine_init_typeinfo);
7674a4554c6SHelge Deller }
7684a4554c6SHelge Deller 
769297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
770