xref: /openbmc/qemu/hw/hppa/machine.c (revision 0572f011)
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 "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"
37 
38 #define MIN_SEABIOS_HPPA_VERSION 12 /* require at least this fw version */
39 
40 #define HPA_POWER_BUTTON        (FIRMWARE_END - 0x10)
41 static hwaddr soft_power_reg;
42 
43 #define enable_lasi_lan()       0
44 
45 static DeviceState *lasi_dev;
46 
hppa_powerdown_req(Notifier * n,void * opaque)47 static void hppa_powerdown_req(Notifier *n, void *opaque)
48 {
49     uint32_t val;
50 
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;
56     }
57 
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);
61 }
62 
63 static Notifier hppa_system_powerdown_notifier = {
64     .notify = hppa_powerdown_req
65 };
66 
67 /* Fallback for unassigned PCI I/O operations.  Avoids MCHK.  */
ignore_read(void * opaque,hwaddr addr,unsigned size)68 static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
69 {
70     return 0;
71 }
72 
ignore_write(void * opaque,hwaddr addr,uint64_t v,unsigned size)73 static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size)
74 {
75 }
76 
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,
84     },
85     .impl = {
86         .min_access_size = 1,
87         .max_access_size = 8,
88     },
89 };
90 
hppa_isa_bus(hwaddr addr)91 static ISABus *hppa_isa_bus(hwaddr addr)
92 {
93     ISABus *isa_bus;
94     qemu_irq *isa_irqs;
95     MemoryRegion *isa_region;
96 
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);
101 
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);
106 
107     return isa_bus;
108 }
109 
110 /*
111  * Helper functions to emulate RTC clock and DebugOutputPort
112  */
113 static time_t rtc_ref;
114 
io_cpu_read(void * opaque,hwaddr addr,unsigned size)115 static uint64_t io_cpu_read(void *opaque, hwaddr addr, unsigned size)
116 {
117     uint64_t val = 0;
118 
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 */
126     }
127     return val;
128 }
129 
io_cpu_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)130 static void io_cpu_write(void *opaque, hwaddr addr,
131                          uint64_t val, unsigned size)
132 {
133     unsigned char ch;
134     Chardev *debugout;
135 
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);
147         }
148         break;
149     }
150 }
151 
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,
159     },
160     .impl = {
161         .min_access_size = 1,
162         .max_access_size = 8,
163     },
164 };
165 
166 typedef uint64_t TranslateFn(void *opaque, uint64_t addr);
167 
linux_kernel_virt_to_phys(void * opaque,uint64_t addr)168 static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
169 {
170     addr &= (0x10000000 - 1);
171     return addr;
172 }
173 
translate_pa10(void * dummy,uint64_t addr)174 static uint64_t translate_pa10(void *dummy, uint64_t addr)
175 {
176     return (uint32_t)addr;
177 }
178 
translate_pa20(void * dummy,uint64_t addr)179 static uint64_t translate_pa20(void *dummy, uint64_t addr)
180 {
181     return hppa_abs_to_phys_pa2_w0(addr);
182 }
183 
184 static HPPACPU *cpu[HPPA_MAX_CPUS];
185 static uint64_t firmware_entry;
186 
fw_cfg_boot_set(void * opaque,const char * boot_device,Error ** errp)187 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
188                             Error **errp)
189 {
190     fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
191 }
192 
create_fw_cfg(MachineState * ms,PCIBus * pci_bus,hwaddr addr)193 static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
194                                  hwaddr addr)
195 {
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;
202 
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);
207 
208     val = cpu_to_le64(MIN_SEABIOS_HPPA_VERSION);
209     fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version",
210                     g_memdup2(&val, sizeof(val)), sizeof(val));
211 
212     val = cpu_to_le64(HPPA_TLB_ENTRIES - btlb_entries);
213     fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries",
214                     g_memdup2(&val, sizeof(val)), sizeof(val));
215 
216     val = cpu_to_le64(btlb_entries);
217     fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries",
218                     g_memdup2(&val, sizeof(val)), sizeof(val));
219 
220     len = strlen(mc->name) + 1;
221     fw_cfg_add_file(fw_cfg, "/etc/hppa/machine",
222                     g_memdup2(mc->name, len), len);
223 
224     val = cpu_to_le64(soft_power_reg);
225     fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
226                     g_memdup2(&val, sizeof(val)), sizeof(val));
227 
228     val = cpu_to_le64(CPU_HPA + 16);
229     fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
230                     g_memdup2(&val, sizeof(val)), sizeof(val));
231 
232     val = cpu_to_le64(CPU_HPA + 24);
233     fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
234                     g_memdup2(&val, sizeof(val)), sizeof(val));
235 
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);
238 
239     fw_cfg_add_file(fw_cfg, "/etc/qemu-version",
240                     g_memdup2(qemu_version, sizeof(qemu_version)),
241                     sizeof(qemu_version));
242 
243     fw_cfg_add_extra_pci_roots(pci_bus, fw_cfg);
244 
245     return fw_cfg;
246 }
247 
lasi_init(void)248 static LasiState *lasi_init(void)
249 {
250     DeviceState *dev;
251 
252     dev = qdev_new(TYPE_LASI_CHIP);
253     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
254 
255     return LASI_CHIP(dev);
256 }
257 
dino_init(MemoryRegion * addr_space)258 static DinoState *dino_init(MemoryRegion *addr_space)
259 {
260     DeviceState *dev;
261 
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);
266 
267     return DINO_PCI_HOST_BRIDGE(dev);
268 }
269 
270 /*
271  * Step 1: Create CPUs and Memory
272  */
machine_HP_common_init_cpus(MachineState * machine)273 static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
274 {
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;
280 
281     /* Create CPUs.  */
282     for (unsigned int i = 0; i < smp_cpus; i++) {
283         cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
284     }
285 
286     /*
287      * For now, treat address layout as if PSW_W is clear.
288      * TODO: create a proper hppa64 board model and load elf64 firmware.
289      */
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) */
296     }
297 
298     soft_power_reg = translate(NULL, HPA_POWER_BUTTON);
299 
300     for (unsigned int i = 0; i < smp_cpus; i++) {
301         g_autofree char *name = g_strdup_printf("cpu%u-io-eir", i);
302 
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);
309     }
310 
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);
317 
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;
322     }
323     memory_region_add_subregion_overlap(addr_space, 0, machine->ram, -1);
324 
325     return translate;
326 }
327 
328 /*
329  * Last creation step: Add SCSI discs, NICs, graphics & load firmware
330  */
machine_HP_common_init_tail(MachineState * machine,PCIBus * pci_bus,TranslateFn * translate)331 static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
332                                         TranslateFn *translate)
333 {
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;
349 
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);
354     }
355 
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));
364     }
365 
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());
371     }
372 
373     pci_init_nic_devices(pci_bus, mc->default_nic);
374 
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));
380     }
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 */
387 
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);
396     }
397 
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;
401 
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");
407     }
408 
409     /* register power switch emulation */
410     qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier);
411 
412     /* fw_cfg configuration interface */
413     create_fw_cfg(machine, pci_bus, translate(NULL, FW_CFG_IO_BASE));
414 
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";
423         }
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);
428         }
429 
430         size = load_elf(firmware_filename, NULL, translate, NULL,
431                         &firmware_entry, &firmware_low, &firmware_high, NULL,
432                         true, EM_PARISC, 0, 0);
433 
434         if (size < 0) {
435             error_report("could not load firmware '%s'", firmware_filename);
436             exit(1);
437         }
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);
445         }
446         g_free(firmware_filename);
447     }
448 
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);
454 
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);
460 
461         kernel_entry = linux_kernel_virt_to_phys(NULL, kernel_entry);
462 
463         if (size < 0) {
464             error_report("could not load kernel '%s'", kernel_filename);
465             exit(1);
466         }
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);
471 
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);
476         }
477 
478         if (initrd_filename) {
479             ram_addr_t initrd_base;
480             int64_t initrd_size;
481 
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);
487             }
488 
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;
497 
498             if (initrd_base < kernel_high) {
499                 error_report("kernel and initial ram disk too large!");
500                 exit(1);
501             }
502 
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;
506         }
507     }
508 
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').
513          */
514         kernel_entry = machine->boot_config.has_menu ? machine->boot_config.menu : 0;
515         cpu[0]->env.gr[24] = machine->boot_config.order[0];
516     }
517 
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.
521      */
522     cpu[0]->env.gr[26] = machine->ram_size;
523     cpu[0]->env.gr[25] = kernel_entry;
524 
525     /* tell firmware how many SMP CPUs to present in inventory table */
526     cpu[0]->env.gr[21] = smp_cpus;
527 
528     /* tell firmware fw_cfg port */
529     cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
530 }
531 
532 /*
533  * Create HP B160L workstation
534  */
machine_HP_B160L_init(MachineState * machine)535 static void machine_HP_B160L_init(MachineState *machine)
536 {
537     DeviceState *dev, *dino_dev;
538     MemoryRegion *addr_space = get_system_memory();
539     TranslateFn *translate;
540     ISABus *isa_bus;
541     PCIBus *pci_bus;
542 
543     /* Create CPUs and RAM.  */
544     translate = machine_HP_common_init_cpus(machine);
545 
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);
550     }
551 
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));
557 
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);
565 
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);
569 
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);
574 
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);
578 
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]);
583 
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));
597 
598     /* Add SCSI discs, NICs, graphics & load firmware */
599     machine_HP_common_init_tail(machine, pci_bus, translate);
600 }
601 
astro_init(void)602 static AstroState *astro_init(void)
603 {
604     DeviceState *dev;
605 
606     dev = qdev_new(TYPE_ASTRO_CHIP);
607     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
608 
609     return ASTRO_CHIP(dev);
610 }
611 
612 /*
613  * Create HP C3700 workstation
614  */
machine_HP_C3700_init(MachineState * machine)615 static void machine_HP_C3700_init(MachineState *machine)
616 {
617     PCIBus *pci_bus;
618     AstroState *astro;
619     DeviceState *astro_dev;
620     MemoryRegion *addr_space = get_system_memory();
621     TranslateFn *translate;
622 
623     /* Create CPUs and RAM.  */
624     translate = machine_HP_common_init_cpus(machine);
625 
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);
630     }
631 
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);
640 
641     /* Add SCSI discs, NICs, graphics & load firmware */
642     machine_HP_common_init_tail(machine, pci_bus, translate);
643 }
644 
hppa_machine_reset(MachineState * ms,ShutdownCause reason)645 static void hppa_machine_reset(MachineState *ms, ShutdownCause reason)
646 {
647     unsigned int smp_cpus = ms->smp.cpus;
648     int i;
649 
650     qemu_devices_reset(reason);
651 
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]);
657 
658         cpu_set_pc(cs, firmware_entry);
659         cpu[i]->env.psw = PSW_Q;
660         cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
661 
662         cs->exception_index = -1;
663         cs->halted = 0;
664     }
665 
666     /* already initialized by machine_hppa_init()? */
667     if (cpu[0]->env.gr[26] == ms->ram_size) {
668         return;
669     }
670 
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;
678 }
679 
hppa_nmi(NMIState * n,int cpu_index,Error ** errp)680 static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
681 {
682     CPUState *cs;
683 
684     CPU_FOREACH(cs) {
685         cpu_interrupt(cs, CPU_INTERRUPT_NMI);
686     }
687 }
688 
HP_B160L_machine_init_class_init(ObjectClass * oc,void * data)689 static void HP_B160L_machine_init_class_init(ObjectClass *oc, void *data)
690 {
691     static const char * const valid_cpu_types[] = {
692         TYPE_HPPA_CPU,
693         NULL
694     };
695     MachineClass *mc = MACHINE_CLASS(oc);
696     NMIClass *nc = NMI_CLASS(oc);
697 
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";
711 
712     nc->nmi_monitor_handler = hppa_nmi;
713 }
714 
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 },
721         { }
722     },
723 };
724 
HP_C3700_machine_init_class_init(ObjectClass * oc,void * data)725 static void HP_C3700_machine_init_class_init(ObjectClass *oc, void *data)
726 {
727     static const char * const valid_cpu_types[] = {
728         TYPE_HPPA64_CPU,
729         NULL
730     };
731     MachineClass *mc = MACHINE_CLASS(oc);
732     NMIClass *nc = NMI_CLASS(oc);
733 
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";
747 
748     nc->nmi_monitor_handler = hppa_nmi;
749 }
750 
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 },
757         { }
758     },
759 };
760 
hppa_machine_init_register_types(void)761 static void hppa_machine_init_register_types(void)
762 {
763     type_register_static(&HP_B160L_machine_init_typeinfo);
764     type_register_static(&HP_C3700_machine_init_typeinfo);
765 }
766 
767 type_init(hppa_machine_init_register_types)
768