From f7e97ae3eaeef7c3a1d08f7dfca8c87a902d465b Mon Sep 17 00:00:00 2001 From: Axel Heider Date: Tue, 29 Mar 2022 16:23:58 +0200 Subject: [PATCH] riscv: support qemu-riscv-virt platform Signed-off-by: Axel Heider --- CHANGES | 1 + include/drivers/irq/riscv_plic0.h | 9 +- .../qemu-riscv-virt/sel4/plat/api/constants.h | 11 ++ src/plat/qemu-riscv-virt/config.cmake | 180 ++++++++++++++++++ .../overlay-qemu-riscv-virt.dts | 20 ++ 5 files changed, 218 insertions(+), 3 deletions(-) create mode 100644 libsel4/sel4_plat_include/qemu-riscv-virt/sel4/plat/api/constants.h create mode 100644 src/plat/qemu-riscv-virt/config.cmake create mode 100644 src/plat/qemu-riscv-virt/overlay-qemu-riscv-virt.dts diff --git a/CHANGES b/CHANGES index 800a22b1bd..77ccd0ce1d 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Upcoming release: BREAKING * Added support for the ODroid C4 * Added support for the Avnet MaaXBoard * Added support for arm_hyp on qemu-arm-virt platfrom with cortex-a15 CPU + * Added support for qemu-riscv-virt * Rename libsel4 config option ENABLE_SMP_SUPPORT to CONFIG_ENABLE_SMP_SUPPORT to be namespace compliant. * Rename libsel4 config option AARCH64_VSPACE_S2_START_L1 to CONFIG_AARCH64_VSPACE_S2_START_L1 to be namespace compliant. diff --git a/include/drivers/irq/riscv_plic0.h b/include/drivers/irq/riscv_plic0.h index 4eec75c583..9f7c59a969 100644 --- a/include/drivers/irq/riscv_plic0.h +++ b/include/drivers/irq/riscv_plic0.h @@ -4,15 +4,18 @@ * * SPDX-License-Identifier: GPL-2.0-only * - * SiFive U54/U74 PLIC handling (HiFive Unleashed/Unmatched, Polarfire) + * SiFive U54/U74 PLIC handling (HiFive Unleashed/Unmatched, Polarfire, + * QEMU RISC-V virt) */ #pragma once /* This is a check that prevents using this driver blindly. Extend the list if * this driver is confirmed to be working on other platforms. */ -#if !defined(CONFIG_PLAT_HIFIVE) && !defined(CONFIG_PLAT_POLARFIRE) -#error "This code supports the SiFive U54/U74 PLIC only." +#if !defined(CONFIG_PLAT_HIFIVE) && \ + !defined(CONFIG_PLAT_POLARFIRE) && \ + !defined(CONFIG_PLAT_QEMU_RISCV_VIRT) +#error "Check if this platform suppots a PLIC." #endif /* tell the kernel we have the set trigger feature */ diff --git a/libsel4/sel4_plat_include/qemu-riscv-virt/sel4/plat/api/constants.h b/libsel4/sel4_plat_include/qemu-riscv-virt/sel4/plat/api/constants.h new file mode 100644 index 0000000000..dcd96cda63 --- /dev/null +++ b/libsel4/sel4_plat_include/qemu-riscv-virt/sel4/plat/api/constants.h @@ -0,0 +1,11 @@ +/* + * Copyright 2022, HENSOLDT Cyber + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +/* nothing here */ diff --git a/src/plat/qemu-riscv-virt/config.cmake b/src/plat/qemu-riscv-virt/config.cmake new file mode 100644 index 0000000000..3b5c1c7107 --- /dev/null +++ b/src/plat/qemu-riscv-virt/config.cmake @@ -0,0 +1,180 @@ +# +# Copyright 2022, HENSOLDT Cyber +# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) +# +# SPDX-License-Identifier: GPL-2.0-only +# + +cmake_minimum_required(VERSION 3.7.2) + +declare_platform(qemu-riscv-virt KernelPlatformQEMURiscVVirt PLAT_QEMU_RISCV_VIRT KernelArchRiscV) + +if(KernelPlatformQEMURiscVVirt) + + # ToDo: use setup_seL4_arch("riscv64;riscv32") + if("${KernelSel4Arch}" STREQUAL riscv64) + declare_seL4_arch(riscv64) + elseif("${KernelSel4Arch}" STREQUAL riscv32) + declare_seL4_arch(riscv32) # This is still untested + else() + fallback_declare_seL4_arch_default(riscv64) + endif() + + config_set(KernelOpenSBIPlatform OPENSBI_PLATFORM "generic") + config_set(KernelPlatformFirstHartID FIRST_HART_ID 0) + + # If neither QEMU_DTS nor QEMU_DTB is set explicitly, the device tree is + # extracted from QEMU. This keeps it nicely up to date with the the actual + # QEMU versions that is used, and it's quite convenient for development. + if(NOT DEFINED QEMU_DTS) + + set(QEMU_DTS "${CMAKE_BINARY_DIR}/qemu-riscv-virt.dts") + + if(DEFINED QEMU_DTB) + + set(QEMU_DTS_INFO "converted from ${QEMU_DTB}") + + else() + + message(STATUS "Extracting device tree from QEMU") + set(QEMU_DTB "${CMAKE_BINARY_DIR}/qemu-riscv-virt.dtb") + + # Use the system's QEMU if no custom QEMU is provided. Have a sanity + # check about the version to ensure it can be used. + if(NOT QEMU_BINARY) + set(QEMU_RISCV_VIRT_BINARY "qemu-system-${KernelSel4Arch}") + find_program(QEMU_RISCV_VIRT ${QEMU_RISCV_VIRT_BINARY}) + # RISC-V virtual platform works since QEMU v5.1.0 + set(QEMU_RISCV_VIRT_MIN_VERSION "5.1.0") + execute_process( + COMMAND ${QEMU_RISCV_VIRT} -version + RESULT_VARIABLE error + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE QEMU_STDOUT_MESSAGE + ) + if(error) + message(FATAL_ERROR "Failed to determine QEMU version (${QEMU_RISCV_VIRT})") + endif() + string( + REGEX + MATCH + "[0-9](\\.[0-9])+" + QEMU_VERSION + "${QEMU_STDOUT_MESSAGE}" + ) + if("${QEMU_VERSION}" VERSION_LESS "${QEMU_RISCV_VIRT_MIN_VERSION}") + message( + FATAL_ERROR + "Error: need at least QEMU version ${QEMU_RISCV_VIRT_MIN_VERSION}, found '${QEMU_VERSION}'" + ) + endif() + message(STATUS "using QEMU version ${QEMU_VERSION} from ${QEMU_RISCV_VIRT}") + endif() + + set(QEMU_MACHINE "virt") + #list(APPEND QEMU_MACHINE "aclint=off") # on/off + #list(APPEND QEMU_MACHINE "aia=none") # none/aplic/aplic-imsic + #list(APPEND QEMU_MACHINE "aia-guests=0") # VS-level AIA IMSIC pages per hart + list(APPEND QEMU_MACHINE "dumpdtb=${QEMU_DTB}") + # CMake Lists are just strings with ";" as item separator, but we + # needs commas. CMake 3.12 has a function to serialize a list with + # a custom separator: list(JOIN QEMU_MACHINE "," QEMU_MACHINE) + string( + REPLACE + ";" + "," + QEMU_MACHINE + "${QEMU_MACHINE}" + ) + + if(NOT DEFINED QEMU_CPU) + set(QEMU_CPU "rv${KernelWordSize}") + endif() + + if(NOT DEFINED QEMU_MEMORY) + # Having 2 GiB of memory as default seems a good trade-off. It's + # sufficient for test/demo systems, but still something the host + # can provide without running short on resources. + set(QEMU_MEMORY "2048M") + endif() + + if(KernelMaxNumNodes) + set(QEMU_SMP_OPTION "${KernelMaxNumNodes}") + else() + set(QEMU_SMP_OPTION "1") + endif() + + # Run QEMU to get the device tree binary. Remember the parameter, so + # they can be added to the DTS as reference. + set( + QEMU_CMD + "${QEMU_RISCV_VIRT}" + "-machine" + "${QEMU_MACHINE}" + "-cpu" + "${QEMU_CPU}" + "-smp" + "${QEMU_SMP_OPTION}" + "-m" + "${QEMU_MEMORY}" + "-nographic" + ) + # When dumping the DTB to a file, QEMU prints a status message to + # stderr. Capture it and print on stdout to avoid polluting stderr + # unnecessarily. + execute_process( + COMMAND ${QEMU_CMD} + RESULT_VARIABLE error + ERROR_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE QEMU_STDERR_MESSAGE + OUTPUT_VARIABLE QEMU_STDOUT_MESSAGE + ) + if(error) + if(QEMU_STDERR_MESSAGE) + message("QEMU stderr: ${QEMU_STDERR_MESSAGE}") + endif() + if(QEMU_STDOUT_MESSAGE) + message("QEMU stdout: ${QEMU_STDOUT_MESSAGE}") + endif() + message(FATAL_ERROR "Failed to dump DTB using ${QEMU_RISCV_VIRT}), error ${error}") + endif() + message(STATUS "dumped QEMU DTB to ${QEMU_DTB}") + + string( + REPLACE + ";" + "\n * " + QEMU_DTS_INFO + "${QEMU_CMD}" + ) + set(QEMU_DTS_INFO "device tree from QEMU ${QEMU_VERSION}:\n * ${QEMU_DTS_INFO}") + + endif() + + # At this point there is a DTB file, either it was passed or dumped from + # QEMU. Convert it into a DTS. + execute_process( + COMMAND + dtc -q -I dtb -O dts "${QEMU_DTB}" + OUTPUT_VARIABLE QEMU_DTS_DATA + RESULT_VARIABLE error + ) + if(error) + message(FATAL_ERROR "Failed to create DTS from ${QEMU_DTB}") + endif() + + file(WRITE "${QEMU_DTS}" "/*\n * ${QEMU_DTS_INFO}\n */\n${QEMU_DTS_DATA}") + + endif() + + list(APPEND KernelDTSList "${QEMU_DTS}" "${CMAKE_CURRENT_LIST_DIR}/overlay-qemu-riscv-virt.dts") + + # QEMU emulates a SiFive PLIC/CLINT with 127 interrupt sources by default. + # The CLINT timer pretends to run at 10 MHz, but this speed may not hold in + # practical measurements. + declare_default_headers( + TIMER_FREQUENCY 10000000 PLIC_MAX_NUM_INT 128 + INTERRUPT_CONTROLLER drivers/irq/riscv_plic0.h + ) + +endif() diff --git a/src/plat/qemu-riscv-virt/overlay-qemu-riscv-virt.dts b/src/plat/qemu-riscv-virt/overlay-qemu-riscv-virt.dts new file mode 100644 index 0000000000..36f930b6f5 --- /dev/null +++ b/src/plat/qemu-riscv-virt/overlay-qemu-riscv-virt.dts @@ -0,0 +1,20 @@ +/* + * Copyright 2022, HENSOLDT Cyber + * + * SPDX-License-Identifier: GPL-2.0-only + */ + +/ { + chosen { + /* + * - elfloader and kernel use SBI console by default + * - QEMU emulates a SiFive PLIC and CLINT by default + * + * Nothing needed for elfloader + * seL4,elfloader-devices = ... ; + * + */ + seL4,kernel-devices = + &{/soc/plic@c000000}; + }; +};