Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / hw / hppa / machine.c
blob37ee6387e02a48290ad7dfce64e16fa6476231d3
1 /*
2 * QEMU HPPA hardware system emulator.
3 * (C) Copyright 2018-2023 Helge Deller <deller@gmx.de>
5 * This work is licensed under the GNU GPL license version 2 or later.
6 */
8 #include "qemu/osdep.h"
9 #include "qemu/datadir.h"
10 #include "cpu.h"
11 #include "elf.h"
12 #include "hw/loader.h"
13 #include "qemu/error-report.h"
14 #include "sysemu/reset.h"
15 #include "sysemu/sysemu.h"
16 #include "sysemu/qtest.h"
17 #include "sysemu/runstate.h"
18 #include "hw/rtc/mc146818rtc.h"
19 #include "hw/timer/i8254.h"
20 #include "hw/char/serial.h"
21 #include "hw/char/parallel.h"
22 #include "hw/intc/i8259.h"
23 #include "hw/input/lasips2.h"
24 #include "hw/net/lasi_82596.h"
25 #include "hw/nmi.h"
26 #include "hw/usb.h"
27 #include "hw/pci/pci.h"
28 #include "hw/pci/pci_device.h"
29 #include "hw/pci-host/astro.h"
30 #include "hw/pci-host/dino.h"
31 #include "hw/misc/lasi.h"
32 #include "hppa_hardware.h"
33 #include "qemu/units.h"
34 #include "qapi/error.h"
35 #include "net/net.h"
36 #include "qemu/log.h"
38 #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
40 #define HPA_POWER_BUTTON (FIRMWARE_END - 0x10)
41 static hwaddr soft_power_reg;
43 #define enable_lasi_lan() 0
45 static DeviceState *lasi_dev;
47 static void hppa_powerdown_req(Notifier *n, void *opaque)
49 uint32_t val;
51 val = ldl_be_phys(&address_space_memory, soft_power_reg);
52 if ((val >> 8) == 0) {
53 /* immediately shut down when under hardware control */
54 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
55 return;
58 /* clear bit 31 to indicate that the power switch was pressed. */
59 val &= ~1;
60 stl_be_phys(&address_space_memory, soft_power_reg, val);
63 static Notifier hppa_system_powerdown_notifier = {
64 .notify = hppa_powerdown_req
67 /* Fallback for unassigned PCI I/O operations. Avoids MCHK. */
68 static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
70 return 0;
73 static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
77 static const MemoryRegionOps hppa_pci_ignore_ops = {
78 .read = ignore_read,
79 .write = ignore_write,
80 .endianness = DEVICE_BIG_ENDIAN,
81 .valid = {
82 .min_access_size = 1,
83 .max_access_size = 8,
85 .impl = {
86 .min_access_size = 1,
87 .max_access_size = 8,
91 static ISABus *hppa_isa_bus(hwaddr addr)
93 ISABus *isa_bus;
94 qemu_irq *isa_irqs;
95 MemoryRegion *isa_region;
97 isa_region = g_new(MemoryRegion, 1);
98 memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
99 NULL, "isa-io", 0x800);
100 memory_region_add_subregion(get_system_memory(), addr, isa_region);
102 isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
103 &error_abort);
104 isa_irqs = i8259_init(isa_bus, NULL);
105 isa_bus_register_input_irqs(isa_bus, isa_irqs);
107 return isa_bus;
111 * Helper functions to emulate RTC clock and DebugOutputPort
113 static time_t rtc_ref;
115 static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
117 uint64_t val = 0;
119 switch (addr) {
120 case 0: /* RTC clock */
121 val = time(NULL);
122 val += rtc_ref;
123 break;
124 case 8: /* DebugOutputPort */
125 return 0xe9; /* readback */
127 return val;
130 static void io_cpu_write(void *opaque, hwaddr addr,
131 uint64_t val, unsigned size)
133 unsigned char ch;
134 Chardev *debugout;
136 switch (addr) {
137 case 0: /* RTC clock */
138 rtc_ref = val - time(NULL);
139 break;
140 case 8: /* DebugOutputPort */
141 ch = val;
142 debugout = serial_hd(0);
143 if (debugout) {
144 qemu_chr_fe_write_all(debugout->be, &ch, 1);
145 } else {
146 fprintf(stderr, "%c", ch);
148 break;
152 static const MemoryRegionOps hppa_io_helper_ops = {
153 .read = io_cpu_read,
154 .write = io_cpu_write,
155 .endianness = DEVICE_BIG_ENDIAN,
156 .valid = {
157 .min_access_size = 1,
158 .max_access_size = 8,
160 .impl = {
161 .min_access_size = 1,
162 .max_access_size = 8,
166 typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
168 static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
170 addr &= (0x10000000 - 1);
171 return addr;
174 static uint64_t translate_pa10(void *dummy, uint64_t addr)
176 return (uint32_t)addr;
179 static uint64_t translate_pa20(void *dummy, uint64_t addr)
181 return hppa_abs_to_phys_pa2_w0(addr);
184 static HPPACPU *cpu[HPPA_MAX_CPUS];
185 static uint64_t firmware_entry;
187 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
188 Error **errp)
190 fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
193 static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
194 hwaddr addr)
196 FWCfgState *fw_cfg;
197 uint64_t val;
198 const char qemu_version[] = QEMU_VERSION;
199 MachineClass *mc = MACHINE_GET_CLASS(ms);
200 int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
201 int len;
203 fw_cfg = fw_cfg_init_mem(addr, addr + 4);
204 fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
205 fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
206 fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
208 val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
209 fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
210 g_memdup(&val, sizeof(val)), sizeof(val));
212 val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
213 fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
214 g_memdup(&val, sizeof(val)), sizeof(val));
216 val = cpu_to_le64(btlb_entries);
217 fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
218 g_memdup(&val, sizeof(val)), sizeof(val));
220 len = strlen(mc->name) + 1;
221 fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
222 g_memdup(mc->name, len), len);
224 val = cpu_to_le64(soft_power_reg);
225 fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
226 g_memdup(&val, sizeof(val)), sizeof(val));
228 val = cpu_to_le64(CPU_HPA + 16);
229 fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
230 g_memdup(&val, sizeof(val)), sizeof(val));
232 val = cpu_to_le64(CPU_HPA + 24);
233 fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
234 g_memdup(&val, sizeof(val)), sizeof(val));
236 fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
237 qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
239 fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
240 g_memdup(qemu_version, sizeof(qemu_version)),
241 sizeof(qemu_version));
243 fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
245 return fw_cfg;
248 static LasiState *lasi_init(void)
250 DeviceState *dev;
252 dev = qdev_new(TYPE_LASI_CHIP);
253 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
255 return LASI_CHIP(dev);
258 static DinoState *dino_init(MemoryRegion *addr_space)
260 DeviceState *dev;
262 dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
263 object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
264 &error_fatal);
265 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
267 return DINO_PCI_HOST_BRIDGE(dev);
271 * Step 1: Create CPUs and Memory
273 static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
275 MemoryRegion *addr_space = get_system_memory();
276 unsigned int smp_cpus = machine->smp.cpus;
277 TranslateFn *translate;
278 MemoryRegion *cpu_region;
279 uint64_t ram_max;
281 /* Create CPUs. */
282 for (unsigned int i = 0; i < smp_cpus; i++) {
283 cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
287 * For now, treat address layout as if PSW_W is clear.
288 * TODO: create a proper hppa64 board model and load elf64 firmware.
290 if (hppa_is_pa20(&cpu[0]->env)) {
291 translate = translate_pa20;
292 ram_max = 0xf0000000; /* 3.75 GB (limited by 32-bit firmware) */
293 } else {
294 translate = translate_pa10;
295 ram_max = 0xf0000000; /* 3.75 GB (32-bit CPU) */
298 soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
300 for (unsigned int i = 0; i < smp_cpus; i++) {
301 g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
303 cpu_region = g_new(MemoryRegion, 1);
304 memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
305 cpu[i], name, 4);
306 memory_region_add_subregion(addr_space,
307 translate(NULL, CPU_HPA + i * 0x1000),
308 cpu_region);
311 /* RTC and DebugOutputPort on CPU #0 */
312 cpu_region = g_new(MemoryRegion, 1);
313 memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
314 cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
315 memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
316 cpu_region);
318 /* Main memory region. */
319 if (machine->ram_size > ram_max) {
320 info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
321 machine->ram_size = ram_max;
323 memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
325 return translate;
329 * Last creation step: Add SCSI discs, NICs, graphics & load firmware
331 static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
332 TranslateFn *translate)
334 const char *kernel_filename = machine->kernel_filename;
335 const char *kernel_cmdline = machine->kernel_cmdline;
336 const char *initrd_filename = machine->initrd_filename;
337 const char *firmware = machine->firmware;
338 MachineClass *mc = MACHINE_GET_CLASS(machine);
339 DeviceState *dev;
340 PCIDevice *pci_dev;
341 char *firmware_filename;
342 uint64_t firmware_low, firmware_high;
343 long size;
344 uint64_t kernel_entry = 0, kernel_low, kernel_high;
345 MemoryRegion *addr_space = get_system_memory();
346 MemoryRegion *rom_region;
347 unsigned int smp_cpus = machine->smp.cpus;
348 SysBusDevice *s;
350 /* SCSI disk setup. */
351 if (drive_get_max_bus(IF_SCSI) >= 0) {
352 dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
353 lsi53c8xx_handle_legacy_cmdline(dev);
356 /* Graphics setup. */
357 if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
358 vga_interface_created = true;
359 dev = qdev_new("artist");
360 s = SYS_BUS_DEVICE(dev);
361 sysbus_realize_and_unref(s, &error_fatal);
362 sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
363 sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
366 /* Network setup. */
367 if (lasi_dev) {
368 lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
369 qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
370 enable_lasi_lan());
373 pci_init_nic_devices(pci_bus, mc->default_nic);
375 /* BMC board: HP Powerbar SP2 Diva (with console only) */
376 pci_dev = pci_new(-1, "pci-serial");
377 if (!lasi_dev) {
378 /* bind default keyboard/serial to Diva card */
379 qdev_prop_set_chr(DEVICE(pci_dev), "chardev", serial_hd(0));
381 qdev_prop_set_uint8(DEVICE(pci_dev), "prog_if", 0);
382 pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
383 pci_config_set_vendor_id(pci_dev->config, PCI_VENDOR_ID_HP);
384 pci_config_set_device_id(pci_dev->config, 0x1048);
385 pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID], PCI_VENDOR_ID_HP);
386 pci_set_word(&pci_dev->config[PCI_SUBSYSTEM_ID], 0x1227); /* Powerbar */
388 /* create a second serial PCI card when running Astro */
389 if (serial_hd(1) && !lasi_dev) {
390 pci_dev = pci_new(-1, "pci-serial-4x");
391 qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(1));
392 qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(2));
393 qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(3));
394 qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(4));
395 pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
398 /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
399 if (!lasi_dev && machine->enable_graphics && defaults_enabled()) {
400 USBBus *usb_bus;
402 pci_create_simple(pci_bus, -1, "pci-ohci");
403 usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
404 &error_abort));
405 usb_create_simple(usb_bus, "usb-kbd");
406 usb_create_simple(usb_bus, "usb-mouse");
409 /* register power switch emulation */
410 qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
412 /* fw_cfg configuration interface */
413 create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
415 /* Load firmware. Given that this is not "real" firmware,
416 but one explicitly written for the emulation, we might as
417 well load it directly from an ELF image. Load the 64-bit
418 firmware on 64-bit machines by default if not specified
419 on command line. */
420 if (!qtest_enabled()) {
421 if (!firmware) {
422 firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
424 firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
425 if (firmware_filename == NULL) {
426 error_report("no firmware provided");
427 exit(1);
430 size = load_elf(firmware_filename, NULL, translate, NULL,
431 &firmware_entry, &firmware_low, &firmware_high, NULL,
432 true, EM_PARISC, 0, 0);
434 if (size < 0) {
435 error_report("could not load firmware '%s'", firmware_filename);
436 exit(1);
438 qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
439 "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
440 firmware_low, firmware_high, firmware_entry);
441 if (firmware_low < translate(NULL, FIRMWARE_START) ||
442 firmware_high >= translate(NULL, FIRMWARE_END)) {
443 error_report("Firmware overlaps with memory or IO space");
444 exit(1);
446 g_free(firmware_filename);
449 rom_region = g_new(MemoryRegion, 1);
450 memory_region_init_ram(rom_region, NULL, "firmware",
451 (FIRMWARE_END - FIRMWARE_START), &error_fatal);
452 memory_region_add_subregion(addr_space,
453 translate(NULL, FIRMWARE_START), rom_region);
455 /* Load kernel */
456 if (kernel_filename) {
457 size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
458 NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
459 true, EM_PARISC, 0, 0);
461 kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
463 if (size < 0) {
464 error_report("could not load kernel '%s'", kernel_filename);
465 exit(1);
467 qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
468 "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
469 ", size %" PRIu64 " kB\n",
470 kernel_low, kernel_high, kernel_entry, size / KiB);
472 if (kernel_cmdline) {
473 cpu[0]->env.gr[24] = 0x4000;
474 pstrcpy_targphys("cmdline", cpu[0]->env.gr[24],
475 TARGET_PAGE_SIZE, kernel_cmdline);
478 if (initrd_filename) {
479 ram_addr_t initrd_base;
480 int64_t initrd_size;
482 initrd_size = get_image_size(initrd_filename);
483 if (initrd_size < 0) {
484 error_report("could not load initial ram disk '%s'",
485 initrd_filename);
486 exit(1);
489 /* Load the initrd image high in memory.
490 Mirror the algorithm used by palo:
491 (1) Due to sign-extension problems and PDC,
492 put the initrd no higher than 1G.
493 (2) Reserve 64k for stack. */
494 initrd_base = MIN(machine->ram_size, 1 * GiB);
495 initrd_base = initrd_base - 64 * KiB;
496 initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
498 if (initrd_base < kernel_high) {
499 error_report("kernel and initial ram disk too large!");
500 exit(1);
503 load_image_targphys(initrd_filename, initrd_base, initrd_size);
504 cpu[0]->env.gr[23] = initrd_base;
505 cpu[0]->env.gr[22] = initrd_base + initrd_size;
509 if (!kernel_entry) {
510 /* When booting via firmware, tell firmware if we want interactive
511 * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
512 * or hard disc * (gr[24]='c').
514 kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
515 cpu[0]->env.gr[24] = machine->boot_config.order[0];
518 /* We jump to the firmware entry routine and pass the
519 * various parameters in registers. After firmware initialization,
520 * firmware will start the Linux kernel with ramdisk and cmdline.
522 cpu[0]->env.gr[26] = machine->ram_size;
523 cpu[0]->env.gr[25] = kernel_entry;
525 /* tell firmware how many SMP CPUs to present in inventory table */
526 cpu[0]->env.gr[21] = smp_cpus;
528 /* tell firmware fw_cfg port */
529 cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
533 * Create HP B160L workstation
535 static void machine_HP_B160L_init(MachineState *machine)
537 DeviceState *dev, *dino_dev;
538 MemoryRegion *addr_space = get_system_memory();
539 TranslateFn *translate;
540 ISABus *isa_bus;
541 PCIBus *pci_bus;
543 /* Create CPUs and RAM. */
544 translate = machine_HP_common_init_cpus(machine);
546 if (hppa_is_pa20(&cpu[0]->env)) {
547 error_report("The HP B160L workstation requires a 32-bit "
548 "CPU. Use '-machine C3700' instead.");
549 exit(1);
552 /* Init Lasi chip */
553 lasi_dev = DEVICE(lasi_init());
554 memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
555 sysbus_mmio_get_region(
556 SYS_BUS_DEVICE(lasi_dev), 0));
558 /* Init Dino (PCI host bus chip). */
559 dino_dev = DEVICE(dino_init(addr_space));
560 memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
561 sysbus_mmio_get_region(
562 SYS_BUS_DEVICE(dino_dev), 0));
563 pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
564 assert(pci_bus);
566 /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
567 isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
568 assert(isa_bus);
570 /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
571 serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
572 qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
573 serial_hd(0), DEVICE_BIG_ENDIAN);
575 serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
576 qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
577 serial_hd(1), DEVICE_BIG_ENDIAN);
579 /* Parallel port */
580 parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
581 qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
582 parallel_hds[0]);
584 /* PS/2 Keyboard/Mouse */
585 dev = qdev_new(TYPE_LASIPS2);
586 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
587 sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
588 qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
589 memory_region_add_subregion(addr_space,
590 translate(NULL, LASI_PS2KBD_HPA),
591 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
592 0));
593 memory_region_add_subregion(addr_space,
594 translate(NULL, LASI_PS2KBD_HPA + 0x100),
595 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
596 1));
598 /* Add SCSI discs, NICs, graphics & load firmware */
599 machine_HP_common_init_tail(machine, pci_bus, translate);
602 static AstroState *astro_init(void)
604 DeviceState *dev;
606 dev = qdev_new(TYPE_ASTRO_CHIP);
607 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
609 return ASTRO_CHIP(dev);
613 * Create HP C3700 workstation
615 static void machine_HP_C3700_init(MachineState *machine)
617 PCIBus *pci_bus;
618 AstroState *astro;
619 DeviceState *astro_dev;
620 MemoryRegion *addr_space = get_system_memory();
621 TranslateFn *translate;
623 /* Create CPUs and RAM. */
624 translate = machine_HP_common_init_cpus(machine);
626 if (!hppa_is_pa20(&cpu[0]->env)) {
627 error_report("The HP C3000 workstation requires a 64-bit CPU. "
628 "Use '-machine B160L' instead.");
629 exit(1);
632 /* Init Astro and the Elroys (PCI host bus chips). */
633 astro = astro_init();
634 astro_dev = DEVICE(astro);
635 memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
636 sysbus_mmio_get_region(
637 SYS_BUS_DEVICE(astro_dev), 0));
638 pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
639 assert(pci_bus);
641 /* Add SCSI discs, NICs, graphics & load firmware */
642 machine_HP_common_init_tail(machine, pci_bus, translate);
645 static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
647 unsigned int smp_cpus = ms->smp.cpus;
648 int i;
650 qemu_devices_reset(reason);
652 /* Start all CPUs at the firmware entry point.
653 * Monarch CPU will initialize firmware, secondary CPUs
654 * will enter a small idle loop and wait for rendevouz. */
655 for (i = 0; i < smp_cpus; i++) {
656 CPUState *cs = CPU(cpu[i]);
658 cpu_set_pc(cs, firmware_entry);
659 cpu[i]->env.psw = PSW_Q;
660 cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
662 cs->exception_index = -1;
663 cs->halted = 0;
666 /* already initialized by machine_hppa_init()? */
667 if (cpu[0]->env.gr[26] == ms->ram_size) {
668 return;
671 cpu[0]->env.gr[26] = ms->ram_size;
672 cpu[0]->env.gr[25] = 0; /* no firmware boot menu */
673 cpu[0]->env.gr[24] = 'c';
674 /* gr22/gr23 unused, no initrd while reboot. */
675 cpu[0]->env.gr[21] = smp_cpus;
676 /* tell firmware fw_cfg port */
677 cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
680 static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
682 CPUState *cs;
684 CPU_FOREACH(cs) {
685 cpu_interrupt(cs, CPU_INTERRUPT_NMI);
689 static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
691 static const char * const valid_cpu_types[] = {
692 TYPE_HPPA_CPU,
693 NULL
695 MachineClass *mc = MACHINE_CLASS(oc);
696 NMIClass *nc = NMI_CLASS(oc);
698 mc->desc = "HP B160L workstation";
699 mc->default_cpu_type = TYPE_HPPA_CPU;
700 mc->valid_cpu_types = valid_cpu_types;
701 mc->init = machine_HP_B160L_init;
702 mc->reset = hppa_machine_reset;
703 mc->block_default_type = IF_SCSI;
704 mc->max_cpus = HPPA_MAX_CPUS;
705 mc->default_cpus = 1;
706 mc->is_default = true;
707 mc->default_ram_size = 512 * MiB;
708 mc->default_boot_order = "cd";
709 mc->default_ram_id = "ram";
710 mc->default_nic = "tulip";
712 nc->nmi_monitor_handler = hppa_nmi;
715 static const TypeInfo HP_B160L_machine_init_typeinfo = {
716 .name = MACHINE_TYPE_NAME("B160L"),
717 .parent = TYPE_MACHINE,
718 .class_init = HP_B160L_machine_init_class_init,
719 .interfaces = (InterfaceInfo[]) {
720 { TYPE_NMI },
725 static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
727 static const char * const valid_cpu_types[] = {
728 TYPE_HPPA64_CPU,
729 NULL
731 MachineClass *mc = MACHINE_CLASS(oc);
732 NMIClass *nc = NMI_CLASS(oc);
734 mc->desc = "HP C3700 workstation";
735 mc->default_cpu_type = TYPE_HPPA64_CPU;
736 mc->valid_cpu_types = valid_cpu_types;
737 mc->init = machine_HP_C3700_init;
738 mc->reset = hppa_machine_reset;
739 mc->block_default_type = IF_SCSI;
740 mc->max_cpus = HPPA_MAX_CPUS;
741 mc->default_cpus = 1;
742 mc->is_default = false;
743 mc->default_ram_size = 1024 * MiB;
744 mc->default_boot_order = "cd";
745 mc->default_ram_id = "ram";
746 mc->default_nic = "tulip";
748 nc->nmi_monitor_handler = hppa_nmi;
751 static const TypeInfo HP_C3700_machine_init_typeinfo = {
752 .name = MACHINE_TYPE_NAME("C3700"),
753 .parent = TYPE_MACHINE,
754 .class_init = HP_C3700_machine_init_class_init,
755 .interfaces = (InterfaceInfo[]) {
756 { TYPE_NMI },
761 static void hppa_machine_init_register_types(void)
763 type_register_static(&HP_B160L_machine_init_typeinfo);
764 type_register_static(&HP_C3700_machine_init_typeinfo);
767 type_init(hppa_machine_init_register_types)