From patchwork Fri Dec 7 09:07:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 153099 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp283488ljp; Fri, 7 Dec 2018 01:33:04 -0800 (PST) X-Google-Smtp-Source: AFSGD/WoSxfBCy4ACzqI1V2iV/ZHfozh3AI4/pezR+cuGnuipgfzbuKBSYJ6DB2ZgZI82WaFUwlI X-Received: by 2002:ac8:41c8:: with SMTP id o8mr1292410qtm.232.1544175184175; Fri, 07 Dec 2018 01:33:04 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544175184; cv=none; d=google.com; s=arc-20160816; b=tktUJa7on8GhaMsRgjwDkrfVfkHjQtlVIM7K7y0bRY/cPtCn3QJ6Pz85zhKyEZnW2w STUCronUSR/Q6qDje70arKAkoP7RfUHMzKMGOWpq1hXOb/lZBkZD+dLO+LQYuk/Xi49L HGsq188un6SMra9A2EC9gRlh3cGJlLHJoPimU42VorifTKeygu7/x1+1Up3826GJAL2l DRhMYRt082xpMXphu8iJnPoz5E4hWME50Igbhb18OlpA4pnP5v34YxnGZqgpCEsUn1jc UOkzBZkoWLp6fRWlfMKO3HBXa5BxaOkdV1207t6VAJ+LBggJ9aYCS6SPhyFx8TzFAoxd WKKA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=+tl3ilYm7C+KQEmQIc/4EiG+n1/4vE27aO6jvS+mD74=; b=BMSOLDZEvEKSLXl2qChzBL4blSPsePZ7cF3zXcOsiC/5U+KWqbvIMvFVsqI9D4oyid NoG/sTEHQs7havSzFwP4JQKGdS7oUU1KWMnF75mdgA+U9s0jLu5WUO5bRfUmvsESy+5R sNLkH8yrWPL6htTGLdDIxfEc/IumMEWjN2eUPX9nm9e29bqCphlPLBBenIhSTpMeASX8 GXT4Ah7EJGwSjNZmF2nBjA58qGIzIT0ySAGwErRuFVwBQ8+9mGs3yg1WY6SsZ5IubeOa tA3e1VyESVfjfBkK5LXpeCleyvq5q0iZEVlneg+5rISJoGq9J1HT4PCMrV1us80GwbUF PEcQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=aiKF+b+g; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 43si17107qvw.171.2018.12.07.01.33.03 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 07 Dec 2018 01:33:04 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=aiKF+b+g; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:45020 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVCVL-0007Lc-Mb for patch@linaro.org; Fri, 07 Dec 2018 04:33:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVC7J-000602-Bp for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVC7G-0001mp-Eo for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:13 -0500 Received: from mail-pl1-x641.google.com ([2607:f8b0:4864:20::641]:40732) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gVC7G-0001ff-3j for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:10 -0500 Received: by mail-pl1-x641.google.com with SMTP id u18so1552668plq.7 for ; Fri, 07 Dec 2018 01:08:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=+tl3ilYm7C+KQEmQIc/4EiG+n1/4vE27aO6jvS+mD74=; b=aiKF+b+gWPSkjLAuquc27eGeEirgIHxlmHOuTrt47o7NSZZtxLM6i1BLxqNRDgkRGx qrXDPEOuALZU9hd+sVhpxbY759mx0W2bv77jsi+GipXmCUox65pK+D6Jrlm2y14PekFA Ajc/tmkC+ABAR8BQBISpWW+nyveYY/3fUxL88= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+tl3ilYm7C+KQEmQIc/4EiG+n1/4vE27aO6jvS+mD74=; b=W+iGI/gG+B1RfJgLqq5HxMXsPWAgHbBMebpJ4roRN1JmnkcHzXyeZISPmEcIBYn5sE +u0rNk7qf5EeClw+QvLzdxdzrIdeJBURB3coVi2qK1+5bj96Mknzmy82soXVdPGg/ssl gDe+YYEWsCQj7g+fUYTohirMhpRi96gLf9vmS6OsOKzserr72CqlgfAh2xHQG3q7qKkQ JD5NAJHqQqKxs9hkMNdwLGNlRXWPm9v0AF+hu6cdUchz8XgZkVpJ8b19kfiK3OuIGFx/ a3+tp+V1MumlD3ywemGgDyKqoEwbeYNoolbK9kHCsqf5jD6J4+VCPZ1H60kaTC23PwGS sarw== X-Gm-Message-State: AA+aEWZab7EMEBgUuXOaEb6y64y4uyhsvZ/0sOiBw7f3oepT3zetZsKB NFoN+SDPFbQLCI1hPDblgmctmw== X-Received: by 2002:a17:902:aa0a:: with SMTP id be10mr1359265plb.266.1544173688875; Fri, 07 Dec 2018 01:08:08 -0800 (PST) Received: from localhost.localdomain ([45.56.155.222]) by smtp.gmail.com with ESMTPSA id k38sm3058432pgb.33.2018.12.07.01.08.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Dec 2018 01:08:08 -0800 (PST) From: Hongbo Zhang To: peter.maydell@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Fri, 7 Dec 2018 17:07:54 +0800 Message-Id: <1544173675-14217-2-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1544173675-14217-1-git-send-email-hongbo.zhang@linaro.org> References: <1544173675-14217-1-git-send-email-hongbo.zhang@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::641 Subject: [Qemu-devel] [PATCH v5 1/2] hw/arm: Add arm SBSA reference machine, skeleton part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hongbo Zhang , radoslaw.biernacki@linaro.org, leif.lindholm@linaro.org, ard.biesheuvel@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" 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. - Re-designed memory map. - CPU type cortex-a57. - EL2 and EL3 are enabled. - GIC version 3. - System bus AHCI controller. - System bus XHCI controller(TBD). - 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 --- hw/arm/Makefile.objs | 2 +- hw/arm/sbsa-ref.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/arm/virt.h | 1 + 3 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 hw/arm/sbsa-ref.c -- 2.7.4 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index d51fcec..a8895eb 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += boot.o virt.o sysbus-fdt.o +obj-y += boot.o virt.o sbsa-ref.o sysbus-fdt.o obj-$(CONFIG_ACPI) += virt-acpi-build.o obj-$(CONFIG_DIGIC) += digic_boards.o obj-$(CONFIG_EXYNOS4) += exynos4_boards.o diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c new file mode 100644 index 0000000..1d6252b --- /dev/null +++ b/hw/arm/sbsa-ref.c @@ -0,0 +1,277 @@ +/* + * ARM SBSA Reference Platform emulation + * + * Copyright (c) 2018 Linaro Limited + * Written by Hongbo Zhang + * + * Based on hw/arm/virt.c + * + * 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 . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/arm/arm.h" +#include "hw/arm/virt.h" +#include "hw/devices.h" +#include "net/net.h" +#include "sysemu/device_tree.h" +#include "sysemu/numa.h" +#include "sysemu/sysemu.h" +#include "hw/loader.h" +#include "exec/address-spaces.h" +#include "qemu/error-report.h" +#include "hw/pci-host/gpex.h" +#include "hw/arm/sysbus-fdt.h" +#include "hw/arm/fdt.h" +#include "hw/intc/arm_gic.h" +#include "hw/intc/arm_gicv3_common.h" +#include "kvm_arm.h" +#include "hw/ide/internal.h" +#include "hw/ide/ahci_internal.h" +#include "qemu/units.h" + +#define NUM_IRQS 256 + +#define RAMLIMIT_GB 8192 +#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB) + +static const MemMapEntry sbsa_ref_memmap[] = { + /* 512M boot ROM */ + [VIRT_FLASH] = { 0, 0x20000000 }, + /* 512M secure memery */ + [VIRT_SECURE_MEM] = { 0x20000000, 0x20000000 }, + [VIRT_CPUPERIPHS] = { 0x40000000, 0x00080000 }, + /* GIC distributor and CPU interface expansion spaces reserved */ + [VIRT_GIC_DIST] = { 0x40000000, 0x00010000 }, + [VIRT_GIC_CPU] = { 0x40040000, 0x00010000 }, + /* 64M redistributor space allows up to 512 CPUs */ + [VIRT_GIC_REDIST] = { 0x40080000, 0x04000000 }, + /* Space here reserved for redistributor and vCPU/HYP expansion */ + [VIRT_UART] = { 0x60000000, 0x00001000 }, + [VIRT_RTC] = { 0x60010000, 0x00001000 }, + [VIRT_GPIO] = { 0x60020000, 0x00001000 }, + [VIRT_SECURE_UART] = { 0x60030000, 0x00001000 }, + [VIRT_SMMU] = { 0x60040000, 0x00020000 }, + /* Space here reserved for more SMMUs */ + [VIRT_AHCI] = { 0x60100000, 0x00010000 }, + /* Space here reserved for other devices */ + [VIRT_PCIE_PIO] = { 0x7fff0000, 0x00010000 }, + /* 256M PCIE ECAM space */ + [VIRT_PCIE_ECAM] = { 0x80000000, 0x10000000 }, + /* ~1TB for PCIE MMIO (4GB to 1024GB boundary) */ + [VIRT_PCIE_MMIO] = { 0x100000000ULL, 0xFF00000000ULL }, + [VIRT_MEM] = { 0x10000000000ULL, RAMLIMIT_BYTES }, +}; + +static const int sbsa_ref_irqmap[] = { + [VIRT_UART] = 1, + [VIRT_RTC] = 2, + [VIRT_PCIE] = 3, /* ... to 6 */ + [VIRT_GPIO] = 7, + [VIRT_SECURE_UART] = 8, + [VIRT_AHCI] = 9, +}; + +static void sbsa_ref_init(MachineState *machine) +{ + VirtMachineState *vms = VIRT_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[VIRT_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[VIRT_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[VIRT_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[VIRT_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[VIRT_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(VirtMachineState *vms, int idx) +{ + uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER; + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); + + if (!vmc->disallow_affinity_adjustment) { + clustersz = GICV3_TARGETLIST_BITS; + } + return arm_cpu_mp_affinity(idx, clustersz); +} + +static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms) +{ + VirtMachineState *vms = VIRT_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) +{ + VirtMachineState *vms = VIRT_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 = MACHINE_TYPE_NAME("sbsa-ref"), + .parent = TYPE_VIRT_MACHINE, + .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); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 9a870cc..c73c46b 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -78,6 +78,7 @@ enum { VIRT_GPIO, VIRT_SECURE_UART, VIRT_SECURE_MEM, + VIRT_AHCI, }; typedef enum VirtIOMMUType { From patchwork Fri Dec 7 09:07:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 153098 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp274755ljp; Fri, 7 Dec 2018 01:22:19 -0800 (PST) X-Google-Smtp-Source: AFSGD/WBG8m6n7Q/kAlZ3pUlCZs23mWdgO+x3mZTnvT5gigvBAHo47jPaF8Eqz3m9msaAgIMiMal X-Received: by 2002:a37:2a14:: with SMTP id q20mr1058920qkh.185.1544174539676; Fri, 07 Dec 2018 01:22:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544174539; cv=none; d=google.com; s=arc-20160816; b=uuR3LVqV2WWqojLtT2cxMqIBmkU7NofjpLIyNl1xJskOnUBrzVAidNhuB/sIP+lxRi phWXwevcVAcMmMbQizraCoHbIg3ZiTFeEMr2nK12iQ3NWYu+pzVU2aTZoVNFMCate2EX HapDUuKnI8eW/TP/Ywl7WfskGOut34wxsXyL1gEcF2KnY/03Ng1yfOBfqtPZgTjPdfg8 enjh8k5+gnDd/HHutzRx3pBkaX4bmsjRrIrUB3TCPaNPBX/QjfmgFV5olANBNpIgB7OL eD3Nsd3yv+I3wMw8+cB+q20BlPTNL6IeYY6V3+KD1tNZPeEfRRCmGJirNZFlDioO4yep uHHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:dkim-signature; bh=W1IBDezLIFMZc3HImXICmFn832Ds9Wo1ep/IWPVds8M=; b=KEUrdcUUdBpHP6FQ+5469D4gcqqQCLlMcheiHL6cf7c5fdWMbgk5ziFkr0A7urK12n SHGdeEazlF6O6KNYtJvze1InbGstKFQe+NU/JIaTYNipc/SVMFn07pHVvG7N9HlyVRRF yHt9WLHxnRoKBlsLwi9ZzExtOXP6Izco2s9ZUVPocR05r9Uz0j4iFP4YWXVBMehmmU5C NuC1yk3cuwcob9xahH6IN0mVqFA28BW1s3E7X8ivCw5nf0ym3eT0TB9wXaZfcXsk+Mx0 MXBCMvhQm5pDKOQym7SlPz+pNcJvAjl3/2F+MxaQWl8d5XVZ2arne1BghgnmKrpEFHSj I9zw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=K8ujFlOd; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id r63si115332qkb.132.2018.12.07.01.22.19 for (version=TLS1 cipher=AES128-SHA bits=128/128); Fri, 07 Dec 2018 01:22:19 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=K8ujFlOd; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1]:44958 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVCKw-0004cj-J0 for patch@linaro.org; Fri, 07 Dec 2018 04:22:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33461) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVC7M-000630-CA for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVC7K-00029d-GA for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:16 -0500 Received: from mail-pg1-x544.google.com ([2607:f8b0:4864:20::544]:36514) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gVC7K-00026i-4f for qemu-devel@nongnu.org; Fri, 07 Dec 2018 04:08:14 -0500 Received: by mail-pg1-x544.google.com with SMTP id n2so1454739pgm.3 for ; Fri, 07 Dec 2018 01:08:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=W1IBDezLIFMZc3HImXICmFn832Ds9Wo1ep/IWPVds8M=; b=K8ujFlOdkw9RksD2b2m/k4SG2LpQactauRoWX+15dLLgVUdYALCBx/fxHncaLML5hU jDQW4BC5kG8TBLEaCvIiMdCOQG3X4i0gOgUcg2fG/9vyPDKu1fb7umQ8SL2sBDTMTjY8 Rb0F0j1FlojtmKiQLD08ct8/a26E8Xd9GNEWk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=W1IBDezLIFMZc3HImXICmFn832Ds9Wo1ep/IWPVds8M=; b=YZ/yeZZVp7oW6C9RamPQ/CFGyY0y2LIwcCkqSnVLvYMsnRnGTuwBa6fkB3O4mAEz6b oR3FqBqm2tE+0rs5OMiFWXJ/RDif3UpunLM2aZ66kD03QfaMWi78drWD67sI+NJZA7/c qdsO6Uu8wxJNIYOwBYBmMqyGL/KfEa1aHqI8n3MyikAzxYCThIP54clwRNVYJWNCXbny bwmWbfmAKyMBVmD1pSdwxyJ3msarhDRvv8zkToI9Z6ydXeQzk4+s6XSjDM+n94Om9zia YihArr8YRgewYQt60Hy1ly9hkTBlsSXEoS1SJDe6MAHUHVM8TRs7Xhcyu3ZTXeKuPdm9 KyYg== X-Gm-Message-State: AA+aEWZPUCs8GQiz1739InGagezusUN2Fd187GKbIRcbOoUN/u03cS3L 1C4yZjTmBvAI50wi6eP7v56GcQ== X-Received: by 2002:a63:d047:: with SMTP id s7mr1195215pgi.311.1544173692987; Fri, 07 Dec 2018 01:08:12 -0800 (PST) Received: from localhost.localdomain ([45.56.155.222]) by smtp.gmail.com with ESMTPSA id k38sm3058432pgb.33.2018.12.07.01.08.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 07 Dec 2018 01:08:12 -0800 (PST) From: Hongbo Zhang To: peter.maydell@linaro.org, alex.bennee@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Fri, 7 Dec 2018 17:07:55 +0800 Message-Id: <1544173675-14217-3-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1544173675-14217-1-git-send-email-hongbo.zhang@linaro.org> References: <1544173675-14217-1-git-send-email-hongbo.zhang@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::544 Subject: [Qemu-devel] [PATCH v5 2/2] hw/arm: add Arm SBSA reference machine, devices part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Hongbo Zhang , radoslaw.biernacki@linaro.org, leif.lindholm@linaro.org, ard.biesheuvel@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" Following the previous patch, this patch adds peripheral devices to the newly introduced SBSA-ref machine. Signed-off-by: Hongbo Zhang --- hw/arm/sbsa-ref.c | 421 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 421 insertions(+) -- 2.7.4 diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 1d6252b..b3ef0d1 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -46,6 +46,8 @@ #define RAMLIMIT_GB 8192 #define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB) +#define SATA_NUM_PORTS 6 + static const MemMapEntry sbsa_ref_memmap[] = { /* 512M boot ROM */ [VIRT_FLASH] = { 0, 0x20000000 }, @@ -83,6 +85,399 @@ static const int sbsa_ref_irqmap[] = { [VIRT_AHCI] = 9, }; +/* Firmware on this machine only uses ACPI table to load OS, these limited + * device tree nodes are just to let firmware know the info which varies from + * command line parameters, so it is not necessary to be fully compatible + * with the kernel CPU and NUMA binding rules. + */ +static void create_fdt(VirtMachineState *vms) +{ + void *fdt = create_device_tree(&vms->fdt_size); + const MachineState *ms = MACHINE(vms); + int cpu; + + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + vms->fdt = fdt; + + qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,sbsa-ref"); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); + qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); + + if (have_numa_distance) { + int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t); + uint32_t *matrix = g_malloc0(size); + int idx, i, j; + + for (i = 0; i < nb_numa_nodes; i++) { + for (j = 0; j < nb_numa_nodes; j++) { + idx = (i * nb_numa_nodes + j) * 3; + matrix[idx + 0] = cpu_to_be32(i); + matrix[idx + 1] = cpu_to_be32(j); + matrix[idx + 2] = cpu_to_be32(numa_info[i].distance[j]); + } + } + + qemu_fdt_add_subnode(fdt, "/distance-map"); + qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix", + matrix, size); + g_free(matrix); + } + + qemu_fdt_add_subnode(vms->fdt, "/cpus"); + + for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { + char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); + CPUState *cs = CPU(armcpu); + + qemu_fdt_add_subnode(vms->fdt, nodename); + + if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", + ms->possible_cpus->cpus[cs->cpu_index].props.node_id); + } + + g_free(nodename); + } +} + +static void create_one_flash(const char *name, hwaddr flashbase, + hwaddr flashsize, const char *file, + MemoryRegion *sysmem) +{ + /* Create and map a single flash device. We use the same + * parameters as the flash devices on the Versatile Express board. + */ + DriveInfo *dinfo = drive_get_next(IF_PFLASH); + DeviceState *dev = qdev_create(NULL, "cfi.pflash01"); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + const uint64_t sectorlength = 256 * 1024; + + if (dinfo) { + qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), + &error_abort); + } + + qdev_prop_set_uint32(dev, "num-blocks", flashsize / sectorlength); + qdev_prop_set_uint64(dev, "sector-length", sectorlength); + qdev_prop_set_uint8(dev, "width", 4); + qdev_prop_set_uint8(dev, "device-width", 2); + qdev_prop_set_bit(dev, "big-endian", false); + qdev_prop_set_uint16(dev, "id0", 0x89); + qdev_prop_set_uint16(dev, "id1", 0x18); + qdev_prop_set_uint16(dev, "id2", 0x00); + qdev_prop_set_uint16(dev, "id3", 0x00); + qdev_prop_set_string(dev, "name", name); + qdev_init_nofail(dev); + + memory_region_add_subregion(sysmem, flashbase, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); + + if (file) { + char *fn; + int image_size; + + if (drive_get(IF_PFLASH, 0, 0)) { + error_report("The contents of the first flash device may be " + "specified with -bios or with -drive if=pflash... " + "but you cannot use both options at once"); + exit(1); + } + fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, file); + if (!fn) { + error_report("Could not find ROM image '%s'", file); + exit(1); + } + image_size = load_image_mr(fn, sysbus_mmio_get_region(sbd, 0)); + g_free(fn); + if (image_size < 0) { + error_report("Could not load ROM image '%s'", file); + exit(1); + } + } +} + +static void create_flash(const VirtMachineState *vms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + /* Create one secure and nonsecure flash devices to fill VIRT_FLASH + * space in the memmap, file passed via -bios goes in the first one. + */ + hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2; + hwaddr flashbase = vms->memmap[VIRT_FLASH].base; + + create_one_flash("sbsa-ref.flash0", flashbase, flashsize, + bios_name, secure_sysmem); + create_one_flash("sbsa-ref.flash1", flashbase + flashsize, flashsize, + NULL, sysmem); +} + +static void create_secure_ram(VirtMachineState *vms, + MemoryRegion *secure_sysmem) +{ + MemoryRegion *secram = g_new(MemoryRegion, 1); + hwaddr base = vms->memmap[VIRT_SECURE_MEM].base; + hwaddr size = vms->memmap[VIRT_SECURE_MEM].size; + + memory_region_init_ram(secram, NULL, "sbsa-ref.secure-ram", size, + &error_fatal); + memory_region_add_subregion(secure_sysmem, base, secram); +} + +static void create_gic(VirtMachineState *vms, qemu_irq *pic) +{ + DeviceState *gicdev; + SysBusDevice *gicbusdev; + const char *gictype; + uint32_t redist0_capacity, redist0_count; + int i; + + gictype = gicv3_class_name(); + + gicdev = qdev_create(NULL, gictype); + qdev_prop_set_uint32(gicdev, "revision", 3); + qdev_prop_set_uint32(gicdev, "num-cpu", smp_cpus); + /* Note that the num-irq property counts both internal and external + * interrupts; there are always 32 of the former (mandated by GIC spec). + */ + qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32); + qdev_prop_set_bit(gicdev, "has-security-extensions", true); + + redist0_capacity = + vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE; + redist0_count = MIN(smp_cpus, redist0_capacity); + + qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1); + qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count); + + qdev_init_nofail(gicdev); + gicbusdev = SYS_BUS_DEVICE(gicdev); + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base); + + /* Wire the outputs from each CPU's generic timer and the GICv3 + * maintenance interrupt signal to the appropriate GIC PPI inputs, + * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs. + */ + for (i = 0; i < smp_cpus; i++) { + DeviceState *cpudev = DEVICE(qemu_get_cpu(i)); + int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS; + int irq; + /* Mapping from the output timer irq lines from the CPU to the + * GIC PPI inputs used for this board. + */ + const int timer_irq[] = { + [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ, + [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ, + [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ, + [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ, + }; + + for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) { + qdev_connect_gpio_out(cpudev, irq, + qdev_get_gpio_in(gicdev, + ppibase + timer_irq[irq])); + } + + qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0, + qdev_get_gpio_in(gicdev, ppibase + + ARCH_GICV3_MAINT_IRQ)); + qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, + qdev_get_gpio_in(gicdev, ppibase + + VIRTUAL_PMU_IRQ)); + + sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ)); + sysbus_connect_irq(gicbusdev, i + smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_FIQ)); + sysbus_connect_irq(gicbusdev, i + 2 * smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); + sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); + } + + for (i = 0; i < NUM_IRQS; i++) { + pic[i] = qdev_get_gpio_in(gicdev, i); + } +} + +static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, + MemoryRegion *mem, Chardev *chr) +{ + hwaddr base = vms->memmap[uart].base; + int irq = vms->irqmap[uart]; + DeviceState *dev = qdev_create(NULL, "pl011"); + SysBusDevice *s = SYS_BUS_DEVICE(dev); + + qdev_prop_set_chr(dev, "chardev", chr); + qdev_init_nofail(dev); + memory_region_add_subregion(mem, base, + sysbus_mmio_get_region(s, 0)); + sysbus_connect_irq(s, 0, pic[irq]); +} + +static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) +{ + hwaddr base = vms->memmap[VIRT_RTC].base; + int irq = vms->irqmap[VIRT_RTC]; + + sysbus_create_simple("pl031", base, pic[irq]); +} + +static DeviceState *gpio_key_dev; +static void sbsa_ref_powerdown_req(Notifier *n, void *opaque) +{ + /* use gpio Pin 3 for power button event */ + qemu_set_irq(qdev_get_gpio_in(gpio_key_dev, 0), 1); +} + +static Notifier sbsa_ref_powerdown_notifier = { + .notify = sbsa_ref_powerdown_req +}; + +static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) +{ + DeviceState *pl061_dev; + hwaddr base = vms->memmap[VIRT_GPIO].base; + int irq = vms->irqmap[VIRT_GPIO]; + + pl061_dev = sysbus_create_simple("pl061", base, pic[irq]); + + gpio_key_dev = sysbus_create_simple("gpio-key", -1, + qdev_get_gpio_in(pl061_dev, 3)); + + /* connect powerdown request */ + qemu_register_powerdown_notifier(&sbsa_ref_powerdown_notifier); +} + +static void create_ahci(const VirtMachineState *vms, qemu_irq *pic) +{ + hwaddr base = vms->memmap[VIRT_AHCI].base; + int irq = vms->irqmap[VIRT_AHCI]; + DeviceState *dev; + DriveInfo *hd[SATA_NUM_PORTS]; + SysbusAHCIState *sysahci; + AHCIState *ahci; + int i; + + dev = qdev_create(NULL, "sysbus-ahci"); + qdev_prop_set_uint32(dev, "num-ports", SATA_NUM_PORTS); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[irq]); + + sysahci = SYSBUS_AHCI(dev); + ahci = &sysahci->ahci; + ide_drive_get(hd, ARRAY_SIZE(hd)); + for (i = 0; i < ahci->ports; i++) { + if (hd[i] == NULL) { + continue; + } + ide_create_drive(&ahci->dev[i].port, 0, hd[i]); + } +} + +static void create_smmu(const VirtMachineState *vms, qemu_irq *pic, + PCIBus *bus) +{ + hwaddr base = vms->memmap[VIRT_SMMU].base; + int irq = vms->irqmap[VIRT_SMMU]; + DeviceState *dev; + int i; + + dev = qdev_create(NULL, "arm-smmuv3"); + + object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus", + &error_abort); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + for (i = 0; i < NUM_SMMU_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + } +} + +static void create_pcie(VirtMachineState *vms, qemu_irq *pic) +{ + hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base; + hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size; + hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base; + hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size; + hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base; + int irq = vms->irqmap[VIRT_PCIE]; + MemoryRegion *mmio_alias, *mmio_reg, *ecam_alias, *ecam_reg; + DeviceState *dev; + PCIHostState *pci; + int i; + + dev = qdev_create(NULL, TYPE_GPEX_HOST); + qdev_init_nofail(dev); + + /* Map ECAM space */ + ecam_alias = g_new0(MemoryRegion, 1); + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", + ecam_reg, 0, size_ecam); + memory_region_add_subregion(get_system_memory(), base_ecam, ecam_alias); + + /* Map the MMIO space */ + mmio_alias = g_new0(MemoryRegion, 1); + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", + mmio_reg, base_mmio, size_mmio); + memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); + + /* Map IO port space */ + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_pio); + + for (i = 0; i < GPEX_NUM_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + gpex_set_irq_num(GPEX_HOST(dev), i, irq + i); + } + + pci = PCI_HOST_BRIDGE(dev); + if (pci->bus) { + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (!nd->model) { + nd->model = g_strdup("e1000e"); + } + + pci_nic_init_nofail(nd, pci->bus, nd->model, NULL); + } + } + + pci_create_simple(pci->bus, -1, "VGA"); + + create_smmu(vms, pic, pci->bus); +} + +static void *sbsa_ref_dtb(const struct arm_boot_info *binfo, int *fdt_size) +{ + const VirtMachineState *board = container_of(binfo, VirtMachineState, + bootinfo); + + *fdt_size = board->fdt_size; + return board->fdt; +} + +static void sbsa_ref_machine_done(Notifier *notifier, void *data) +{ + VirtMachineState *vms = container_of(notifier, VirtMachineState, + machine_done); + ARMCPU *cpu = ARM_CPU(first_cpu); + struct arm_boot_info *info = &vms->bootinfo; + AddressSpace *as = arm_boot_address_space(cpu, info); + + if (arm_load_dtb(info->dtb_start, info, info->dtb_limit, as) < 0) { + exit(1); + } +} + static void sbsa_ref_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -93,6 +488,7 @@ static void sbsa_ref_init(MachineState *machine) bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0); const CPUArchIdList *possible_cpus; int n, sbsa_max_cpus; + qemu_irq pic[NUM_IRQS]; if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) { error_report("sbsa-ref: CPU type other than the built-in " @@ -176,13 +572,38 @@ static void sbsa_ref_init(MachineState *machine) machine->ram_size); memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram); + create_fdt(vms); + + create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); + + create_secure_ram(vms, secure_sysmem); + + create_gic(vms, pic); + + create_uart(vms, pic, VIRT_UART, sysmem, serial_hd(0)); + + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1)); + + create_rtc(vms, pic); + + create_gpio(vms, pic); + + create_ahci(vms, pic); + + create_pcie(vms, pic); + 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[VIRT_MEM].base; + vms->bootinfo.get_dtb = sbsa_ref_dtb; + vms->bootinfo.skip_dtb_autoload = true; vms->bootinfo.firmware_loaded = firmware_loaded; arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo); + + vms->machine_done.notify = sbsa_ref_machine_done; + qemu_add_machine_init_done_notifier(&vms->machine_done); } static uint64_t sbsa_ref_cpu_mp_affinity(VirtMachineState *vms, int idx)