xref: /qemu/hw/hppa/machine.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
1 /*
2  * QEMU HPPA hardware system emulator.
3  * (C) Copyright 2018-2023 Helge Deller <deller@gmx.de>
4  *
5  * This work is licensed under the GNU GPL license version 2 or later.
6  */
7 
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 "exec/target_page.h"
15 #include "system/reset.h"
16 #include "system/system.h"
17 #include "system/qtest.h"
18 #include "system/runstate.h"
19 #include "hw/rtc/mc146818rtc.h"
20 #include "hw/timer/i8254.h"
21 #include "hw/char/serial-mm.h"
22 #include "hw/char/parallel.h"
23 #include "hw/intc/i8259.h"
24 #include "hw/input/lasips2.h"
25 #include "hw/net/lasi_82596.h"
26 #include "hw/nmi.h"
27 #include "hw/usb.h"
28 #include "hw/pci/pci.h"
29 #include "hw/pci/pci_device.h"
30 #include "hw/pci-host/astro.h"
31 #include "hw/pci-host/dino.h"
32 #include "hw/misc/lasi.h"
33 #include "hppa_hardware.h"
34 #include "qemu/units.h"
35 #include "qapi/error.h"
36 #include "net/net.h"
37 #include "qemu/log.h"
38 
39 #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
40 
41 #define HPA_POWER_BUTTON        (FIRMWARE_END - 0x10)
42 static hwaddr soft_power_reg;
43 
44 #define enable_lasi_lan()       0
45 
46 static DeviceState *lasi_dev;
47 
hppa_powerdown_req(Notifier * n,void * opaque)48 static void hppa_powerdown_req(Notifier *n, void *opaque)
49 {
50     uint32_t val;
51 
52     val = ldl_be_phys(&address_space_memory, soft_power_reg);
53     if ((val >> 8) == 0) {
54         /* immediately shut down when under hardware control */
55         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
56         return;
57     }
58 
59     /* clear bit 31 to indicate that the power switch was pressed. */
60     val &= ~1;
61     stl_be_phys(&address_space_memory, soft_power_reg, val);
62 }
63 
64 static Notifier hppa_system_powerdown_notifier = {
65     .notify = hppa_powerdown_req
66 };
67 
68 /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
ignore_read(void * opaque,hwaddr addr,unsigned size)69 static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
70 {
71     return 0;
72 }
73 
ignore_write(void * opaque,hwaddr addr,uint64_t v,unsigned size)74 static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
75 {
76 }
77 
78 static const MemoryRegionOps hppa_pci_ignore_ops = {
79     .read = ignore_read,
80     .write = ignore_write,
81     .endianness = DEVICE_BIG_ENDIAN,
82     .valid = {
83         .min_access_size = 1,
84         .max_access_size = 8,
85     },
86     .impl = {
87         .min_access_size = 1,
88         .max_access_size = 8,
89     },
90 };
91 
hppa_isa_bus(hwaddr addr)92 static ISABus *hppa_isa_bus(hwaddr addr)
93 {
94     ISABus *isa_bus;
95     qemu_irq *isa_irqs;
96     MemoryRegion *isa_region;
97 
98     isa_region = g_new(MemoryRegion, 1);
99     memory_region_init_io(isa_region, NULL, &hppa_pci_ignore_ops,
100                           NULL, "isa-io", 0x800);
101     memory_region_add_subregion(get_system_memory(), addr, isa_region);
102 
103     isa_bus = isa_bus_new(NULL, get_system_memory(), isa_region,
104                           &error_abort);
105     isa_irqs = i8259_init(isa_bus, NULL);
106     isa_bus_register_input_irqs(isa_bus, isa_irqs);
107 
108     return isa_bus;
109 }
110 
111 /*
112  * Helper functions to emulate RTC clock and DebugOutputPort
113  */
114 static time_t rtc_ref;
115 
io_cpu_read(void * opaque,hwaddr addr,unsigned size)116 static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
117 {
118     uint64_t val = 0;
119 
120     switch (addr) {
121     case 0:             /* RTC clock */
122         val = time(NULL);
123         val += rtc_ref;
124         break;
125     case 8:             /* DebugOutputPort */
126         return 0xe9;    /* readback */
127     }
128     return val;
129 }
130 
io_cpu_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)131 static void io_cpu_write(void *opaque, hwaddr addr,
132                          uint64_t val, unsigned size)
133 {
134     unsigned char ch;
135     Chardev *debugout;
136 
137     switch (addr) {
138     case 0:             /* RTC clock */
139         rtc_ref = val - time(NULL);
140         break;
141     case 8:             /* DebugOutputPort */
142         ch = val;
143         debugout = serial_hd(0);
144         if (debugout) {
145             qemu_chr_fe_write_all(debugout->be, &ch, 1);
146         } else {
147             fprintf(stderr, "%c", ch);
148         }
149         break;
150     }
151 }
152 
153 static const MemoryRegionOps hppa_io_helper_ops = {
154     .read = io_cpu_read,
155     .write = io_cpu_write,
156     .endianness = DEVICE_BIG_ENDIAN,
157     .valid = {
158         .min_access_size = 1,
159         .max_access_size = 8,
160     },
161     .impl = {
162         .min_access_size = 1,
163         .max_access_size = 8,
164     },
165 };
166 
167 typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
168 
linux_kernel_virt_to_phys(void * opaque,uint64_t addr)169 static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
170 {
171     addr &= (0x10000000 - 1);
172     return addr;
173 }
174 
translate_pa10(void * dummy,uint64_t addr)175 static uint64_t translate_pa10(void *dummy, uint64_t addr)
176 {
177     return (uint32_t)addr;
178 }
179 
translate_pa20(void * dummy,uint64_t addr)180 static uint64_t translate_pa20(void *dummy, uint64_t addr)
181 {
182     return hppa_abs_to_phys_pa2_w0(addr);
183 }
184 
185 static HPPACPU *cpu[HPPA_MAX_CPUS];
186 static uint64_t firmware_entry;
187 
fw_cfg_boot_set(void * opaque,const char * boot_device,Error ** errp)188 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
189                             Error **errp)
190 {
191     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
192 }
193 
create_fw_cfg(MachineState * ms,PCIBus * pci_bus,hwaddr addr)194 static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
195                                  hwaddr addr)
196 {
197     FWCfgState *fw_cfg;
198     uint64_t val;
199     const char qemu_version[] = QEMU_VERSION;
200     MachineClass *mc = MACHINE_GET_CLASS(ms);
201     int btlb_entries = HPPA_BTLB_ENTRIES(&cpu[0]->env);
202     int len;
203 
204     fw_cfg = fw_cfg_init_mem(addr, addr + 4);
205     fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus);
206     fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS);
207     fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ms->ram_size);
208 
209     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
210     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
211                     g_memdup2(&val, sizeof(val)), sizeof(val));
212 
213     val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
214     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
215                     g_memdup2(&val, sizeof(val)), sizeof(val));
216 
217     val = cpu_to_le64(btlb_entries);
218     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
219                     g_memdup2(&val, sizeof(val)), sizeof(val));
220 
221     len = strlen(mc->name) + 1;
222     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
223                     g_memdup2(mc->name, len), len);
224 
225     val = cpu_to_le64(soft_power_reg);
226     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
227                     g_memdup2(&val, sizeof(val)), sizeof(val));
228 
229     val = cpu_to_le64(CPU_HPA + 16);
230     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
231                     g_memdup2(&val, sizeof(val)), sizeof(val));
232 
233     val = cpu_to_le64(CPU_HPA + 24);
234     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
235                     g_memdup2(&val, sizeof(val)), sizeof(val));
236 
237     fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_config.order[0]);
238     qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
239 
240     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
241                     g_memdup2(qemu_version, sizeof(qemu_version)),
242                     sizeof(qemu_version));
243 
244     pci_bus_add_fw_cfg_extra_pci_roots(fw_cfg, pci_bus, &error_abort);
245 
246     return fw_cfg;
247 }
248 
lasi_init(void)249 static LasiState *lasi_init(void)
250 {
251     DeviceState *dev;
252 
253     dev = qdev_new(TYPE_LASI_CHIP);
254     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
255 
256     return LASI_CHIP(dev);
257 }
258 
dino_init(MemoryRegion * addr_space)259 static DinoState *dino_init(MemoryRegion *addr_space)
260 {
261     DeviceState *dev;
262 
263     dev = qdev_new(TYPE_DINO_PCI_HOST_BRIDGE);
264     object_property_set_link(OBJECT(dev), "memory-as", OBJECT(addr_space),
265                              &error_fatal);
266     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
267 
268     return DINO_PCI_HOST_BRIDGE(dev);
269 }
270 
271 /*
272  * Step 1: Create CPUs and Memory
273  */
machine_HP_common_init_cpus(MachineState * machine)274 static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
275 {
276     MemoryRegion *addr_space = get_system_memory();
277     unsigned int smp_cpus = machine->smp.cpus;
278     TranslateFn *translate;
279     MemoryRegion *cpu_region;
280     uint64_t ram_max;
281 
282     /* Create CPUs.  */
283     for (unsigned int i = 0; i < smp_cpus; i++) {
284         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
285     }
286 
287     /* Initialize memory */
288     if (hppa_is_pa20(&cpu[0]->env)) {
289         translate = translate_pa20;
290         ram_max = 256 * GiB;       /* like HP rp8440 */
291     } else {
292         translate = translate_pa10;
293         ram_max = FIRMWARE_START;  /* 3.75 GB (32-bit CPU) */
294     }
295 
296     soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
297 
298     for (unsigned int i = 0; i < smp_cpus; i++) {
299         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
300 
301         cpu_region = g_new(MemoryRegion, 1);
302         memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
303                               cpu[i], name, 4);
304         memory_region_add_subregion(addr_space,
305                                     translate(NULL, CPU_HPA + i * 0x1000),
306                                     cpu_region);
307     }
308 
309     /* RTC and DebugOutputPort on CPU #0 */
310     cpu_region = g_new(MemoryRegion, 1);
311     memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
312                           cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
313     memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
314                                 cpu_region);
315 
316     /* Main memory region. */
317     if (machine->ram_size > ram_max) {
318         info_report("Max RAM size limited to %" PRIu64 " MB", ram_max / MiB);
319         machine->ram_size = ram_max;
320     }
321     if (machine->ram_size <= FIRMWARE_START) {
322         /* contiguous memory up to 3.75 GB RAM */
323         memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
324     } else {
325         /* non-contiguous: Memory above 3.75 GB is mapped at RAM_MAP_HIGH */
326         MemoryRegion *mem_region;
327         mem_region = g_new(MemoryRegion, 2);
328         memory_region_init_alias(&mem_region[0], &addr_space->parent_obj,
329                               "LowMem", machine->ram, 0, FIRMWARE_START);
330         memory_region_init_alias(&mem_region[1], &addr_space->parent_obj,
331                               "HighMem", machine->ram, FIRMWARE_START,
332                               machine->ram_size - FIRMWARE_START);
333         memory_region_add_subregion_overlap(addr_space, 0, &mem_region[0], -1);
334         memory_region_add_subregion_overlap(addr_space, RAM_MAP_HIGH,
335                                             &mem_region[1], -1);
336     }
337 
338     return translate;
339 }
340 
341 /*
342  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
343  */
machine_HP_common_init_tail(MachineState * machine,PCIBus * pci_bus,TranslateFn * translate)344 static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
345                                         TranslateFn *translate)
346 {
347     const char *kernel_filename = machine->kernel_filename;
348     const char *kernel_cmdline = machine->kernel_cmdline;
349     const char *initrd_filename = machine->initrd_filename;
350     const char *firmware = machine->firmware;
351     MachineClass *mc = MACHINE_GET_CLASS(machine);
352     DeviceState *dev;
353     PCIDevice *pci_dev;
354     char *firmware_filename;
355     uint64_t firmware_low, firmware_high;
356     long size;
357     uint64_t kernel_entry = 0, kernel_low, kernel_high;
358     MemoryRegion *addr_space = get_system_memory();
359     MemoryRegion *rom_region;
360     SysBusDevice *s;
361 
362     /* SCSI disk setup. */
363     if (drive_get_max_bus(IF_SCSI) >= 0) {
364         dev = DEVICE(pci_create_simple(pci_bus, -1, "lsi53c895a"));
365         lsi53c8xx_handle_legacy_cmdline(dev);
366     }
367 
368     /* Graphics setup. */
369     if (machine->enable_graphics && vga_interface_type != VGA_NONE) {
370         dev = qdev_new("artist");
371         s = SYS_BUS_DEVICE(dev);
372         bool disabled = object_property_get_bool(OBJECT(dev), "disable", NULL);
373         if (!disabled) {
374             sysbus_realize_and_unref(s, &error_fatal);
375             vga_interface_created = true;
376             sysbus_mmio_map(s, 0, translate(NULL, LASI_GFX_HPA));
377             sysbus_mmio_map(s, 1, translate(NULL, ARTIST_FB_ADDR));
378         }
379     }
380 
381     /* Network setup. */
382     if (lasi_dev) {
383         lasi_82596_init(addr_space, translate(NULL, LASI_LAN_HPA),
384                         qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
385                         enable_lasi_lan());
386     }
387 
388     pci_init_nic_devices(pci_bus, mc->default_nic);
389 
390     /* BMC board: HP Diva GSP */
391     dev = qdev_new("diva-gsp");
392     if (!object_property_get_bool(OBJECT(dev), "disable", NULL)) {
393         pci_dev = pci_new_multifunction(PCI_DEVFN(2, 0), "diva-gsp");
394         if (!lasi_dev) {
395             /* bind default keyboard/serial to Diva card */
396             qdev_prop_set_chr(DEVICE(pci_dev), "chardev1", serial_hd(0));
397             qdev_prop_set_chr(DEVICE(pci_dev), "chardev2", serial_hd(1));
398             qdev_prop_set_chr(DEVICE(pci_dev), "chardev3", serial_hd(2));
399             qdev_prop_set_chr(DEVICE(pci_dev), "chardev4", serial_hd(3));
400         }
401         pci_realize_and_unref(pci_dev, pci_bus, &error_fatal);
402     }
403 
404     /* create USB OHCI controller for USB keyboard & mouse on Astro machines */
405     if (!lasi_dev && machine->enable_graphics && defaults_enabled()) {
406         USBBus *usb_bus;
407 
408         pci_create_simple(pci_bus, -1, "pci-ohci");
409         usb_bus = USB_BUS(object_resolve_type_unambiguous(TYPE_USB_BUS,
410                                                           &error_abort));
411         usb_create_simple(usb_bus, "usb-kbd");
412         usb_create_simple(usb_bus, "usb-mouse");
413     }
414 
415     /* register power switch emulation */
416     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
417 
418     /* fw_cfg configuration interface */
419     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
420 
421     /* Load firmware.  Given that this is not "real" firmware,
422        but one explicitly written for the emulation, we might as
423        well load it directly from an ELF image. Load the 64-bit
424        firmware on 64-bit machines by default if not specified
425        on command line. */
426     if (!qtest_enabled()) {
427         if (!firmware) {
428             firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
429         }
430         firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
431         if (firmware_filename == NULL) {
432             error_report("no firmware provided");
433             exit(1);
434         }
435 
436         size = load_elf(firmware_filename, NULL, translate, NULL,
437                         &firmware_entry, &firmware_low, &firmware_high, NULL,
438                         ELFDATA2MSB, EM_PARISC, 0, 0);
439 
440         if (size < 0) {
441             error_report("could not load firmware '%s'", firmware_filename);
442             exit(1);
443         }
444         qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
445                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
446                       firmware_low, firmware_high, firmware_entry);
447         if (firmware_low < translate(NULL, FIRMWARE_START) ||
448             firmware_high >= translate(NULL, FIRMWARE_END)) {
449             error_report("Firmware overlaps with memory or IO space");
450             exit(1);
451         }
452         g_free(firmware_filename);
453     }
454 
455     rom_region = g_new(MemoryRegion, 1);
456     memory_region_init_ram(rom_region, NULL, "firmware",
457                            (FIRMWARE_END - FIRMWARE_START), &error_fatal);
458     memory_region_add_subregion(addr_space,
459                                 translate(NULL, FIRMWARE_START), rom_region);
460 
461     /* Load kernel */
462     if (kernel_filename) {
463         size = load_elf(kernel_filename, NULL, linux_kernel_virt_to_phys,
464                         NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
465                         ELFDATA2MSB, EM_PARISC, 0, 0);
466 
467         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
468 
469         if (size < 0) {
470             error_report("could not load kernel '%s'", kernel_filename);
471             exit(1);
472         }
473         qemu_log_mask(CPU_LOG_PAGE, "Kernel loaded at 0x%08" PRIx64
474                       "-0x%08" PRIx64 ", entry at 0x%08" PRIx64
475                       ", size %" PRIu64 " kB\n",
476                       kernel_low, kernel_high, kernel_entry, size / KiB);
477 
478         if (kernel_cmdline) {
479             cpu[0]->env.cmdline_or_bootorder = 0x4000;
480             pstrcpy_targphys("cmdline", cpu[0]->env.cmdline_or_bootorder,
481                              TARGET_PAGE_SIZE, kernel_cmdline);
482         }
483 
484         if (initrd_filename) {
485             ram_addr_t initrd_base;
486             int64_t initrd_size;
487 
488             initrd_size = get_image_size(initrd_filename);
489             if (initrd_size < 0) {
490                 error_report("could not load initial ram disk '%s'",
491                              initrd_filename);
492                 exit(1);
493             }
494 
495             /* Load the initrd image high in memory.
496                Mirror the algorithm used by palo:
497                (1) Due to sign-extension problems and PDC,
498                put the initrd no higher than 1G.
499                (2) Reserve 64k for stack.  */
500             initrd_base = MIN(machine->ram_size, 1 * GiB);
501             initrd_base = initrd_base - 64 * KiB;
502             initrd_base = (initrd_base - initrd_size) & TARGET_PAGE_MASK;
503 
504             if (initrd_base < kernel_high) {
505                 error_report("kernel and initial ram disk too large!");
506                 exit(1);
507             }
508 
509             load_image_targphys(initrd_filename, initrd_base, initrd_size);
510             cpu[0]->env.initrd_base = initrd_base;
511             cpu[0]->env.initrd_end  = initrd_base + initrd_size;
512         }
513     }
514 
515     if (!kernel_entry) {
516         /* When booting via firmware, tell firmware if we want interactive
517          * mode (kernel_entry=1), and to boot from CD (cmdline_or_bootorder='d')
518          * or hard disc (cmdline_or_bootorder='c').
519          */
520         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
521         cpu[0]->env.cmdline_or_bootorder = machine->boot_config.order[0];
522     }
523 
524     /* Keep initial kernel_entry for first boot */
525     cpu[0]->env.kernel_entry = kernel_entry;
526 }
527 
528 /*
529  * Create HP B160L workstation
530  */
machine_HP_B160L_init(MachineState * machine)531 static void machine_HP_B160L_init(MachineState *machine)
532 {
533     DeviceState *dev, *dino_dev;
534     MemoryRegion *addr_space = get_system_memory();
535     TranslateFn *translate;
536     ISABus *isa_bus;
537     PCIBus *pci_bus;
538 
539     /* Create CPUs and RAM.  */
540     translate = machine_HP_common_init_cpus(machine);
541 
542     if (hppa_is_pa20(&cpu[0]->env)) {
543         error_report("The HP B160L workstation requires a 32-bit "
544                      "CPU. Use '-machine C3700' instead.");
545         exit(1);
546     }
547 
548     /* Init Lasi chip */
549     lasi_dev = DEVICE(lasi_init());
550     memory_region_add_subregion(addr_space, translate(NULL, LASI_HPA),
551                                 sysbus_mmio_get_region(
552                                     SYS_BUS_DEVICE(lasi_dev), 0));
553 
554     /* Init Dino (PCI host bus chip).  */
555     dino_dev = DEVICE(dino_init(addr_space));
556     memory_region_add_subregion(addr_space, translate(NULL, DINO_HPA),
557                                 sysbus_mmio_get_region(
558                                     SYS_BUS_DEVICE(dino_dev), 0));
559     pci_bus = PCI_BUS(qdev_get_child_bus(dino_dev, "pci"));
560     assert(pci_bus);
561 
562     /* Create ISA bus, needed for PS/2 kbd/mouse port emulation */
563     isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
564     assert(isa_bus);
565 
566     /* Serial ports: Lasi and Dino use a 7.272727 MHz clock. */
567     serial_mm_init(addr_space, translate(NULL, LASI_UART_HPA + 0x800), 0,
568         qdev_get_gpio_in(lasi_dev, LASI_IRQ_UART_HPA), 7272727 / 16,
569         serial_hd(0), DEVICE_BIG_ENDIAN);
570 
571     serial_mm_init(addr_space, translate(NULL, DINO_UART_HPA + 0x800), 0,
572         qdev_get_gpio_in(dino_dev, DINO_IRQ_RS232INT), 7272727 / 16,
573         serial_hd(1), DEVICE_BIG_ENDIAN);
574 
575     /* Parallel port */
576     parallel_mm_init(addr_space, translate(NULL, LASI_LPT_HPA + 0x800), 0,
577                      qdev_get_gpio_in(lasi_dev, LASI_IRQ_LAN_HPA),
578                      parallel_hds[0]);
579 
580     /* PS/2 Keyboard/Mouse */
581     dev = qdev_new(TYPE_LASIPS2);
582     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
583     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
584                        qdev_get_gpio_in(lasi_dev, LASI_IRQ_PS2KBD_HPA));
585     memory_region_add_subregion(addr_space,
586                                 translate(NULL, LASI_PS2KBD_HPA),
587                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
588                                                        0));
589     memory_region_add_subregion(addr_space,
590                                 translate(NULL, LASI_PS2KBD_HPA + 0x100),
591                                 sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
592                                                        1));
593 
594     /* Add SCSI discs, NICs, graphics & load firmware */
595     machine_HP_common_init_tail(machine, pci_bus, translate);
596 }
597 
astro_init(void)598 static AstroState *astro_init(void)
599 {
600     DeviceState *dev;
601 
602     dev = qdev_new(TYPE_ASTRO_CHIP);
603     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
604 
605     return ASTRO_CHIP(dev);
606 }
607 
608 /*
609  * Create HP C3700 workstation
610  */
machine_HP_C3700_init(MachineState * machine)611 static void machine_HP_C3700_init(MachineState *machine)
612 {
613     PCIBus *pci_bus;
614     AstroState *astro;
615     DeviceState *astro_dev;
616     MemoryRegion *addr_space = get_system_memory();
617     TranslateFn *translate;
618 
619     /* Create CPUs and RAM.  */
620     translate = machine_HP_common_init_cpus(machine);
621 
622     if (!hppa_is_pa20(&cpu[0]->env)) {
623         error_report("The HP C3000 workstation requires a 64-bit CPU. "
624                      "Use '-machine B160L' instead.");
625         exit(1);
626     }
627 
628     /* Init Astro and the Elroys (PCI host bus chips).  */
629     astro = astro_init();
630     astro_dev = DEVICE(astro);
631     memory_region_add_subregion(addr_space, translate(NULL, ASTRO_HPA),
632                                 sysbus_mmio_get_region(
633                                     SYS_BUS_DEVICE(astro_dev), 0));
634     pci_bus = PCI_BUS(qdev_get_child_bus(DEVICE(astro->elroy[0]), "pci"));
635     assert(pci_bus);
636 
637     /* Add SCSI discs, NICs, graphics & load firmware */
638     machine_HP_common_init_tail(machine, pci_bus, translate);
639 }
640 
hppa_machine_reset(MachineState * ms,ResetType type)641 static void hppa_machine_reset(MachineState *ms, ResetType type)
642 {
643     unsigned int smp_cpus = ms->smp.cpus;
644     int i;
645 
646     qemu_devices_reset(type);
647 
648     /* Start all CPUs at the firmware entry point.
649      *  Monarch CPU will initialize firmware, secondary CPUs
650      *  will enter a small idle loop and wait for rendevouz. */
651     for (i = 0; i < smp_cpus; i++) {
652         CPUState *cs = CPU(cpu[i]);
653 
654         /* reset CPU */
655         resettable_reset(OBJECT(cs), RESET_TYPE_COLD);
656 
657         cpu_set_pc(cs, firmware_entry);
658         cpu[i]->env.psw = PSW_Q;
659         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
660     }
661 
662     cpu[0]->env.gr[26] = ms->ram_size;
663     cpu[0]->env.gr[25] = cpu[0]->env.kernel_entry;
664     cpu[0]->env.gr[24] = cpu[0]->env.cmdline_or_bootorder;
665     cpu[0]->env.gr[23] = cpu[0]->env.initrd_base;
666     cpu[0]->env.gr[22] = cpu[0]->env.initrd_end;
667     cpu[0]->env.gr[21] = smp_cpus;
668     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
669 
670     /* reset static fields to avoid starting Linux kernel & initrd on reboot */
671     cpu[0]->env.kernel_entry = 0;
672     cpu[0]->env.initrd_base = 0;
673     cpu[0]->env.initrd_end = 0;
674     cpu[0]->env.cmdline_or_bootorder = 'c';
675 }
676 
hppa_nmi(NMIState * n,int cpu_index,Error ** errp)677 static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
678 {
679     CPUState *cs;
680 
681     CPU_FOREACH(cs) {
682         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
683     }
684 }
685 
HP_B160L_machine_init_class_init(ObjectClass * oc,const void * data)686 static void HP_B160L_machine_init_class_init(ObjectClass *oc, const void *data)
687 {
688     static const char * const valid_cpu_types[] = {
689         TYPE_HPPA_CPU,
690         NULL
691     };
692     MachineClass *mc = MACHINE_CLASS(oc);
693     NMIClass *nc = NMI_CLASS(oc);
694 
695     mc->desc = "HP B160L workstation";
696     mc->default_cpu_type = TYPE_HPPA_CPU;
697     mc->valid_cpu_types = valid_cpu_types;
698     mc->init = machine_HP_B160L_init;
699     mc->reset = hppa_machine_reset;
700     mc->block_default_type = IF_SCSI;
701     mc->max_cpus = HPPA_MAX_CPUS;
702     mc->default_cpus = 1;
703     mc->is_default = true;
704     mc->default_ram_size = 512 * MiB;
705     mc->default_boot_order = "cd";
706     mc->default_ram_id = "ram";
707     mc->default_nic = "tulip";
708 
709     nc->nmi_monitor_handler = hppa_nmi;
710 }
711 
712 static const TypeInfo HP_B160L_machine_init_typeinfo = {
713     .name = MACHINE_TYPE_NAME("B160L"),
714     .parent = TYPE_MACHINE,
715     .class_init = HP_B160L_machine_init_class_init,
716     .interfaces = (const InterfaceInfo[]) {
717         { TYPE_NMI },
718         { }
719     },
720 };
721 
HP_C3700_machine_init_class_init(ObjectClass * oc,const void * data)722 static void HP_C3700_machine_init_class_init(ObjectClass *oc, const void *data)
723 {
724     static const char * const valid_cpu_types[] = {
725         TYPE_HPPA64_CPU,
726         NULL
727     };
728     MachineClass *mc = MACHINE_CLASS(oc);
729     NMIClass *nc = NMI_CLASS(oc);
730 
731     mc->desc = "HP C3700 workstation";
732     mc->default_cpu_type = TYPE_HPPA64_CPU;
733     mc->valid_cpu_types = valid_cpu_types;
734     mc->init = machine_HP_C3700_init;
735     mc->reset = hppa_machine_reset;
736     mc->block_default_type = IF_SCSI;
737     mc->max_cpus = HPPA_MAX_CPUS;
738     mc->default_cpus = 1;
739     mc->is_default = false;
740     mc->default_ram_size = 1024 * MiB;
741     mc->default_boot_order = "cd";
742     mc->default_ram_id = "ram";
743     mc->default_nic = "tulip";
744 
745     nc->nmi_monitor_handler = hppa_nmi;
746 }
747 
748 static const TypeInfo HP_C3700_machine_init_typeinfo = {
749     .name = MACHINE_TYPE_NAME("C3700"),
750     .parent = TYPE_MACHINE,
751     .class_init = HP_C3700_machine_init_class_init,
752     .interfaces = (const InterfaceInfo[]) {
753         { TYPE_NMI },
754         { }
755     },
756 };
757 
hppa_machine_init_register_types(void)758 static void hppa_machine_init_register_types(void)
759 {
760     type_register_static(&HP_B160L_machine_init_typeinfo);
761     type_register_static(&HP_C3700_machine_init_typeinfo);
762 }
763 
764 type_init(hppa_machine_init_register_types)
765