* [RFC PATCH v2 1/3] hw/arm/bcm2836: Add the ARMv8 BCM2838
2020-10-18 20:55 [RFC PATCH v2 0/3] hw/arm: Add the Raspberry Pi 4B Philippe Mathieu-Daudé
@ 2020-10-18 20:55 ` Philippe Mathieu-Daudé
2020-10-18 20:55 ` [RFC PATCH v2 2/3] hw/arm/raspi: Add the Raspberry Pi 4 model B Philippe Mathieu-Daudé
2020-10-18 20:55 ` [NOTFORMERGE PATCH v2 3/3] hw/arm/raspi: Remove unsupported raspi4 peripherals from device tree Philippe Mathieu-Daudé
2 siblings, 0 replies; 4+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-10-18 20:55 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Luc Michel, Philippe Mathieu-Daudé,
Andrew Baumann, Esteban Bosse, qemu-arm, Stewart Hildebrand,
Johnny Sun
The BCM2838 share the same peripheral base block from the BCM283x
family, but connects 4 Cortex-A72 cores via a GICv2.
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
include/hw/arm/bcm2836.h | 3 +
hw/arm/bcm2836.c | 179 +++++++++++++++++++++++++++++++++++++++
hw/arm/trace-events | 2 +
3 files changed, 184 insertions(+)
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
index 6f90cabfa3a..92561e96aa2 100644
--- a/include/hw/arm/bcm2836.h
+++ b/include/hw/arm/bcm2836.h
@@ -14,6 +14,7 @@
#include "hw/arm/bcm2835_peripherals.h"
#include "hw/intc/bcm2836_control.h"
+#include "hw/intc/arm_gic.h"
#include "target/arm/cpu.h"
#include "qom/object.h"
@@ -29,6 +30,7 @@ OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
#define TYPE_BCM2835 "bcm2835"
#define TYPE_BCM2836 "bcm2836"
#define TYPE_BCM2837 "bcm2837"
+#define TYPE_BCM2838 "bcm2838"
struct BCM283XState {
/*< private >*/
@@ -40,6 +42,7 @@ struct BCM283XState {
struct {
ARMCPU core;
} cpu[BCM283X_NCPUS];
+ GICState gic;
BCM2836ControlState control;
BCM2835PeripheralState peripherals;
};
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
index de7ade2878e..fe795217e26 100644
--- a/hw/arm/bcm2836.c
+++ b/hw/arm/bcm2836.c
@@ -16,6 +16,7 @@
#include "hw/arm/bcm2836.h"
#include "hw/arm/raspi_platform.h"
#include "hw/sysbus.h"
+#include "trace.h"
typedef struct BCM283XClass {
/*< private >*/
@@ -26,6 +27,7 @@ typedef struct BCM283XClass {
unsigned core_count;
hwaddr peri_base; /* Peripheral base address seen by the CPU */
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
+ hwaddr gic_base;
int clusterid;
} BCM283XClass;
@@ -52,6 +54,10 @@ static void bcm2836_init(Object *obj)
qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
}
+ if (bc->gic_base) {
+ object_initialize_child(obj, "gic", &s->gic, TYPE_ARM_GIC);
+ }
+
if (bc->ctrl_base) {
object_initialize_child(obj, "control", &s->control,
TYPE_BCM2836_CONTROL);
@@ -170,6 +176,161 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
}
}
+#ifdef TARGET_AARCH64
+
+#define GIC400_MAINTAINANCE_IRQ 9
+#define GIC400_TIMER_NS_EL2_IRQ 10
+#define GIC400_TIMER_VIRT_IRQ 11
+#define GIC400_LEGACY_FIQ 12
+#define GIC400_TIMER_S_EL1_IRQ 13
+#define GIC400_TIMER_NS_EL1_IRQ 14
+#define GIC400_LEGACY_IRQ 15
+
+/* Number of external interrupt lines to configure the GIC with */
+#define GIC_NUM_IRQS 128
+
+#define PPI(cpu, irq) (GIC_NUM_IRQS + (cpu) * GIC_INTERNAL + GIC_NR_SGIS + irq)
+
+#define GIC_BASE_OFS 0x0000
+#define GIC_DIST_OFS 0x1000
+#define GIC_CPU_OFS 0x2000
+#define GIC_VIFACE_THIS_OFS 0x4000
+#define GIC_VIFACE_OTHER_OFS(cpu) (0x5000 + (cpu) * 0x200)
+#define GIC_VCPU_OFS 0x6000
+
+#define VIRTUAL_PMU_IRQ 7
+
+static void bcm2838_gic_set_irq(void *opaque, int irq, int level)
+{
+ BCM283XState *s = (BCM283XState *)opaque;
+
+ trace_bcm2838_gic_set_irq(irq, level);
+ qemu_set_irq(qdev_get_gpio_in(DEVICE(&s->gic), irq), level);
+}
+
+static void bcm2838_realize(DeviceState *dev, Error **errp)
+{
+ BCM283XState *s = BCM283X(dev);
+ BCM283XClass *bc = BCM283X_GET_CLASS(dev);
+ int n;
+
+ if (!bcm283x_common_realize(dev, errp)) {
+ return;
+ }
+
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
+ bc->peri_base, 1);
+
+ /* bcm2836 interrupt controller (and mailboxes, etc.) */
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base);
+
+ /* Create cores */
+ for (n = 0; n < bc->core_count; n++) {
+ /* TODO: this should be converted to a property of ARM_CPU */
+ s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
+
+ /* set periphbase/CBAR value for CPU-local registers */
+ if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar",
+ bc->peri_base, errp)) {
+ return;
+ }
+
+ /* start powered off if not enabled */
+ if (!object_property_set_bool(OBJECT(&s->cpu[n].core),
+ "start-powered-off",
+ n >= s->enabled_cpus,
+ errp)) {
+ return;
+ }
+
+ if (!qdev_realize(DEVICE(&s->cpu[n].core), NULL, errp)) {
+ return;
+ }
+ }
+
+ if (!object_property_set_uint(OBJECT(&s->gic), "revision", 2, errp)) {
+ return;
+ }
+
+ if (!object_property_set_uint(OBJECT(&s->gic), "num-cpu", BCM283X_NCPUS,
+ errp)) {
+ return;
+ }
+
+ if (!object_property_set_uint(OBJECT(&s->gic),
+ "num-irq", GIC_NUM_IRQS + GIC_INTERNAL,
+ errp)) {
+ return;
+ }
+
+ if (!object_property_set_bool(OBJECT(&s->gic),
+ "has-virtualization-extensions",
+ true, errp)) {
+ return;
+ }
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->gic), errp)) {
+ return;
+ }
+
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 0,
+ bc->ctrl_base + bc->gic_base + GIC_DIST_OFS);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 1,
+ bc->ctrl_base + bc->gic_base + GIC_CPU_OFS);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 2,
+ bc->ctrl_base + bc->gic_base + GIC_VIFACE_THIS_OFS);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 3,
+ bc->ctrl_base + bc->gic_base + GIC_VCPU_OFS);
+
+ for (n = 0; n < BCM283X_NCPUS; n++) {
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gic), 4 + n,
+ bc->ctrl_base + bc->gic_base + GIC_VIFACE_OTHER_OFS(n));
+ }
+
+ for (n = 0; n < BCM283X_NCPUS; n++) {
+ DeviceState *cpudev = DEVICE(&s->cpu[n]);
+ DeviceState *gicdev = DEVICE(&s->gic);
+
+ /* Connect the GICv2 outputs to the CPU */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), n,
+ qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), n + BCM283X_NCPUS,
+ qdev_get_gpio_in(cpudev, ARM_CPU_FIQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), n + 2 * BCM283X_NCPUS,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), n + 3 * BCM283X_NCPUS,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), n + 4 * BCM283X_NCPUS,
+ qdev_get_gpio_in(gicdev,
+ PPI(n, GIC400_MAINTAINANCE_IRQ)));
+
+ /* Connect timers from the CPU to the interrupt controller */
+ qdev_connect_gpio_out(cpudev, GTIMER_PHYS,
+ qdev_get_gpio_in(gicdev, PPI(n, GIC400_TIMER_NS_EL1_IRQ)));
+ qdev_connect_gpio_out(cpudev, GTIMER_VIRT,
+ qdev_get_gpio_in(gicdev, PPI(n, GIC400_TIMER_VIRT_IRQ)));
+ qdev_connect_gpio_out(cpudev, GTIMER_HYP,
+ qdev_get_gpio_in(gicdev, PPI(n, GIC400_TIMER_NS_EL2_IRQ)));
+ qdev_connect_gpio_out(cpudev, GTIMER_SEC,
+ qdev_get_gpio_in(gicdev, PPI(n, GIC400_TIMER_S_EL1_IRQ)));
+ /* PMU interrupt */
+ qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0,
+ qdev_get_gpio_in(gicdev, PPI(n, VIRTUAL_PMU_IRQ)));
+ }
+
+ /* Pass through inbound GPIO lines to the GIC */
+ qdev_init_gpio_in(dev, bcm2838_gic_set_irq, GIC_NUM_IRQS);
+
+ /* Pass through outbound IRQ lines from the GIC */
+ qdev_pass_gpios(DEVICE(&s->gic), DEVICE(&s->peripherals), NULL);
+}
+#endif /* TARGET_AARCH64 */
+
static void bcm283x_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -215,6 +376,20 @@ static void bcm2837_class_init(ObjectClass *oc, void *data)
bc->clusterid = 0x0;
dc->realize = bcm2836_realize;
};
+
+static void bcm2838_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ BCM283XClass *bc = BCM283X_CLASS(oc);
+
+ bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a72");
+ bc->core_count = BCM283X_NCPUS;
+ bc->peri_base = 0xfe000000;
+ bc->ctrl_base = 0xff800000;
+ bc->gic_base = 0x40000;
+ bc->clusterid = 0x0;
+ dc->realize = bcm2838_realize;
+};
#endif
static const TypeInfo bcm283x_types[] = {
@@ -231,6 +406,10 @@ static const TypeInfo bcm283x_types[] = {
.name = TYPE_BCM2837,
.parent = TYPE_BCM283X,
.class_init = bcm2837_class_init,
+ }, {
+ .name = TYPE_BCM2838,
+ .parent = TYPE_BCM283X,
+ .class_init = bcm2838_class_init,
#endif
}, {
.name = TYPE_BCM283X,
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index c8a4d80f6bd..37487424b28 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -53,3 +53,5 @@ smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
+# bcm2836.c
+bcm2838_gic_set_irq(int irq, int level) "gic irq:%d lvl:%d"
--
2.26.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH v2 2/3] hw/arm/raspi: Add the Raspberry Pi 4 model B
2020-10-18 20:55 [RFC PATCH v2 0/3] hw/arm: Add the Raspberry Pi 4B Philippe Mathieu-Daudé
2020-10-18 20:55 ` [RFC PATCH v2 1/3] hw/arm/bcm2836: Add the ARMv8 BCM2838 Philippe Mathieu-Daudé
@ 2020-10-18 20:55 ` Philippe Mathieu-Daudé
2020-10-18 20:55 ` [NOTFORMERGE PATCH v2 3/3] hw/arm/raspi: Remove unsupported raspi4 peripherals from device tree Philippe Mathieu-Daudé
2 siblings, 0 replies; 4+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-10-18 20:55 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Luc Michel, Philippe Mathieu-Daudé,
Andrew Baumann, Esteban Bosse, qemu-arm, Stewart Hildebrand,
Johnny Sun
Add 2 variants of the raspi4:
- raspi4b1g: Raspberry Pi 4B (revision 1.1, with 1 GiB of RAM)
- raspi4b2g Raspberry Pi 4B (revision 1.2, with 2 GiB)
Example booting the 2GiB machine using content from [*]:
$ qemu-system-aarch64 -M raspi4b2g -serial stdio \
-kernel raspberrypi/firmware/boot/kernel8.img \
-dtb raspberrypi/firmware/boot/bcm2711-rpi-4-b.dtb \
-append 'printk.time=0 earlycon=pl011,0xfe201000 console=ttyAMA0'
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
[ 0.000000] Linux version 5.4.51-v8+ (dom@buildbot) (gcc version 5.4.0 20160609 (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.9)) #1333 SMP PREEMPT Mon Aug 10 16:58:35 BST 2020
[ 0.000000] Machine model: Raspberry Pi 4 Model B
[ 0.000000] earlycon: pl11 at MMIO 0x00000000fe201000 (options '')
[ 0.000000] printk: bootconsole [pl11] enabled
[ 0.000000] efi: Getting EFI parameters from FDT:
[ 0.000000] efi: UEFI not found.
[ 0.000000] Reserved memory: created CMA memory pool at 0x000000002c000000, size 64 MiB
[ 0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[ 0.000000] Detected PIPT I-cache on CPU0
[ 0.000000] CPU features: detected: EL2 vector hardening
[ 0.000000] ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware
[ 0.000000] software IO TLB: mapped [mem 0x3bfff000-0x3ffff000] (64MB)
[ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[ 0.000000] GIC: Using split EOI/Deactivate mode
[ 0.633289] smp: Bringing up secondary CPUs ...
[ 0.694226] Detected PIPT I-cache on CPU1
[ 0.699002] CPU1: Booted secondary processor 0x0000000001 [0x410fd083]
[ 0.782443] Detected PIPT I-cache on CPU2
[ 0.783511] CPU2: Booted secondary processor 0x0000000002 [0x410fd083]
[ 0.848854] Detected PIPT I-cache on CPU3
[ 0.850003] CPU3: Booted secondary processor 0x0000000003 [0x410fd083]
[ 0.857099] smp: Brought up 1 node, 4 CPUs
[ 0.863500] SMP: Total of 4 processors activated.
[ 0.865446] CPU features: detected: 32-bit EL0 Support
[ 0.866667] CPU features: detected: CRC32 instructions
[ 2.235648] CPU: All CPU(s) started at EL2
...
[*] http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware/raspberrypi-kernel_1.20200512-2_armhf.deb
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
hw/arm/raspi.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 4ea200572ea..6a793766840 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -73,6 +73,7 @@ typedef enum RaspiProcessorId {
PROCESSOR_ID_BCM2835 = 0,
PROCESSOR_ID_BCM2836 = 1,
PROCESSOR_ID_BCM2837 = 2,
+ PROCESSOR_ID_BCM2838 = 3,
} RaspiProcessorId;
static const struct {
@@ -82,6 +83,7 @@ static const struct {
[PROCESSOR_ID_BCM2835] = {TYPE_BCM2835, 1},
[PROCESSOR_ID_BCM2836] = {TYPE_BCM2836, BCM283X_NCPUS},
[PROCESSOR_ID_BCM2837] = {TYPE_BCM2837, BCM283X_NCPUS},
+ [PROCESSOR_ID_BCM2838] = {TYPE_BCM2838, BCM283X_NCPUS},
};
static uint64_t board_ram_size(uint32_t board_rev)
@@ -366,6 +368,24 @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
rmc->board_rev = 0xa02082;
raspi_machine_class_common_init(mc, rmc->board_rev);
};
+
+static void raspi4b1g_machine_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
+
+ rmc->board_rev = 0xa03111;
+ raspi_machine_class_common_init(mc, rmc->board_rev);
+};
+
+static void raspi4b2g_machine_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
+
+ rmc->board_rev = 0xb03112;
+ raspi_machine_class_common_init(mc, rmc->board_rev);
+};
#endif /* TARGET_AARCH64 */
static const TypeInfo raspi_machine_types[] = {
@@ -390,6 +410,14 @@ static const TypeInfo raspi_machine_types[] = {
.name = MACHINE_TYPE_NAME("raspi3b"),
.parent = TYPE_RASPI_MACHINE,
.class_init = raspi3b_machine_class_init,
+ }, {
+ .name = MACHINE_TYPE_NAME("raspi4b1g"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi4b1g_machine_class_init,
+ }, {
+ .name = MACHINE_TYPE_NAME("raspi4b2g"),
+ .parent = TYPE_RASPI_MACHINE,
+ .class_init = raspi4b2g_machine_class_init,
#endif
}, {
.name = TYPE_RASPI_MACHINE,
--
2.26.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [NOTFORMERGE PATCH v2 3/3] hw/arm/raspi: Remove unsupported raspi4 peripherals from device tree
2020-10-18 20:55 [RFC PATCH v2 0/3] hw/arm: Add the Raspberry Pi 4B Philippe Mathieu-Daudé
2020-10-18 20:55 ` [RFC PATCH v2 1/3] hw/arm/bcm2836: Add the ARMv8 BCM2838 Philippe Mathieu-Daudé
2020-10-18 20:55 ` [RFC PATCH v2 2/3] hw/arm/raspi: Add the Raspberry Pi 4 model B Philippe Mathieu-Daudé
@ 2020-10-18 20:55 ` Philippe Mathieu-Daudé
2 siblings, 0 replies; 4+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-10-18 20:55 UTC (permalink / raw)
To: qemu-devel
Cc: Peter Maydell, Luc Michel, Philippe Mathieu-Daudé,
Andrew Baumann, Esteban Bosse, qemu-arm, Stewart Hildebrand,
Johnny Sun
Kludge when using Linux kernels to reach userland.
No device in DT -> no hardware initialization.
Linux 5.9 uses the RPI_FIRMWARE_GET_CLOCKS so we now need to
implement that feature too. Look like a cat and mouse game...
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
---
hw/arm/raspi.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
index 6a793766840..93eb6591ee8 100644
--- a/hw/arm/raspi.c
+++ b/hw/arm/raspi.c
@@ -25,6 +25,7 @@
#include "hw/arm/boot.h"
#include "sysemu/sysemu.h"
#include "qom/object.h"
+#include <libfdt.h>
#define SMPBOOT_ADDR 0x300 /* this should leave enough space for ATAGS */
#define MVBAR_ADDR 0x400 /* secure vectors */
@@ -200,6 +201,29 @@ static void reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
cpu_set_pc(cs, info->smp_loader_start);
}
+static void raspi4_modify_dtb(const struct arm_boot_info *info, void *fdt)
+{
+ int offset;
+
+ offset = fdt_node_offset_by_compatible(fdt, -1, "brcm,genet-v5");
+ if (offset >= 0) {
+ /* FIXME we shouldn't nop the parent */
+ offset = fdt_parent_offset(fdt, offset);
+ if (offset >= 0) {
+ if (!fdt_nop_node(fdt, offset)) {
+ warn_report("dtc: bcm2838-genet removed!");
+ }
+ }
+ }
+
+ offset = fdt_node_offset_by_compatible(fdt, -1, "brcm,avs-tmon-bcm2838");
+ if (offset >= 0) {
+ if (!fdt_nop_node(fdt, offset)) {
+ warn_report("dtc: bcm2838-tmon removed!");
+ }
+ }
+}
+
static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
size_t ram_size)
{
@@ -234,6 +258,9 @@ static void setup_boot(MachineState *machine, RaspiProcessorId processor_id,
}
s->binfo.secondary_cpu_reset_hook = reset_secondary;
}
+ if (processor_id >= PROCESSOR_ID_BCM2838) {
+ s->binfo.modify_dtb = raspi4_modify_dtb;
+ }
/* If the user specified a "firmware" image (e.g. UEFI), we bypass
* the normal Linux boot process
--
2.26.2
^ permalink raw reply related [flat|nested] 4+ messages in thread