From patchwork Sun Jun 30 10:20:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 168173 Delivered-To: patch@linaro.org Received: by 2002:a92:4782:0:0:0:0:0 with SMTP id e2csp1625654ilk; Sun, 30 Jun 2019 03:22:07 -0700 (PDT) X-Google-Smtp-Source: APXvYqxi68+pe730fp/YPUcexqeL/cPw2X5p34caSKyM9O4EXkydLQmeXHuLpxE7WaqYYafnR3Qm X-Received: by 2002:a50:b4fd:: with SMTP id x58mr21948221edd.97.1561890126917; Sun, 30 Jun 2019 03:22:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561890126; cv=none; d=google.com; s=arc-20160816; b=WoG8H24B7SD7rleubnjZdvTGp9vIGEd75pT7vfYpnzv9DLRB2FsBmjZsD4BXgRNPgM tZcIXkl1FTHM6+5DMJCmDCmEntifAJ9FXfhjS1JsPjIp1pcefsHrlMm5fA1XEZTSRlLt EFcmk4XtyTT3YnMXG+FhhZnVVWZsbsj5Ot0Vch9k+di2h7GoFxvLiAnnH9416FKzhduW 6nj9h1/QyN0Z+7KByTfXdqOiAul5Tp70tBdTaoDXhuUkCz/IRBqfwDca7dtYkEqAYpzH SbCtnmNQ1q0Ms93jpr9RKdyA76QEb0B4on9WYEm9vN/juL2dwVo3vIQPdNu/jMfJWeFU PHYg== 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=5oD05dphrRbZ7JrCgkcfAPZGRaVpSL2TcmyWvWdRW8Y=; b=jodj4mdhBqAg9YoS8J8RkmAg555qXcllqeHalnj4hPSY4iNDRtGc/6RYf8+MtkUuMp iSlQ08aYfrFnIXLg6w31PWLpMTSa+I+dEKMd2U09OqyC3kZGcJU9XCktnGTnmkJZI/Y3 91IKO3dyu5zS5IvCG2KQcky3nMJy6VZTrN4GgRStcw8sJ9prqFzg+kaClET440UofhUP pPiXLzqgchITgviKppyt4h+NgaRsSmnPickjatakwBflU5SSbclOEm1JnSkaI5CkKrug +jnmA83jfJiJg8xkqf0I9llCBO6Zp162Lj31o6fQXM1wFVUZ29+fjoyNIh3dCI6XmDbX d67A== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=dgkNHFnq; 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 bs8si4826324ejb.306.2019.06.30.03.22.06 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 30 Jun 2019 03:22:06 -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=dgkNHFnq; 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 ([::1]:43804 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hhWyD-0001ut-Py for patch@linaro.org; Sun, 30 Jun 2019 06:22:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47007) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hhWxQ-0001Sx-OQ for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hhWxN-0004EF-MN for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:16 -0400 Received: from mail-pf1-x442.google.com ([2607:f8b0:4864:20::442]:33774) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hhWxN-0004Cz-6q for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:13 -0400 Received: by mail-pf1-x442.google.com with SMTP id x15so5126946pfq.0 for ; Sun, 30 Jun 2019 03:21:12 -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=5oD05dphrRbZ7JrCgkcfAPZGRaVpSL2TcmyWvWdRW8Y=; b=dgkNHFnqp2zS/FirS0NU9A9njlC5T5Zd+iloE9kH/g0eeKu21cMzdaUJV56CCxg2Sl 8ZNKllBoa9vAV1EuEbJJu0IwvstioCWwhIQy9FCLGvqfNOH/VbLRnDbDcEDvQ6n9WByw AJOUNRaotsPG00WKutFLfkllGJEVcPUUL7pg2/D7MU+FVL6YhB/uWNtBZJ4MHs1X6Sbi mW9TZIcbGUPGoaZUAvu0DWIUkIsa3QIp5g02PDL3SqmtH96MY5r4SKo4a+Xrg8WEO8FX KgajbD2xZPUB+ert0JROCj0PTnb4AYaDXAKCZfaDH/6N958frlqv3MWn0FGHveFb9xs+ MXQQ== 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=5oD05dphrRbZ7JrCgkcfAPZGRaVpSL2TcmyWvWdRW8Y=; b=mMGEDGS+W/8riOKDwiali+Nyu5kp3BaQxXRfEm2OYA2IOdaB9t9rd5JfnJPxGgIKGM LyK8McZkJ+fOktuVbvizGxuNiO4eSMhLh2fGVmOHsSmtjKT+ulFUA+2Qe8S5SFtkjE18 Qio94+D0rJyXiWRa+ZDRKJdx28AhYZ133b4p2oGY2UMG9rVa1Jyw4uQfWx5WlOom9FhJ 5ktHkbVwfhAvsEF/8wphjDLIYkLMx2UD/qRyuYy70bsJP52ROxZU0WTP0cbxtnK7PVtH oExhLqH5cxYDf72XyvHrS6aZ9DsdZn+E8Bqd0f+Etg+z3dxlvfapDL9Rx12b+0hNNZLH npuw== X-Gm-Message-State: APjAAAUGkgkcPS0rc8cXj1qAO2+HJbAx4OmSf2BnoJCwQBAmWAyMd4Uw NMAXa+5axPeoKtZVKjhQ5tJing== X-Received: by 2002:a17:90a:b011:: with SMTP id x17mr24482364pjq.113.1561890071457; Sun, 30 Jun 2019 03:21:11 -0700 (PDT) Received: from localhost.localdomain ([114.246.94.159]) by smtp.gmail.com with ESMTPSA id m100sm8714549pje.12.2019.06.30.03.21.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 30 Jun 2019 03:21:10 -0700 (PDT) From: Hongbo Zhang To: peter.maydell@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Sun, 30 Jun 2019 18:20:33 +0800 Message-Id: <1561890034-15921-2-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1561890034-15921-1-git-send-email-hongbo.zhang@linaro.org> References: <1561890034-15921-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 v9 1/2] hw/arm: Add arm SBSA reference machine, skeleton part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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 | 16 +++ hw/arm/Makefile.objs | 1 + hw/arm/sbsa-ref.c | 281 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 299 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 1f2e0e7..f9fdb73 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -19,6 +19,7 @@ CONFIG_SX1=y CONFIG_NSERIES=y CONFIG_STELLARIS=y CONFIG_REALVIEW=y +CONFIG_SBSA_REF=y CONFIG_VERSATILE=y CONFIG_VEXPRESS=y CONFIG_ZYNQ=y diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 9aced9d..18e47b2 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -184,6 +184,22 @@ config REALVIEW select DS1338 # I2C RTC+NVRAM select USB_OHCI +config SBSA_REF + bool + imply PCI_DEVICES + select A15MPCORE + select AHCI + select ARM_SMMUV3 + select GPIO_KEY + select PCI_EXPRESS + select PCI_EXPRESS_GENERIC_BRIDGE + select PFLASH_CFI01 + select PL011 # UART + select PL031 # RTC + select PL061 # GPIO + select PLATFORM_BUS + select USB_EHCI_SYSBUS + config SABRELITE bool select FSL_IMX6 diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 994e67d..43ce8d5 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -19,6 +19,7 @@ obj-$(CONFIG_SPITZ) += spitz.o obj-$(CONFIG_TOSA) += tosa.o obj-$(CONFIG_Z2) += z2.o obj-$(CONFIG_REALVIEW) += realview.o +obj-$(CONFIG_SBSA_REF) += sbsa-ref.o obj-$(CONFIG_STELLARIS) += stellaris.o obj-$(CONFIG_COLLIE) += collie.o obj-$(CONFIG_VERSATILE) += versatilepb.o diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c new file mode 100644 index 0000000..eaf97e8 --- /dev/null +++ b/hw/arm/sbsa-ref.c @@ -0,0 +1,281 @@ +/* + * 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/boot.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; + 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 *sms = SBSA_MACHINE(machine); + MachineClass *mc = MACHINE_GET_CLASS(machine); + MemoryRegion *sysmem = get_system_memory(); + MemoryRegion *secure_sysmem = NULL; + MemoryRegion *ram = g_new(MemoryRegion, 1); + 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 for this machine"); + exit(1); + } + + /* + * This machine has EL3 enabled, external firmware should supply PSCI + * implementation, so the QEMU's internal PSCI is disabled. + */ + sms->psci_conduit = QEMU_PSCI_CONDUIT_DISABLED; + + sbsa_max_cpus = sbsa_ref_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); + } + + sms->smp_cpus = smp_cpus; + + if (machine->ram_size > sbsa_ref_memmap[SBSA_MEM].size) { + error_report("sbsa-ref: cannot model more than %dGB RAM", RAMLIMIT_GB); + exit(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, + sbsa_ref_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, sbsa_ref_memmap[SBSA_MEM].base, ram); + + sms->bootinfo.ram_size = machine->ram_size; + sms->bootinfo.kernel_filename = machine->kernel_filename; + sms->bootinfo.nb_cpus = smp_cpus; + sms->bootinfo.board_id = -1; + sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base; + arm_load_kernel(ARM_CPU(first_cpu), &sms->bootinfo); +} + +static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, 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 *sms = 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(sms, 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_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, + .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 Sun Jun 30 10:20:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hongbo Zhang X-Patchwork-Id: 168171 Delivered-To: patch@linaro.org Received: by 2002:a92:4782:0:0:0:0:0 with SMTP id e2csp1625512ilk; Sun, 30 Jun 2019 03:21:56 -0700 (PDT) X-Google-Smtp-Source: APXvYqxMZI5jBlnEZTGZt6KwZnjdfTdC0jIbGIZPavwNYAT2V2eI+tT63YrGuioSqbqBqRMb3h7p X-Received: by 2002:aa7:c14f:: with SMTP id r15mr22326762edp.116.1561890116548; Sun, 30 Jun 2019 03:21:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561890116; cv=none; d=google.com; s=arc-20160816; b=BoS+QASTFPp4q3ZaaI9jM/X6nx4lmEa0QbqHC8nzRNiG8ouuc1i2l0YPft1btGZKTM X7OE+l0N93TrCSjIO4jRxpIJupKP6NuQ4djf3StWxlBv+sE1rT9FTDDgGo0pAUhSmxVx 4P7jTlqdq3QgAEMbofZo5+VnRMdMPOWFpEW5Sxu61VhA1coJy2D2lhv7scIToya0bf6U EO8YEbaGx+mKHhCqvD0mv24iEsqJfC7NBqE5LIkuNJ1NGblMtZ47nwkRriHaEUKa3Lhr ccmfoCXx/URMb53b/dgupOXM8UpkwEJq2wKLNfIMylbHVem1kMR86J5xVYfARBai+sik EBjA== 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=CKGKAjYZuPTe3VTe+xXz5uBHxeOHomuNETsNJcHY2qc=; b=yAUYBzeek5mgpAJMNyjUjsbn7ZzVNfhMAqnZ6uhexd5NUdrnbj2L2qlWRIwTEQ63mt yb/fU1v2l1ATJEAufQckysVlTPjziKYh8ZDpIHqJwFbQBZ+SqspT51nD0beDyl06FaRQ fDXRrD0oK0nkyjM4V66zoLakYh4TCvqMOHp+en8rE0P3gBuBYYDsK6BGT6OF38icseNf ZFY8YQLgUwryRzR7yrDFkp0+9EsCIkwyHRTsNyBX+4LkZVOLDOXLCwVVxuBqj3W9PoBU eidxsx5EvkPyUDRbiyFJnOMwR+AB9PebdJfuPSGN1aeanF7bqpgrLVGWdsl2yvZygQcS RVIw== ARC-Authentication-Results: i=1; mx.google.com; dkim=fail header.i=@linaro.org header.s=google header.b=VtTUbsAi; 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 g26si4966762ejr.355.2019.06.30.03.21.56 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 30 Jun 2019 03:21:56 -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=VtTUbsAi; 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 ([::1]:43798 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hhWy3-0001Vs-F5 for patch@linaro.org; Sun, 30 Jun 2019 06:21:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:47027) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hhWxU-0001U9-Ql for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hhWxQ-0004GZ-Mj for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:20 -0400 Received: from mail-pl1-x641.google.com ([2607:f8b0:4864:20::641]:33389) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1hhWxP-0004Eq-41 for qemu-devel@nongnu.org; Sun, 30 Jun 2019 06:21:15 -0400 Received: by mail-pl1-x641.google.com with SMTP id c14so5765791plo.0 for ; Sun, 30 Jun 2019 03:21:14 -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=CKGKAjYZuPTe3VTe+xXz5uBHxeOHomuNETsNJcHY2qc=; b=VtTUbsAiOXEye65Ovqu6+eF12uG1Urxww/s7fM1KKUSOLPp+q5jwxZMkIHiH5m68yO YiePFswmMBKBjZil0SVtl54khD+yZnYjlNOyg56dnvg02qViHq36Fyx4xssnmw3V1ysf H8CqF/lJ1M7stmy78+ryi7Nd0ignUf6qC4EQjzat323Sg8fIhyTw5JDkrloApfJZAfUQ oxqUjbomNPtjQGUmIXiR0U9Kuy1Z0e25pDLV67dE2djpceq2YIocvE3bgkvDZgMQdTBD /la2r3pCXfDS3NtSJos1zIfvVkhIsyTyFy4vuf/m0N2maMhm0gpJ074gGLN2u+Ok32Xl sevQ== 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=CKGKAjYZuPTe3VTe+xXz5uBHxeOHomuNETsNJcHY2qc=; b=R5LExTMWQiBz2O6Pd+PCzsAIF2NXnJXUfP8UvKgr8WcIRXTeMO1ODz6l0JVJvB0Hpi 5VZ/hQdQtty2nkm15BRUMFNaqnY6+44dHw/Vnu3hTy1pCRoaiWfHDV8L6SaPe2sWfWVp nE2Uva0d8oAsIzh0cj2rH89AqsRHA4NbywWdh6C0Ki4tuR0RXsEZqH7AdPlDSMWuWw4g WVsLYLem0ZgaqbxKfj/trqV+u06GcS14e0Tw/zNZmyh34pGO/3EHYrpSduEdlAZ164Nh CAttFQlik5gl2tnice39vsKszqRdWx48BugMQVSt57RS5UC1f5/3pNopZkvHKaQtSGqU JGHg== X-Gm-Message-State: APjAAAWkm9dVEBRemRNQFlZTSQvoSyl7YTxUWOX6I9RkSJZE9ZPgYv28 +wz+yuOLUUDf/xBFY8XQt3KT9A== X-Received: by 2002:a17:902:b187:: with SMTP id s7mr22149893plr.309.1561890073726; Sun, 30 Jun 2019 03:21:13 -0700 (PDT) Received: from localhost.localdomain ([114.246.94.159]) by smtp.gmail.com with ESMTPSA id m100sm8714549pje.12.2019.06.30.03.21.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 30 Jun 2019 03:21:13 -0700 (PDT) From: Hongbo Zhang To: peter.maydell@linaro.org, qemu-devel@nongnu.org, qemu-arm@nongnu.org Date: Sun, 30 Jun 2019 18:20:34 +0800 Message-Id: <1561890034-15921-3-git-send-email-hongbo.zhang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1561890034-15921-1-git-send-email-hongbo.zhang@linaro.org> References: <1561890034-15921-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 v9 2/2] hw/arm: Add arm SBSA reference machine, devices part X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 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 | 525 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 525 insertions(+) -- 2.7.4 diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index eaf97e8..3b2b9cb 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -18,21 +18,41 @@ */ #include "qemu/osdep.h" +#include "qemu-common.h" #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" #include "exec/hwaddr.h" #include "kvm_arm.h" #include "hw/arm/boot.h" +#include "hw/block/flash.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, @@ -67,6 +87,7 @@ typedef struct { void *fdt; int fdt_size; int psci_conduit; + PFlashCFI01 *flash[2]; } SBSAMachineState; #define TYPE_SBSA_MACHINE MACHINE_TYPE_NAME("sbsa-ref") @@ -113,6 +134,455 @@ 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 *sms) +{ + void *fdt = create_device_tree(&sms->fdt_size); + const MachineState *ms = MACHINE(sms); + int cpu; + + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + sms->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(sms->fdt, "/cpus"); + + for (cpu = sms->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(sms->fdt, nodename); + + if (ms->possible_cpus->cpus[cs->cpu_index].props.has_node_id) { + qemu_fdt_setprop_cell(sms->fdt, nodename, "numa-node-id", + ms->possible_cpus->cpus[cs->cpu_index].props.node_id); + } + + g_free(nodename); + } +} + +#define SBSA_FLASH_SECTOR_SIZE (256 * KiB) + +static PFlashCFI01 *sbsa_flash_create1(SBSAMachineState *sms, + const char *name, + const char *alias_prop_name) +{ + /* + * Create a single flash device. We use the same parameters as + * the flash devices on the Versatile Express board. + */ + DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01); + + qdev_prop_set_uint64(dev, "sector-length", SBSA_FLASH_SECTOR_SIZE); + 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); + object_property_add_child(OBJECT(sms), name, OBJECT(dev), + &error_abort); + object_property_add_alias(OBJECT(sms), alias_prop_name, + OBJECT(dev), "drive", &error_abort); + return PFLASH_CFI01(dev); +} + +static void sbsa_flash_create(SBSAMachineState *sms) +{ + sms->flash[0] = sbsa_flash_create1(sms, "sbsa.flash0", "pflash0"); + sms->flash[1] = sbsa_flash_create1(sms, "sbsa.flash1", "pflash1"); +} + +static void sbsa_flash_map1(PFlashCFI01 *flash, + hwaddr base, hwaddr size, + MemoryRegion *sysmem) +{ + DeviceState *dev = DEVICE(flash); + + assert(size % SBSA_FLASH_SECTOR_SIZE == 0); + assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX); + qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE); + qdev_init_nofail(dev); + + memory_region_add_subregion(sysmem, base, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), + 0)); +} + +static void sbsa_flash_map(SBSAMachineState *sms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + /* + * Map two flash devices to fill the SBSA_FLASH space in the memmap. + * sysmem is the system memory space. secure_sysmem is the secure view + * of the system, and the first flash device should be made visible only + * there. The second flash device is visible to both secure and nonsecure. + * If sysmem == secure_sysmem this means there is no separate Secure + * address space and both flash devices are generally visible. + */ + hwaddr flashsize = sbsa_ref_memmap[SBSA_FLASH].size / 2; + hwaddr flashbase = sbsa_ref_memmap[SBSA_FLASH].base; + + sbsa_flash_map1(sms->flash[0], flashbase, flashsize, + secure_sysmem); + sbsa_flash_map1(sms->flash[1], flashbase + flashsize, flashsize, + sysmem); +} + +static bool sbsa_firmware_init(SBSAMachineState *sms, + MemoryRegion *sysmem, + MemoryRegion *secure_sysmem) +{ + int i; + BlockBackend *pflash_blk0; + + /* Map legacy -drive if=pflash to machine properties */ + for (i = 0; i < ARRAY_SIZE(sms->flash); i++) { + pflash_cfi01_legacy_drive(sms->flash[i], + drive_get(IF_PFLASH, 0, i)); + } + + sbsa_flash_map(sms, sysmem, secure_sysmem); + + pflash_blk0 = pflash_cfi01_get_blk(sms->flash[0]); + + if (bios_name) { + char *fname; + MemoryRegion *mr; + int image_size; + + if (pflash_blk0) { + 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); + } + + /* Fall back to -bios */ + + fname = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); + if (!fname) { + error_report("Could not find ROM image '%s'", bios_name); + exit(1); + } + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(sms->flash[0]), 0); + image_size = load_image_mr(fname, mr); + g_free(fname); + if (image_size < 0) { + error_report("Could not load ROM image '%s'", bios_name); + exit(1); + } + } + + return pflash_blk0 || bios_name; +} + +static void create_secure_ram(SBSAMachineState *sms, + MemoryRegion *secure_sysmem) +{ + MemoryRegion *secram = g_new(MemoryRegion, 1); + hwaddr base = sbsa_ref_memmap[SBSA_SECURE_MEM].base; + hwaddr size = sbsa_ref_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 *sms, 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 = + sbsa_ref_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, sbsa_ref_memmap[SBSA_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 1, sbsa_ref_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 *sms, qemu_irq *pic, int uart, + MemoryRegion *mem, Chardev *chr) +{ + hwaddr base = sbsa_ref_memmap[uart].base; + int irq = sbsa_ref_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 *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_RTC].base; + int irq = sbsa_ref_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 *sms, qemu_irq *pic) +{ + DeviceState *pl061_dev; + hwaddr base = sbsa_ref_memmap[SBSA_GPIO].base; + int irq = sbsa_ref_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 *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_AHCI].base; + int irq = sbsa_ref_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 *sms, qemu_irq *pic) +{ + hwaddr base = sbsa_ref_memmap[SBSA_EHCI].base; + int irq = sbsa_ref_irqmap[SBSA_EHCI]; + + sysbus_create_simple("platform-ehci-usb", base, pic[irq]); +} + +static void create_smmu(const SBSAMachineState *sms, qemu_irq *pic, + PCIBus *bus) +{ + hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base; + int irq = sbsa_ref_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 *sms, qemu_irq *pic) +{ + hwaddr base_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].base; + hwaddr size_ecam = sbsa_ref_memmap[SBSA_PCIE_ECAM].size; + hwaddr base_mmio = sbsa_ref_memmap[SBSA_PCIE_MMIO].base; + hwaddr size_mmio = sbsa_ref_memmap[SBSA_PCIE_MMIO].size; + hwaddr base_mmio_high = sbsa_ref_memmap[SBSA_PCIE_MMIO_HIGH].base; + hwaddr size_mmio_high = sbsa_ref_memmap[SBSA_PCIE_MMIO_HIGH].size; + hwaddr base_pio = sbsa_ref_memmap[SBSA_PCIE_PIO].base; + int irq = sbsa_ref_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(sms, 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 *sms = SBSA_MACHINE(machine); @@ -120,8 +590,10 @@ static void sbsa_ref_init(MachineState *machine) MemoryRegion *sysmem = get_system_memory(); MemoryRegion *secure_sysmem = NULL; MemoryRegion *ram = g_new(MemoryRegion, 1); + bool firmware_loaded; 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 " @@ -135,6 +607,27 @@ static void sbsa_ref_init(MachineState *machine) } /* + * The Secure view of the world is the same as the NonSecure, + * but with a few extra devices. Create it as a container region + * containing the system memory at low priority; any secure-only + * devices go in at higher priority and take precedence. + */ + 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); + + firmware_loaded = sbsa_firmware_init(sms, sysmem, + secure_sysmem ?: sysmem); + + 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. */ @@ -195,11 +688,34 @@ static void sbsa_ref_init(MachineState *machine) machine->ram_size); memory_region_add_subregion(sysmem, sbsa_ref_memmap[SBSA_MEM].base, ram); + create_fdt(sms); + + create_secure_ram(sms, secure_sysmem); + + create_gic(sms, pic); + + create_uart(sms, pic, SBSA_UART, sysmem, serial_hd(0)); + create_uart(sms, pic, SBSA_SECURE_UART, secure_sysmem, serial_hd(1)); + /* Second secure UART for RAS and MM from EL0 */ + create_uart(sms, pic, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2)); + + create_rtc(sms, pic); + + create_gpio(sms, pic); + + create_ahci(sms, pic); + + create_ehci(sms, pic); + + create_pcie(sms, pic); + sms->bootinfo.ram_size = machine->ram_size; sms->bootinfo.kernel_filename = machine->kernel_filename; sms->bootinfo.nb_cpus = smp_cpus; sms->bootinfo.board_id = -1; sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base; + sms->bootinfo.get_dtb = sbsa_ref_dtb; + sms->bootinfo.firmware_loaded = firmware_loaded; arm_load_kernel(ARM_CPU(first_cpu), &sms->bootinfo); } @@ -248,6 +764,13 @@ 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 *sms = SBSA_MACHINE(obj); + + sbsa_flash_create(sms); +} + static void sbsa_ref_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -270,6 +793,8 @@ static void sbsa_ref_class_init(ObjectClass *oc, void *data) 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, };