qemu

Форк
0
/
machine.c 
767 строк · 24.4 Кб
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

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.  */
68
static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
69
{
70
    return 0;
71
}
72

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

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

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

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

168
static uint64_t linux_kernel_virt_to_phys(void *opaque, uint64_t addr)
169
{
170
    addr &= (0x10000000 - 1);
171
    return addr;
172
}
173

174
static uint64_t translate_pa10(void *dummy, uint64_t addr)
175
{
176
    return (uint32_t)addr;
177
}
178

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

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

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

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

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
 */
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
 */
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
 */
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

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
 */
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

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

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

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

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

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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.