[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [PATCH v6 1/2] hw/arm: Add arm SBSA reference machine, sk
From: |
Ard Biesheuvel |
Subject: |
Re: [Qemu-arm] [PATCH v6 1/2] hw/arm: Add arm SBSA reference machine, skeleton part |
Date: |
Fri, 15 Mar 2019 11:41:11 +0100 |
On Fri, 15 Mar 2019 at 11:08, Hongbo Zhang <address@hidden> 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 <address@hidden>
> ---
> 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 <address@hidden>
> + *
> + * 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
>