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.
8 #include "qemu/osdep.h"
9 #include "qemu/datadir.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/runstate.h"
17 #include "hw/rtc/mc146818rtc.h"
18 #include "hw/timer/i8254.h"
19 #include "hw/char/serial.h"
20 #include "hw/char/parallel.h"
21 #include "hw/intc/i8259.h"
22 #include "hw/input/lasips2.h"
23 #include "hw/net/lasi_82596.h"
26 #include "hw/pci/pci.h"
27 #include "hw/pci/pci_device.h"
28 #include "hw/pci-host/astro.h"
29 #include "hw/pci-host/dino.h"
30 #include "hw/misc/lasi.h"
31 #include "hppa_hardware.h"
32 #include "qemu/units.h"
33 #include "qapi/error.h"
37 #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
39 /* Power button address at &PAGE0->pad[4] */
40 #define HPA_POWER_BUTTON (0x40 + 4 * sizeof(uint32_t))
42 #define enable_lasi_lan() 0
44 static DeviceState
*lasi_dev
;
46 static void hppa_powerdown_req(Notifier
*n
, void *opaque
)
48 hwaddr soft_power_reg
= HPA_POWER_BUTTON
;
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
);
58 /* clear bit 31 to indicate that the power switch was pressed. */
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
)
73 static void ignore_write(void *opaque
, hwaddr addr
, uint64_t v
, unsigned size
)
77 static const MemoryRegionOps hppa_pci_ignore_ops
= {
79 .write
= ignore_write
,
80 .endianness
= DEVICE_BIG_ENDIAN
,
91 static ISABus
*hppa_isa_bus(hwaddr addr
)
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
,
104 isa_irqs
= i8259_init(isa_bus
, NULL
);
105 isa_bus_register_input_irqs(isa_bus
, isa_irqs
);
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
)
120 case 0: /* RTC clock */
124 case 8: /* DebugOutputPort */
125 return 0xe9; /* readback */
130 static void io_cpu_write(void *opaque
, hwaddr addr
,
131 uint64_t val
, unsigned size
)
137 case 0: /* RTC clock */
138 rtc_ref
= val
- time(NULL
);
140 case 8: /* DebugOutputPort */
142 debugout
= serial_hd(0);
144 qemu_chr_fe_write_all(debugout
->be
, &ch
, 1);
146 fprintf(stderr
, "%c", ch
);
152 static const MemoryRegionOps hppa_io_helper_ops
= {
154 .write
= io_cpu_write
,
155 .endianness
= DEVICE_BIG_ENDIAN
,
157 .min_access_size
= 1,
158 .max_access_size
= 8,
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);
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
,
190 fw_cfg_modify_i16(opaque
, FW_CFG_BOOT_DEVICE
, boot_device
[0]);
193 static FWCfgState
*create_fw_cfg(MachineState
*ms
, PCIBus
*pci_bus
,
198 const char qemu_version
[] = QEMU_VERSION
;
199 MachineClass
*mc
= MACHINE_GET_CLASS(ms
);
200 int btlb_entries
= HPPA_BTLB_ENTRIES(&cpu
[0]->env
);
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(HPA_POWER_BUTTON
);
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
);
248 static LasiState
*lasi_init(void)
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
)
262 dev
= qdev_new(TYPE_DINO_PCI_HOST_BRIDGE
);
263 object_property_set_link(OBJECT(dev
), "memory-as", OBJECT(addr_space
),
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
;
281 for (unsigned int i
= 0; i
< smp_cpus
; i
++) {
282 cpu
[i
] = HPPA_CPU(cpu_create(machine
->cpu_type
));
286 * For now, treat address layout as if PSW_W is clear.
287 * TODO: create a proper hppa64 board model and load elf64 firmware.
289 if (hppa_is_pa20(&cpu
[0]->env
)) {
290 translate
= translate_pa20
;
292 translate
= translate_pa10
;
295 for (unsigned int i
= 0; i
< smp_cpus
; i
++) {
296 g_autofree
char *name
= g_strdup_printf("cpu%u-io-eir", i
);
298 cpu_region
= g_new(MemoryRegion
, 1);
299 memory_region_init_io(cpu_region
, OBJECT(cpu
[i
]), &hppa_io_eir_ops
,
301 memory_region_add_subregion(addr_space
,
302 translate(NULL
, CPU_HPA
+ i
* 0x1000),
306 /* RTC and DebugOutputPort on CPU #0 */
307 cpu_region
= g_new(MemoryRegion
, 1);
308 memory_region_init_io(cpu_region
, OBJECT(cpu
[0]), &hppa_io_helper_ops
,
309 cpu
[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
310 memory_region_add_subregion(addr_space
, translate(NULL
, CPU_HPA
+ 16),
313 /* Main memory region. */
314 if (machine
->ram_size
> 3 * GiB
) {
315 error_report("RAM size is currently restricted to 3GB");
318 memory_region_add_subregion_overlap(addr_space
, 0, machine
->ram
, -1);
324 * Last creation step: Add SCSI discs, NICs, graphics & load firmware
326 static void machine_HP_common_init_tail(MachineState
*machine
, PCIBus
*pci_bus
,
327 TranslateFn
*translate
)
329 const char *kernel_filename
= machine
->kernel_filename
;
330 const char *kernel_cmdline
= machine
->kernel_cmdline
;
331 const char *initrd_filename
= machine
->initrd_filename
;
332 MachineClass
*mc
= MACHINE_GET_CLASS(machine
);
335 char *firmware_filename
;
336 uint64_t firmware_low
, firmware_high
;
338 uint64_t kernel_entry
= 0, kernel_low
, kernel_high
;
339 MemoryRegion
*addr_space
= get_system_memory();
340 MemoryRegion
*rom_region
;
342 unsigned int smp_cpus
= machine
->smp
.cpus
;
345 /* SCSI disk setup. */
346 dev
= DEVICE(pci_create_simple(pci_bus
, -1, "lsi53c895a"));
347 lsi53c8xx_handle_legacy_cmdline(dev
);
349 /* Graphics setup. */
350 if (machine
->enable_graphics
&& vga_interface_type
!= VGA_NONE
) {
351 vga_interface_created
= true;
352 dev
= qdev_new("artist");
353 s
= SYS_BUS_DEVICE(dev
);
354 sysbus_realize_and_unref(s
, &error_fatal
);
355 sysbus_mmio_map(s
, 0, translate(NULL
, LASI_GFX_HPA
));
356 sysbus_mmio_map(s
, 1, translate(NULL
, ARTIST_FB_ADDR
));
360 if (enable_lasi_lan()) {
361 lasi_82596_init(addr_space
, translate(NULL
, LASI_LAN_HPA
),
362 qdev_get_gpio_in(lasi_dev
, LASI_IRQ_LAN_HPA
));
365 for (i
= 0; i
< nb_nics
; i
++) {
366 if (!enable_lasi_lan()) {
367 pci_nic_init_nofail(&nd_table
[i
], pci_bus
, mc
->default_nic
, NULL
);
371 /* BMC board: HP Powerbar SP2 Diva (with console only) */
372 pci_dev
= pci_new(-1, "pci-serial");
374 /* bind default keyboard/serial to Diva card */
375 qdev_prop_set_chr(DEVICE(pci_dev
), "chardev", serial_hd(0));
377 qdev_prop_set_uint8(DEVICE(pci_dev
), "prog_if", 0);
378 pci_realize_and_unref(pci_dev
, pci_bus
, &error_fatal
);
379 pci_config_set_vendor_id(pci_dev
->config
, PCI_VENDOR_ID_HP
);
380 pci_config_set_device_id(pci_dev
->config
, 0x1048);
381 pci_set_word(&pci_dev
->config
[PCI_SUBSYSTEM_VENDOR_ID
], PCI_VENDOR_ID_HP
);
382 pci_set_word(&pci_dev
->config
[PCI_SUBSYSTEM_ID
], 0x1227); /* Powerbar */
384 /* create a second serial PCI card when running Astro */
386 pci_dev
= pci_new(-1, "pci-serial-4x");
387 qdev_prop_set_chr(DEVICE(pci_dev
), "chardev1", serial_hd(1));
388 qdev_prop_set_chr(DEVICE(pci_dev
), "chardev2", serial_hd(2));
389 qdev_prop_set_chr(DEVICE(pci_dev
), "chardev3", serial_hd(3));
390 qdev_prop_set_chr(DEVICE(pci_dev
), "chardev4", serial_hd(4));
391 pci_realize_and_unref(pci_dev
, pci_bus
, &error_fatal
);
394 /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
395 if (!lasi_dev
&& machine
->enable_graphics
) {
396 pci_create_simple(pci_bus
, -1, "pci-ohci");
397 usb_create_simple(usb_bus_find(-1), "usb-kbd");
398 usb_create_simple(usb_bus_find(-1), "usb-mouse");
401 /* register power switch emulation */
402 qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier
);
404 /* fw_cfg configuration interface */
405 create_fw_cfg(machine
, pci_bus
, translate(NULL
, FW_CFG_IO_BASE
));
407 /* Load firmware. Given that this is not "real" firmware,
408 but one explicitly written for the emulation, we might as
409 well load it directly from an ELF image. */
410 firmware_filename
= qemu_find_file(QEMU_FILE_TYPE_BIOS
,
411 machine
->firmware
?: "hppa-firmware.img");
412 if (firmware_filename
== NULL
) {
413 error_report("no firmware provided");
417 size
= load_elf(firmware_filename
, NULL
, translate
, NULL
,
418 &firmware_entry
, &firmware_low
, &firmware_high
, NULL
,
419 true, EM_PARISC
, 0, 0);
422 error_report("could not load firmware '%s'", firmware_filename
);
425 qemu_log_mask(CPU_LOG_PAGE
, "Firmware loaded at 0x%08" PRIx64
426 "-0x%08" PRIx64
", entry at 0x%08" PRIx64
".\n",
427 firmware_low
, firmware_high
, firmware_entry
);
428 if (firmware_low
< translate(NULL
, FIRMWARE_START
) ||
429 firmware_high
>= translate(NULL
, FIRMWARE_END
)) {
430 error_report("Firmware overlaps with memory or IO space");
433 g_free(firmware_filename
);
435 rom_region
= g_new(MemoryRegion
, 1);
436 memory_region_init_ram(rom_region
, NULL
, "firmware",
437 (FIRMWARE_END
- FIRMWARE_START
), &error_fatal
);
438 memory_region_add_subregion(addr_space
,
439 translate(NULL
, FIRMWARE_START
), rom_region
);
442 if (kernel_filename
) {
443 size
= load_elf(kernel_filename
, NULL
, linux_kernel_virt_to_phys
,
444 NULL
, &kernel_entry
, &kernel_low
, &kernel_high
, NULL
,
445 true, EM_PARISC
, 0, 0);
447 kernel_entry
= linux_kernel_virt_to_phys(NULL
, kernel_entry
);
450 error_report("could not load kernel '%s'", kernel_filename
);
453 qemu_log_mask(CPU_LOG_PAGE
, "Kernel loaded at 0x%08" PRIx64
454 "-0x%08" PRIx64
", entry at 0x%08" PRIx64
455 ", size %" PRIu64
" kB\n",
456 kernel_low
, kernel_high
, kernel_entry
, size
/ KiB
);
458 if (kernel_cmdline
) {
459 cpu
[0]->env
.gr
[24] = 0x4000;
460 pstrcpy_targphys("cmdline", cpu
[0]->env
.gr
[24],
461 TARGET_PAGE_SIZE
, kernel_cmdline
);
464 if (initrd_filename
) {
465 ram_addr_t initrd_base
;
468 initrd_size
= get_image_size(initrd_filename
);
469 if (initrd_size
< 0) {
470 error_report("could not load initial ram disk '%s'",
475 /* Load the initrd image high in memory.
476 Mirror the algorithm used by palo:
477 (1) Due to sign-extension problems and PDC,
478 put the initrd no higher than 1G.
479 (2) Reserve 64k for stack. */
480 initrd_base
= MIN(machine
->ram_size
, 1 * GiB
);
481 initrd_base
= initrd_base
- 64 * KiB
;
482 initrd_base
= (initrd_base
- initrd_size
) & TARGET_PAGE_MASK
;
484 if (initrd_base
< kernel_high
) {
485 error_report("kernel and initial ram disk too large!");
489 load_image_targphys(initrd_filename
, initrd_base
, initrd_size
);
490 cpu
[0]->env
.gr
[23] = initrd_base
;
491 cpu
[0]->env
.gr
[22] = initrd_base
+ initrd_size
;
496 /* When booting via firmware, tell firmware if we want interactive
497 * mode (kernel_entry=1), and to boot from CD (gr[24]='d')
498 * or hard disc * (gr[24]='c').
500 kernel_entry
= machine
->boot_config
.has_menu
? machine
->boot_config
.menu
: 0;
501 cpu
[0]->env
.gr
[24] = machine
->boot_config
.order
[0];
504 /* We jump to the firmware entry routine and pass the
505 * various parameters in registers. After firmware initialization,
506 * firmware will start the Linux kernel with ramdisk and cmdline.
508 cpu
[0]->env
.gr
[26] = machine
->ram_size
;
509 cpu
[0]->env
.gr
[25] = kernel_entry
;
511 /* tell firmware how many SMP CPUs to present in inventory table */
512 cpu
[0]->env
.gr
[21] = smp_cpus
;
514 /* tell firmware fw_cfg port */
515 cpu
[0]->env
.gr
[19] = FW_CFG_IO_BASE
;
519 * Create HP B160L workstation
521 static void machine_HP_B160L_init(MachineState
*machine
)
523 DeviceState
*dev
, *dino_dev
;
524 MemoryRegion
*addr_space
= get_system_memory();
525 TranslateFn
*translate
;
529 /* Create CPUs and RAM. */
530 translate
= machine_HP_common_init_cpus(machine
);
532 if (hppa_is_pa20(&cpu
[0]->env
)) {
533 error_report("The HP B160L workstation requires a 32-bit "
534 "CPU. Use '-machine C3700' instead.");
539 lasi_dev
= DEVICE(lasi_init());
540 memory_region_add_subregion(addr_space
, translate(NULL
, LASI_HPA
),
541 sysbus_mmio_get_region(
542 SYS_BUS_DEVICE(lasi_dev
), 0));
544 /* Init Dino (PCI host bus chip). */
545 dino_dev
= DEVICE(dino_init(addr_space
));
546 memory_region_add_subregion(addr_space
, translate(NULL
, DINO_HPA
),
547 sysbus_mmio_get_region(
548 SYS_BUS_DEVICE(dino_dev
), 0));
549 pci_bus
= PCI_BUS(qdev_get_child_bus(dino_dev
, "pci"));
552 /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
553 isa_bus
= hppa_isa_bus(translate(NULL
, IDE_HPA
));
556 /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
557 serial_mm_init(addr_space
, translate(NULL
, LASI_UART_HPA
+ 0x800), 0,
558 qdev_get_gpio_in(lasi_dev
, LASI_IRQ_UART_HPA
), 7272727 / 16,
559 serial_hd(0), DEVICE_BIG_ENDIAN
);
561 serial_mm_init(addr_space
, translate(NULL
, DINO_UART_HPA
+ 0x800), 0,
562 qdev_get_gpio_in(dino_dev
, DINO_IRQ_RS232INT
), 7272727 / 16,
563 serial_hd(1), DEVICE_BIG_ENDIAN
);
566 parallel_mm_init(addr_space
, translate(NULL
, LASI_LPT_HPA
+ 0x800), 0,
567 qdev_get_gpio_in(lasi_dev
, LASI_IRQ_LAN_HPA
),
570 /* PS/2 Keyboard/Mouse */
571 dev
= qdev_new(TYPE_LASIPS2
);
572 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
573 sysbus_connect_irq(SYS_BUS_DEVICE(dev
), 0,
574 qdev_get_gpio_in(lasi_dev
, LASI_IRQ_PS2KBD_HPA
));
575 memory_region_add_subregion(addr_space
,
576 translate(NULL
, LASI_PS2KBD_HPA
),
577 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev
),
579 memory_region_add_subregion(addr_space
,
580 translate(NULL
, LASI_PS2KBD_HPA
+ 0x100),
581 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev
),
584 /* Add SCSI discs, NICs, graphics & load firmware */
585 machine_HP_common_init_tail(machine
, pci_bus
, translate
);
588 static AstroState
*astro_init(void)
592 dev
= qdev_new(TYPE_ASTRO_CHIP
);
593 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
595 return ASTRO_CHIP(dev
);
599 * Create HP C3700 workstation
601 static void machine_HP_C3700_init(MachineState
*machine
)
605 DeviceState
*astro_dev
;
606 MemoryRegion
*addr_space
= get_system_memory();
607 TranslateFn
*translate
;
609 /* Create CPUs and RAM. */
610 translate
= machine_HP_common_init_cpus(machine
);
612 if (!hppa_is_pa20(&cpu
[0]->env
)) {
613 error_report("The HP C3000 workstation requires a 64-bit CPU. "
614 "Use '-machine B160L' instead.");
618 /* Init Astro and the Elroys (PCI host bus chips). */
619 astro
= astro_init();
620 astro_dev
= DEVICE(astro
);
621 memory_region_add_subregion(addr_space
, translate(NULL
, ASTRO_HPA
),
622 sysbus_mmio_get_region(
623 SYS_BUS_DEVICE(astro_dev
), 0));
624 pci_bus
= PCI_BUS(qdev_get_child_bus(DEVICE(astro
->elroy
[0]), "pci"));
627 /* Add SCSI discs, NICs, graphics & load firmware */
628 machine_HP_common_init_tail(machine
, pci_bus
, translate
);
631 static void hppa_machine_reset(MachineState
*ms
, ShutdownCause reason
)
633 unsigned int smp_cpus
= ms
->smp
.cpus
;
636 qemu_devices_reset(reason
);
638 /* Start all CPUs at the firmware entry point.
639 * Monarch CPU will initialize firmware, secondary CPUs
640 * will enter a small idle loop and wait for rendevouz. */
641 for (i
= 0; i
< smp_cpus
; i
++) {
642 CPUState
*cs
= CPU(cpu
[i
]);
644 cpu_set_pc(cs
, firmware_entry
);
645 cpu
[i
]->env
.psw
= PSW_Q
;
646 cpu
[i
]->env
.gr
[5] = CPU_HPA
+ i
* 0x1000;
648 cs
->exception_index
= -1;
652 /* already initialized by machine_hppa_init()? */
653 if (cpu
[0]->env
.gr
[26] == ms
->ram_size
) {
657 cpu
[0]->env
.gr
[26] = ms
->ram_size
;
658 cpu
[0]->env
.gr
[25] = 0; /* no firmware boot menu */
659 cpu
[0]->env
.gr
[24] = 'c';
660 /* gr22/gr23 unused, no initrd while reboot. */
661 cpu
[0]->env
.gr
[21] = smp_cpus
;
662 /* tell firmware fw_cfg port */
663 cpu
[0]->env
.gr
[19] = FW_CFG_IO_BASE
;
666 static void hppa_nmi(NMIState
*n
, int cpu_index
, Error
**errp
)
671 cpu_interrupt(cs
, CPU_INTERRUPT_NMI
);
675 static void HP_B160L_machine_init_class_init(ObjectClass
*oc
, void *data
)
677 static const char * const valid_cpu_types
[] = {
681 MachineClass
*mc
= MACHINE_CLASS(oc
);
682 NMIClass
*nc
= NMI_CLASS(oc
);
684 mc
->desc
= "HP B160L workstation";
685 mc
->default_cpu_type
= TYPE_HPPA_CPU
;
686 mc
->valid_cpu_types
= valid_cpu_types
;
687 mc
->init
= machine_HP_B160L_init
;
688 mc
->reset
= hppa_machine_reset
;
689 mc
->block_default_type
= IF_SCSI
;
690 mc
->max_cpus
= HPPA_MAX_CPUS
;
691 mc
->default_cpus
= 1;
692 mc
->is_default
= true;
693 mc
->default_ram_size
= 512 * MiB
;
694 mc
->default_boot_order
= "cd";
695 mc
->default_ram_id
= "ram";
696 mc
->default_nic
= "tulip";
698 nc
->nmi_monitor_handler
= hppa_nmi
;
701 static const TypeInfo HP_B160L_machine_init_typeinfo
= {
702 .name
= MACHINE_TYPE_NAME("B160L"),
703 .parent
= TYPE_MACHINE
,
704 .class_init
= HP_B160L_machine_init_class_init
,
705 .interfaces
= (InterfaceInfo
[]) {
711 static void HP_C3700_machine_init_class_init(ObjectClass
*oc
, void *data
)
713 static const char * const valid_cpu_types
[] = {
717 MachineClass
*mc
= MACHINE_CLASS(oc
);
718 NMIClass
*nc
= NMI_CLASS(oc
);
720 mc
->desc
= "HP C3700 workstation";
721 mc
->default_cpu_type
= TYPE_HPPA64_CPU
;
722 mc
->valid_cpu_types
= valid_cpu_types
;
723 mc
->init
= machine_HP_C3700_init
;
724 mc
->reset
= hppa_machine_reset
;
725 mc
->block_default_type
= IF_SCSI
;
726 mc
->max_cpus
= HPPA_MAX_CPUS
;
727 mc
->default_cpus
= 1;
728 mc
->is_default
= false;
729 mc
->default_ram_size
= 1024 * MiB
;
730 mc
->default_boot_order
= "cd";
731 mc
->default_ram_id
= "ram";
732 mc
->default_nic
= "tulip";
734 nc
->nmi_monitor_handler
= hppa_nmi
;
737 static const TypeInfo HP_C3700_machine_init_typeinfo
= {
738 .name
= MACHINE_TYPE_NAME("C3700"),
739 .parent
= TYPE_MACHINE
,
740 .class_init
= HP_C3700_machine_init_class_init
,
741 .interfaces
= (InterfaceInfo
[]) {
747 static void hppa_machine_init_register_types(void)
749 type_register_static(&HP_B160L_machine_init_typeinfo
);
750 type_register_static(&HP_C3700_machine_init_typeinfo
);
753 type_init(hppa_machine_init_register_types
)