diff mbox series

[v6,1/2] hw/arm: Add arm SBSA reference machine, skeleton part

Message ID 1552644466-24625-2-git-send-email-hongbo.zhang@linaro.org
State Superseded
Headers show
Series Add Arm SBSA Reference Machine | expand

Commit Message

Hongbo Zhang March 15, 2019, 10:07 a.m. UTC
For the Aarch64, there is one machine 'virt', it is primarily meant to
run on KVM and execute virtualization workloads, but we need an
environment as faithful as possible to physical hardware, for supporting
firmware and OS development for pysical Aarch64 machines.

This patch introduces new machine type 'sbsa-ref' with main features:
 - Based on 'virt' machine type.
 - A new memory map.
 - CPU type cortex-a57.
 - EL2 and EL3 are enabled.
 - GIC version 3.
 - System bus AHCI controller.
 - System bus EHCI controller.
 - CDROM and hard disc on AHCI bus.
 - E1000E ethernet card on PCIE bus.
 - VGA display adaptor on PCIE bus.
 - No virtio deivces.
 - No fw_cfg device.
 - No ACPI table supplied.
 - Only minimal device tree nodes.

Arm Trusted Firmware and UEFI porting to this are done accordingly, and
it should supply ACPI tables to load OS, the minimal device tree nodes
supplied from this platform are only to pass the dynamic info reflecting
command line input to firmware, not for loading OS.

To make the review easier, this task is split into two patches, the
fundamental sceleton part and the peripheral devices part, this patch is
the first part.

Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org>

---
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Kconfig                  |   3 +
 hw/arm/Makefile.objs            |   1 +
 hw/arm/sbsa-ref.c               | 303 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 308 insertions(+)
 create mode 100644 hw/arm/sbsa-ref.c

-- 
2.7.4

Comments

Ard Biesheuvel March 15, 2019, 10:41 a.m. UTC | #1
On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:
>

> For the Aarch64, there is one machine 'virt', it is primarily meant to

> run on KVM and execute virtualization workloads, but we need an

> environment as faithful as possible to physical hardware, for supporting

> firmware and OS development for pysical Aarch64 machines.

>

> This patch introduces new machine type 'sbsa-ref' with main features:

>  - Based on 'virt' machine type.

>  - A new memory map.

>  - CPU type cortex-a57.

>  - EL2 and EL3 are enabled.

>  - GIC version 3.

>  - System bus AHCI controller.

>  - System bus EHCI controller.


Hello Hongbo,

Apologies for bringing this up now, but I seem to remember that the
EHCI does not support 64-bit DMA. Did you run into any issues with
this? Or was this fixed in QEMU in the mean time?


>  - CDROM and hard disc on AHCI bus.

>  - E1000E ethernet card on PCIE bus.

>  - VGA display adaptor on PCIE bus.

>  - No virtio deivces.

>  - No fw_cfg device.

>  - No ACPI table supplied.

>  - Only minimal device tree nodes.

>

> Arm Trusted Firmware and UEFI porting to this are done accordingly, and

> it should supply ACPI tables to load OS, the minimal device tree nodes

> supplied from this platform are only to pass the dynamic info reflecting

> command line input to firmware, not for loading OS.

>

> To make the review easier, this task is split into two patches, the

> fundamental sceleton part and the peripheral devices part, this patch is

> the first part.

>

> Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org>

> ---

>  default-configs/arm-softmmu.mak |   1 +

>  hw/arm/Kconfig                  |   3 +

>  hw/arm/Makefile.objs            |   1 +

>  hw/arm/sbsa-ref.c               | 303 ++++++++++++++++++++++++++++++++++++++++

>  4 files changed, 308 insertions(+)

>  create mode 100644 hw/arm/sbsa-ref.c

>

> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak

> index 2a7efc1..4fbb6ac 100644

> --- a/default-configs/arm-softmmu.mak

> +++ b/default-configs/arm-softmmu.mak

> @@ -144,6 +144,7 @@ CONFIG_IOH3420=y

>  CONFIG_I82801B11=y

>  CONFIG_ACPI=y

>  CONFIG_ARM_VIRT=y

> +CONFIG_SBSA_REF=y

>  CONFIG_SMBIOS=y

>  CONFIG_ASPEED_SOC=y

>  CONFIG_SMBUS_EEPROM=y

> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig

> index d298fbd..6654914 100644

> --- a/hw/arm/Kconfig

> +++ b/hw/arm/Kconfig

> @@ -38,6 +38,9 @@ config PXA2XX

>  config REALVIEW

>      bool

>

> +config SBSA_REF

> +    bool

> +

>  config STELLARIS

>      bool

>

> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs

> index fa57c7c..fa812ec 100644

> --- a/hw/arm/Makefile.objs

> +++ b/hw/arm/Makefile.objs

> @@ -12,6 +12,7 @@ obj-$(CONFIG_NSERIES) += nseries.o

>  obj-$(CONFIG_OMAP) += omap_sx1.o palm.o

>  obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o

>  obj-$(CONFIG_REALVIEW) += realview.o

> +obj-$(CONFIG_SBSA_REF) += sbsa-ref.o

>  obj-$(CONFIG_STELLARIS) += stellaris.o

>  obj-$(CONFIG_STRONGARM) += collie.o

>  obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o

> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c

> new file mode 100644

> index 0000000..b6d31f2

> --- /dev/null

> +++ b/hw/arm/sbsa-ref.c

> @@ -0,0 +1,303 @@

> +/*

> + * ARM SBSA Reference Platform emulation

> + *

> + * Copyright (c) 2018 Linaro Limited

> + * Written by Hongbo Zhang <hongbo.zhang@linaro.org>

> + *

> + * This program is free software; you can redistribute it and/or modify it

> + * under the terms and conditions of the GNU General Public License,

> + * version 2 or later, as published by the Free Software Foundation.

> + *

> + * This program is distributed in the hope it will be useful, but WITHOUT

> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for

> + * more details.

> + *

> + * You should have received a copy of the GNU General Public License along with

> + * this program.  If not, see <http://www.gnu.org/licenses/>.

> + */

> +

> +#include "qemu/osdep.h"

> +#include "qapi/error.h"

> +#include "qemu/error-report.h"

> +#include "qemu/units.h"

> +#include "sysemu/numa.h"

> +#include "sysemu/sysemu.h"

> +#include "exec/address-spaces.h"

> +#include "exec/hwaddr.h"

> +#include "kvm_arm.h"

> +#include "hw/arm/arm.h"

> +#include "hw/boards.h"

> +#include "hw/intc/arm_gicv3_common.h"

> +

> +#define RAMLIMIT_GB 8192

> +#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)

> +

> +enum {

> +    SBSA_FLASH,

> +    SBSA_MEM,

> +    SBSA_CPUPERIPHS,

> +    SBSA_GIC_DIST,

> +    SBSA_GIC_REDIST,

> +    SBSA_SMMU,

> +    SBSA_UART,

> +    SBSA_RTC,

> +    SBSA_PCIE,

> +    SBSA_PCIE_MMIO,

> +    SBSA_PCIE_MMIO_HIGH,

> +    SBSA_PCIE_PIO,

> +    SBSA_PCIE_ECAM,

> +    SBSA_GPIO,

> +    SBSA_SECURE_UART,

> +    SBSA_SECURE_MEM,

> +    SBSA_AHCI,

> +    SBSA_EHCI,

> +};

> +

> +typedef struct MemMapEntry {

> +    hwaddr base;

> +    hwaddr size;

> +} MemMapEntry;

> +

> +typedef struct {

> +    MachineState parent;

> +    struct arm_boot_info bootinfo;

> +    const MemMapEntry *memmap;

> +    const int *irqmap;

> +    int smp_cpus;

> +    void *fdt;

> +    int fdt_size;

> +    int psci_conduit;

> +} SBSAMachineState;

> +

> +#define TYPE_SBSA_MACHINE   MACHINE_TYPE_NAME("sbsa-ref")

> +#define SBSA_MACHINE(obj) \

> +    OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE)

> +

> +static const MemMapEntry sbsa_ref_memmap[] = {

> +    /* 512M boot ROM */

> +    [SBSA_FLASH] =              {          0, 0x20000000 },

> +    /* 512M secure memory */

> +    [SBSA_SECURE_MEM] =         { 0x20000000, 0x20000000 },

> +    /* Space reserved for CPU peripheral devices */

> +    [SBSA_CPUPERIPHS] =         { 0x40000000, 0x00040000 },

> +    [SBSA_GIC_DIST] =           { 0x40060000, 0x00010000 },

> +    [SBSA_GIC_REDIST] =         { 0x40080000, 0x04000000 },

> +    [SBSA_UART] =               { 0x60000000, 0x00001000 },

> +    [SBSA_RTC] =                { 0x60010000, 0x00001000 },

> +    [SBSA_GPIO] =               { 0x60020000, 0x00001000 },

> +    [SBSA_SECURE_UART] =        { 0x60030000, 0x00001000 },

> +    [SBSA_SMMU] =               { 0x60040000, 0x00020000 },

> +    /* Space here reserved for more SMMUs */

> +    [SBSA_AHCI] =               { 0x60100000, 0x00010000 },

> +    [SBSA_EHCI] =               { 0x60110000, 0x00010000 },

> +    /* Space here reserved for other devices */

> +    [SBSA_PCIE_PIO] =           { 0x7fff0000, 0x00010000 },

> +    /* 256M PCIE ECAM space */

> +    [SBSA_PCIE_ECAM] =          { 0x80000000, 0x10000000 },

> +    /* 32-bit address PCIE MMIO space */

> +    [SBSA_PCIE_MMIO] =          { 0x90000000, 0x70000000 },


Can we swap these around? I.e., MMIO first and then ECAM? That way,
the MMIO base is aligned to the size of the largest BAR it can support
(0x4000_0000), which is a bit cleaner, and less likely to cause
problems with PCI resource allocators.

> +    /* ~1TB PCIE MMIO space (4GB to 1024GB boundary) */

> +    [SBSA_PCIE_MMIO_HIGH] =     { 0x100000000ULL, 0xFF00000000ULL },

> +    [SBSA_MEM] =                { 0x10000000000ULL, RAMLIMIT_BYTES },

> +};

> +

> +static const int sbsa_ref_irqmap[] = {

> +    [SBSA_UART] = 1,

> +    [SBSA_RTC] = 2,

> +    [SBSA_PCIE] = 3, /* ... to 6 */

> +    [SBSA_GPIO] = 7,

> +    [SBSA_SECURE_UART] = 8,

> +    [SBSA_AHCI] = 9,

> +    [SBSA_EHCI] = 10,

> +};

> +

> +static void sbsa_ref_init(MachineState *machine)

> +{

> +    SBSAMachineState *vms = SBSA_MACHINE(machine);

> +    MachineClass *mc = MACHINE_GET_CLASS(machine);

> +    MemoryRegion *sysmem = get_system_memory();

> +    MemoryRegion *secure_sysmem = NULL;

> +    MemoryRegion *ram = g_new(MemoryRegion, 1);

> +    bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);

> +    const CPUArchIdList *possible_cpus;

> +    int n, sbsa_max_cpus;

> +

> +    if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {

> +        error_report("sbsa-ref: CPU type other than the built-in "

> +                     "cortex-a57 not supported");

> +        exit(1);

> +    }

> +

> +    if (kvm_enabled()) {

> +        error_report("sbsa-ref: KVM is not supported at this machine");

> +        exit(1);

> +    }

> +

> +    if (machine->kernel_filename && firmware_loaded) {

> +        error_report("sbsa-ref: No fw_cfg device on this machine, "

> +                     "so -kernel option is not supported when firmware loaded, "

> +                     "please load OS from hard disk instead");

> +        exit(1);

> +    }

> +

> +    /*

> +     * This machine has EL3 enabled, external firmware should supply PSCI

> +     * implementation, so the QEMU's internal PSCI is disabled.

> +     */

> +    vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;

> +

> +    sbsa_max_cpus = vms->memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE;

> +

> +    if (max_cpus > sbsa_max_cpus) {

> +        error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "

> +                     "supported by machine 'sbsa-ref' (%d)",

> +                     max_cpus, sbsa_max_cpus);

> +        exit(1);

> +    }

> +

> +    vms->smp_cpus = smp_cpus;

> +

> +    if (machine->ram_size > vms->memmap[SBSA_MEM].size) {

> +        error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB);

> +        exit(1);

> +    }

> +

> +    secure_sysmem = g_new(MemoryRegion, 1);

> +    memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",

> +                       UINT64_MAX);

> +    memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);

> +

> +    possible_cpus = mc->possible_cpu_arch_ids(machine);

> +    for (n = 0; n < possible_cpus->len; n++) {

> +        Object *cpuobj;

> +        CPUState *cs;

> +

> +        if (n >= smp_cpus) {

> +            break;

> +        }

> +

> +        cpuobj = object_new(possible_cpus->cpus[n].type);

> +        object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,

> +                                "mp-affinity", NULL);

> +

> +        cs = CPU(cpuobj);

> +        cs->cpu_index = n;

> +

> +        numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),

> +                          &error_fatal);

> +

> +        if (object_property_find(cpuobj, "reset-cbar", NULL)) {

> +            object_property_set_int(cpuobj, vms->memmap[SBSA_CPUPERIPHS].base,

> +                                    "reset-cbar", &error_abort);

> +        }

> +

> +        object_property_set_link(cpuobj, OBJECT(sysmem), "memory",

> +                                 &error_abort);

> +

> +        object_property_set_link(cpuobj, OBJECT(secure_sysmem),

> +                                 "secure-memory", &error_abort);

> +

> +        object_property_set_bool(cpuobj, true, "realized", &error_fatal);

> +        object_unref(cpuobj);

> +    }

> +

> +    memory_region_allocate_system_memory(ram, NULL, "sbsa-ref.ram",

> +                                         machine->ram_size);

> +    memory_region_add_subregion(sysmem, vms->memmap[SBSA_MEM].base, ram);

> +

> +    vms->bootinfo.ram_size = machine->ram_size;

> +    vms->bootinfo.kernel_filename = machine->kernel_filename;

> +    vms->bootinfo.nb_cpus = smp_cpus;

> +    vms->bootinfo.board_id = -1;

> +    vms->bootinfo.loader_start = vms->memmap[SBSA_MEM].base;

> +    vms->bootinfo.firmware_loaded = firmware_loaded;

> +    arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo);

> +}

> +

> +static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *vms, int idx)

> +{

> +    uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;

> +    return arm_cpu_mp_affinity(idx, clustersz);

> +}

> +

> +static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)

> +{

> +    SBSAMachineState *vms = SBSA_MACHINE(ms);

> +    int n;

> +

> +    if (ms->possible_cpus) {

> +        assert(ms->possible_cpus->len == max_cpus);

> +        return ms->possible_cpus;

> +    }

> +

> +    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +

> +                                  sizeof(CPUArchId) * max_cpus);

> +    ms->possible_cpus->len = max_cpus;

> +    for (n = 0; n < ms->possible_cpus->len; n++) {

> +        ms->possible_cpus->cpus[n].type = ms->cpu_type;

> +        ms->possible_cpus->cpus[n].arch_id =

> +            sbsa_ref_cpu_mp_affinity(vms, n);

> +        ms->possible_cpus->cpus[n].props.has_thread_id = true;

> +        ms->possible_cpus->cpus[n].props.thread_id = n;

> +    }

> +    return ms->possible_cpus;

> +}

> +

> +static CpuInstanceProperties

> +sbsa_ref_cpu_index_to_props(MachineState *ms, unsigned cpu_index)

> +{

> +    MachineClass *mc = MACHINE_GET_CLASS(ms);

> +    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);

> +

> +    assert(cpu_index < possible_cpus->len);

> +    return possible_cpus->cpus[cpu_index].props;

> +}

> +

> +static int64_t

> +sbsa_ref_get_default_cpu_node_id(const MachineState *ms, int idx)

> +{

> +    return idx % nb_numa_nodes;

> +}

> +

> +static void sbsa_ref_instance_init(Object *obj)

> +{

> +    SBSAMachineState *vms = SBSA_MACHINE(obj);

> +

> +    vms->memmap = sbsa_ref_memmap;

> +    vms->irqmap = sbsa_ref_irqmap;

> +}

> +

> +static void sbsa_ref_class_init(ObjectClass *oc, void *data)

> +{

> +    MachineClass *mc = MACHINE_CLASS(oc);

> +

> +    mc->init = sbsa_ref_init;

> +    mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";

> +    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");

> +    mc->max_cpus = 512;

> +    mc->pci_allow_0_address = true;

> +    mc->minimum_page_bits = 12;

> +    mc->block_default_type = IF_IDE;

> +    mc->no_cdrom = 1;

> +    mc->default_ram_size = 1 * GiB;

> +    mc->default_cpus = 4;

> +    mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;

> +    mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;

> +    mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id;

> +}

> +

> +static const TypeInfo sbsa_ref_info = {

> +    .name          = TYPE_SBSA_MACHINE,

> +    .parent        = TYPE_MACHINE,

> +    .instance_size = sizeof(SBSAMachineState),

> +    .instance_init = sbsa_ref_instance_init,

> +    .class_init    = sbsa_ref_class_init,

> +};

> +

> +static void sbsa_ref_machine_init(void)

> +{

> +    type_register_static(&sbsa_ref_info);

> +}

> +

> +type_init(sbsa_ref_machine_init);

> --

> 2.7.4

>
Hongbo Zhang March 18, 2019, 2:39 a.m. UTC | #2
On Fri, 15 Mar 2019 at 18:41, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>

> On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> >

> > For the Aarch64, there is one machine 'virt', it is primarily meant to

> > run on KVM and execute virtualization workloads, but we need an

> > environment as faithful as possible to physical hardware, for supporting

> > firmware and OS development for pysical Aarch64 machines.

> >

> > This patch introduces new machine type 'sbsa-ref' with main features:

> >  - Based on 'virt' machine type.

> >  - A new memory map.

> >  - CPU type cortex-a57.

> >  - EL2 and EL3 are enabled.

> >  - GIC version 3.

> >  - System bus AHCI controller.

> >  - System bus EHCI controller.

>

> Hello Hongbo,

>

> Apologies for bringing this up now, but I seem to remember that the

> EHCI does not support 64-bit DMA. Did you run into any issues with

> this? Or was this fixed in QEMU in the mean time?

>

Hi Ard,
Which EHCI do you mean?
This time I use a newly introduced system bus EHCI, commit 114529f7
and I only tested USB mouse and key board, didn't test DMA function.

>

> >  - CDROM and hard disc on AHCI bus.

> >  - E1000E ethernet card on PCIE bus.

> >  - VGA display adaptor on PCIE bus.

> >  - No virtio deivces.

> >  - No fw_cfg device.

> >  - No ACPI table supplied.

> >  - Only minimal device tree nodes.

> >

> > Arm Trusted Firmware and UEFI porting to this are done accordingly, and

> > it should supply ACPI tables to load OS, the minimal device tree nodes

> > supplied from this platform are only to pass the dynamic info reflecting

> > command line input to firmware, not for loading OS.

> >

> > To make the review easier, this task is split into two patches, the

> > fundamental sceleton part and the peripheral devices part, this patch is

> > the first part.

> >

> > Signed-off-by: Hongbo Zhang <hongbo.zhang@linaro.org>

> > ---

> >  default-configs/arm-softmmu.mak |   1 +

> >  hw/arm/Kconfig                  |   3 +

> >  hw/arm/Makefile.objs            |   1 +

> >  hw/arm/sbsa-ref.c               | 303 ++++++++++++++++++++++++++++++++++++++++

> >  4 files changed, 308 insertions(+)

> >  create mode 100644 hw/arm/sbsa-ref.c

> >

> > diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak

> > index 2a7efc1..4fbb6ac 100644

> > --- a/default-configs/arm-softmmu.mak

> > +++ b/default-configs/arm-softmmu.mak

> > @@ -144,6 +144,7 @@ CONFIG_IOH3420=y

> >  CONFIG_I82801B11=y

> >  CONFIG_ACPI=y

> >  CONFIG_ARM_VIRT=y

> > +CONFIG_SBSA_REF=y

> >  CONFIG_SMBIOS=y

> >  CONFIG_ASPEED_SOC=y

> >  CONFIG_SMBUS_EEPROM=y

> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig

> > index d298fbd..6654914 100644

> > --- a/hw/arm/Kconfig

> > +++ b/hw/arm/Kconfig

> > @@ -38,6 +38,9 @@ config PXA2XX

> >  config REALVIEW

> >      bool

> >

> > +config SBSA_REF

> > +    bool

> > +

> >  config STELLARIS

> >      bool

> >

> > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs

> > index fa57c7c..fa812ec 100644

> > --- a/hw/arm/Makefile.objs

> > +++ b/hw/arm/Makefile.objs

> > @@ -12,6 +12,7 @@ obj-$(CONFIG_NSERIES) += nseries.o

> >  obj-$(CONFIG_OMAP) += omap_sx1.o palm.o

> >  obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o

> >  obj-$(CONFIG_REALVIEW) += realview.o

> > +obj-$(CONFIG_SBSA_REF) += sbsa-ref.o

> >  obj-$(CONFIG_STELLARIS) += stellaris.o

> >  obj-$(CONFIG_STRONGARM) += collie.o

> >  obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o

> > diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c

> > new file mode 100644

> > index 0000000..b6d31f2

> > --- /dev/null

> > +++ b/hw/arm/sbsa-ref.c

> > @@ -0,0 +1,303 @@

> > +/*

> > + * ARM SBSA Reference Platform emulation

> > + *

> > + * Copyright (c) 2018 Linaro Limited

> > + * Written by Hongbo Zhang <hongbo.zhang@linaro.org>

> > + *

> > + * This program is free software; you can redistribute it and/or modify it

> > + * under the terms and conditions of the GNU General Public License,

> > + * version 2 or later, as published by the Free Software Foundation.

> > + *

> > + * This program is distributed in the hope it will be useful, but WITHOUT

> > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

> > + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for

> > + * more details.

> > + *

> > + * You should have received a copy of the GNU General Public License along with

> > + * this program.  If not, see <http://www.gnu.org/licenses/>.

> > + */

> > +

> > +#include "qemu/osdep.h"

> > +#include "qapi/error.h"

> > +#include "qemu/error-report.h"

> > +#include "qemu/units.h"

> > +#include "sysemu/numa.h"

> > +#include "sysemu/sysemu.h"

> > +#include "exec/address-spaces.h"

> > +#include "exec/hwaddr.h"

> > +#include "kvm_arm.h"

> > +#include "hw/arm/arm.h"

> > +#include "hw/boards.h"

> > +#include "hw/intc/arm_gicv3_common.h"

> > +

> > +#define RAMLIMIT_GB 8192

> > +#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)

> > +

> > +enum {

> > +    SBSA_FLASH,

> > +    SBSA_MEM,

> > +    SBSA_CPUPERIPHS,

> > +    SBSA_GIC_DIST,

> > +    SBSA_GIC_REDIST,

> > +    SBSA_SMMU,

> > +    SBSA_UART,

> > +    SBSA_RTC,

> > +    SBSA_PCIE,

> > +    SBSA_PCIE_MMIO,

> > +    SBSA_PCIE_MMIO_HIGH,

> > +    SBSA_PCIE_PIO,

> > +    SBSA_PCIE_ECAM,

> > +    SBSA_GPIO,

> > +    SBSA_SECURE_UART,

> > +    SBSA_SECURE_MEM,

> > +    SBSA_AHCI,

> > +    SBSA_EHCI,

> > +};

> > +

> > +typedef struct MemMapEntry {

> > +    hwaddr base;

> > +    hwaddr size;

> > +} MemMapEntry;

> > +

> > +typedef struct {

> > +    MachineState parent;

> > +    struct arm_boot_info bootinfo;

> > +    const MemMapEntry *memmap;

> > +    const int *irqmap;

> > +    int smp_cpus;

> > +    void *fdt;

> > +    int fdt_size;

> > +    int psci_conduit;

> > +} SBSAMachineState;

> > +

> > +#define TYPE_SBSA_MACHINE   MACHINE_TYPE_NAME("sbsa-ref")

> > +#define SBSA_MACHINE(obj) \

> > +    OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE)

> > +

> > +static const MemMapEntry sbsa_ref_memmap[] = {

> > +    /* 512M boot ROM */

> > +    [SBSA_FLASH] =              {          0, 0x20000000 },

> > +    /* 512M secure memory */

> > +    [SBSA_SECURE_MEM] =         { 0x20000000, 0x20000000 },

> > +    /* Space reserved for CPU peripheral devices */

> > +    [SBSA_CPUPERIPHS] =         { 0x40000000, 0x00040000 },

> > +    [SBSA_GIC_DIST] =           { 0x40060000, 0x00010000 },

> > +    [SBSA_GIC_REDIST] =         { 0x40080000, 0x04000000 },

> > +    [SBSA_UART] =               { 0x60000000, 0x00001000 },

> > +    [SBSA_RTC] =                { 0x60010000, 0x00001000 },

> > +    [SBSA_GPIO] =               { 0x60020000, 0x00001000 },

> > +    [SBSA_SECURE_UART] =        { 0x60030000, 0x00001000 },

> > +    [SBSA_SMMU] =               { 0x60040000, 0x00020000 },

> > +    /* Space here reserved for more SMMUs */

> > +    [SBSA_AHCI] =               { 0x60100000, 0x00010000 },

> > +    [SBSA_EHCI] =               { 0x60110000, 0x00010000 },

> > +    /* Space here reserved for other devices */

> > +    [SBSA_PCIE_PIO] =           { 0x7fff0000, 0x00010000 },

> > +    /* 256M PCIE ECAM space */

> > +    [SBSA_PCIE_ECAM] =          { 0x80000000, 0x10000000 },

> > +    /* 32-bit address PCIE MMIO space */

> > +    [SBSA_PCIE_MMIO] =          { 0x90000000, 0x70000000 },

>

> Can we swap these around? I.e., MMIO first and then ECAM? That way,

> the MMIO base is aligned to the size of the largest BAR it can support

> (0x4000_0000), which is a bit cleaner, and less likely to cause

> problems with PCI resource allocators.

>

Yes sure.

> > +    /* ~1TB PCIE MMIO space (4GB to 1024GB boundary) */

> > +    [SBSA_PCIE_MMIO_HIGH] =     { 0x100000000ULL, 0xFF00000000ULL },

> > +    [SBSA_MEM] =                { 0x10000000000ULL, RAMLIMIT_BYTES },

> > +};

> > +

> > +static const int sbsa_ref_irqmap[] = {

> > +    [SBSA_UART] = 1,

> > +    [SBSA_RTC] = 2,

> > +    [SBSA_PCIE] = 3, /* ... to 6 */

> > +    [SBSA_GPIO] = 7,

> > +    [SBSA_SECURE_UART] = 8,

> > +    [SBSA_AHCI] = 9,

> > +    [SBSA_EHCI] = 10,

> > +};

> > +

> > +static void sbsa_ref_init(MachineState *machine)

> > +{

> > +    SBSAMachineState *vms = SBSA_MACHINE(machine);

> > +    MachineClass *mc = MACHINE_GET_CLASS(machine);

> > +    MemoryRegion *sysmem = get_system_memory();

> > +    MemoryRegion *secure_sysmem = NULL;

> > +    MemoryRegion *ram = g_new(MemoryRegion, 1);

> > +    bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);

> > +    const CPUArchIdList *possible_cpus;

> > +    int n, sbsa_max_cpus;

> > +

> > +    if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {

> > +        error_report("sbsa-ref: CPU type other than the built-in "

> > +                     "cortex-a57 not supported");

> > +        exit(1);

> > +    }

> > +

> > +    if (kvm_enabled()) {

> > +        error_report("sbsa-ref: KVM is not supported at this machine");

> > +        exit(1);

> > +    }

> > +

> > +    if (machine->kernel_filename && firmware_loaded) {

> > +        error_report("sbsa-ref: No fw_cfg device on this machine, "

> > +                     "so -kernel option is not supported when firmware loaded, "

> > +                     "please load OS from hard disk instead");

> > +        exit(1);

> > +    }

> > +

> > +    /*

> > +     * This machine has EL3 enabled, external firmware should supply PSCI

> > +     * implementation, so the QEMU's internal PSCI is disabled.

> > +     */

> > +    vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;

> > +

> > +    sbsa_max_cpus = vms->memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE;

> > +

> > +    if (max_cpus > sbsa_max_cpus) {

> > +        error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "

> > +                     "supported by machine 'sbsa-ref' (%d)",

> > +                     max_cpus, sbsa_max_cpus);

> > +        exit(1);

> > +    }

> > +

> > +    vms->smp_cpus = smp_cpus;

> > +

> > +    if (machine->ram_size > vms->memmap[SBSA_MEM].size) {

> > +        error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB);

> > +        exit(1);

> > +    }

> > +

> > +    secure_sysmem = g_new(MemoryRegion, 1);

> > +    memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",

> > +                       UINT64_MAX);

> > +    memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);

> > +

> > +    possible_cpus = mc->possible_cpu_arch_ids(machine);

> > +    for (n = 0; n < possible_cpus->len; n++) {

> > +        Object *cpuobj;

> > +        CPUState *cs;

> > +

> > +        if (n >= smp_cpus) {

> > +            break;

> > +        }

> > +

> > +        cpuobj = object_new(possible_cpus->cpus[n].type);

> > +        object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,

> > +                                "mp-affinity", NULL);

> > +

> > +        cs = CPU(cpuobj);

> > +        cs->cpu_index = n;

> > +

> > +        numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),

> > +                          &error_fatal);

> > +

> > +        if (object_property_find(cpuobj, "reset-cbar", NULL)) {

> > +            object_property_set_int(cpuobj, vms->memmap[SBSA_CPUPERIPHS].base,

> > +                                    "reset-cbar", &error_abort);

> > +        }

> > +

> > +        object_property_set_link(cpuobj, OBJECT(sysmem), "memory",

> > +                                 &error_abort);

> > +

> > +        object_property_set_link(cpuobj, OBJECT(secure_sysmem),

> > +                                 "secure-memory", &error_abort);

> > +

> > +        object_property_set_bool(cpuobj, true, "realized", &error_fatal);

> > +        object_unref(cpuobj);

> > +    }

> > +

> > +    memory_region_allocate_system_memory(ram, NULL, "sbsa-ref.ram",

> > +                                         machine->ram_size);

> > +    memory_region_add_subregion(sysmem, vms->memmap[SBSA_MEM].base, ram);

> > +

> > +    vms->bootinfo.ram_size = machine->ram_size;

> > +    vms->bootinfo.kernel_filename = machine->kernel_filename;

> > +    vms->bootinfo.nb_cpus = smp_cpus;

> > +    vms->bootinfo.board_id = -1;

> > +    vms->bootinfo.loader_start = vms->memmap[SBSA_MEM].base;

> > +    vms->bootinfo.firmware_loaded = firmware_loaded;

> > +    arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo);

> > +}

> > +

> > +static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *vms, int idx)

> > +{

> > +    uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;

> > +    return arm_cpu_mp_affinity(idx, clustersz);

> > +}

> > +

> > +static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)

> > +{

> > +    SBSAMachineState *vms = SBSA_MACHINE(ms);

> > +    int n;

> > +

> > +    if (ms->possible_cpus) {

> > +        assert(ms->possible_cpus->len == max_cpus);

> > +        return ms->possible_cpus;

> > +    }

> > +

> > +    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +

> > +                                  sizeof(CPUArchId) * max_cpus);

> > +    ms->possible_cpus->len = max_cpus;

> > +    for (n = 0; n < ms->possible_cpus->len; n++) {

> > +        ms->possible_cpus->cpus[n].type = ms->cpu_type;

> > +        ms->possible_cpus->cpus[n].arch_id =

> > +            sbsa_ref_cpu_mp_affinity(vms, n);

> > +        ms->possible_cpus->cpus[n].props.has_thread_id = true;

> > +        ms->possible_cpus->cpus[n].props.thread_id = n;

> > +    }

> > +    return ms->possible_cpus;

> > +}

> > +

> > +static CpuInstanceProperties

> > +sbsa_ref_cpu_index_to_props(MachineState *ms, unsigned cpu_index)

> > +{

> > +    MachineClass *mc = MACHINE_GET_CLASS(ms);

> > +    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);

> > +

> > +    assert(cpu_index < possible_cpus->len);

> > +    return possible_cpus->cpus[cpu_index].props;

> > +}

> > +

> > +static int64_t

> > +sbsa_ref_get_default_cpu_node_id(const MachineState *ms, int idx)

> > +{

> > +    return idx % nb_numa_nodes;

> > +}

> > +

> > +static void sbsa_ref_instance_init(Object *obj)

> > +{

> > +    SBSAMachineState *vms = SBSA_MACHINE(obj);

> > +

> > +    vms->memmap = sbsa_ref_memmap;

> > +    vms->irqmap = sbsa_ref_irqmap;

> > +}

> > +

> > +static void sbsa_ref_class_init(ObjectClass *oc, void *data)

> > +{

> > +    MachineClass *mc = MACHINE_CLASS(oc);

> > +

> > +    mc->init = sbsa_ref_init;

> > +    mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";

> > +    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");

> > +    mc->max_cpus = 512;

> > +    mc->pci_allow_0_address = true;

> > +    mc->minimum_page_bits = 12;

> > +    mc->block_default_type = IF_IDE;

> > +    mc->no_cdrom = 1;

> > +    mc->default_ram_size = 1 * GiB;

> > +    mc->default_cpus = 4;

> > +    mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;

> > +    mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;

> > +    mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id;

> > +}

> > +

> > +static const TypeInfo sbsa_ref_info = {

> > +    .name          = TYPE_SBSA_MACHINE,

> > +    .parent        = TYPE_MACHINE,

> > +    .instance_size = sizeof(SBSAMachineState),

> > +    .instance_init = sbsa_ref_instance_init,

> > +    .class_init    = sbsa_ref_class_init,

> > +};

> > +

> > +static void sbsa_ref_machine_init(void)

> > +{

> > +    type_register_static(&sbsa_ref_info);

> > +}

> > +

> > +type_init(sbsa_ref_machine_init);

> > --

> > 2.7.4

> >
Ard Biesheuvel March 20, 2019, 10:27 a.m. UTC | #3
On Mon, 18 Mar 2019 at 03:39, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:
>

> On Fri, 15 Mar 2019 at 18:41, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

> >

> > On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> > >

> > > For the Aarch64, there is one machine 'virt', it is primarily meant to

> > > run on KVM and execute virtualization workloads, but we need an

> > > environment as faithful as possible to physical hardware, for supporting

> > > firmware and OS development for pysical Aarch64 machines.

> > >

> > > This patch introduces new machine type 'sbsa-ref' with main features:

> > >  - Based on 'virt' machine type.

> > >  - A new memory map.

> > >  - CPU type cortex-a57.

> > >  - EL2 and EL3 are enabled.

> > >  - GIC version 3.

> > >  - System bus AHCI controller.

> > >  - System bus EHCI controller.

> >

> > Hello Hongbo,

> >

> > Apologies for bringing this up now, but I seem to remember that the

> > EHCI does not support 64-bit DMA. Did you run into any issues with

> > this? Or was this fixed in QEMU in the mean time?

> >

> Hi Ard,

> Which EHCI do you mean?

> This time I use a newly introduced system bus EHCI, commit 114529f7

> and I only tested USB mouse and key board, didn't test DMA function.

>


The host controller doesn't work without DMA, so if mouse and keyboard
worked for you, and no DRAM exists below the 4 GB mark, this has
apparently been fixed in QEMU.
Hongbo Zhang April 4, 2019, 8:27 a.m. UTC | #4
I would like to wait for more days to see if there are any further
comments, and if no I will send another iteration with memory map
slightly changed.

On Wed, 20 Mar 2019 at 18:27, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
>

> On Mon, 18 Mar 2019 at 03:39, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> >

> > On Fri, 15 Mar 2019 at 18:41, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

> > >

> > > On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> > > >

> > > > For the Aarch64, there is one machine 'virt', it is primarily meant to

> > > > run on KVM and execute virtualization workloads, but we need an

> > > > environment as faithful as possible to physical hardware, for supporting

> > > > firmware and OS development for pysical Aarch64 machines.

> > > >

> > > > This patch introduces new machine type 'sbsa-ref' with main features:

> > > >  - Based on 'virt' machine type.

> > > >  - A new memory map.

> > > >  - CPU type cortex-a57.

> > > >  - EL2 and EL3 are enabled.

> > > >  - GIC version 3.

> > > >  - System bus AHCI controller.

> > > >  - System bus EHCI controller.

> > >

> > > Hello Hongbo,

> > >

> > > Apologies for bringing this up now, but I seem to remember that the

> > > EHCI does not support 64-bit DMA. Did you run into any issues with

> > > this? Or was this fixed in QEMU in the mean time?

> > >

> > Hi Ard,

> > Which EHCI do you mean?

> > This time I use a newly introduced system bus EHCI, commit 114529f7

> > and I only tested USB mouse and key board, didn't test DMA function.

> >

>

> The host controller doesn't work without DMA, so if mouse and keyboard

> worked for you, and no DRAM exists below the 4 GB mark, this has

> apparently been fixed in QEMU.
Peter Maydell April 4, 2019, 8:47 a.m. UTC | #5
On Thu, 4 Apr 2019 at 15:27, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:
> I would like to wait for more days to see if there are any further

> comments, and if no I will send another iteration with memory map

> slightly changed.


This is on my to-review list, but I've been a bit busy with work for
the 4.0 release -- sorry I haven't been able to get to this yet. I'll
try to have at least a first look over the next day or so, but I can't
promise I'll manage that, so please go ahead and send out your next
iteration whenever you're ready to do that.

thanks
-- PMM
Radoslaw Biernacki April 4, 2019, 8:50 a.m. UTC | #6
There is one additional need which we just discovered with Fu Wei.
We need second secure UART for RAS and MM from EL0.
I'm adding a patch here (not sure if addresses and IRQ's are in your style
so please check those).
I will adapt FW to your changes in next patch.

From fbc84e29b966f94a27fe84195987e6ba0c55c1bc Mon Sep 17 00:00:00 2001
From: Radoslaw Biernacki <radoslaw.biernacki@gmail.com>

Date: Thu, 4 Apr 2019 14:41:21 +0700
Subject: [PATCH] Add 2nd secure uart Rebase of Fu Wei patch

---
 hw/arm/sbsa-ref.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
index 6b26111840..dcfb34ff5b 100644
--- a/hw/arm/sbsa-ref.c
+++ b/hw/arm/sbsa-ref.c
@@ -67,6 +67,7 @@ enum {
     SBSA_PCIE_ECAM,
     SBSA_GPIO,
     SBSA_SECURE_UART,
+    SBSA_SECURE_UART_MM,
     SBSA_SECURE_MEM,
     SBSA_AHCI,
     SBSA_EHCI,
@@ -105,7 +106,9 @@ static const MemMapEntry sbsa_ref_memmap[] = {
     [SBSA_RTC] =                { 0x60010000, 0x00001000 },
     [SBSA_GPIO] =               { 0x60020000, 0x00001000 },
     [SBSA_SECURE_UART] =        { 0x60030000, 0x00001000 },
-    [SBSA_SMMU] =               { 0x60040000, 0x00020000 },
+    /* The UART is a secure UART for S-EL0 OS testing */
+    [SBSA_SECURE_UART_MM] =     { 0x60040000, 0x00001000 },
+    [SBSA_SMMU] =               { 0x60050000, 0x00020000 },
     /* Space here reserved for more SMMUs */
     [SBSA_AHCI] =               { 0x60100000, 0x00010000 },
     [SBSA_EHCI] =               { 0x60110000, 0x00010000 },
@@ -126,8 +129,9 @@ static const int sbsa_ref_irqmap[] = {
     [SBSA_PCIE] = 3, /* ... to 6 */
     [SBSA_GPIO] = 7,
     [SBSA_SECURE_UART] = 8,
-    [SBSA_AHCI] = 9,
-    [SBSA_EHCI] = 10,
+    [SBSA_SECURE_UART_MM] = 9,
+    [SBSA_AHCI] = 10,
+    [SBSA_EHCI] = 11,
 };

 /*
@@ -645,6 +649,7 @@ static void sbsa_ref_init(MachineState *machine)
     create_uart(vms, pic, SBSA_UART, sysmem, serial_hd(0));

     create_uart(vms, pic, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
+    create_uart(vms, pic, SBSA_SECURE_UART_MM, secure_sysmem,
serial_hd(2));

     create_rtc(vms, pic);

-- 
2.17.1


On Thu, 4 Apr 2019 at 15:27, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> I would like to wait for more days to see if there are any further

> comments, and if no I will send another iteration with memory map

> slightly changed.

>

> On Wed, 20 Mar 2019 at 18:27, Ard Biesheuvel <ard.biesheuvel@linaro.org>

> wrote:

> >

> > On Mon, 18 Mar 2019 at 03:39, Hongbo Zhang <hongbo.zhang@linaro.org>

> wrote:

> > >

> > > On Fri, 15 Mar 2019 at 18:41, Ard Biesheuvel <

> ard.biesheuvel@linaro.org> wrote:

> > > >

> > > > On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org>

> wrote:

> > > > >

> > > > > For the Aarch64, there is one machine 'virt', it is primarily

> meant to

> > > > > run on KVM and execute virtualization workloads, but we need an

> > > > > environment as faithful as possible to physical hardware, for

> supporting

> > > > > firmware and OS development for pysical Aarch64 machines.

> > > > >

> > > > > This patch introduces new machine type 'sbsa-ref' with main

> features:

> > > > >  - Based on 'virt' machine type.

> > > > >  - A new memory map.

> > > > >  - CPU type cortex-a57.

> > > > >  - EL2 and EL3 are enabled.

> > > > >  - GIC version 3.

> > > > >  - System bus AHCI controller.

> > > > >  - System bus EHCI controller.

> > > >

> > > > Hello Hongbo,

> > > >

> > > > Apologies for bringing this up now, but I seem to remember that the

> > > > EHCI does not support 64-bit DMA. Did you run into any issues with

> > > > this? Or was this fixed in QEMU in the mean time?

> > > >

> > > Hi Ard,

> > > Which EHCI do you mean?

> > > This time I use a newly introduced system bus EHCI, commit 114529f7

> > > and I only tested USB mouse and key board, didn't test DMA function.

> > >

> >

> > The host controller doesn't work without DMA, so if mouse and keyboard

> > worked for you, and no DRAM exists below the 4 GB mark, this has

> > apparently been fixed in QEMU.

>
Hongbo Zhang April 4, 2019, 8:53 a.m. UTC | #7
On Thu, 4 Apr 2019 at 16:47, Peter Maydell <peter.maydell@linaro.org> wrote:
>

> On Thu, 4 Apr 2019 at 15:27, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

> > I would like to wait for more days to see if there are any further

> > comments, and if no I will send another iteration with memory map

> > slightly changed.

>

> This is on my to-review list, but I've been a bit busy with work for

> the 4.0 release -- sorry I haven't been able to get to this yet. I'll

> try to have at least a first look over the next day or so, but I can't

> promise I'll manage that, so please go ahead and send out your next

> iteration whenever you're ready to do that.

>

Understand, thanks.

> thanks

> -- PMM
Hongbo Zhang April 4, 2019, 8:56 a.m. UTC | #8
On Thu, 4 Apr 2019 at 16:51, Radoslaw Biernacki
<radoslaw.biernacki@linaro.org> wrote:
>

> There is one additional need which we just discovered with Fu Wei.

> We need second secure UART for RAS and MM from EL0.

> I'm adding a patch here (not sure if addresses and IRQ's are in your style so please check those).

> I will adapt FW to your changes in next patch.

>

OK, I will take this into my next version of patch.
Thanks.

> From fbc84e29b966f94a27fe84195987e6ba0c55c1bc Mon Sep 17 00:00:00 2001

> From: Radoslaw Biernacki <radoslaw.biernacki@gmail.com>

> Date: Thu, 4 Apr 2019 14:41:21 +0700

> Subject: [PATCH] Add 2nd secure uart Rebase of Fu Wei patch

>

> ---

>  hw/arm/sbsa-ref.c | 11 ++++++++---

>  1 file changed, 8 insertions(+), 3 deletions(-)

>

> diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c

> index 6b26111840..dcfb34ff5b 100644

> --- a/hw/arm/sbsa-ref.c

> +++ b/hw/arm/sbsa-ref.c

> @@ -67,6 +67,7 @@ enum {

>      SBSA_PCIE_ECAM,

>      SBSA_GPIO,

>      SBSA_SECURE_UART,

> +    SBSA_SECURE_UART_MM,

>      SBSA_SECURE_MEM,

>      SBSA_AHCI,

>      SBSA_EHCI,

> @@ -105,7 +106,9 @@ static const MemMapEntry sbsa_ref_memmap[] = {

>      [SBSA_RTC] =                { 0x60010000, 0x00001000 },

>      [SBSA_GPIO] =               { 0x60020000, 0x00001000 },

>      [SBSA_SECURE_UART] =        { 0x60030000, 0x00001000 },

> -    [SBSA_SMMU] =               { 0x60040000, 0x00020000 },

> +    /* The UART is a secure UART for S-EL0 OS testing */

> +    [SBSA_SECURE_UART_MM] =     { 0x60040000, 0x00001000 },

> +    [SBSA_SMMU] =               { 0x60050000, 0x00020000 },

>      /* Space here reserved for more SMMUs */

>      [SBSA_AHCI] =               { 0x60100000, 0x00010000 },

>      [SBSA_EHCI] =               { 0x60110000, 0x00010000 },

> @@ -126,8 +129,9 @@ static const int sbsa_ref_irqmap[] = {

>      [SBSA_PCIE] = 3, /* ... to 6 */

>      [SBSA_GPIO] = 7,

>      [SBSA_SECURE_UART] = 8,

> -    [SBSA_AHCI] = 9,

> -    [SBSA_EHCI] = 10,

> +    [SBSA_SECURE_UART_MM] = 9,

> +    [SBSA_AHCI] = 10,

> +    [SBSA_EHCI] = 11,

>  };

>

>  /*

> @@ -645,6 +649,7 @@ static void sbsa_ref_init(MachineState *machine)

>      create_uart(vms, pic, SBSA_UART, sysmem, serial_hd(0));

>

>      create_uart(vms, pic, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));

> +    create_uart(vms, pic, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2));

>

>      create_rtc(vms, pic);

>

> --

> 2.17.1

>

>

> On Thu, 4 Apr 2019 at 15:27, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

>>

>> I would like to wait for more days to see if there are any further

>> comments, and if no I will send another iteration with memory map

>> slightly changed.

>>

>> On Wed, 20 Mar 2019 at 18:27, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

>> >

>> > On Mon, 18 Mar 2019 at 03:39, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

>> > >

>> > > On Fri, 15 Mar 2019 at 18:41, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:

>> > > >

>> > > > On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <hongbo.zhang@linaro.org> wrote:

>> > > > >

>> > > > > For the Aarch64, there is one machine 'virt', it is primarily meant to

>> > > > > run on KVM and execute virtualization workloads, but we need an

>> > > > > environment as faithful as possible to physical hardware, for supporting

>> > > > > firmware and OS development for pysical Aarch64 machines.

>> > > > >

>> > > > > This patch introduces new machine type 'sbsa-ref' with main features:

>> > > > >  - Based on 'virt' machine type.

>> > > > >  - A new memory map.

>> > > > >  - CPU type cortex-a57.

>> > > > >  - EL2 and EL3 are enabled.

>> > > > >  - GIC version 3.

>> > > > >  - System bus AHCI controller.

>> > > > >  - System bus EHCI controller.

>> > > >

>> > > > Hello Hongbo,

>> > > >

>> > > > Apologies for bringing this up now, but I seem to remember that the

>> > > > EHCI does not support 64-bit DMA. Did you run into any issues with

>> > > > this? Or was this fixed in QEMU in the mean time?

>> > > >

>> > > Hi Ard,

>> > > Which EHCI do you mean?

>> > > This time I use a newly introduced system bus EHCI, commit 114529f7

>> > > and I only tested USB mouse and key board, didn't test DMA function.

>> > >

>> >

>> > The host controller doesn't work without DMA, so if mouse and keyboard

>> > worked for you, and no DRAM exists below the 4 GB mark, this has

>> > apparently been fixed in QEMU.
diff mbox series

Patch

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 2a7efc1..4fbb6ac 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -144,6 +144,7 @@  CONFIG_IOH3420=y
 CONFIG_I82801B11=y
 CONFIG_ACPI=y
 CONFIG_ARM_VIRT=y
+CONFIG_SBSA_REF=y
 CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_SMBUS_EEPROM=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d298fbd..6654914 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -38,6 +38,9 @@  config PXA2XX
 config REALVIEW
     bool
 
+config SBSA_REF
+    bool
+
 config STELLARIS
     bool
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index fa57c7c..fa812ec 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -12,6 +12,7 @@  obj-$(CONFIG_NSERIES) += nseries.o
 obj-$(CONFIG_OMAP) += omap_sx1.o palm.o
 obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o
 obj-$(CONFIG_REALVIEW) += realview.o
+obj-$(CONFIG_SBSA_REF) += sbsa-ref.o
 obj-$(CONFIG_STELLARIS) += stellaris.o
 obj-$(CONFIG_STRONGARM) += collie.o
 obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
new file mode 100644
index 0000000..b6d31f2
--- /dev/null
+++ b/hw/arm/sbsa-ref.c
@@ -0,0 +1,303 @@ 
+/*
+ * ARM SBSA Reference Platform emulation
+ *
+ * Copyright (c) 2018 Linaro Limited
+ * Written by Hongbo Zhang <hongbo.zhang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/units.h"
+#include "sysemu/numa.h"
+#include "sysemu/sysemu.h"
+#include "exec/address-spaces.h"
+#include "exec/hwaddr.h"
+#include "kvm_arm.h"
+#include "hw/arm/arm.h"
+#include "hw/boards.h"
+#include "hw/intc/arm_gicv3_common.h"
+
+#define RAMLIMIT_GB 8192
+#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)
+
+enum {
+    SBSA_FLASH,
+    SBSA_MEM,
+    SBSA_CPUPERIPHS,
+    SBSA_GIC_DIST,
+    SBSA_GIC_REDIST,
+    SBSA_SMMU,
+    SBSA_UART,
+    SBSA_RTC,
+    SBSA_PCIE,
+    SBSA_PCIE_MMIO,
+    SBSA_PCIE_MMIO_HIGH,
+    SBSA_PCIE_PIO,
+    SBSA_PCIE_ECAM,
+    SBSA_GPIO,
+    SBSA_SECURE_UART,
+    SBSA_SECURE_MEM,
+    SBSA_AHCI,
+    SBSA_EHCI,
+};
+
+typedef struct MemMapEntry {
+    hwaddr base;
+    hwaddr size;
+} MemMapEntry;
+
+typedef struct {
+    MachineState parent;
+    struct arm_boot_info bootinfo;
+    const MemMapEntry *memmap;
+    const int *irqmap;
+    int smp_cpus;
+    void *fdt;
+    int fdt_size;
+    int psci_conduit;
+} SBSAMachineState;
+
+#define TYPE_SBSA_MACHINE   MACHINE_TYPE_NAME("sbsa-ref")
+#define SBSA_MACHINE(obj) \
+    OBJECT_CHECK(SBSAMachineState, (obj), TYPE_SBSA_MACHINE)
+
+static const MemMapEntry sbsa_ref_memmap[] = {
+    /* 512M boot ROM */
+    [SBSA_FLASH] =              {          0, 0x20000000 },
+    /* 512M secure memory */
+    [SBSA_SECURE_MEM] =         { 0x20000000, 0x20000000 },
+    /* Space reserved for CPU peripheral devices */
+    [SBSA_CPUPERIPHS] =         { 0x40000000, 0x00040000 },
+    [SBSA_GIC_DIST] =           { 0x40060000, 0x00010000 },
+    [SBSA_GIC_REDIST] =         { 0x40080000, 0x04000000 },
+    [SBSA_UART] =               { 0x60000000, 0x00001000 },
+    [SBSA_RTC] =                { 0x60010000, 0x00001000 },
+    [SBSA_GPIO] =               { 0x60020000, 0x00001000 },
+    [SBSA_SECURE_UART] =        { 0x60030000, 0x00001000 },
+    [SBSA_SMMU] =               { 0x60040000, 0x00020000 },
+    /* Space here reserved for more SMMUs */
+    [SBSA_AHCI] =               { 0x60100000, 0x00010000 },
+    [SBSA_EHCI] =               { 0x60110000, 0x00010000 },
+    /* Space here reserved for other devices */
+    [SBSA_PCIE_PIO] =           { 0x7fff0000, 0x00010000 },
+    /* 256M PCIE ECAM space */
+    [SBSA_PCIE_ECAM] =          { 0x80000000, 0x10000000 },
+    /* 32-bit address PCIE MMIO space */
+    [SBSA_PCIE_MMIO] =          { 0x90000000, 0x70000000 },
+    /* ~1TB PCIE MMIO space (4GB to 1024GB boundary) */
+    [SBSA_PCIE_MMIO_HIGH] =     { 0x100000000ULL, 0xFF00000000ULL },
+    [SBSA_MEM] =                { 0x10000000000ULL, RAMLIMIT_BYTES },
+};
+
+static const int sbsa_ref_irqmap[] = {
+    [SBSA_UART] = 1,
+    [SBSA_RTC] = 2,
+    [SBSA_PCIE] = 3, /* ... to 6 */
+    [SBSA_GPIO] = 7,
+    [SBSA_SECURE_UART] = 8,
+    [SBSA_AHCI] = 9,
+    [SBSA_EHCI] = 10,
+};
+
+static void sbsa_ref_init(MachineState *machine)
+{
+    SBSAMachineState *vms = SBSA_MACHINE(machine);
+    MachineClass *mc = MACHINE_GET_CLASS(machine);
+    MemoryRegion *sysmem = get_system_memory();
+    MemoryRegion *secure_sysmem = NULL;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
+    const CPUArchIdList *possible_cpus;
+    int n, sbsa_max_cpus;
+
+    if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
+        error_report("sbsa-ref: CPU type other than the built-in "
+                     "cortex-a57 not supported");
+        exit(1);
+    }
+
+    if (kvm_enabled()) {
+        error_report("sbsa-ref: KVM is not supported at this machine");
+        exit(1);
+    }
+
+    if (machine->kernel_filename && firmware_loaded) {
+        error_report("sbsa-ref: No fw_cfg device on this machine, "
+                     "so -kernel option is not supported when firmware loaded, "
+                     "please load OS from hard disk instead");
+        exit(1);
+    }
+
+    /*
+     * This machine has EL3 enabled, external firmware should supply PSCI
+     * implementation, so the QEMU's internal PSCI is disabled.
+     */
+    vms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED;
+
+    sbsa_max_cpus = vms->memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE;
+
+    if (max_cpus > sbsa_max_cpus) {
+        error_report("Number of SMP CPUs requested (%d) exceeds max CPUs "
+                     "supported by machine 'sbsa-ref' (%d)",
+                     max_cpus, sbsa_max_cpus);
+        exit(1);
+    }
+
+    vms->smp_cpus = smp_cpus;
+
+    if (machine->ram_size > vms->memmap[SBSA_MEM].size) {
+        error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB);
+        exit(1);
+    }
+
+    secure_sysmem = g_new(MemoryRegion, 1);
+    memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
+                       UINT64_MAX);
+    memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
+
+    possible_cpus = mc->possible_cpu_arch_ids(machine);
+    for (n = 0; n < possible_cpus->len; n++) {
+        Object *cpuobj;
+        CPUState *cs;
+
+        if (n >= smp_cpus) {
+            break;
+        }
+
+        cpuobj = object_new(possible_cpus->cpus[n].type);
+        object_property_set_int(cpuobj, possible_cpus->cpus[n].arch_id,
+                                "mp-affinity", NULL);
+
+        cs = CPU(cpuobj);
+        cs->cpu_index = n;
+
+        numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
+                          &error_fatal);
+
+        if (object_property_find(cpuobj, "reset-cbar", NULL)) {
+            object_property_set_int(cpuobj, vms->memmap[SBSA_CPUPERIPHS].base,
+                                    "reset-cbar", &error_abort);
+        }
+
+        object_property_set_link(cpuobj, OBJECT(sysmem), "memory",
+                                 &error_abort);
+
+        object_property_set_link(cpuobj, OBJECT(secure_sysmem),
+                                 "secure-memory", &error_abort);
+
+        object_property_set_bool(cpuobj, true, "realized", &error_fatal);
+        object_unref(cpuobj);
+    }
+
+    memory_region_allocate_system_memory(ram, NULL, "sbsa-ref.ram",
+                                         machine->ram_size);
+    memory_region_add_subregion(sysmem, vms->memmap[SBSA_MEM].base, ram);
+
+    vms->bootinfo.ram_size = machine->ram_size;
+    vms->bootinfo.kernel_filename = machine->kernel_filename;
+    vms->bootinfo.nb_cpus = smp_cpus;
+    vms->bootinfo.board_id = -1;
+    vms->bootinfo.loader_start = vms->memmap[SBSA_MEM].base;
+    vms->bootinfo.firmware_loaded = firmware_loaded;
+    arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo);
+}
+
+static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *vms, int idx)
+{
+    uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
+    return arm_cpu_mp_affinity(idx, clustersz);
+}
+
+static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)
+{
+    SBSAMachineState *vms = SBSA_MACHINE(ms);
+    int n;
+
+    if (ms->possible_cpus) {
+        assert(ms->possible_cpus->len == max_cpus);
+        return ms->possible_cpus;
+    }
+
+    ms->possible_cpus = g_malloc0(sizeof(CPUArchIdList) +
+                                  sizeof(CPUArchId) * max_cpus);
+    ms->possible_cpus->len = max_cpus;
+    for (n = 0; n < ms->possible_cpus->len; n++) {
+        ms->possible_cpus->cpus[n].type = ms->cpu_type;
+        ms->possible_cpus->cpus[n].arch_id =
+            sbsa_ref_cpu_mp_affinity(vms, n);
+        ms->possible_cpus->cpus[n].props.has_thread_id = true;
+        ms->possible_cpus->cpus[n].props.thread_id = n;
+    }
+    return ms->possible_cpus;
+}
+
+static CpuInstanceProperties
+sbsa_ref_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(ms);
+
+    assert(cpu_index < possible_cpus->len);
+    return possible_cpus->cpus[cpu_index].props;
+}
+
+static int64_t
+sbsa_ref_get_default_cpu_node_id(const MachineState *ms, int idx)
+{
+    return idx % nb_numa_nodes;
+}
+
+static void sbsa_ref_instance_init(Object *obj)
+{
+    SBSAMachineState *vms = SBSA_MACHINE(obj);
+
+    vms->memmap = sbsa_ref_memmap;
+    vms->irqmap = sbsa_ref_irqmap;
+}
+
+static void sbsa_ref_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->init = sbsa_ref_init;
+    mc->desc = "QEMU 'SBSA Reference' ARM Virtual Machine";
+    mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
+    mc->max_cpus = 512;
+    mc->pci_allow_0_address = true;
+    mc->minimum_page_bits = 12;
+    mc->block_default_type = IF_IDE;
+    mc->no_cdrom = 1;
+    mc->default_ram_size = 1 * GiB;
+    mc->default_cpus = 4;
+    mc->possible_cpu_arch_ids = sbsa_ref_possible_cpu_arch_ids;
+    mc->cpu_index_to_instance_props = sbsa_ref_cpu_index_to_props;
+    mc->get_default_cpu_node_id = sbsa_ref_get_default_cpu_node_id;
+}
+
+static const TypeInfo sbsa_ref_info = {
+    .name          = TYPE_SBSA_MACHINE,
+    .parent        = TYPE_MACHINE,
+    .instance_size = sizeof(SBSAMachineState),
+    .instance_init = sbsa_ref_instance_init,
+    .class_init    = sbsa_ref_class_init,
+};
+
+static void sbsa_ref_machine_init(void)
+{
+    type_register_static(&sbsa_ref_info);
+}
+
+type_init(sbsa_ref_machine_init);