From patchwork Thu Apr 18 04:04:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 162433 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp256100jan; Wed, 17 Apr 2019 21:05:55 -0700 (PDT) X-Google-Smtp-Source: APXvYqyDYon2PMpMRsqSf2IKLPFZ9dOtyHRGEZ8pfmIebO8lTVZfMYSnd3jvjJu2wKMnBHdEtT3w X-Received: by 2002:a1c:c504:: with SMTP id v4mr1346454wmf.45.1555560355020; Wed, 17 Apr 2019 21:05:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555560355; cv=none; d=google.com; s=arc-20160816; b=XCQVD/vBLvcvhobkkD/C8Hqeu70W1mDLTxbRAUaKsjaSjdL/53xVdqX7FraxHUFJLp uM93BZ/RCmIIvb6FCHgw5v4F9AFZ83TWFs+W9TQaDzcOTESmZ50h14YrRZ4qIorotKAF SyXCeHxiCE8Uq2x41/zVlqzq6NXKOE5mwgESaeAMbPFBJ445Jr18cqn5EUAYQS0YY+Qm OXKtj3wGqU3aSJ6X7NHTFcguBnUFIDbY9R5Lpw6FNyvBH0mEvP/pIruf/9ev8kFCoH5y j2f4xY9dY5heX9fjO0FVHDDK1/rT1Lg5gGEuY00Aca/7WBk3w2EPkMS1SxPOUE7GlWcM 7OrQ== 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=SeC4zHquZf1BNV6kB7AnuQfbjQW0BHDNO1VSxrHLAoM=; b=N5026uX628rqwfd5H2+SNmzWqPT3lK1poxir1rIB9VGPcrstKCS4PGicxOM2TPhiFZ k1ojAesSn73hw4r31ToWonXJ8fCNjXUfphGIIUtsuzYPUcZ8pCSGTu/pdzj1+Av3ooD/ +0KmoexesGmTEbj2l4HyWqAdH9tGzashfvnDHbzRRayhWh77oafEhRnJaw+/BnLKLgmk W3riRZzYVX2xwqqK1M4r4LkS1+2PBzn7eYGMbaiMy8kO6Xf0lSuhHCCufUGIDrqRo9qx XF5qpbZ0FSK4U7HCN26QoF2opg4NXObTrWnJRtT79PRIJAnFHJDG9UTTwdYFkAJ5ATFS 331Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=GZ1JeXvF; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 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. [209.51.188.17]) by mx.google.com with ESMTPS id e5si619799wmh.91.2019.04.17.21.05.54 for (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 17 Apr 2019 21:05:55 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=GZ1JeXvF; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 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 ([127.0.0.1]:35245 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hGyJ7-0002Ex-M1 for patch@linaro.org; Thu, 18 Apr 2019 00:05:53 -0400 Received: from eggs.gnu.org ([209.51.188.92]:57907) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hGyIc-00025u-Hi for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hGyIY-0001wO-Sa for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:22 -0400 Received: from mail-pf1-x442.google.com ([2607:f8b0:4864:20::442]:35761) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hGyIX-0001rl-07 for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:17 -0400 Received: by mail-pf1-x442.google.com with SMTP id t21so483110pfh.2 for ; Wed, 17 Apr 2019 21:05:16 -0700 (PDT) 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=SeC4zHquZf1BNV6kB7AnuQfbjQW0BHDNO1VSxrHLAoM=; b=GZ1JeXvFj5ae436dEn/uFqCY7I/lEH+vcKFu1cVrYdyC1T8VZLFK+zBPd7F+Sj/nPK kAuuzUYh15YxkxeMgjLqcwV4mTibULP+POzDi0eL7N/0gHYHQDv3IAmc+usFxYhFj66b XFXPjYMTczrnOSj/9BcXcDddg/NUFJbzq99sAqVE8dBdIKMxBZBKJx6IQ+HKdSdnCBAz yHNZsBscSuMHCPkifuBIgPpZy+teNdz4j6QfEufZA3e+aJS28OdyJqUiR7C8IsFaxxAe Mk0y685OlVNk2th4Frx6h2OkbNue4IKUb6IYvKSUstISeC/ZKnUAaaAtc+GM42x9IBqD 0nPA== 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=SeC4zHquZf1BNV6kB7AnuQfbjQW0BHDNO1VSxrHLAoM=; b=KxoHhPIZ8Q1vf6peWSXUi9sN70d+XO8b3sg47IOCgXi1mwRuJyr8DrzSQcKF2jHXLf GiDaOFMb5iOpzwYdtXTm8Fg3EyNfYLo8nBlHuVeNc696RRamJBD7ctAigzIUfof83v0B 5R2cZt1rXY7Xa/Oerieqfcm0EwEg0rZVQlkg2HovaL7mkvFNA2nF0hKkMBJ+hZ5dVZYk +V8RbFWTgGHhm4vFEaNJy/rVh7bqNHHAqGJsjdnH3r8oTVGe5m4s5r2D4PXsSYGJgV+X iDNNd0WoJARgd0jcwnX/gCvs4/f2wbAWx7JUH+r32SQRUmWI4G3t1brJ++rQjWDbuPTf x/LQ== X-Gm-Message-State: APjAAAWhdX/qrvwBWtnUgZu+Q48XqnoRYEXY+abRRjL34uUfogmUJNfB rqHuaF9gnkz2Zmik6uwyTB4Pzg== X-Received: by 2002:a62:6004:: with SMTP id u4mr3852689pfb.257.1555560315464; Wed, 17 Apr 2019 21:05:15 -0700 (PDT) Received: from localhost.localdomain ([38.106.11.25]) by smtp.gmail.com with ESMTPSA id h8sm910688pfo.149.2019.04.17.21.05.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 17 Apr 2019 21:05:14 -0700 (PDT) From: Hongbo Zhang To: peter.maydell@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Thu, 18 Apr 2019 12:04:50 +0800 Message-Id: <1555560291-3415-2-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1555560291-3415-1-git-send-email-hongbo.zhang@linaro.org> References: <1555560291-3415-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::442 Subject: [Qemu-devel] [PATCH v7 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. - 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 --- default-configs/arm-softmmu.mak | 1 + hw/arm/Kconfig | 3 + hw/arm/Makefile.objs | 1 + hw/arm/sbsa-ref.c | 306 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 hw/arm/sbsa-ref.c -- 2.7.4 diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 613d19a..1a2352e 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -145,6 +145,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..652ec13 --- /dev/null +++ b/hw/arm/sbsa-ref.c @@ -0,0 +1,306 @@ +/* + * ARM SBSA Reference Platform emulation + * + * Copyright (c) 2018 Linaro Limited + * Written by Hongbo Zhang + * + * 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 "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_UART_MM, + 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_SECURE_UART_MM] = { 0x60040000, 0x00001000 }, + [SBSA_SMMU] = { 0x60050000, 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 }, + /* 32-bit address PCIE MMIO space */ + [SBSA_PCIE_MMIO] = { 0x80000000, 0x70000000 }, + /* 256M PCIE ECAM space */ + [SBSA_PCIE_ECAM] = { 0xf0000000, 0x10000000 }, + /* ~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_SECURE_UART_MM] = 9, + [SBSA_AHCI] = 10, + [SBSA_EHCI] = 11, +}; + +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); From patchwork Thu Apr 18 04:04:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 162434 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp257434jan; Wed, 17 Apr 2019 21:07:39 -0700 (PDT) X-Google-Smtp-Source: APXvYqz15n7y4BSwtlKAxedusB7RCIS+igp/qDEY+QZAZvymuUr0CaGKHWVPUQQbvkFJO6aXKNlO X-Received: by 2002:adf:c18d:: with SMTP id x13mr53968972wre.246.1555560459879; Wed, 17 Apr 2019 21:07:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1555560459; cv=none; d=google.com; s=arc-20160816; b=r4F9egz8XHIZCJm7eXtbckZbLQOSHSIzUndc9DLOqZ4tFfBK8K9rGgoMRrXItn42KB J85+7gTXf69hIyr/paJB7E/OdbwHu4Uk5B8LcL2FPLBGPvJBKYUFBm8T7Z2X+zCOxZFW s37bXoVD4uOG3Ne02Xku9O7FLYHD5i80iS7F8x+Ly0n3XVALvEN7IvkhloR3I5NDaLoP KDPHbsA6ufV1dThckdLDCS24Zak90bqNnOgJcdgpiF6T2Zud9lE+TvJvak51WJyyOUnW AxDdSOyFqRkkn+djGocVDQ448pg7DGiUzoWRvG5OjRNGoJ0WHuLSizDC+4ZBcxolq54O GMxQ== 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=+RH+Ui4b5wc2/yJel9rhq51E5AUQ3jvmY6g/+lrpsUM=; b=DrEra4AmzIWRvm2I8N7Yhdj8z4m0DzYmbrIcrUcSoCmzagVK85a19FdCGiziC9deJL +E7FaQY4LYRvlrOBYGfWjer/9nreHxmK2D7ivZYKt5ptLspSNe2uboNCFG6I8enfbQWQ 6R4PRZNXz0IiYugwqwQchtQq8yF0LRIEOSIBQ7SleQibmCUMBQ2MGFmdzbPaXHw9upWF Ir7e6sSzB3MW1lBF9qDmPaQiDmsD44zykwoVrb847poM9uABVB5rsLRh0uwQbvv1Scfo y3W6BNzEuMpffEgOQ0RQX0bRMjCJ8Mz6ZNDNO1ifOWGT3+HEaTSUAT+wpYx/3eKQtgAd MFEw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=rmzeMY6D; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 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. [209.51.188.17]) by mx.google.com with ESMTPS id f16si699627wre.289.2019.04.17.21.07.39 for (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 17 Apr 2019 21:07:39 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=rmzeMY6D; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 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 ([127.0.0.1]:35263 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hGyKo-0003bh-Dg for patch@linaro.org; Thu, 18 Apr 2019 00:07:38 -0400 Received: from eggs.gnu.org ([209.51.188.92]:57951) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hGyIg-00029w-EG for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hGyId-000213-0p for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:26 -0400 Received: from mail-pg1-x541.google.com ([2607:f8b0:4864:20::541]:46265) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hGyIc-00020P-Jw for qemu-devel@nongnu.org; Thu, 18 Apr 2019 00:05:22 -0400 Received: by mail-pg1-x541.google.com with SMTP id 10so155117pgv.13 for ; Wed, 17 Apr 2019 21:05:22 -0700 (PDT) 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=+RH+Ui4b5wc2/yJel9rhq51E5AUQ3jvmY6g/+lrpsUM=; b=rmzeMY6DTOEbsBEDdWBLnUk8C29lrsLG7mvGkMxVrZP9YBaAfNwmQWDVCp0qzrJTtg mDu6nRAPh2f0NDrFFBlA8n5MMZTpgC1PtNPEwhzb/3/wcNbyjagQiWFQp/fHu62PS1Ba fQTHKwJ7VH4eN66B/w8NiX/M6ycaDvonMKUanhptzcHFF1E7GmO9U04rHbXSIfoUuMK+ c82ZEL9O37+Wo/Tp3X2Tg8mkSXth2omzIvH9rjEyZg9Laly25bB8PVzvUSzijhB15Lov VwIeL7u4goAHXA/7SMGogNG5Ro5oYcbQjiOS5Embz6wDnsAjX8A5p9WxBE7InHVTcwhv 50Jw== 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=+RH+Ui4b5wc2/yJel9rhq51E5AUQ3jvmY6g/+lrpsUM=; b=YJhexF5OVG81NNWoG2USpVLuNHgA3rBEAM3MJRhXMyK2CHp9JWd9Ha3v+6VSo1094i tDwnfyr8ivNZXhKHTgLEhoPDbe5NHwkH3fmNkkpBF2AkOaipz85B/KS6Fsf8cQTYuhKn vfrWkYZ0sPSO4vWvJdK+mGgbC/l5LW69bwq9zHdMbQCU3HQnfceNqbX1NIdzzGcnBywk 0PJN7uPtlQPLZ67HKh+zSoimjtgs6PAcV3e78o6+DHn8ofdpcBsDkpAeETNXE0L59XBM i92BRyKycBlqkQ7gFp6DVA4vfVZYfUyG7CeKkURQbiGJnYqWVWlwV2Ny91yVY3WQlCbJ uztg== X-Gm-Message-State: APjAAAVsyLuKzoC4TRzrz1QHkJWW7ceTphAfsQVATvxO9JgqOV4PS0uv qfyftPGcu8xtI7oPSnkpiNaX7w== X-Received: by 2002:a63:720c:: with SMTP id n12mr86693858pgc.348.1555560321545; Wed, 17 Apr 2019 21:05:21 -0700 (PDT) Received: from localhost.localdomain ([38.106.11.25]) by smtp.gmail.com with ESMTPSA id h8sm910688pfo.149.2019.04.17.21.05.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 17 Apr 2019 21:05:20 -0700 (PDT) From: Hongbo Zhang To: peter.maydell@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Thu, 18 Apr 2019 12:04:51 +0800 Message-Id: <1555560291-3415-3-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1555560291-3415-1-git-send-email-hongbo.zhang@linaro.org> References: <1555560291-3415-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::541 Subject: [Qemu-devel] [PATCH v7 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 | 451 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) -- 2.7.4 diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 652ec13..3fb0027 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -21,6 +21,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/units.h" +#include "sysemu/device_tree.h" #include "sysemu/numa.h" #include "sysemu/sysemu.h" #include "exec/address-spaces.h" @@ -28,11 +29,28 @@ #include "kvm_arm.h" #include "hw/arm/arm.h" #include "hw/boards.h" +#include "hw/ide/internal.h" +#include "hw/ide/ahci_internal.h" #include "hw/intc/arm_gicv3_common.h" +#include "hw/loader.h" +#include "hw/pci-host/gpex.h" +#include "hw/usb.h" +#include "net/net.h" #define RAMLIMIT_GB 8192 #define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB) +#define NUM_IRQS 256 +#define NUM_SMMU_IRQS 4 +#define NUM_SATA_PORTS 6 + +#define VIRTUAL_PMU_IRQ 7 +#define ARCH_GIC_MAINT_IRQ 9 +#define ARCH_TIMER_VIRT_IRQ 11 +#define ARCH_TIMER_S_EL1_IRQ 13 +#define ARCH_TIMER_NS_EL1_IRQ 14 +#define ARCH_TIMER_NS_EL2_IRQ 10 + enum { SBSA_FLASH, SBSA_MEM, @@ -115,6 +133,415 @@ static const int sbsa_ref_irqmap[] = { [SBSA_EHCI] = 11, }; +/* + * 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(SBSAMachineState *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 SBSAMachineState *vms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + /* + * Create one secure and nonsecure flash devices to fill SBSA_FLASH + * space in the memmap, file passed via -bios goes in the first one. + */ + hwaddr flashsize = vms->memmap[SBSA_FLASH].size / 2; + hwaddr flashbase = vms->memmap[SBSA_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(SBSAMachineState *vms, + MemoryRegion *secure_sysmem) +{ + MemoryRegion *secram = g_new(MemoryRegion, 1); + hwaddr base = vms->memmap[SBSA_SECURE_MEM].base; + hwaddr size = vms->memmap[SBSA_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(SBSAMachineState *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[SBSA_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[SBSA_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 1, vms->memmap[SBSA_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_GIC_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 SBSAMachineState *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 SBSAMachineState *vms, qemu_irq *pic) +{ + hwaddr base = vms->memmap[SBSA_RTC].base; + int irq = vms->irqmap[SBSA_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 SBSAMachineState *vms, qemu_irq *pic) +{ + DeviceState *pl061_dev; + hwaddr base = vms->memmap[SBSA_GPIO].base; + int irq = vms->irqmap[SBSA_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 SBSAMachineState *vms, qemu_irq *pic) +{ + hwaddr base = vms->memmap[SBSA_AHCI].base; + int irq = vms->irqmap[SBSA_AHCI]; + DeviceState *dev; + DriveInfo *hd[NUM_SATA_PORTS]; + SysbusAHCIState *sysahci; + AHCIState *ahci; + int i; + + dev = qdev_create(NULL, "sysbus-ahci"); + qdev_prop_set_uint32(dev, "num-ports", NUM_SATA_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_ehci(const SBSAMachineState *vms, qemu_irq *pic) +{ + hwaddr base = vms->memmap[SBSA_EHCI].base; + int irq = vms->irqmap[SBSA_EHCI]; + USBBus *usb_bus; + + sysbus_create_simple("platform-ehci-usb", base, pic[irq]); + + usb_bus = usb_bus_find(-1); + usb_create_simple(usb_bus, "usb-kbd"); + usb_create_simple(usb_bus, "usb-mouse"); +} + +static void create_smmu(const SBSAMachineState *vms, qemu_irq *pic, + PCIBus *bus) +{ + hwaddr base = vms->memmap[SBSA_SMMU].base; + int irq = vms->irqmap[SBSA_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(SBSAMachineState *vms, qemu_irq *pic) +{ + hwaddr base_ecam = vms->memmap[SBSA_PCIE_ECAM].base; + hwaddr size_ecam = vms->memmap[SBSA_PCIE_ECAM].size; + hwaddr base_mmio = vms->memmap[SBSA_PCIE_MMIO].base; + hwaddr size_mmio = vms->memmap[SBSA_PCIE_MMIO].size; + hwaddr base_mmio_high = vms->memmap[SBSA_PCIE_MMIO_HIGH].base; + hwaddr size_mmio_high = vms->memmap[SBSA_PCIE_MMIO_HIGH].size; + hwaddr base_pio = vms->memmap[SBSA_PCIE_PIO].base; + int irq = vms->irqmap[SBSA_PCIE]; + MemoryRegion *mmio_alias, *mmio_alias_high, *mmio_reg; + MemoryRegion *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 the MMIO_HIGH space */ + mmio_alias_high = g_new0(MemoryRegion, 1); + memory_region_init_alias(mmio_alias_high, OBJECT(dev), "pcie-mmio-high", + mmio_reg, base_mmio_high, size_mmio_high); + memory_region_add_subregion(get_system_memory(), base_mmio_high, + mmio_alias_high); + + /* 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 SBSAMachineState *board = container_of(binfo, SBSAMachineState, + bootinfo); + + *fdt_size = board->fdt_size; + return board->fdt; +} + static void sbsa_ref_init(MachineState *machine) { SBSAMachineState *vms = SBSA_MACHINE(machine); @@ -125,6 +552,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 " @@ -209,11 +637,34 @@ static void sbsa_ref_init(MachineState *machine) machine->ram_size); memory_region_add_subregion(sysmem, vms->memmap[SBSA_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, 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); + + create_gpio(vms, pic); + + create_ahci(vms, pic); + + create_ehci(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[SBSA_MEM].base; + vms->bootinfo.get_dtb = sbsa_ref_dtb; vms->bootinfo.firmware_loaded = firmware_loaded; arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo); }