qemu/hw/m68k/virt.c
<<
>>
Prefs
   1/*
   2 * SPDX-License-Identifier: GPL-2.0-or-later
   3 *
   4 * QEMU Vitual M68K Machine
   5 *
   6 * (c) 2020 Laurent Vivier <laurent@vivier.eu>
   7 *
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "qemu/units.h"
  12#include "qemu-common.h"
  13#include "sysemu/sysemu.h"
  14#include "cpu.h"
  15#include "hw/boards.h"
  16#include "hw/qdev-properties.h"
  17#include "elf.h"
  18#include "hw/loader.h"
  19#include "ui/console.h"
  20#include "hw/sysbus.h"
  21#include "standard-headers/asm-m68k/bootinfo.h"
  22#include "standard-headers/asm-m68k/bootinfo-virt.h"
  23#include "bootinfo.h"
  24#include "net/net.h"
  25#include "qapi/error.h"
  26#include "sysemu/qtest.h"
  27#include "sysemu/runstate.h"
  28#include "sysemu/reset.h"
  29
  30#include "hw/intc/m68k_irqc.h"
  31#include "hw/misc/virt_ctrl.h"
  32#include "hw/char/goldfish_tty.h"
  33#include "hw/rtc/goldfish_rtc.h"
  34#include "hw/intc/goldfish_pic.h"
  35#include "hw/virtio/virtio-mmio.h"
  36#include "hw/virtio/virtio-blk.h"
  37
  38/*
  39 * 6 goldfish-pic for CPU IRQ #1 to IRQ #6
  40 * CPU IRQ #1 -> PIC #1
  41 *               IRQ #1 to IRQ #31 -> unused
  42 *               IRQ #32 -> goldfish-tty
  43 * CPU IRQ #2 -> PIC #2
  44 *               IRQ #1 to IRQ #32 -> virtio-mmio from 1 to 32
  45 * CPU IRQ #3 -> PIC #3
  46 *               IRQ #1 to IRQ #32 -> virtio-mmio from 33 to 64
  47 * CPU IRQ #4 -> PIC #4
  48 *               IRQ #1 to IRQ #32 -> virtio-mmio from 65 to 96
  49 * CPU IRQ #5 -> PIC #5
  50 *               IRQ #1 to IRQ #32 -> virtio-mmio from 97 to 128
  51 * CPU IRQ #6 -> PIC #6
  52 *               IRQ #1 -> goldfish-rtc
  53 *               IRQ #2 to IRQ #32 -> unused
  54 * CPU IRQ #7 -> NMI
  55 */
  56
  57#define PIC_IRQ_BASE(num)     (8 + (num - 1) * 32)
  58#define PIC_IRQ(num, irq)     (PIC_IRQ_BASE(num) + irq - 1)
  59#define PIC_GPIO(pic_irq)     (qdev_get_gpio_in(pic_dev[(pic_irq - 8) / 32], \
  60                                                (pic_irq - 8) % 32))
  61
  62#define VIRT_GF_PIC_MMIO_BASE 0xff000000     /* MMIO: 0xff000000 - 0xff005fff */
  63#define VIRT_GF_PIC_IRQ_BASE  1              /* IRQ: #1 -> #6 */
  64#define VIRT_GF_PIC_NB        6
  65
  66/* 2 goldfish-rtc (and timer) */
  67#define VIRT_GF_RTC_MMIO_BASE 0xff006000     /* MMIO: 0xff006000 - 0xff007fff */
  68#define VIRT_GF_RTC_IRQ_BASE  PIC_IRQ(6, 1)  /* PIC: #6, IRQ: #1 */
  69#define VIRT_GF_RTC_NB        2
  70
  71/* 1 goldfish-tty */
  72#define VIRT_GF_TTY_MMIO_BASE 0xff008000     /* MMIO: 0xff008000 - 0xff008fff */
  73#define VIRT_GF_TTY_IRQ_BASE  PIC_IRQ(1, 32) /* PIC: #1, IRQ: #32 */
  74
  75/* 1 virt-ctrl */
  76#define VIRT_CTRL_MMIO_BASE 0xff009000    /* MMIO: 0xff009000 - 0xff009fff */
  77#define VIRT_CTRL_IRQ_BASE  PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
  78
  79/*
  80 * virtio-mmio size is 0x200 bytes
  81 * we use 4 goldfish-pic to attach them,
  82 * we can attach 32 virtio devices / goldfish-pic
  83 * -> we can manage 32 * 4 = 128 virtio devices
  84 */
  85#define VIRT_VIRTIO_MMIO_BASE 0xff010000     /* MMIO: 0xff010000 - 0xff01ffff */
  86#define VIRT_VIRTIO_IRQ_BASE  PIC_IRQ(2, 1)  /* PIC: 2, 3, 4, 5, IRQ: ALL */
  87
  88static void main_cpu_reset(void *opaque)
  89{
  90    M68kCPU *cpu = opaque;
  91    CPUState *cs = CPU(cpu);
  92
  93    cpu_reset(cs);
  94    cpu->env.aregs[7] = ldl_phys(cs->as, 0);
  95    cpu->env.pc = ldl_phys(cs->as, 4);
  96}
  97
  98static void virt_init(MachineState *machine)
  99{
 100    M68kCPU *cpu = NULL;
 101    int32_t kernel_size;
 102    uint64_t elf_entry;
 103    ram_addr_t initrd_base;
 104    int32_t initrd_size;
 105    ram_addr_t ram_size = machine->ram_size;
 106    const char *kernel_filename = machine->kernel_filename;
 107    const char *initrd_filename = machine->initrd_filename;
 108    const char *kernel_cmdline = machine->kernel_cmdline;
 109    hwaddr parameters_base;
 110    DeviceState *dev;
 111    DeviceState *irqc_dev;
 112    DeviceState *pic_dev[VIRT_GF_PIC_NB];
 113    SysBusDevice *sysbus;
 114    hwaddr io_base;
 115    int i;
 116
 117    if (ram_size > 3399672 * KiB) {
 118        /*
 119         * The physical memory can be up to 4 GiB - 16 MiB, but linux
 120         * kernel crashes after this limit (~ 3.2 GiB)
 121         */
 122        error_report("Too much memory for this machine: %" PRId64 " KiB, "
 123                     "maximum 3399672 KiB", ram_size / KiB);
 124        exit(1);
 125    }
 126
 127    /* init CPUs */
 128    cpu = M68K_CPU(cpu_create(machine->cpu_type));
 129    qemu_register_reset(main_cpu_reset, cpu);
 130
 131    /* RAM */
 132    memory_region_add_subregion(get_system_memory(), 0, machine->ram);
 133
 134    /* IRQ Controller */
 135
 136    irqc_dev = qdev_new(TYPE_M68K_IRQC);
 137    sysbus_realize_and_unref(SYS_BUS_DEVICE(irqc_dev), &error_fatal);
 138
 139    /*
 140     * 6 goldfish-pic
 141     *
 142     * map: 0xff000000 - 0xff006fff = 28 KiB
 143     * IRQ: #1 (lower priority) -> #6 (higher priority)
 144     *
 145     */
 146    io_base = VIRT_GF_PIC_MMIO_BASE;
 147    for (i = 0; i < VIRT_GF_PIC_NB; i++) {
 148        pic_dev[i] = qdev_new(TYPE_GOLDFISH_PIC);
 149        sysbus = SYS_BUS_DEVICE(pic_dev[i]);
 150        qdev_prop_set_uint8(pic_dev[i], "index", i);
 151        sysbus_realize_and_unref(sysbus, &error_fatal);
 152
 153        sysbus_mmio_map(sysbus, 0, io_base);
 154        sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(irqc_dev, i));
 155
 156        io_base += 0x1000;
 157    }
 158
 159    /* goldfish-rtc */
 160    io_base = VIRT_GF_RTC_MMIO_BASE;
 161    for (i = 0; i < VIRT_GF_RTC_NB; i++) {
 162        dev = qdev_new(TYPE_GOLDFISH_RTC);
 163        sysbus = SYS_BUS_DEVICE(dev);
 164        sysbus_realize_and_unref(sysbus, &error_fatal);
 165        sysbus_mmio_map(sysbus, 0, io_base);
 166        sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_GF_RTC_IRQ_BASE + i));
 167
 168        io_base += 0x1000;
 169    }
 170
 171    /* goldfish-tty */
 172    dev = qdev_new(TYPE_GOLDFISH_TTY);
 173    sysbus = SYS_BUS_DEVICE(dev);
 174    qdev_prop_set_chr(dev, "chardev", serial_hd(0));
 175    sysbus_realize_and_unref(sysbus, &error_fatal);
 176    sysbus_mmio_map(sysbus, 0, VIRT_GF_TTY_MMIO_BASE);
 177    sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_GF_TTY_IRQ_BASE));
 178
 179    /* virt controller */
 180    dev = qdev_new(TYPE_VIRT_CTRL);
 181    sysbus = SYS_BUS_DEVICE(dev);
 182    sysbus_realize_and_unref(sysbus, &error_fatal);
 183    sysbus_mmio_map(sysbus, 0, VIRT_CTRL_MMIO_BASE);
 184    sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_CTRL_IRQ_BASE));
 185
 186    /* virtio-mmio */
 187    io_base = VIRT_VIRTIO_MMIO_BASE;
 188    for (i = 0; i < 128; i++) {
 189        dev = qdev_new(TYPE_VIRTIO_MMIO);
 190        qdev_prop_set_bit(dev, "force-legacy", false);
 191        sysbus = SYS_BUS_DEVICE(dev);
 192        sysbus_realize_and_unref(sysbus, &error_fatal);
 193        sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_VIRTIO_IRQ_BASE + i));
 194        sysbus_mmio_map(sysbus, 0, io_base);
 195        io_base += 0x200;
 196    }
 197
 198    if (kernel_filename) {
 199        CPUState *cs = CPU(cpu);
 200        uint64_t high;
 201
 202        kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
 203                               &elf_entry, NULL, &high, NULL, 1,
 204                               EM_68K, 0, 0);
 205        if (kernel_size < 0) {
 206            error_report("could not load kernel '%s'", kernel_filename);
 207            exit(1);
 208        }
 209        stl_phys(cs->as, 4, elf_entry); /* reset initial PC */
 210        parameters_base = (high + 1) & ~1;
 211
 212        BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_VIRT);
 213        BOOTINFO1(cs->as, parameters_base, BI_FPUTYPE, FPU_68040);
 214        BOOTINFO1(cs->as, parameters_base, BI_MMUTYPE, MMU_68040);
 215        BOOTINFO1(cs->as, parameters_base, BI_CPUTYPE, CPU_68040);
 216        BOOTINFO2(cs->as, parameters_base, BI_MEMCHUNK, 0, ram_size);
 217
 218        BOOTINFO1(cs->as, parameters_base, BI_VIRT_QEMU_VERSION,
 219                  ((QEMU_VERSION_MAJOR << 24) | (QEMU_VERSION_MINOR << 16) |
 220                   (QEMU_VERSION_MICRO << 8)));
 221        BOOTINFO2(cs->as, parameters_base, BI_VIRT_GF_PIC_BASE,
 222                  VIRT_GF_PIC_MMIO_BASE, VIRT_GF_PIC_IRQ_BASE);
 223        BOOTINFO2(cs->as, parameters_base, BI_VIRT_GF_RTC_BASE,
 224                  VIRT_GF_RTC_MMIO_BASE, VIRT_GF_RTC_IRQ_BASE);
 225        BOOTINFO2(cs->as, parameters_base, BI_VIRT_GF_TTY_BASE,
 226                  VIRT_GF_TTY_MMIO_BASE, VIRT_GF_TTY_IRQ_BASE);
 227        BOOTINFO2(cs->as, parameters_base, BI_VIRT_CTRL_BASE,
 228                  VIRT_CTRL_MMIO_BASE, VIRT_CTRL_IRQ_BASE);
 229        BOOTINFO2(cs->as, parameters_base, BI_VIRT_VIRTIO_BASE,
 230                  VIRT_VIRTIO_MMIO_BASE, VIRT_VIRTIO_IRQ_BASE);
 231
 232        if (kernel_cmdline) {
 233            BOOTINFOSTR(cs->as, parameters_base, BI_COMMAND_LINE,
 234                        kernel_cmdline);
 235        }
 236
 237        /* load initrd */
 238        if (initrd_filename) {
 239            initrd_size = get_image_size(initrd_filename);
 240            if (initrd_size < 0) {
 241                error_report("could not load initial ram disk '%s'",
 242                             initrd_filename);
 243                exit(1);
 244            }
 245
 246            initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
 247            load_image_targphys(initrd_filename, initrd_base,
 248                                ram_size - initrd_base);
 249            BOOTINFO2(cs->as, parameters_base, BI_RAMDISK, initrd_base,
 250                      initrd_size);
 251        } else {
 252            initrd_base = 0;
 253            initrd_size = 0;
 254        }
 255        BOOTINFO0(cs->as, parameters_base, BI_LAST);
 256    }
 257}
 258
 259static void virt_machine_class_init(ObjectClass *oc, void *data)
 260{
 261    MachineClass *mc = MACHINE_CLASS(oc);
 262    mc->desc = "QEMU M68K Virtual Machine";
 263    mc->init = virt_init;
 264    mc->default_cpu_type = M68K_CPU_TYPE_NAME("m68040");
 265    mc->max_cpus = 1;
 266    mc->no_floppy = 1;
 267    mc->no_parallel = 1;
 268    mc->default_ram_id = "m68k_virt.ram";
 269}
 270
 271static const TypeInfo virt_machine_info = {
 272    .name       = MACHINE_TYPE_NAME("virt"),
 273    .parent     = TYPE_MACHINE,
 274    .abstract   = true,
 275    .class_init = virt_machine_class_init,
 276};
 277
 278static void virt_machine_register_types(void)
 279{
 280    type_register_static(&virt_machine_info);
 281}
 282
 283type_init(virt_machine_register_types)
 284
 285#define DEFINE_VIRT_MACHINE(major, minor, latest) \
 286    static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
 287                                                    void *data) \
 288    { \
 289        MachineClass *mc = MACHINE_CLASS(oc); \
 290        virt_machine_##major##_##minor##_options(mc); \
 291        mc->desc = "QEMU " # major "." # minor " M68K Virtual Machine"; \
 292        if (latest) { \
 293            mc->alias = "virt"; \
 294        } \
 295    } \
 296    static const TypeInfo machvirt_##major##_##minor##_info = { \
 297        .name = MACHINE_TYPE_NAME("virt-" # major "." # minor), \
 298        .parent = MACHINE_TYPE_NAME("virt"), \
 299        .class_init = virt_##major##_##minor##_class_init, \
 300    }; \
 301    static void machvirt_machine_##major##_##minor##_init(void) \
 302    { \
 303        type_register_static(&machvirt_##major##_##minor##_info); \
 304    } \
 305    type_init(machvirt_machine_##major##_##minor##_init);
 306
 307static void virt_machine_6_2_options(MachineClass *mc)
 308{
 309}
 310DEFINE_VIRT_MACHINE(6, 2, true)
 311
 312static void virt_machine_6_1_options(MachineClass *mc)
 313{
 314    virt_machine_6_2_options(mc);
 315    compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
 316}
 317DEFINE_VIRT_MACHINE(6, 1, false)
 318
 319static void virt_machine_6_0_options(MachineClass *mc)
 320{
 321    virt_machine_6_1_options(mc);
 322    compat_props_add(mc->compat_props, hw_compat_6_0, hw_compat_6_0_len);
 323}
 324DEFINE_VIRT_MACHINE(6, 0, false)
 325