xref: /qemu/hw/hppa/machine.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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"
149c2ff9cdSPierrick Bouvier #include "exec/target_page.h"
1532cad1ffSPhilippe Mathieu-Daudé #include "system/reset.h"
1632cad1ffSPhilippe Mathieu-Daudé #include "system/system.h"
1732cad1ffSPhilippe Mathieu-Daudé #include "system/qtest.h"
1832cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
19bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
20813dff13SHelge Deller #include "hw/timer/i8254.h"
217e6b5497SBernhard Beschow #include "hw/char/serial-mm.h"
229701e569SMark Cave-Ayland #include "hw/char/parallel.h"
23134ba73fSMark Cave-Ayland #include "hw/intc/i8259.h"
24d26c575cSMark Cave-Ayland #include "hw/input/lasips2.h"
25376b8519SHelge Deller #include "hw/net/lasi_82596.h"
264a4554c6SHelge Deller #include "hw/nmi.h"
272ed4faa0SHelge Deller #include "hw/usb.h"
28134ba73fSMark Cave-Ayland #include "hw/pci/pci.h"
297df6f751SHelge Deller #include "hw/pci/pci_device.h"
302ed4faa0SHelge Deller #include "hw/pci-host/astro.h"
310db9350eSMark Cave-Ayland #include "hw/pci-host/dino.h"
3245f569a1SMark Cave-Ayland #include "hw/misc/lasi.h"
33148da670SMark Cave-Ayland #include "hppa_hardware.h"
34c108cc59SPhilippe Mathieu-Daudé #include "qemu/units.h"
35813dff13SHelge Deller #include "qapi/error.h"
36852c27e2SPaolo Bonzini #include "net/net.h"
37691cbbadSRichard Henderson #include "qemu/log.h"
38813dff13SHelge Deller 
39f88131d9SHelge Deller #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
4028b71a2eSHelge Deller 
41ed35afcbSHelge Deller #define HPA_POWER_BUTTON        (FIRMWARE_END - 0x10)
42ed35afcbSHelge Deller static hwaddr soft_power_reg;
43b28c4a64SHelge Deller 
44932befaaSMark Cave-Ayland #define enable_lasi_lan()       0
45932befaaSMark Cave-Ayland 
467df6f751SHelge Deller static DeviceState *lasi_dev;
47932befaaSMark Cave-Ayland 
hppa_powerdown_req(Notifier * n,void * opaque)48b28c4a64SHelge Deller static void hppa_powerdown_req(Notifier *n, void *opaque)
49b28c4a64SHelge Deller {
50b28c4a64SHelge Deller     uint32_t val;
51b28c4a64SHelge Deller 
52b28c4a64SHelge Deller     val = ldl_be_phys(&address_space_memory, soft_power_reg);
53b28c4a64SHelge Deller     if ((val >> 8) == 0) {
54b28c4a64SHelge Deller         /* immediately shut down when under hardware control */
55b28c4a64SHelge Deller         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
56b28c4a64SHelge Deller         return;
57b28c4a64SHelge Deller     }
58b28c4a64SHelge Deller 
59b28c4a64SHelge Deller     /* clear bit 31 to indicate that the power switch was pressed. */
60b28c4a64SHelge Deller     val &= ~1;
61b28c4a64SHelge Deller     stl_be_phys(&address_space_memory, soft_power_reg, val);
62b28c4a64SHelge Deller }
63b28c4a64SHelge Deller 
64b28c4a64SHelge Deller static Notifier hppa_system_powerdown_notifier = {
65b28c4a64SHelge Deller     .notify = hppa_powerdown_req
66b28c4a64SHelge Deller };
67b28c4a64SHelge Deller 
6828f5332aSMark Cave-Ayland /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
ignore_read(void * opaque,hwaddr addr,unsigned size)6928f5332aSMark Cave-Ayland static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
7028f5332aSMark Cave-Ayland {
7128f5332aSMark Cave-Ayland     return 0;
7228f5332aSMark Cave-Ayland }
7328f5332aSMark Cave-Ayland 
ignore_write(void * opaque,hwaddr addr,uint64_t v,unsigned size)7428f5332aSMark Cave-Ayland static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
7528f5332aSMark Cave-Ayland {
7628f5332aSMark Cave-Ayland }
7728f5332aSMark Cave-Ayland 
7828f5332aSMark Cave-Ayland static const MemoryRegionOps hppa_pci_ignore_ops = {
7928f5332aSMark Cave-Ayland     .read = ignore_read,
8028f5332aSMark Cave-Ayland     .write = ignore_write,
8128f5332aSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
8228f5332aSMark Cave-Ayland     .valid = {
8328f5332aSMark Cave-Ayland         .min_access_size = 1,
8428f5332aSMark Cave-Ayland         .max_access_size = 8,
8528f5332aSMark Cave-Ayland     },
8628f5332aSMark Cave-Ayland     .impl = {
8728f5332aSMark Cave-Ayland         .min_access_size = 1,
8828f5332aSMark Cave-Ayland         .max_access_size = 8,
8928f5332aSMark Cave-Ayland     },
9028f5332aSMark Cave-Ayland };
91b28c4a64SHelge Deller 
hppa_isa_bus(hwaddr addr)92f386a16eSRichard Henderson static ISABus *hppa_isa_bus(hwaddr addr)
93a72bd606SHelge Deller {
94a72bd606SHelge Deller     ISABus *isa_bus;
95a72bd606SHelge Deller     qemu_irq *isa_irqs;
96a72bd606SHelge Deller     MemoryRegion *isa_region;
97a72bd606SHelge Deller 
98a72bd606SHelge Deller     isa_region = g_new(MemoryRegion, 1);
99a72bd606SHelge Deller     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
100a72bd606SHelge Deller                           NULL, "isa-io", 0x800);
101f386a16eSRichard Henderson     memory_region_add_subregion(get_system_memory(), addr, isa_region);
102a72bd606SHelge Deller 
103a72bd606SHelge Deller     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
104a72bd606SHelge Deller                           &error_abort);
105a536f564SHelge Deller     isa_irqs = i8259_init(isa_bus, NULL);
1067067887eSPhilippe Mathieu-Daudé     isa_bus_register_input_irqs(isa_bus, isa_irqs);
107a72bd606SHelge Deller 
108a72bd606SHelge Deller     return isa_bus;
109a72bd606SHelge Deller }
110a72bd606SHelge Deller 
111e2c41ee5SHelge Deller /*
112e2c41ee5SHelge Deller  * Helper functions to emulate RTC clock and DebugOutputPort
113e2c41ee5SHelge Deller  */
114e2c41ee5SHelge Deller static time_t rtc_ref;
115e2c41ee5SHelge Deller 
io_cpu_read(void * opaque,hwaddr addr,unsigned size)116e2c41ee5SHelge Deller static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
117e2c41ee5SHelge Deller {
118e2c41ee5SHelge Deller     uint64_t val = 0;
119e2c41ee5SHelge Deller 
120e2c41ee5SHelge Deller     switch (addr) {
121e2c41ee5SHelge Deller     case 0:             /* RTC clock */
122e2c41ee5SHelge Deller         val = time(NULL);
123e2c41ee5SHelge Deller         val += rtc_ref;
124e2c41ee5SHelge Deller         break;
125e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
126e2c41ee5SHelge Deller         return 0xe9;    /* readback */
127e2c41ee5SHelge Deller     }
128e2c41ee5SHelge Deller     return val;
129e2c41ee5SHelge Deller }
130e2c41ee5SHelge Deller 
io_cpu_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)131e2c41ee5SHelge Deller static void io_cpu_write(void *opaque, hwaddr addr,
132e2c41ee5SHelge Deller                          uint64_t val, unsigned size)
133e2c41ee5SHelge Deller {
134e2c41ee5SHelge Deller     unsigned char ch;
135e2c41ee5SHelge Deller     Chardev *debugout;
136e2c41ee5SHelge Deller 
137e2c41ee5SHelge Deller     switch (addr) {
138e2c41ee5SHelge Deller     case 0:             /* RTC clock */
139e2c41ee5SHelge Deller         rtc_ref = val - time(NULL);
140e2c41ee5SHelge Deller         break;
141e2c41ee5SHelge Deller     case 8:             /* DebugOutputPort */
142e2c41ee5SHelge Deller         ch = val;
143e2c41ee5SHelge Deller         debugout = serial_hd(0);
144e2c41ee5SHelge Deller         if (debugout) {
145e2c41ee5SHelge Deller             qemu_chr_fe_write_all(debugout->be, &ch, 1);
146e2c41ee5SHelge Deller         } else {
147e2c41ee5SHelge Deller             fprintf(stderr, "%c", ch);
148e2c41ee5SHelge Deller         }
149e2c41ee5SHelge Deller         break;
150e2c41ee5SHelge Deller     }
151e2c41ee5SHelge Deller }
152e2c41ee5SHelge Deller 
153e2c41ee5SHelge Deller static const MemoryRegionOps hppa_io_helper_ops = {
154e2c41ee5SHelge Deller     .read = io_cpu_read,
155e2c41ee5SHelge Deller     .write = io_cpu_write,
156e2c41ee5SHelge Deller     .endianness = DEVICE_BIG_ENDIAN,
157e2c41ee5SHelge Deller     .valid = {
158e2c41ee5SHelge Deller         .min_access_size = 1,
159e2c41ee5SHelge Deller         .max_access_size = 8,
160e2c41ee5SHelge Deller     },
161e2c41ee5SHelge Deller     .impl = {
162e2c41ee5SHelge Deller         .min_access_size = 1,
163e2c41ee5SHelge Deller         .max_access_size = 8,
164e2c41ee5SHelge Deller     },
165e2c41ee5SHelge Deller };
166e2c41ee5SHelge Deller 
167f386a16eSRichard Henderson typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
168e2c41ee5SHelge Deller 
linux_kernel_virt_to_phys(void * opaque,uint64_t addr)169f386a16eSRichard Henderson static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
170a72bd606SHelge Deller {
171a72bd606SHelge Deller     addr &= (0x10000000 - 1);
172a72bd606SHelge Deller     return addr;
173a72bd606SHelge Deller }
174a72bd606SHelge Deller 
translate_pa10(void * dummy,uint64_t addr)175f386a16eSRichard Henderson static uint64_t translate_pa10(void *dummy, uint64_t addr)
176f386a16eSRichard Henderson {
177f386a16eSRichard Henderson     return (uint32_t)addr;
178f386a16eSRichard Henderson }
179f386a16eSRichard Henderson 
translate_pa20(void * dummy,uint64_t addr)180f386a16eSRichard Henderson static uint64_t translate_pa20(void *dummy, uint64_t addr)
181f386a16eSRichard Henderson {
182f386a16eSRichard Henderson     return hppa_abs_to_phys_pa2_w0(addr);
183f386a16eSRichard Henderson }
184f386a16eSRichard Henderson 
185a72bd606SHelge Deller static HPPACPU *cpu[HPPA_MAX_CPUS];
186a72bd606SHelge Deller static uint64_t firmware_entry;
187813dff13SHelge Deller 
fw_cfg_boot_set(void * opaque,const char * boot_device,Error ** errp)18832ff8bf2SHelge Deller static void fw_cfg_boot_set(void *opaque, const char *boot_device,
18932ff8bf2SHelge Deller                             Error **errp)
19032ff8bf2SHelge Deller {
19132ff8bf2SHelge Deller     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
19232ff8bf2SHelge Deller }
19332ff8bf2SHelge Deller 
create_fw_cfg(MachineState * ms,PCIBus * pci_bus,hwaddr addr)194f386a16eSRichard Henderson static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
195f386a16eSRichard Henderson                                  hwaddr addr)
19628b71a2eSHelge Deller {
19728b71a2eSHelge Deller     FWCfgState *fw_cfg;
19828b71a2eSHelge Deller     uint64_t val;
199069d2966SHelge Deller     const char qemu_version[] = QEMU_VERSION;
200bcd4dd4cSHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(ms);
2019cf2112bSRichard Henderson     int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
202bcd4dd4cSHelge Deller     int len;
20328b71a2eSHelge Deller 
204f386a16eSRichard Henderson     fw_cfg = fw_cfg_init_mem(addr, addr + 4);
20528b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
20628b71a2eSHelge Deller     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
207bfdf22bcSPaolo Bonzini     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
20828b71a2eSHelge Deller 
20928b71a2eSHelge Deller     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
21028b71a2eSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
2110572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
21228b71a2eSHelge Deller 
2139cf2112bSRichard Henderson     val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
214df5c6a50SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
2150572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
216df5c6a50SHelge Deller 
2179cf2112bSRichard Henderson     val = cpu_to_le64(btlb_entries);
218bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
2190572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
220bcd4dd4cSHelge Deller 
221bcd4dd4cSHelge Deller     len = strlen(mc->name) + 1;
222bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
2230572f011SPhilippe Mathieu-Daudé                     g_memdup2(mc->name, len), len);
224bcd4dd4cSHelge Deller 
225ed35afcbSHelge Deller     val = cpu_to_le64(soft_power_reg);
226bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
2270572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
228bcd4dd4cSHelge Deller 
229e2c41ee5SHelge Deller     val = cpu_to_le64(CPU_HPA + 16);
230e2c41ee5SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
2310572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
232e2c41ee5SHelge Deller 
233bcd4dd4cSHelge Deller     val = cpu_to_le64(CPU_HPA + 24);
234bcd4dd4cSHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
2350572f011SPhilippe Mathieu-Daudé                     g_memdup2(&val, sizeof(val)), sizeof(val));
236b28c4a64SHelge Deller 
23797ec4d21SPaolo Bonzini     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
23832ff8bf2SHelge Deller     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
23932ff8bf2SHelge Deller 
240069d2966SHelge Deller     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
2410572f011SPhilippe Mathieu-Daudé                     g_memdup2(qemu_version, sizeof(qemu_version)),
242069d2966SHelge Deller                     sizeof(qemu_version));
243069d2966SHelge Deller 
244e5fd678aSPhilippe Mathieu-Daudé     pci_bus_add_fw_cfg_extra_pci_roots(fw_cfg, pci_bus, &error_abort);
245bcd4dd4cSHelge Deller 
24628b71a2eSHelge Deller     return fw_cfg;
24728b71a2eSHelge Deller }
24828b71a2eSHelge Deller 
lasi_init(void)249e881e3c8SMark Cave-Ayland static LasiState *lasi_init(void)
250e881e3c8SMark Cave-Ayland {
251e881e3c8SMark Cave-Ayland     DeviceState *dev;
252e881e3c8SMark Cave-Ayland 
253e881e3c8SMark Cave-Ayland     dev = qdev_new(TYPE_LASI_CHIP);
254e881e3c8SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
255e881e3c8SMark Cave-Ayland 
256e881e3c8SMark Cave-Ayland     return LASI_CHIP(dev);
257e881e3c8SMark Cave-Ayland }
258e881e3c8SMark Cave-Ayland 
dino_init(MemoryRegion * addr_space)2590d068996SMark Cave-Ayland static DinoState *dino_init(MemoryRegion *addr_space)
2600d068996SMark Cave-Ayland {
2610d068996SMark Cave-Ayland     DeviceState *dev;
2620d068996SMark Cave-Ayland 
2630d068996SMark Cave-Ayland     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
2640d068996SMark Cave-Ayland     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
2650d068996SMark Cave-Ayland                              &error_fatal);
2660d068996SMark Cave-Ayland     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
2670d068996SMark Cave-Ayland 
2680d068996SMark Cave-Ayland     return DINO_PCI_HOST_BRIDGE(dev);
2690d068996SMark Cave-Ayland }
2700d068996SMark Cave-Ayland 
2717df6f751SHelge Deller /*
2727df6f751SHelge Deller  * Step 1: Create CPUs and Memory
2737df6f751SHelge Deller  */
machine_HP_common_init_cpus(MachineState * machine)274f386a16eSRichard Henderson static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
275813dff13SHelge Deller {
276a72bd606SHelge Deller     MemoryRegion *addr_space = get_system_memory();
27733decbd2SLike Xu     unsigned int smp_cpus = machine->smp.cpus;
278f386a16eSRichard Henderson     TranslateFn *translate;
279f386a16eSRichard Henderson     MemoryRegion *cpu_region;
28092039f61SHelge Deller     uint64_t ram_max;
281a72bd606SHelge Deller 
282a72bd606SHelge Deller     /* Create CPUs.  */
283f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
284a72bd606SHelge Deller         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
285f386a16eSRichard Henderson     }
286f386a16eSRichard Henderson 
287d0ad4118SHelge Deller     /* Initialize memory */
288f386a16eSRichard Henderson     if (hppa_is_pa20(&cpu[0]->env)) {
289f386a16eSRichard Henderson         translate = translate_pa20;
290d0ad4118SHelge Deller         ram_max = 256 * GiB;       /* like HP rp8440 */
291f386a16eSRichard Henderson     } else {
292f386a16eSRichard Henderson         translate = translate_pa10;
293d0ad4118SHelge Deller         ram_max = FIRMWARE_START;  /* 3.75 GB (32-bit CPU) */
294f386a16eSRichard Henderson     }
295f386a16eSRichard Henderson 
296ed35afcbSHelge Deller     soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
297ed35afcbSHelge Deller 
298f386a16eSRichard Henderson     for (unsigned int i = 0; i < smp_cpus; i++) {
299f386a16eSRichard Henderson         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
300a72bd606SHelge Deller 
301a72bd606SHelge Deller         cpu_region = g_new(MemoryRegion, 1);
302a72bd606SHelge Deller         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
303266a880eSPaolo Bonzini                               cpu[i], name, 4);
304f386a16eSRichard Henderson         memory_region_add_subregion(addr_space,
305f386a16eSRichard Henderson                                     translate(NULL, CPU_HPA + i * 0x1000),
306a72bd606SHelge Deller                                     cpu_region);
307813dff13SHelge Deller     }
308813dff13SHelge Deller 
309e2c41ee5SHelge Deller     /* RTC and DebugOutputPort on CPU #0 */
310e2c41ee5SHelge Deller     cpu_region = g_new(MemoryRegion, 1);
311e2c41ee5SHelge Deller     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
312e2c41ee5SHelge Deller                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
313f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
314f386a16eSRichard Henderson                                 cpu_region);
315e2c41ee5SHelge Deller 
316a72bd606SHelge Deller     /* Main memory region. */
31792039f61SHelge Deller     if (machine->ram_size > ram_max) {
31892039f61SHelge Deller         info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
31992039f61SHelge Deller         machine->ram_size = ram_max;
320b7746b11SPhilippe Mathieu-Daudé     }
321d0ad4118SHelge Deller     if (machine->ram_size <= FIRMWARE_START) {
322d0ad4118SHelge Deller         /* contiguous memory up to 3.75 GB RAM */
3237c59c1e0SIgor Mammedov         memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
324d0ad4118SHelge Deller     } else {
325d0ad4118SHelge Deller         /* non-contiguous: Memory above 3.75 GB is mapped at RAM_MAP_HIGH */
326d0ad4118SHelge Deller         MemoryRegion *mem_region;
327d0ad4118SHelge Deller         mem_region = g_new(MemoryRegion, 2);
328d0ad4118SHelge Deller         memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
329d0ad4118SHelge Deller                               "LowMem", machine->ram, 0, FIRMWARE_START);
330d0ad4118SHelge Deller         memory_region_init_alias(&mem_region[1], &addr_space->parent_obj,
331d0ad4118SHelge Deller                               "HighMem", machine->ram, FIRMWARE_START,
332d0ad4118SHelge Deller                               machine->ram_size - FIRMWARE_START);
333d0ad4118SHelge Deller         memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1);
334d0ad4118SHelge Deller         memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH,
335d0ad4118SHelge Deller                                             &mem_region[1], -1);
336d0ad4118SHelge Deller     }
337f386a16eSRichard Henderson 
338f386a16eSRichard Henderson     return translate;
3397df6f751SHelge Deller }
3407c59c1e0SIgor Mammedov 
3417df6f751SHelge Deller /*
3427df6f751SHelge Deller  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
3437df6f751SHelge Deller  */
machine_HP_common_init_tail(MachineState * machine,PCIBus * pci_bus,TranslateFn * translate)344f386a16eSRichard Henderson static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
345f386a16eSRichard Henderson                                         TranslateFn *translate)
3467df6f751SHelge Deller {
3477df6f751SHelge Deller     const char *kernel_filename = machine->kernel_filename;
3487df6f751SHelge Deller     const char *kernel_cmdline = machine->kernel_cmdline;
3497df6f751SHelge Deller     const char *initrd_filename = machine->initrd_filename;
350a9314795SHelge Deller     const char *firmware = machine->firmware;
3517df6f751SHelge Deller     MachineClass *mc = MACHINE_GET_CLASS(machine);
3527df6f751SHelge Deller     DeviceState *dev;
3532ed4faa0SHelge Deller     PCIDevice *pci_dev;
3547df6f751SHelge Deller     char *firmware_filename;
3557df6f751SHelge Deller     uint64_t firmware_low, firmware_high;
3567df6f751SHelge Deller     long size;
3577df6f751SHelge Deller     uint64_t kernel_entry = 0, kernel_low, kernel_high;
3587df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
3597df6f751SHelge Deller     MemoryRegion *rom_region;
3607df6f751SHelge Deller     SysBusDevice *s;
36128b71a2eSHelge Deller 
362a72bd606SHelge Deller     /* SCSI disk setup. */
363d8a32200SHelge Deller     if (drive_get_max_bus(IF_SCSI) >= 0) {
364877eb21dSMark Cave-Ayland         dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
365877eb21dSMark Cave-Ayland         lsi53c8xx_handle_legacy_cmdline(dev);
366d8a32200SHelge Deller     }
367a72bd606SHelge Deller 
3684765384cSSven Schnelle     /* Graphics setup. */
3694765384cSSven Schnelle     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
3703e80f690SMarkus Armbruster         dev = qdev_new("artist");
3714765384cSSven Schnelle         s = SYS_BUS_DEVICE(dev);
372b6247273SHelge Deller         bool disabled = object_property_get_bool(OBJECT(dev), "disable", NULL);
373b6247273SHelge Deller         if (!disabled) {
3743c6ef471SMarkus Armbruster             sysbus_realize_and_unref(s, &error_fatal);
375b6247273SHelge Deller             vga_interface_created = true;
376f386a16eSRichard Henderson             sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
377f386a16eSRichard Henderson             sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
3784765384cSSven Schnelle         }
379b6247273SHelge Deller     }
3804765384cSSven Schnelle 
3810e6de551SHelge Deller     /* Network setup. */
3822a98878fSDavid Woodhouse     if (lasi_dev) {
383f386a16eSRichard Henderson         lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
3842a98878fSDavid Woodhouse                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
3852a98878fSDavid Woodhouse                         enable_lasi_lan());
386c3c3fe47SMark Cave-Ayland     }
387c3c3fe47SMark Cave-Ayland 
3882dfe2f86SDavid Woodhouse     pci_init_nic_devices(pci_bus, mc->default_nic);
389a72bd606SHelge Deller 
390c061efcaSHelge Deller     /* BMC board: HP Diva GSP */
391c061efcaSHelge Deller     dev = qdev_new("diva-gsp");
392c061efcaSHelge Deller     if (!object_property_get_bool(OBJECT(dev), "disable", NULL)) {
393c061efcaSHelge Deller         pci_dev = pci_new_multifunction(PCI_DEVFN(2, 0), "diva-gsp");
3942ed4faa0SHelge Deller         if (!lasi_dev) {
3952ed4faa0SHelge Deller             /* bind default keyboard/serial to Diva card */
396c061efcaSHelge Deller             qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(0));
397c061efcaSHelge Deller             qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(1));
398c061efcaSHelge Deller             qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(2));
399c061efcaSHelge Deller             qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(3));
4002ed4faa0SHelge Deller         }
4012ed4faa0SHelge Deller         pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
4022ed4faa0SHelge Deller     }
4032ed4faa0SHelge Deller 
4042ed4faa0SHelge Deller     /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
40582523f4aSPaolo Bonzini     if (!lasi_dev && machine->enable_graphics && defaults_enabled()) {
40682523f4aSPaolo Bonzini         USBBus *usb_bus;
40782523f4aSPaolo Bonzini 
4082ed4faa0SHelge Deller         pci_create_simple(pci_bus, -1, "pci-ohci");
40982523f4aSPaolo Bonzini         usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
41082523f4aSPaolo Bonzini                                                           &error_abort));
41182523f4aSPaolo Bonzini         usb_create_simple(usb_bus, "usb-kbd");
41282523f4aSPaolo Bonzini         usb_create_simple(usb_bus, "usb-mouse");
4132ed4faa0SHelge Deller     }
4142ed4faa0SHelge Deller 
415b28c4a64SHelge Deller     /* register power switch emulation */
416b28c4a64SHelge Deller     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
417b28c4a64SHelge Deller 
4187df6f751SHelge Deller     /* fw_cfg configuration interface */
419f386a16eSRichard Henderson     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
4207df6f751SHelge Deller 
421a72bd606SHelge Deller     /* Load firmware.  Given that this is not "real" firmware,
422a72bd606SHelge Deller        but one explicitly written for the emulation, we might as
423a9314795SHelge Deller        well load it directly from an ELF image. Load the 64-bit
424a9314795SHelge Deller        firmware on 64-bit machines by default if not specified
425a9314795SHelge Deller        on command line. */
426a9314795SHelge Deller     if (!qtest_enabled()) {
427a9314795SHelge Deller         if (!firmware) {
428a9314795SHelge Deller             firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
429a9314795SHelge Deller         }
430a9314795SHelge Deller         firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
431a72bd606SHelge Deller         if (firmware_filename == NULL) {
432a72bd606SHelge Deller             error_report("no firmware provided");
433a72bd606SHelge Deller             exit(1);
434a72bd606SHelge Deller         }
435a72bd606SHelge Deller 
436f386a16eSRichard Henderson         size = load_elf(firmware_filename, NULL, translate, NULL,
4376cdda0ffSAleksandar Markovic                         &firmware_entry, &firmware_low, &firmware_high, NULL,
438adc1a4a2SPhilippe Mathieu-Daudé                         ELFDATA2MSB, EM_PARISC, 0, 0);
439a72bd606SHelge Deller 
440a72bd606SHelge Deller         if (size < 0) {
441a72bd606SHelge Deller             error_report("could not load firmware '%s'", firmware_filename);
442a72bd606SHelge Deller             exit(1);
443a72bd606SHelge Deller         }
444691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
445691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
446a72bd606SHelge Deller                       firmware_low, firmware_high, firmware_entry);
447f386a16eSRichard Henderson         if (firmware_low < translate(NULL, FIRMWARE_START) ||
448f386a16eSRichard Henderson             firmware_high >= translate(NULL, FIRMWARE_END)) {
449a72bd606SHelge Deller             error_report("Firmware overlaps with memory or IO space");
450a72bd606SHelge Deller             exit(1);
451a72bd606SHelge Deller         }
452a72bd606SHelge Deller         g_free(firmware_filename);
453a9314795SHelge Deller     }
454a72bd606SHelge Deller 
455a72bd606SHelge Deller     rom_region = g_new(MemoryRegion, 1);
4566a3a2e82SIgor Mammedov     memory_region_init_ram(rom_region, NULL, "firmware",
4576a3a2e82SIgor Mammedov                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
458f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
459f386a16eSRichard Henderson                                 translate(NULL, FIRMWARE_START), rom_region);
460a72bd606SHelge Deller 
461a72bd606SHelge Deller     /* Load kernel */
462a72bd606SHelge Deller     if (kernel_filename) {
463f386a16eSRichard Henderson         size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
4646cdda0ffSAleksandar Markovic                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
465adc1a4a2SPhilippe Mathieu-Daudé                         ELFDATA2MSB, EM_PARISC, 0, 0);
466a72bd606SHelge Deller 
467f386a16eSRichard Henderson         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
468a72bd606SHelge Deller 
469a72bd606SHelge Deller         if (size < 0) {
470a72bd606SHelge Deller             error_report("could not load kernel '%s'", kernel_filename);
471a72bd606SHelge Deller             exit(1);
472a72bd606SHelge Deller         }
473691cbbadSRichard Henderson         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
474691cbbadSRichard Henderson                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
475c108cc59SPhilippe Mathieu-Daudé                       ", size %" PRIu64 " kB\n",
476c108cc59SPhilippe Mathieu-Daudé                       kernel_low, kernel_high, kernel_entry, size / KiB);
477a72bd606SHelge Deller 
478a72bd606SHelge Deller         if (kernel_cmdline) {
479c656f293SHelge Deller             cpu[0]->env.cmdline_or_bootorder = 0x4000;
480c656f293SHelge Deller             pstrcpy_targphys("cmdline", cpu[0]->env.cmdline_or_bootorder,
481a72bd606SHelge Deller                              TARGET_PAGE_SIZE, kernel_cmdline);
482a72bd606SHelge Deller         }
483a72bd606SHelge Deller 
484a72bd606SHelge Deller         if (initrd_filename) {
485a72bd606SHelge Deller             ram_addr_t initrd_base;
486f3839fdaSLi Zhijian             int64_t initrd_size;
487a72bd606SHelge Deller 
488a72bd606SHelge Deller             initrd_size = get_image_size(initrd_filename);
489a72bd606SHelge Deller             if (initrd_size < 0) {
490a72bd606SHelge Deller                 error_report("could not load initial ram disk '%s'",
491a72bd606SHelge Deller                              initrd_filename);
492a72bd606SHelge Deller                 exit(1);
493a72bd606SHelge Deller             }
494a72bd606SHelge Deller 
495a72bd606SHelge Deller             /* Load the initrd image high in memory.
496a72bd606SHelge Deller                Mirror the algorithm used by palo:
497a72bd606SHelge Deller                (1) Due to sign-extension problems and PDC,
498a72bd606SHelge Deller                put the initrd no higher than 1G.
499a72bd606SHelge Deller                (2) Reserve 64k for stack.  */
500bfdf22bcSPaolo Bonzini             initrd_base = MIN(machine->ram_size, 1 * GiB);
501c108cc59SPhilippe Mathieu-Daudé             initrd_base = initrd_base - 64 * KiB;
502a72bd606SHelge Deller             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
503a72bd606SHelge Deller 
504a72bd606SHelge Deller             if (initrd_base < kernel_high) {
505a72bd606SHelge Deller                 error_report("kernel and initial ram disk too large!");
506a72bd606SHelge Deller                 exit(1);
507a72bd606SHelge Deller             }
508a72bd606SHelge Deller 
509a72bd606SHelge Deller             load_image_targphys(initrd_filename, initrd_base, initrd_size);
510c656f293SHelge Deller             cpu[0]->env.initrd_base = initrd_base;
511c656f293SHelge Deller             cpu[0]->env.initrd_end  = initrd_base + initrd_size;
512a72bd606SHelge Deller         }
513a72bd606SHelge Deller     }
514a72bd606SHelge Deller 
515a72bd606SHelge Deller     if (!kernel_entry) {
516a72bd606SHelge Deller         /* When booting via firmware, tell firmware if we want interactive
517c656f293SHelge Deller          * mode (kernel_entry=1), and to boot from CD (cmdline_or_bootorder='d')
518c656f293SHelge Deller          * or hard disc (cmdline_or_bootorder='c').
519a72bd606SHelge Deller          */
52097ec4d21SPaolo Bonzini         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
521c656f293SHelge Deller         cpu[0]->env.cmdline_or_bootorder = machine->boot_config.order[0];
522a72bd606SHelge Deller     }
523a72bd606SHelge Deller 
524c656f293SHelge Deller     /* Keep initial kernel_entry for first boot */
525c656f293SHelge Deller     cpu[0]->env.kernel_entry = kernel_entry;
526a72bd606SHelge Deller }
527a72bd606SHelge Deller 
5287df6f751SHelge Deller /*
5297df6f751SHelge Deller  * Create HP B160L workstation
5307df6f751SHelge Deller  */
machine_HP_B160L_init(MachineState * machine)5317df6f751SHelge Deller static void machine_HP_B160L_init(MachineState *machine)
5327df6f751SHelge Deller {
5337df6f751SHelge Deller     DeviceState *dev, *dino_dev;
5347df6f751SHelge Deller     MemoryRegion *addr_space = get_system_memory();
535f386a16eSRichard Henderson     TranslateFn *translate;
5367df6f751SHelge Deller     ISABus *isa_bus;
5377df6f751SHelge Deller     PCIBus *pci_bus;
5387df6f751SHelge Deller 
5397df6f751SHelge Deller     /* Create CPUs and RAM.  */
540f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
5417df6f751SHelge Deller 
5423d1611bfSHelge Deller     if (hppa_is_pa20(&cpu[0]->env)) {
5433d1611bfSHelge Deller         error_report("The HP B160L workstation requires a 32-bit "
5443d1611bfSHelge Deller                      "CPU. Use '-machine C3700' instead.");
5453d1611bfSHelge Deller         exit(1);
5463d1611bfSHelge Deller     }
5473d1611bfSHelge Deller 
5487df6f751SHelge Deller     /* Init Lasi chip */
5497df6f751SHelge Deller     lasi_dev = DEVICE(lasi_init());
550f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
5517df6f751SHelge Deller                                 sysbus_mmio_get_region(
5527df6f751SHelge Deller                                     SYS_BUS_DEVICE(lasi_dev), 0));
5537df6f751SHelge Deller 
5547df6f751SHelge Deller     /* Init Dino (PCI host bus chip).  */
5557df6f751SHelge Deller     dino_dev = DEVICE(dino_init(addr_space));
556f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
5577df6f751SHelge Deller                                 sysbus_mmio_get_region(
5587df6f751SHelge Deller                                     SYS_BUS_DEVICE(dino_dev), 0));
5597df6f751SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
5607df6f751SHelge Deller     assert(pci_bus);
5617df6f751SHelge Deller 
5627df6f751SHelge Deller     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
563f386a16eSRichard Henderson     isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
5647df6f751SHelge Deller     assert(isa_bus);
5657df6f751SHelge Deller 
5667df6f751SHelge Deller     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
567f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
5687df6f751SHelge Deller         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
5697df6f751SHelge Deller         serial_hd(0), DEVICE_BIG_ENDIAN);
5707df6f751SHelge Deller 
571f386a16eSRichard Henderson     serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
5727df6f751SHelge Deller         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
5737df6f751SHelge Deller         serial_hd(1), DEVICE_BIG_ENDIAN);
5747df6f751SHelge Deller 
5757df6f751SHelge Deller     /* Parallel port */
576f386a16eSRichard Henderson     parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
5777df6f751SHelge Deller                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
5787df6f751SHelge Deller                      parallel_hds[0]);
5797df6f751SHelge Deller 
5807df6f751SHelge Deller     /* PS/2 Keyboard/Mouse */
5817df6f751SHelge Deller     dev = qdev_new(TYPE_LASIPS2);
5827df6f751SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
5837df6f751SHelge Deller     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
5847df6f751SHelge Deller                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
585f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
586f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA),
5877df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5887df6f751SHelge Deller                                                        0));
589f386a16eSRichard Henderson     memory_region_add_subregion(addr_space,
590f386a16eSRichard Henderson                                 translate(NULL, LASI_PS2KBD_HPA + 0x100),
5917df6f751SHelge Deller                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
5927df6f751SHelge Deller                                                        1));
5937df6f751SHelge Deller 
5947df6f751SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
595f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
5967df6f751SHelge Deller }
5977df6f751SHelge Deller 
astro_init(void)5982ed4faa0SHelge Deller static AstroState *astro_init(void)
5992ed4faa0SHelge Deller {
6002ed4faa0SHelge Deller     DeviceState *dev;
6012ed4faa0SHelge Deller 
6022ed4faa0SHelge Deller     dev = qdev_new(TYPE_ASTRO_CHIP);
6032ed4faa0SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
6042ed4faa0SHelge Deller 
6052ed4faa0SHelge Deller     return ASTRO_CHIP(dev);
6062ed4faa0SHelge Deller }
6072ed4faa0SHelge Deller 
6082ed4faa0SHelge Deller /*
6092ed4faa0SHelge Deller  * Create HP C3700 workstation
6102ed4faa0SHelge Deller  */
machine_HP_C3700_init(MachineState * machine)6112ed4faa0SHelge Deller static void machine_HP_C3700_init(MachineState *machine)
6122ed4faa0SHelge Deller {
6132ed4faa0SHelge Deller     PCIBus *pci_bus;
6142ed4faa0SHelge Deller     AstroState *astro;
6152ed4faa0SHelge Deller     DeviceState *astro_dev;
6162ed4faa0SHelge Deller     MemoryRegion *addr_space = get_system_memory();
617f386a16eSRichard Henderson     TranslateFn *translate;
6182ed4faa0SHelge Deller 
6192ed4faa0SHelge Deller     /* Create CPUs and RAM.  */
620f386a16eSRichard Henderson     translate = machine_HP_common_init_cpus(machine);
6212ed4faa0SHelge Deller 
6223d1611bfSHelge Deller     if (!hppa_is_pa20(&cpu[0]->env)) {
6233d1611bfSHelge Deller         error_report("The HP C3000 workstation requires a 64-bit CPU. "
6243d1611bfSHelge Deller                      "Use '-machine B160L' instead.");
6253d1611bfSHelge Deller         exit(1);
6263d1611bfSHelge Deller     }
6273d1611bfSHelge Deller 
6282ed4faa0SHelge Deller     /* Init Astro and the Elroys (PCI host bus chips).  */
6292ed4faa0SHelge Deller     astro = astro_init();
6302ed4faa0SHelge Deller     astro_dev = DEVICE(astro);
631f386a16eSRichard Henderson     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
6322ed4faa0SHelge Deller                                 sysbus_mmio_get_region(
6332ed4faa0SHelge Deller                                     SYS_BUS_DEVICE(astro_dev), 0));
6342ed4faa0SHelge Deller     pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
6352ed4faa0SHelge Deller     assert(pci_bus);
6362ed4faa0SHelge Deller 
6372ed4faa0SHelge Deller     /* Add SCSI discs, NICs, graphics & load firmware */
638f386a16eSRichard Henderson     machine_HP_common_init_tail(machine, pci_bus, translate);
6392ed4faa0SHelge Deller }
6402ed4faa0SHelge Deller 
hppa_machine_reset(MachineState * ms,ResetType type)6411b063fe2SJuraj Marcin static void hppa_machine_reset(MachineState *ms, ResetType type)
642a72bd606SHelge Deller {
64333decbd2SLike Xu     unsigned int smp_cpus = ms->smp.cpus;
644a72bd606SHelge Deller     int i;
645a72bd606SHelge Deller 
6461b063fe2SJuraj Marcin     qemu_devices_reset(type);
647a72bd606SHelge Deller 
648a72bd606SHelge Deller     /* Start all CPUs at the firmware entry point.
649a72bd606SHelge Deller      *  Monarch CPU will initialize firmware, secondary CPUs
65050ba97e9SHelge Deller      *  will enter a small idle loop and wait for rendevouz. */
651a72bd606SHelge Deller     for (i = 0; i < smp_cpus; i++) {
65250ba97e9SHelge Deller         CPUState *cs = CPU(cpu[i]);
65350ba97e9SHelge Deller 
65420f7b890SHelge Deller         /* reset CPU */
65520f7b890SHelge Deller         resettable_reset(OBJECT(cs), RESET_TYPE_COLD);
65620f7b890SHelge Deller 
65750ba97e9SHelge Deller         cpu_set_pc(cs, firmware_entry);
65850ba97e9SHelge Deller         cpu[i]->env.psw = PSW_Q;
659a72bd606SHelge Deller         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
660a72bd606SHelge Deller     }
661a72bd606SHelge Deller 
662bfdf22bcSPaolo Bonzini     cpu[0]->env.gr[26] = ms->ram_size;
663c656f293SHelge Deller     cpu[0]->env.gr[25] = cpu[0]->env.kernel_entry;
664c656f293SHelge Deller     cpu[0]->env.gr[24] = cpu[0]->env.cmdline_or_bootorder;
665c656f293SHelge Deller     cpu[0]->env.gr[23] = cpu[0]->env.initrd_base;
666c656f293SHelge Deller     cpu[0]->env.gr[22] = cpu[0]->env.initrd_end;
667a72bd606SHelge Deller     cpu[0]->env.gr[21] = smp_cpus;
66824576007SHelge Deller     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
669c656f293SHelge Deller 
670c656f293SHelge Deller     /* reset static fields to avoid starting Linux kernel & initrd on reboot */
671c656f293SHelge Deller     cpu[0]->env.kernel_entry = 0;
672c656f293SHelge Deller     cpu[0]->env.initrd_base = 0;
673c656f293SHelge Deller     cpu[0]->env.initrd_end = 0;
674c656f293SHelge Deller     cpu[0]->env.cmdline_or_bootorder = 'c';
675a72bd606SHelge Deller }
676a72bd606SHelge Deller 
hppa_nmi(NMIState * n,int cpu_index,Error ** errp)6774a4554c6SHelge Deller static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
6784a4554c6SHelge Deller {
6794a4554c6SHelge Deller     CPUState *cs;
6804a4554c6SHelge Deller 
6814a4554c6SHelge Deller     CPU_FOREACH(cs) {
6824a4554c6SHelge Deller         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
6834a4554c6SHelge Deller     }
6844a4554c6SHelge Deller }
685a72bd606SHelge Deller 
HP_B160L_machine_init_class_init(ObjectClass * oc,const void * data)68612d1a768SPhilippe Mathieu-Daudé static void HP_B160L_machine_init_class_init(ObjectClass *oc, const void *data)
687790a4428SGavin Shan {
688790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
6893d1611bfSHelge Deller         TYPE_HPPA_CPU,
6903d1611bfSHelge Deller         NULL
6913d1611bfSHelge Deller     };
69242cc2bf6SMark Cave-Ayland     MachineClass *mc = MACHINE_CLASS(oc);
69342cc2bf6SMark Cave-Ayland     NMIClass *nc = NMI_CLASS(oc);
69442cc2bf6SMark Cave-Ayland 
6957df6f751SHelge Deller     mc->desc = "HP B160L workstation";
696a72bd606SHelge Deller     mc->default_cpu_type = TYPE_HPPA_CPU;
697790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
6987df6f751SHelge Deller     mc->init = machine_HP_B160L_init;
699a72bd606SHelge Deller     mc->reset = hppa_machine_reset;
700813dff13SHelge Deller     mc->block_default_type = IF_SCSI;
701a72bd606SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
702a72bd606SHelge Deller     mc->default_cpus = 1;
703ea0ac7f6SPhilippe Mathieu-Daudé     mc->is_default = true;
704d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 512 * MiB;
705813dff13SHelge Deller     mc->default_boot_order = "cd";
7067c59c1e0SIgor Mammedov     mc->default_ram_id = "ram";
7079f8981a9SThomas Huth     mc->default_nic = "tulip";
708813dff13SHelge Deller 
7094a4554c6SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7104a4554c6SHelge Deller }
7114a4554c6SHelge Deller 
7127df6f751SHelge Deller static const TypeInfo HP_B160L_machine_init_typeinfo = {
7137df6f751SHelge Deller     .name = MACHINE_TYPE_NAME("B160L"),
714c165905cSMark Cave-Ayland     .parent = TYPE_MACHINE,
7157df6f751SHelge Deller     .class_init = HP_B160L_machine_init_class_init,
716*2cd09e47SPhilippe Mathieu-Daudé     .interfaces = (const InterfaceInfo[]) {
7174a4554c6SHelge Deller         { TYPE_NMI },
7184a4554c6SHelge Deller         { }
7194a4554c6SHelge Deller     },
7204a4554c6SHelge Deller };
7214a4554c6SHelge Deller 
HP_C3700_machine_init_class_init(ObjectClass * oc,const void * data)72212d1a768SPhilippe Mathieu-Daudé static void HP_C3700_machine_init_class_init(ObjectClass *oc, const void *data)
723790a4428SGavin Shan {
724790a4428SGavin Shan     static const char * const valid_cpu_types[] = {
7253d1611bfSHelge Deller         TYPE_HPPA64_CPU,
7263d1611bfSHelge Deller         NULL
7273d1611bfSHelge Deller     };
7282ed4faa0SHelge Deller     MachineClass *mc = MACHINE_CLASS(oc);
7292ed4faa0SHelge Deller     NMIClass *nc = NMI_CLASS(oc);
7302ed4faa0SHelge Deller 
7312ed4faa0SHelge Deller     mc->desc = "HP C3700 workstation";
732fd9b04bfSHelge Deller     mc->default_cpu_type = TYPE_HPPA64_CPU;
733790a4428SGavin Shan     mc->valid_cpu_types = valid_cpu_types;
7342ed4faa0SHelge Deller     mc->init = machine_HP_C3700_init;
7352ed4faa0SHelge Deller     mc->reset = hppa_machine_reset;
7362ed4faa0SHelge Deller     mc->block_default_type = IF_SCSI;
7372ed4faa0SHelge Deller     mc->max_cpus = HPPA_MAX_CPUS;
7382ed4faa0SHelge Deller     mc->default_cpus = 1;
7392ed4faa0SHelge Deller     mc->is_default = false;
7402ed4faa0SHelge Deller     mc->default_ram_size = 1024 * MiB;
7412ed4faa0SHelge Deller     mc->default_boot_order = "cd";
7422ed4faa0SHelge Deller     mc->default_ram_id = "ram";
7432ed4faa0SHelge Deller     mc->default_nic = "tulip";
7442ed4faa0SHelge Deller 
7452ed4faa0SHelge Deller     nc->nmi_monitor_handler = hppa_nmi;
7462ed4faa0SHelge Deller }
7472ed4faa0SHelge Deller 
7482ed4faa0SHelge Deller static const TypeInfo HP_C3700_machine_init_typeinfo = {
7492ed4faa0SHelge Deller     .name = MACHINE_TYPE_NAME("C3700"),
7502ed4faa0SHelge Deller     .parent = TYPE_MACHINE,
7512ed4faa0SHelge Deller     .class_init = HP_C3700_machine_init_class_init,
752*2cd09e47SPhilippe Mathieu-Daudé     .interfaces = (const InterfaceInfo[]) {
7532ed4faa0SHelge Deller         { TYPE_NMI },
7542ed4faa0SHelge Deller         { }
7552ed4faa0SHelge Deller     },
7562ed4faa0SHelge Deller };
7572ed4faa0SHelge Deller 
hppa_machine_init_register_types(void)758297d4103SMark Cave-Ayland static void hppa_machine_init_register_types(void)
7594a4554c6SHelge Deller {
7607df6f751SHelge Deller     type_register_static(&HP_B160L_machine_init_typeinfo);
7612ed4faa0SHelge Deller     type_register_static(&HP_C3700_machine_init_typeinfo);
7624a4554c6SHelge Deller }
7634a4554c6SHelge Deller 
764297d4103SMark Cave-Ayland type_init(hppa_machine_init_register_types)
765