qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 4/4] m68k: add Virtual M68k Machine


From: Laurent Vivier
Subject: Re: [PATCH 4/4] m68k: add Virtual M68k Machine
Date: Tue, 13 Oct 2020 21:01:37 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.11.0

Le 13/10/2020 à 19:56, Philippe Mathieu-Daudé a écrit :
> On 10/13/20 5:51 PM, Laurent Vivier wrote:
>> The machine is based on Goldfish interfaces defined by Google
>> for Android simulator. It uses Goldfish-rtc (timer and RTC),
>> Goldfish-pic (PIC) and Goldfish-tty (for serial port and early tty).
>>
>> The machine is created with 128 virtio-mmio bus, and they can
>> be used to use serial console, GPU, disk, NIC, HID, ...
>>
>> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
>> ---
>>   default-configs/devices/m68k-softmmu.mak      |   1 +
>>   .../standard-headers/asm-m68k/bootinfo-virt.h |  17 +
>>   hw/m68k/virt.c                                | 296 ++++++++++++++++++
>>   MAINTAINERS                                   |   9 +
>>   hw/m68k/Kconfig                               |   8 +
>>   hw/m68k/meson.build                           |   1 +
>>   6 files changed, 332 insertions(+)
>>   create mode 100644 include/standard-headers/asm-m68k/bootinfo-virt.h
>>   create mode 100644 hw/m68k/virt.c
...
>> +/*
>> + * The GLUE (General Logic Unit) is an Apple custom integrated
>> circuit chip
>> + * that performs a variety of functions (RAM management, clock
>> generation, ...).
>> + * The GLUE chip receives interrupt requests from various devices,
>> + * assign priority to each, and asserts one or more interrupt line to
>> the
>> + * CPU.
> 
> Does your virt machine really requires a GLUE? Or only another
> cascaded PIC?

I agree code needs cleanup here.

We need something to set the ÌRQ level (priority) and vector (see
m68k_set_irq_level()).

>> + */
>> +
>> +typedef struct {
>> +    M68kCPU *cpu;
>> +    uint8_t ipr;
>> +} GLUEState;
>> +
>> +static void GLUE_set_irq(void *opaque, int irq, int level)
>> +{
>> +    GLUEState *s = opaque;
>> +    int i;
>> +
>> +    if (level) {
>> +        s->ipr |= 1 << irq;
>> +    } else {
>> +        s->ipr &= ~(1 << irq);
>> +    }
>> +
>> +    for (i = 7; i >= 0; i--) {
>> +        if ((s->ipr >> i) & 1) {
>> +            m68k_set_irq_level(s->cpu, i + 1, i + 25);
>> +            return;
>> +        }
>> +    }
>> +    m68k_set_irq_level(s->cpu, 0, 0);
>> +}
>> +
>> +static void main_cpu_reset(void *opaque)
>> +{
>> +    M68kCPU *cpu = opaque;
>> +    CPUState *cs = CPU(cpu);
>> +
>> +    cpu_reset(cs);
>> +    cpu->env.aregs[7] = ldl_phys(cs->as, 0);
>> +    cpu->env.pc = ldl_phys(cs->as, 4);
>> +}
>> +
>> +static void virt_init(MachineState *machine)
>> +{
>> +    M68kCPU *cpu = NULL;
>> +    int32_t kernel_size;
>> +    uint64_t elf_entry;
>> +    ram_addr_t initrd_base;
>> +    int32_t initrd_size;
>> +    ram_addr_t ram_size = machine->ram_size;
>> +    const char *kernel_filename = machine->kernel_filename;
>> +    const char *initrd_filename = machine->initrd_filename;
>> +    const char *kernel_cmdline = machine->kernel_cmdline;
>> +    hwaddr parameters_base;
>> +    DeviceState *dev;
>> +    DeviceState *pic_dev[7];
>> +    GLUEState *irq;
>> +    qemu_irq *cpu_pic;
>> +    SysBusDevice *sysbus;
>> +    hwaddr io_base;
>> +    int i;
>> +
>> +
>> +    if (ram_size > 3399672 * KiB) {
>> +        /*
>> +         * The physical memory can be up to 4 GiB - 16 MiB, but linux
>> +         * kernel crashes after this limit (~ 3.2 GiB)
>> +         */
>> +        error_report("Too much memory for this machine: %" PRId64 "
>> KiB, "
>> +                     "maximum 3399672 KiB", ram_size / KiB);
>> +        exit(1);
>> +    }
>> +
>> +    /* init CPUs */
>> +    cpu = M68K_CPU(cpu_create(machine->cpu_type));
> 
> Due to BOOTINFO1(..., BI_CPUTYPE, CPU_68040) below, don't you
> need to check machine->cpu_type == M68K_CPU_TYPE_NAME("m68040")?

Yes, you're right.

68030MMU is not implemented. So we can't use other CPU than 68040.

> 
>> +    qemu_register_reset(main_cpu_reset, cpu);
>> +
>> +    /* RAM */
>> +    memory_region_add_subregion(get_system_memory(), 0, machine->ram);
>> +
>> +    /* IRQ Glue */
>> +
>> +    irq = g_new0(GLUEState, 1);
>> +    irq->cpu = cpu;
>> +    cpu_pic = qemu_allocate_irqs(GLUE_set_irq, irq, 8);
>> +
>> +    /*
>> +     * 6 goldfish-pic
>> +     *
>> +     * map: 0xff000000 - 0xff006fff = 28 KiB
>> +     * IRQ: #1 (lower priority) -> #6 (higher priority)
>> +     *
>> +     */
>> +    io_base = VIRT_GF_PIC_MMIO_BASE;
>> +    for (i = 0; i < 6; i++) {
>> +        pic_dev[i] = qdev_new(TYPE_GOLDFISH_PIC);
>> +        sysbus = SYS_BUS_DEVICE(pic_dev[i]);
>> +        sysbus_realize_and_unref(sysbus, &error_fatal);
>> +
>> +        sysbus_mmio_map(sysbus, 0, io_base);
>> +        sysbus_connect_irq(sysbus, 0, cpu_pic[i]);
>> +
>> +        io_base += 0x1000;
>> +    }
>> +
>> +    /* goldfish-rtc */
>> +    dev = qdev_new(TYPE_GOLDFISH_RTC);
>> +    sysbus = SYS_BUS_DEVICE(dev);
>> +    sysbus_realize_and_unref(sysbus, &error_fatal);
>> +    sysbus_mmio_map(sysbus, 0, VIRT_GF_RTC_MMIO_BASE);
>> +    sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_GF_RTC_IRQ_BASE));
>> +
>> +    /* goldfish-tty */
>> +    dev = qdev_new(TYPE_GOLDFISH_TTY);
>> +    sysbus = SYS_BUS_DEVICE(dev);
>> +    qdev_prop_set_chr(dev, "chardev", serial_hd(0));
>> +    sysbus_realize_and_unref(sysbus, &error_fatal);
>> +    sysbus_mmio_map(sysbus, 0, VIRT_GF_TTY_MMIO_BASE);
>> +    sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_GF_TTY_IRQ_BASE));
>> +
>> +    /* virtio-mmio */
>> +    io_base = VIRT_VIRTIO_MMIO_BASE;
>> +    for (i = 0; i < 128; i++) {
>> +        dev = qdev_new(TYPE_VIRTIO_MMIO);
>> +        qdev_prop_set_bit(dev, "force-legacy", false);
>> +        sysbus = SYS_BUS_DEVICE(dev);
>> +        sysbus_realize_and_unref(sysbus, &error_fatal);
>> +        sysbus_connect_irq(sysbus, 0, PIC_GPIO(VIRT_VIRTIO_IRQ_BASE +
>> i));
>> +        sysbus_mmio_map(sysbus, 0, io_base);
>> +        io_base += 0x200;
>> +    }
>> +
>> +    if (kernel_filename) {
>> +        CPUState *cs = CPU(cpu);
>> +        uint64_t high;
>> +
>> +        kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
>> +                               &elf_entry, NULL, &high, NULL, 1,
>> +                               EM_68K, 0, 0);
>> +        if (kernel_size < 0) {
>> +            error_report("could not load kernel '%s'", kernel_filename);
>> +            exit(1);
>> +        }
>> +        stl_phys(cs->as, 4, elf_entry); /* reset initial PC */
>> +        parameters_base = (high + 1) & ~1;
>> +
>> +        BOOTINFO1(cs->as, parameters_base, BI_MACHTYPE, MACH_VIRT);
>> +        BOOTINFO1(cs->as, parameters_base, BI_FPUTYPE, FPU_68040);
>> +        BOOTINFO1(cs->as, parameters_base, BI_MMUTYPE, MMU_68040);
>> +        BOOTINFO1(cs->as, parameters_base, BI_CPUTYPE, CPU_68040);
> 
> (see machine->cpu_type question earlier).

see answer above.

>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index d0962a22e1b4..b08cf4251246 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1101,6 +1101,15 @@ F: include/hw/nubus/*
>>   F: include/hw/display/macfb.h
>>   F: include/hw/block/swim.h
>>   +virt
> 
> Maybe "m68k virt".

We have "virt" only for ARM, RISCV, Xtensa, ...
the m68k is implied by the qemu-system-m68k

> 
>> +M: Laurent Vivier <laurent@vivier.eu>
>> +S: Maintained
>> +F: hw/m68k/virt.c
>> +F: hw/char/goldfish_tty.c
>> +F: hw/intc/goldfish_pic.c
>> +F: include/hw/char/goldfish_tty.h
>> +F: include/hw/intc/goldfish_pic.h
>> +

Thanks,
Laurent




reply via email to

[Prev in Thread] Current Thread [Next in Thread]