
Hi Patrick,
On Wed, 2 Oct 2024 at 03:52, Patrick Rudolph patrick.rudolph@9elements.com wrote:
Add support for Arm sbsa [1] v0.3+ that is supported by QEMU [2].
Unlike other Arm based platforms the machine only provides a minimal FDT that contains number of CPUs, ammount of memory and machine-version. The boot firmware has to provide ACPI tables to the OS. Due to this design a full DTB is added here as well that allows U-Boot's driver to properly function. The DTB is appended at the end of the U-Boot image and will be merged with the QEMU provided DTB.
In addition provide documentation how to use, enable binman to fabricate both ROMs that are required to boot and add ACPI tables to make it full compatible to the EDK2 reference implementation.
The board was tested using Fedora 40 Aarch64 Workstation. It's able to boot from USB and AHCI or network.
Tested and found working:
- serial
- PCI
- xHCI
- Bochs display
- AHCI
- network using e1000e
- CPU init
- Booting Fedora 40
1: Server Base System Architecture (SBSA) 2: https://www.qemu.org/docs/master/system/arm/sbsa.html
Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com Cc: Peter Robinson pbrobinson@gmail.com Cc: Simon Glass sjg@chromium.org Cc: Tom Rini trini@konsulko.com
Changelog v3:
- Add GIC and GIC-ITS to devicetree
- Select GICv3 driver
- Drop acpi_fill_madt and use driver model instead
Changelog v4:
- Drop CPU platform code
- Enhance the DT to allow MADT generation from DT
Changelog v5:
- Add full DT and place it at the end of U-Boot
- Merge DT with QEMU's DT
- Drop DT generation code
- Fix flash region length
- Drop enable_caches()
- Support platforms that do not pass FDT in x0
Changelog v6:
- Update header order
- Drop pad-byte from DT
- select BINMAN_FDT
- select E1000_NO_NVM
- drop config.h include
- drop a few CFG_ defines that were used for SPL
arch/arm/Kconfig | 3 +- arch/arm/dts/qemu-sbsa.dts | 136 ++++++ arch/arm/include/asm/arch-qemu-sbsa/boot0.h | 34 ++ arch/arm/mach-qemu/Kconfig | 36 +- board/emulation/qemu-arm/MAINTAINERS | 2 + board/emulation/qemu-sbsa/Kconfig | 57 +++ board/emulation/qemu-sbsa/Makefile | 8 + board/emulation/qemu-sbsa/acpi.c | 192 ++++++++ board/emulation/qemu-sbsa/dsdt.asl | 483 ++++++++++++++++++++ board/emulation/qemu-sbsa/lowlevel_init.S | 22 + board/emulation/qemu-sbsa/qemu-sbsa.c | 311 +++++++++++++ board/emulation/qemu-sbsa/qemu-sbsa.env | 14 + board/emulation/qemu-sbsa/qemu-sbsa.h | 38 ++ board/emulation/qemu-sbsa/smc.c | 71 +++ configs/qemu-arm-sbsa_defconfig | 10 + doc/board/emulation/index.rst | 1 + doc/board/emulation/qemu-sbsa.rst | 98 ++++ doc/develop/driver-model/virtio.rst | 1 + include/configs/qemu-sbsa.h | 95 ++++ 19 files changed, 1605 insertions(+), 7 deletions(-) create mode 100644 arch/arm/dts/qemu-sbsa.dts create mode 100644 arch/arm/include/asm/arch-qemu-sbsa/boot0.h create mode 100644 board/emulation/qemu-sbsa/Kconfig create mode 100644 board/emulation/qemu-sbsa/Makefile create mode 100644 board/emulation/qemu-sbsa/acpi.c create mode 100644 board/emulation/qemu-sbsa/dsdt.asl create mode 100644 board/emulation/qemu-sbsa/lowlevel_init.S create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.c create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.env create mode 100644 board/emulation/qemu-sbsa/qemu-sbsa.h create mode 100644 board/emulation/qemu-sbsa/smc.c create mode 100644 configs/qemu-arm-sbsa_defconfig create mode 100644 doc/board/emulation/qemu-sbsa.rst create mode 100644 include/configs/qemu-sbsa.h
With the tweaks below:
Reviewed-by: Simon Glass sjg@chromium.org
[..]
diff --git a/arch/arm/dts/qemu-sbsa.dts b/arch/arm/dts/qemu-sbsa.dts new file mode 100644 index 0000000000..f743ea3863 --- /dev/null +++ b/arch/arm/dts/qemu-sbsa.dts @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/*
- Devicetree with onboard devices for qemu_sbsa-ref for internal use only!
- DO NOT PASS TO THE OS!
- As QEMU provides only a minimal devicetree this one is merged with
- it and then fixed at runtime.
- Copyright 2024 9elements GmbH
- */
+#include "configs/qemu-sbsa.h"
+/dts-v1/;
+#define MAKE_PROP(x) (x>>32) (x&0xffffffff)
+/ {
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&intc>;
compatible = "linux,sbsa-ref";
binman: binman {
multiple-images;
};
cpus {
/* Filled by fdtdec_board_setup() */
};
memory {
/* Filled by fdtdec_board_setup() */
};
soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
uart0 {
compatible = "arm,pl011";
status = "okay";
reg = <MAKE_PROP(SBSA_UART_BASE_ADDR)
Can you use
reg = /bits 64/ <0x60000000>
instead?
Same for those below.
MAKE_PROP(SBSA_UART_LENGTH)>;
};
ahci {
compatible = "generic-ahci";
status = "okay";
reg = <MAKE_PROP(SBSA_AHCI_BASE_ADDR)
MAKE_PROP(SBSA_AHCI_LENGTH)>;
};
xhci {
compatible = "generic-xhci";
status = "okay";
reg = <MAKE_PROP(SBSA_XHCI_BASE_ADDR)
MAKE_PROP(SBSA_XHCI_LENGTH)>;
};
pci {
#address-cells = <3>;
#size-cells = <2>;
compatible = "pci-host-ecam-generic";
device_type = "pci";
status = "okay";
reg = <MAKE_PROP(SBSA_PCIE_ECAM_BASE_ADDR)
MAKE_PROP(SBSA_PCIE_ECAM_LENGTH)>;
bus-range = <0 0xff>;
ranges = <0x01000000 0 0
MAKE_PROP(SBSA_PIO_BASE_ADDR)
MAKE_PROP(SBSA_PIO_LENGTH)>,
<0x02000000 MAKE_PROP(SBSA_PCIE_MMIO_BASE_ADDR)
MAKE_PROP(SBSA_PCIE_MMIO_BASE_ADDR)
MAKE_PROP(SBSA_PCIE_MMIO_LENGTH)>,
<0x43000000 MAKE_PROP(SBSA_PCIE_MMIO_HIGH_BASE_ADDR)
MAKE_PROP(SBSA_PCIE_MMIO_HIGH_BASE_ADDR)
MAKE_PROP(SBSA_PCIE_MMIO_HIGH_LENGTH)>;
};
};
intc: interrupt-controller {
compatible = "arm,gic-v3";
#interrupt-cells = <1>;
status = "okay";
interrupt-controller;
interrupts = <25>;
reg = <MAKE_PROP(SBSA_GIC_DIST_BASE_ADDR)
MAKE_PROP(SBSA_GIC_DIST_LENGTH)>,
<MAKE_PROP(SBSA_GIC_REDIST_BASE_ADDR)
MAKE_PROP(SBSA_GIC_REDIST_LENGTH)>,
<0 0 0 0>,
<MAKE_PROP(SBSA_GIC_HBASE_ADDR)
MAKE_PROP(SBSA_GIC_HBASE_LENGTH)>,
<MAKE_PROP(SBSA_GIC_VBASE_ADDR)
MAKE_PROP(SBSA_GIC_VBASE_LENGTH)>;
};
its {
compatible = "arm,gic-v3-its";
status = "disabled";
};
+};
+&binman {
secure-world {
filename = "secure-world.rom";
size = <SBSA_SECURE_FLASH_LENGTH>;
bl1 {
offset = <0x0>;
description = "ARM Trusted Firmware BL1";
filename = "bl1.bin";
We should create a new entry type for this, like atf-bl31 - but that can come later.
type = "blob-ext";
};
fip {
offset = <0x12000>;
description = "ARM Trusted Firmware FIP";
filename = "fip.bin";
Normally binman would create the fip, but for now this is fine.
type = "blob-ext";
};
};
unsecure-world {
filename = "unsecure-world.rom";
size = <SBSA_FLASH_LENGTH>;
u-boot {
};
u-boot-dtb {
compress = "lz4";
};
};
+};
[..]
diff --git a/doc/develop/driver-model/virtio.rst b/doc/develop/driver-model/virtio.rst index 8ac9c94caf..31b94d0467 100644 --- a/doc/develop/driver-model/virtio.rst +++ b/doc/develop/driver-model/virtio.rst @@ -34,6 +34,7 @@ The following QEMU targets are supported.
- qemu_arm_defconfig
- qemu_arm64_defconfig
- qemu-arm-sbsa_defconfig
- qemu-riscv32_defconfig
- qemu-riscv64_defconfig
- qemu-x86_defconfig
diff --git a/include/configs/qemu-sbsa.h b/include/configs/qemu-sbsa.h new file mode 100644 index 0000000000..efc96981d3 --- /dev/null +++ b/include/configs/qemu-sbsa.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2024 9elements GmbH
- */
+#ifndef __CONFIG_H +#define __CONFIG_H
+/* Physical memory map */
+/* SECURE_FLASH */ +#define SBSA_SECURE_FLASH_BASE_ADDR 0x00000000 +#define SBSA_SECURE_FLASH_LENGTH 0x10000000
+/* FLASH */ +#define SBSA_FLASH_BASE_ADDR 0x10000000 +#define SBSA_FLASH_LENGTH 0x10000000
+/* PERIPH */ +#define SBSA_PERIPH_BASE_ADDR 0x40000000
+/* GIC_DIST */ +#define SBSA_GIC_DIST_BASE_ADDR 0x40060000 +#define SBSA_GIC_DIST_LENGTH 0x00020000
+#define SBSA_GIC_VBASE_ADDR 0x2c020000 +#define SBSA_GIC_VBASE_LENGTH 0x00010000
+#define SBSA_GIC_HBASE_ADDR 0x2c010000 +#define SBSA_GIC_HBASE_LENGTH 0x00010000
+/* GIC_REDIST */ +#define SBSA_GIC_REDIST_BASE_ADDR 0x40080000 +#define SBSA_GIC_REDIST_LENGTH 0x04000000
+/* GIC_ITS */ +#define SBSA_GIC_ITS_BASE_ADDR 0x44081000
+/* UART */ +#define SBSA_UART_BASE_ADDR 0x60000000 +#define SBSA_UART_LENGTH 0x00001000
+/* RTC */ +#define SBSA_RTC_BASE_ADDR 0x60010000
+/* GPIO */ +#define SBSA_GPIO_BASE_ADDR 0x60020000
+/* SMMU */ +#define SBSA_SMMU_BASE_ADDR 0x60050000
+/* SATA */ +#define SBSA_AHCI_BASE_ADDR 0x60100000 +#define SBSA_AHCI_LENGTH 0x00010000
+/* xHCI */ +#define SBSA_XHCI_BASE_ADDR 0x60110000 +#define SBSA_XHCI_LENGTH 0x00010000
+/* PIO */ +#define SBSA_PIO_BASE_ADDR 0x7fff0000 +#define SBSA_PIO_LENGTH 0x00010000
+/* PCIE_MMIO */ +#define SBSA_PCIE_MMIO_BASE_ADDR 0x80000000 +#define SBSA_PCIE_MMIO_LENGTH 0x70000000 +#define SBSA_PCIE_MMIO_END 0xefffffff
+/* PCIE_ECAM */ +#define SBSA_PCIE_ECAM_BASE_ADDR 0xf0000000 +#define SBSA_PCIE_ECAM_LENGTH 0x10000000 +#define SBSA_PCIE_ECAM_END 0xffffffff
+/* PCIE_MMIO_HIGH */ +#ifdef __ACPI__ +#define SBSA_PCIE_MMIO_HIGH_BASE_ADDR 0x100000000 +#define SBSA_PCIE_MMIO_HIGH_LENGTH 0xFF00000000 +#define SBSA_PCIE_MMIO_HIGH_END 0xFFFFFFFFFF +#else +#define SBSA_PCIE_MMIO_HIGH_BASE_ADDR 0x100000000ULL +#define SBSA_PCIE_MMIO_HIGH_LENGTH 0xFF00000000ULL +#define SBSA_PCIE_MMIO_HIGH_END 0xFFFFFFFFFFULL +#endif
+/* MEM */ +#ifdef __ACPI__ +#define SBSA_MEM_BASE_ADDR 0x10000000000 +#else +#define SBSA_MEM_BASE_ADDR 0x10000000000ULL +#endif
+#define CFG_SYS_INIT_RAM_ADDR SBSA_MEM_BASE_ADDR +#define CFG_SYS_INIT_RAM_SIZE 0x1000000
Can you move these to the file that needs them? We are trying to keep this file empty.
+#endif /* __CONFIG_H */
2.46.2
Regards, Simon