2019-07-01 19:26:18 +03:00
|
|
|
/*
|
|
|
|
* ARM SBSA Reference Platform emulation
|
|
|
|
*
|
|
|
|
* Copyright (c) 2018 Linaro Limited
|
|
|
|
* Written by Hongbo Zhang <hongbo.zhang@linaro.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2 or later, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "qemu/osdep.h"
|
2020-10-28 14:36:57 +03:00
|
|
|
#include "qemu/datadir.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qemu/error-report.h"
|
|
|
|
#include "qemu/units.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "sysemu/device_tree.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "sysemu/numa.h"
|
2019-08-12 08:23:59 +03:00
|
|
|
#include "sysemu/runstate.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "sysemu/sysemu.h"
|
|
|
|
#include "exec/hwaddr.h"
|
|
|
|
#include "kvm_arm.h"
|
|
|
|
#include "hw/arm/boot.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/block/flash.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/boards.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/ide/internal.h"
|
|
|
|
#include "hw/ide/ahci_internal.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/intc/arm_gicv3_common.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/loader.h"
|
|
|
|
#include "hw/pci-host/gpex.h"
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-properties.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "hw/usb.h"
|
2020-02-25 01:22:23 +03:00
|
|
|
#include "hw/char/pl011.h"
|
2020-10-27 04:59:27 +03:00
|
|
|
#include "hw/watchdog/sbsa_gwdt.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
#include "net/net.h"
|
2020-09-03 23:43:22 +03:00
|
|
|
#include "qom/object.h"
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
#define RAMLIMIT_GB 8192
|
|
|
|
#define RAMLIMIT_BYTES (RAMLIMIT_GB * GiB)
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
#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
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
enum {
|
|
|
|
SBSA_FLASH,
|
|
|
|
SBSA_MEM,
|
|
|
|
SBSA_CPUPERIPHS,
|
|
|
|
SBSA_GIC_DIST,
|
|
|
|
SBSA_GIC_REDIST,
|
2020-08-26 17:19:52 +03:00
|
|
|
SBSA_SECURE_EC,
|
2021-08-06 05:31:19 +03:00
|
|
|
SBSA_GWDT_WS0,
|
2020-10-27 04:59:27 +03:00
|
|
|
SBSA_GWDT_REFRESH,
|
|
|
|
SBSA_GWDT_CONTROL,
|
2019-07-01 19:26:18 +03:00
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct SBSAMachineState {
|
2019-07-01 19:26:18 +03:00
|
|
|
MachineState parent;
|
|
|
|
struct arm_boot_info bootinfo;
|
|
|
|
int smp_cpus;
|
|
|
|
void *fdt;
|
|
|
|
int fdt_size;
|
|
|
|
int psci_conduit;
|
2019-12-06 19:23:03 +03:00
|
|
|
DeviceState *gic;
|
2019-07-01 19:26:18 +03:00
|
|
|
PFlashCFI01 *flash[2];
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
#define TYPE_SBSA_MACHINE MACHINE_TYPE_NAME("sbsa-ref")
|
2020-09-16 21:25:19 +03:00
|
|
|
OBJECT_DECLARE_SIMPLE_TYPE(SBSAMachineState, SBSA_MACHINE)
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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 },
|
2020-08-26 17:19:52 +03:00
|
|
|
[SBSA_SECURE_EC] = { 0x50000000, 0x00001000 },
|
2020-10-27 04:59:27 +03:00
|
|
|
[SBSA_GWDT_REFRESH] = { 0x50010000, 0x00001000 },
|
|
|
|
[SBSA_GWDT_CONTROL] = { 0x50011000, 0x00001000 },
|
2019-07-01 19:26:18 +03:00
|
|
|
[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 },
|
|
|
|
};
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
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,
|
2020-10-07 13:07:32 +03:00
|
|
|
[SBSA_SMMU] = 12, /* ... to 15 */
|
2021-08-06 05:31:19 +03:00
|
|
|
[SBSA_GWDT_WS0] = 16,
|
2019-07-01 19:26:18 +03:00
|
|
|
};
|
|
|
|
|
2020-11-20 17:17:05 +03:00
|
|
|
static const char * const valid_cpus[] = {
|
|
|
|
ARM_CPU_TYPE_NAME("cortex-a57"),
|
|
|
|
ARM_CPU_TYPE_NAME("cortex-a72"),
|
2022-05-06 21:02:41 +03:00
|
|
|
ARM_CPU_TYPE_NAME("cortex-a76"),
|
2022-05-06 21:02:42 +03:00
|
|
|
ARM_CPU_TYPE_NAME("neoverse-n1"),
|
2021-02-16 18:01:22 +03:00
|
|
|
ARM_CPU_TYPE_NAME("max"),
|
2020-11-20 17:17:05 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool cpu_type_valid(const char *cpu)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
|
|
|
|
if (strcmp(cpu, valid_cpus[i]) == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-08-27 15:43:35 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
2019-08-09 09:57:22 +03:00
|
|
|
int nb_numa_nodes = ms->numa_state->num_nodes;
|
2019-07-01 19:26:18 +03:00
|
|
|
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);
|
|
|
|
|
2022-05-05 14:39:47 +03:00
|
|
|
/*
|
|
|
|
* This versioning scheme is for informing platform fw only. It is neither:
|
|
|
|
* - A QEMU versioned machine type; a given version of QEMU will emulate
|
|
|
|
* a given version of the platform.
|
|
|
|
* - A reflection of level of SBSA (now SystemReady SR) support provided.
|
|
|
|
*
|
|
|
|
* machine-version-major: updated when changes breaking fw compatibility
|
|
|
|
* are introduced.
|
|
|
|
* machine-version-minor: updated when features are added that don't break
|
|
|
|
* fw compatibility.
|
|
|
|
*/
|
|
|
|
qemu_fdt_setprop_cell(fdt, "/", "machine-version-major", 0);
|
|
|
|
qemu_fdt_setprop_cell(fdt, "/", "machine-version-minor", 0);
|
|
|
|
|
2019-08-09 09:57:23 +03:00
|
|
|
if (ms->numa_state->have_numa_distance) {
|
2019-07-01 19:26:18 +03:00
|
|
|
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);
|
2019-08-09 09:57:24 +03:00
|
|
|
matrix[idx + 2] =
|
|
|
|
cpu_to_be32(ms->numa_state->nodes[i].distance[j]);
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qemu_fdt_add_subnode(fdt, "/distance-map");
|
|
|
|
qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix",
|
|
|
|
matrix, size);
|
|
|
|
g_free(matrix);
|
|
|
|
}
|
|
|
|
|
2020-08-27 15:43:35 +03:00
|
|
|
/*
|
|
|
|
* From Documentation/devicetree/bindings/arm/cpus.yaml
|
|
|
|
* On ARM v8 64-bit systems this property is required
|
|
|
|
* and matches the MPIDR_EL1 register affinity bits.
|
|
|
|
*
|
|
|
|
* * If cpus node's #address-cells property is set to 2
|
|
|
|
*
|
|
|
|
* The first reg cell bits [7:0] must be set to
|
|
|
|
* bits [39:32] of MPIDR_EL1.
|
|
|
|
*
|
|
|
|
* The second reg cell bits [23:0] must be set to
|
|
|
|
* bits [23:0] of MPIDR_EL1.
|
|
|
|
*/
|
2019-07-01 19:26:18 +03:00
|
|
|
qemu_fdt_add_subnode(sms->fdt, "/cpus");
|
2020-08-27 15:43:35 +03:00
|
|
|
qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#address-cells", 2);
|
|
|
|
qemu_fdt_setprop_cell(sms->fdt, "/cpus", "#size-cells", 0x0);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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);
|
2020-08-27 15:43:35 +03:00
|
|
|
uint64_t mpidr = sbsa_ref_cpu_mp_affinity(sms, cpu);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
qemu_fdt_add_subnode(sms->fdt, nodename);
|
2020-08-27 15:43:35 +03:00
|
|
|
qemu_fdt_setprop_u64(sms->fdt, nodename, "reg", mpidr);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2020-06-10 08:31:59 +03:00
|
|
|
DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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);
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 18:29:22 +03:00
|
|
|
object_property_add_child(OBJECT(sms), name, OBJECT(dev));
|
2019-07-01 19:26:18 +03:00
|
|
|
object_property_add_alias(OBJECT(sms), alias_prop_name,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 18:29:22 +03:00
|
|
|
OBJECT(dev), "drive");
|
2019-07-01 19:26:18 +03:00
|
|
|
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);
|
|
|
|
|
2020-05-11 23:52:46 +03:00
|
|
|
assert(QEMU_IS_ALIGNED(size, SBSA_FLASH_SECTOR_SIZE));
|
2019-07-01 19:26:18 +03:00
|
|
|
assert(size / SBSA_FLASH_SECTOR_SIZE <= UINT32_MAX);
|
|
|
|
qdev_prop_set_uint32(dev, "num-blocks", size / SBSA_FLASH_SECTOR_SIZE);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
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)
|
|
|
|
{
|
2020-10-26 17:30:16 +03:00
|
|
|
const char *bios_name;
|
2019-07-01 19:26:18 +03:00
|
|
|
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]);
|
|
|
|
|
2020-10-26 17:30:16 +03:00
|
|
|
bios_name = MACHINE(sms)->firmware;
|
2019-07-01 19:26:18 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_gic(SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
2019-05-18 23:54:26 +03:00
|
|
|
unsigned int smp_cpus = MACHINE(sms)->smp.cpus;
|
2019-07-01 19:26:18 +03:00
|
|
|
SysBusDevice *gicbusdev;
|
|
|
|
const char *gictype;
|
|
|
|
uint32_t redist0_capacity, redist0_count;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
gictype = gicv3_class_name();
|
|
|
|
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
sms->gic = qdev_new(gictype);
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_prop_set_uint32(sms->gic, "revision", 3);
|
|
|
|
qdev_prop_set_uint32(sms->gic, "num-cpu", smp_cpus);
|
2019-07-01 19:26:18 +03:00
|
|
|
/*
|
|
|
|
* Note that the num-irq property counts both internal and external
|
|
|
|
* interrupts; there are always 32 of the former (mandated by GIC spec).
|
|
|
|
*/
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_prop_set_uint32(sms->gic, "num-irq", NUM_IRQS + 32);
|
|
|
|
qdev_prop_set_bit(sms->gic, "has-security-extensions", true);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
redist0_capacity =
|
|
|
|
sbsa_ref_memmap[SBSA_GIC_REDIST].size / GICV3_REDIST_SIZE;
|
|
|
|
redist0_count = MIN(smp_cpus, redist0_capacity);
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_prop_set_uint32(sms->gic, "len-redist-region-count", 1);
|
|
|
|
qdev_prop_set_uint32(sms->gic, "redist-region-count[0]", redist0_count);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
gicbusdev = SYS_BUS_DEVICE(sms->gic);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(gicbusdev, &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
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,
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_get_gpio_in(sms->gic,
|
2019-07-01 19:26:18 +03:00
|
|
|
ppibase + timer_irq[irq]));
|
|
|
|
}
|
|
|
|
|
|
|
|
qdev_connect_gpio_out_named(cpudev, "gicv3-maintenance-interrupt", 0,
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_get_gpio_in(sms->gic, ppibase
|
2019-07-01 19:26:18 +03:00
|
|
|
+ ARCH_GIC_MAINT_IRQ));
|
|
|
|
qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
|
2019-12-06 19:23:03 +03:00
|
|
|
qdev_get_gpio_in(sms->gic, ppibase
|
2019-07-01 19:26:18 +03:00
|
|
|
+ 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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_uart(const SBSAMachineState *sms, int uart,
|
2019-07-01 19:26:18 +03:00
|
|
|
MemoryRegion *mem, Chardev *chr)
|
|
|
|
{
|
|
|
|
hwaddr base = sbsa_ref_memmap[uart].base;
|
|
|
|
int irq = sbsa_ref_irqmap[uart];
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
DeviceState *dev = qdev_new(TYPE_PL011);
|
2019-07-01 19:26:18 +03:00
|
|
|
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
|
|
|
|
|
|
|
qdev_prop_set_chr(dev, "chardev", chr);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
memory_region_add_subregion(mem, base,
|
|
|
|
sysbus_mmio_get_region(s, 0));
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq));
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_rtc(const SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
hwaddr base = sbsa_ref_memmap[SBSA_RTC].base;
|
|
|
|
int irq = sbsa_ref_irqmap[SBSA_RTC];
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_create_simple("pl031", base, qdev_get_gpio_in(sms->gic, irq));
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
2020-10-27 04:59:27 +03:00
|
|
|
static void create_wdt(const SBSAMachineState *sms)
|
|
|
|
{
|
|
|
|
hwaddr rbase = sbsa_ref_memmap[SBSA_GWDT_REFRESH].base;
|
|
|
|
hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base;
|
|
|
|
DeviceState *dev = qdev_new(TYPE_WDT_SBSA);
|
|
|
|
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
2021-08-06 05:31:19 +03:00
|
|
|
int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0];
|
2020-10-27 04:59:27 +03:00
|
|
|
|
|
|
|
sysbus_realize_and_unref(s, &error_fatal);
|
|
|
|
sysbus_mmio_map(s, 0, rbase);
|
|
|
|
sysbus_mmio_map(s, 1, cbase);
|
|
|
|
sysbus_connect_irq(s, 0, qdev_get_gpio_in(sms->gic, irq));
|
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
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
|
|
|
|
};
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_gpio(const SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
DeviceState *pl061_dev;
|
|
|
|
hwaddr base = sbsa_ref_memmap[SBSA_GPIO].base;
|
|
|
|
int irq = sbsa_ref_irqmap[SBSA_GPIO];
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
pl061_dev = sysbus_create_simple("pl061", base,
|
|
|
|
qdev_get_gpio_in(sms->gic, irq));
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_ahci(const SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
dev = qdev_new("sysbus-ahci");
|
2019-07-01 19:26:18 +03:00
|
|
|
qdev_prop_set_uint32(dev, "num-ports", NUM_SATA_PORTS);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(sms->gic, irq));
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
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]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_ehci(const SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
hwaddr base = sbsa_ref_memmap[SBSA_EHCI].base;
|
|
|
|
int irq = sbsa_ref_irqmap[SBSA_EHCI];
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_create_simple("platform-ehci-usb", base,
|
|
|
|
qdev_get_gpio_in(sms->gic, irq));
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_smmu(const SBSAMachineState *sms, PCIBus *bus)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
hwaddr base = sbsa_ref_memmap[SBSA_SMMU].base;
|
|
|
|
int irq = sbsa_ref_irqmap[SBSA_SMMU];
|
|
|
|
DeviceState *dev;
|
|
|
|
int i;
|
|
|
|
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
dev = qdev_new("arm-smmuv3");
|
2019-07-01 19:26:18 +03:00
|
|
|
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_set_link(OBJECT(dev), "primary-bus", OBJECT(bus),
|
2019-07-01 19:26:18 +03:00
|
|
|
&error_abort);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
|
|
|
for (i = 0; i < NUM_SMMU_IRQS; i++) {
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
|
2020-10-07 13:07:31 +03:00
|
|
|
qdev_get_gpio_in(sms->gic, irq + i));
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
static void create_pcie(SBSAMachineState *sms)
|
2019-07-01 19:26:18 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
qdev: Convert uses of qdev_create() with Coccinelle
This is the transformation explained in the commit before previous.
Takes care of just one pattern that needs conversion. More to come in
this series.
Coccinelle script:
@ depends on !(file in "hw/arm/highbank.c")@
expression bus, type_name, dev, expr;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr;
identifier DOWN;
@@
- dev = DOWN(qdev_create(bus, type_name));
+ dev = DOWN(qdev_new(type_name));
... when != dev = expr
- qdev_init_nofail(DEVICE(dev));
+ qdev_realize_and_unref(DEVICE(dev), bus, &error_fatal);
@@
expression bus, type_name, expr;
identifier dev;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- qdev_init_nofail(dev);
+ qdev_realize_and_unref(dev, bus, &error_fatal);
@@
expression bus, type_name, dev, expr, errp;
symbol true;
@@
- dev = qdev_create(bus, type_name);
+ dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
@@
expression bus, type_name, expr, errp;
identifier dev;
symbol true;
@@
- DeviceState *dev = qdev_create(bus, type_name);
+ DeviceState *dev = qdev_new(type_name);
... when != dev = expr
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize_and_unref(dev, bus, errp);
The first rule exempts hw/arm/highbank.c, because it matches along two
control flow paths there, with different @type_name. Covered by the
next commit's manual conversions.
Missing #include "qapi/error.h" added manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-10-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:31:58 +03:00
|
|
|
dev = qdev_new(TYPE_GPEX_HOST);
|
sysbus: Convert to sysbus_realize() etc. with Coccinelle
Convert from qdev_realize(), qdev_realize_and_unref() with null @bus
argument to sysbus_realize(), sysbus_realize_and_unref().
Coccinelle script:
@@
expression dev, errp;
@@
- qdev_realize(DEVICE(dev), NULL, errp);
+ sysbus_realize(SYS_BUS_DEVICE(dev), errp);
@@
expression sysbus_dev, dev, errp;
@@
+ sysbus_dev = SYS_BUS_DEVICE(dev);
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
- sysbus_dev = SYS_BUS_DEVICE(dev);
@@
expression sysbus_dev, dev, errp;
expression expr;
@@
sysbus_dev = SYS_BUS_DEVICE(dev);
... when != dev = expr;
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(sysbus_dev, errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(DEVICE(dev), NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
@@
expression dev, errp;
@@
- qdev_realize_and_unref(dev, NULL, errp);
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), errp);
Whitespace changes minimized manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-46-armbru@redhat.com>
[Conflicts in hw/misc/empty_slot.c and hw/sparc/leon3.c resolved]
2020-06-10 08:32:34 +03:00
|
|
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
/* 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++) {
|
2019-12-06 19:23:03 +03:00
|
|
|
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i,
|
2020-08-28 12:02:43 +03:00
|
|
|
qdev_get_gpio_in(sms->gic, irq + i));
|
2019-07-01 19:26:18 +03:00
|
|
|
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");
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_smmu(sms, pci->bus);
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-08-26 17:19:52 +03:00
|
|
|
static void create_secure_ec(MemoryRegion *mem)
|
|
|
|
{
|
|
|
|
hwaddr base = sbsa_ref_memmap[SBSA_SECURE_EC].base;
|
|
|
|
DeviceState *dev = qdev_new("sbsa-ec");
|
|
|
|
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
|
|
|
|
|
|
|
memory_region_add_subregion(mem, base,
|
|
|
|
sysbus_mmio_get_region(s, 0));
|
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
static void sbsa_ref_init(MachineState *machine)
|
|
|
|
{
|
2019-05-18 23:54:26 +03:00
|
|
|
unsigned int smp_cpus = machine->smp.cpus;
|
|
|
|
unsigned int max_cpus = machine->smp.max_cpus;
|
2019-07-01 19:26:18 +03:00
|
|
|
SBSAMachineState *sms = SBSA_MACHINE(machine);
|
|
|
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
|
|
|
MemoryRegion *sysmem = get_system_memory();
|
2019-07-08 16:11:31 +03:00
|
|
|
MemoryRegion *secure_sysmem = g_new(MemoryRegion, 1);
|
2019-07-01 19:26:18 +03:00
|
|
|
bool firmware_loaded;
|
2019-07-01 19:26:18 +03:00
|
|
|
const CPUArchIdList *possible_cpus;
|
|
|
|
int n, sbsa_max_cpus;
|
|
|
|
|
2020-11-20 17:17:05 +03:00
|
|
|
if (!cpu_type_valid(machine->cpu_type)) {
|
2021-10-08 09:36:04 +03:00
|
|
|
error_report("sbsa-ref: CPU type %s not supported", machine->cpu_type);
|
2019-07-01 19:26:18 +03:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kvm_enabled()) {
|
|
|
|
error_report("sbsa-ref: KVM is not supported for this machine");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
memory_region_init(secure_sysmem, OBJECT(machine), "secure-memory",
|
|
|
|
UINT64_MAX);
|
|
|
|
memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1);
|
|
|
|
|
2019-07-08 16:11:31 +03:00
|
|
|
firmware_loaded = sbsa_firmware_init(sms, sysmem, secure_sysmem);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_set_int(cpuobj, "mp-affinity",
|
|
|
|
possible_cpus->cpus[n].arch_id, NULL);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
|
|
|
cs = CPU(cpuobj);
|
|
|
|
cs->cpu_index = n;
|
|
|
|
|
|
|
|
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
|
|
|
|
&error_fatal);
|
|
|
|
|
2020-09-14 16:56:17 +03:00
|
|
|
if (object_property_find(cpuobj, "reset-cbar")) {
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_set_int(cpuobj, "reset-cbar",
|
2019-07-01 19:26:18 +03:00
|
|
|
sbsa_ref_memmap[SBSA_CPUPERIPHS].base,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
&error_abort);
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_set_link(cpuobj, "memory", OBJECT(sysmem),
|
2019-07-01 19:26:18 +03:00
|
|
|
&error_abort);
|
|
|
|
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 19:05:54 +03:00
|
|
|
object_property_set_link(cpuobj, "secure-memory",
|
|
|
|
OBJECT(secure_sysmem), &error_abort);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
qdev: Convert bus-less devices to qdev_realize() with Coccinelle
All remaining conversions to qdev_realize() are for bus-less devices.
Coccinelle script:
// only correct for bus-less @dev!
@@
expression errp;
expression dev;
@@
- qdev_init_nofail(dev);
+ qdev_realize(dev, NULL, &error_fatal);
@ depends on !(file in "hw/core/qdev.c") && !(file in "hw/core/bus.c")@
expression errp;
expression dev;
symbol true;
@@
- object_property_set_bool(OBJECT(dev), true, "realized", errp);
+ qdev_realize(DEVICE(dev), NULL, errp);
@ depends on !(file in "hw/core/qdev.c") && !(file in "hw/core/bus.c")@
expression errp;
expression dev;
symbol true;
@@
- object_property_set_bool(dev, true, "realized", errp);
+ qdev_realize(DEVICE(dev), NULL, errp);
Note that Coccinelle chokes on ARMSSE typedef vs. macro in
hw/arm/armsse.c. Worked around by temporarily renaming the macro for
the spatch run.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-57-armbru@redhat.com>
2020-06-10 08:32:45 +03:00
|
|
|
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
2019-07-01 19:26:18 +03:00
|
|
|
object_unref(cpuobj);
|
|
|
|
}
|
|
|
|
|
2020-02-19 19:09:04 +03:00
|
|
|
memory_region_add_subregion(sysmem, sbsa_ref_memmap[SBSA_MEM].base,
|
|
|
|
machine->ram);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
create_fdt(sms);
|
|
|
|
|
|
|
|
create_secure_ram(sms, secure_sysmem);
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_gic(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_uart(sms, SBSA_UART, sysmem, serial_hd(0));
|
|
|
|
create_uart(sms, SBSA_SECURE_UART, secure_sysmem, serial_hd(1));
|
2019-07-01 19:26:18 +03:00
|
|
|
/* Second secure UART for RAS and MM from EL0 */
|
2019-12-06 19:23:03 +03:00
|
|
|
create_uart(sms, SBSA_SECURE_UART_MM, secure_sysmem, serial_hd(2));
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_rtc(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2020-10-27 04:59:27 +03:00
|
|
|
create_wdt(sms);
|
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_gpio(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_ahci(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_ehci(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2019-12-06 19:23:03 +03:00
|
|
|
create_pcie(sms);
|
2019-07-01 19:26:18 +03:00
|
|
|
|
2020-08-26 17:19:52 +03:00
|
|
|
create_secure_ec(secure_sysmem);
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
sms->bootinfo.ram_size = machine->ram_size;
|
|
|
|
sms->bootinfo.board_id = -1;
|
|
|
|
sms->bootinfo.loader_start = sbsa_ref_memmap[SBSA_MEM].base;
|
2019-07-01 19:26:18 +03:00
|
|
|
sms->bootinfo.get_dtb = sbsa_ref_dtb;
|
|
|
|
sms->bootinfo.firmware_loaded = firmware_loaded;
|
2019-08-09 09:57:21 +03:00
|
|
|
arm_load_kernel(ARM_CPU(first_cpu), machine, &sms->bootinfo);
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static const CPUArchIdList *sbsa_ref_possible_cpu_arch_ids(MachineState *ms)
|
|
|
|
{
|
2019-05-18 23:54:26 +03:00
|
|
|
unsigned int max_cpus = ms->smp.max_cpus;
|
2019-07-01 19:26:18 +03:00
|
|
|
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)
|
|
|
|
{
|
2019-08-09 09:57:22 +03:00
|
|
|
return idx % ms->numa_state->num_nodes;
|
2019-07-01 19:26:18 +03:00
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
static void sbsa_ref_instance_init(Object *obj)
|
|
|
|
{
|
|
|
|
SBSAMachineState *sms = SBSA_MACHINE(obj);
|
|
|
|
|
|
|
|
sbsa_flash_create(sms);
|
|
|
|
}
|
|
|
|
|
2019-07-01 19:26:18 +03:00
|
|
|
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;
|
2020-02-19 19:09:04 +03:00
|
|
|
mc->default_ram_id = "sbsa-ref.ram";
|
2019-07-01 19:26:18 +03:00
|
|
|
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,
|
2019-07-01 19:26:18 +03:00
|
|
|
.instance_init = sbsa_ref_instance_init,
|
2019-07-01 19:26:18 +03:00
|
|
|
.class_init = sbsa_ref_class_init,
|
|
|
|
.instance_size = sizeof(SBSAMachineState),
|
|
|
|
};
|
|
|
|
|
|
|
|
static void sbsa_ref_machine_init(void)
|
|
|
|
{
|
|
|
|
type_register_static(&sbsa_ref_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_init(sbsa_ref_machine_init);
|