Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[patch-axel-87] support qemu-riscv-virt platform #11

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
9 changes: 6 additions & 3 deletions include/drivers/irq/riscv_plic0.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <sel4/arch/constants_cortex_a53.h>
#elif defined(CONFIG_ARM_CORTEX_A57)
#include <sel4/arch/constants_cortex_a57.h>
#elif defined(CONFIG_ARM_CORTEX_A72)
#include <sel4/arch/constants_cortex_a72.h>
#else
#error "unsupported core"
#endif
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright 2022, HENSOLDT Cyber
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#pragma once

#include <autoconf.h>

/* nothing here */
290 changes: 200 additions & 90 deletions src/plat/qemu-arm-virt/config.cmake
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#
# Copyright 2022, HENSOLDT Cyber
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: GPL-2.0-only
Expand All @@ -8,112 +9,220 @@ cmake_minimum_required(VERSION 3.7.2)

declare_platform(qemu-arm-virt KernelPlatformQEMUArmVirt PLAT_QEMU_ARM_VIRT KernelArchARM)

set(MIN_QEMU_VERSION "3.1.0")

set(qemu_user_top 0xa0000000)

macro(setup_qemu_armv7)
if("${KernelSel4Arch}" STREQUAL aarch32)
declare_seL4_arch(aarch32)
elseif("${KernelSel4Arch}" STREQUAL arm_hyp)
declare_seL4_arch(arm_hyp)
else()
fallback_declare_seL4_arch_default(aarch32)
endif()
if(KernelSel4ArchArmHyp)
set(qemu_user_top 0xe0000000)
endif()
set(QEMU_ARCH "arm")
set(KernelArchArmV7a ON)
endmacro()

macro(setup_qemu_armv8)
declare_seL4_arch(aarch64)
set(QEMU_ARCH "aarch64")
set(KernelArchArmV8a ON)
endmacro()

if(KernelPlatformQEMUArmVirt)
if("${ARM_CPU}" STREQUAL "cortex-a15")
if("${KernelSel4Arch}" STREQUAL aarch32)
declare_seL4_arch(aarch32)
elseif("${KernelSel4Arch}" STREQUAL arm_hyp)
declare_seL4_arch(arm_hyp)
else()
fallback_declare_seL4_arch_default(aarch32)
endif()
if(KernelSel4ArchArmHyp)
set(qemu_user_top 0xe0000000)
endif()
set(QEMU_ARCH "arm")

if(NOT ARM_CPU)
message(STATUS "ARM_CPU not set, defaulting to cortex-a53")
set(ARM_CPU "cortex-a53")
endif()

if("${ARM_CPU}" STREQUAL "cortex-a7")
setup_qemu_armv7()
set(KernelArmCortexA7 ON)
elseif("${ARM_CPU}" STREQUAL "cortex-a15")
setup_qemu_armv7()
set(KernelArmCortexA15 ON)
set(KernelArchArmV7a ON)
set(KernelArchArmV7ve ON)
elseif("${ARM_CPU}" STREQUAL "cortex-a53")
declare_seL4_arch(aarch64)
set(QEMU_ARCH "aarch64")
setup_qemu_armv8()
set(KernelArmCortexA53 ON)
set(KernelArchArmV8a ON)
elseif("${ARM_CPU}" STREQUAL "cortex-a57")
declare_seL4_arch(aarch64)
set(QEMU_ARCH "aarch64")
setup_qemu_armv8()
set(KernelArmCortexA57 ON)
set(KernelArchArmV8a ON)
elseif("${ARM_CPU}" STREQUAL "cortex-a72")
setup_qemu_armv8()
set(KernelArmCortexA72 ON)
else()
message(STATUS "Default cpu specified for virt board: cortex-a53")
declare_seL4_arch(aarch64)
set(ARM_CPU "cortex-a53")
set(QEMU_ARCH "aarch64")
set(KernelArmCortexA53 ON)
set(KernelArchArmV8a ON)
endif()
execute_process(
COMMAND qemu-system-${QEMU_ARCH} -version
OUTPUT_VARIABLE QEMU_VERSION_STR
RESULT_VARIABLE error
)
if(error)
message(FATAL_ERROR "Failed to determine qemu version (qemu-system-${QEMU_ARCH})")
endif()
string(
REGEX
MATCH
"[0-9](\\.[0-9])+"
QEMU_VERSION
${QEMU_VERSION_STR}
)
if("${QEMU_VERSION}" VERSION_LESS "${MIN_QEMU_VERSION}")
message(FATAL_ERROR "Error: qemu version must be at least ${MIN_QEMU_VERSION}")
message(FATAL_ERROR "Unsupported ARM_CPU: '${ARM_CPU}'")
endif()

if("${QEMU_MEMORY}" STREQUAL "")
set(QEMU_MEMORY "1024")
endif()
message(STATUS "QEMU MEMORY is: ${QEMU_MEMORY}")
config_set(KernelARMPlatform ARM_PLAT qemu-arm-virt)
set(DTBPath "${CMAKE_BINARY_DIR}/virt.dtb")
set(DTSPath "${CMAKE_BINARY_DIR}/virt.dts")
if(KernelArmHypervisorSupport OR KernelSel4ArchArmHyp)
set(QEMU_VIRT_OPTION "virtualization=on,highmem=off,secure=off")
else()
if(Kernel32)
set(QEMU_VIRT_OPTION "virtualization=off,highmem=off")
else()
set(QEMU_VIRT_OPTION "virtualization=off")

# 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-arm-virt.dts")

if(NOT DEFINED QEMU_DTB)

message(STATUS "Extracting device tree from QEMU")
set(QEMU_DTB "${CMAKE_BINARY_DIR}/qemu-arm-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_BINARY "qemu-system-${QEMU_ARCH}")
find_program(QEMU_BINARY ${QEMU_BINARY})
# ARM virtual platform works since QEMU 3.1.0
set(MIN_QEMU_VERSION "3.1.0")
execute_process(
COMMAND ${QEMU_BINARY} -version
RESULT_VARIABLE error
OUTPUT_STRIP_TRAILING_WHITESPACE
OUTPUT_VARIABLE QEMU_STDOUT_MESSAGE
)
if(error)
message(FATAL_ERROR "Failed to determine QEMU version (${QEMU_BINARY})")
endif()
string(
REGEX
MATCH
"[0-9](\\.[0-9])+"
QEMU_VERSION
"${QEMU_STDOUT_MESSAGE}"
)
if("${QEMU_VERSION}" VERSION_LESS "${MIN_QEMU_VERSION}")
message(
FATAL_ERROR
"Error: need at least QEMU version ${MIN_QEMU_VERSION}, found '${QEMU_VERSION}'"
)
endif()

endif()

if(NOT DEFINED QEMU_MACHINE)
set(QEMU_MACHINE "virt")
list(APPEND QEMU_MACHINE "secure=off")
if(KernelArmHypervisorSupport OR KernelSel4ArchArmHyp)
list(APPEND QEMU_MACHINE "virtualization=on")
endif()
if(Kernel32)
list(APPEND QEMU_MACHINE "highmem=off")
endif()
list(APPEND QEMU_MACHINE "dumpdtb=${QEMU_DTB}")

# Lists are just strings with ";" as item separator, so we can
# just replace them by ",". The cleaner way would be using the
# CMake 3.12 feature: list(JOIN QEMU_MACHINE "," QEMU_MACHINE)
string(
REPLACE
";"
","
QEMU_MACHINE
"${QEMU_MACHINE}"
)

endif()

if(NOT DEFINED QEMU_MEMORY)
# Having 1 GiB of memory as default is a legacy from the past
# that is kept for compatibility. It should be increased to
# 2 GiB, which seems a good trade-off nowadays. It's sufficient
# for test/demo systems, but still something the host can
# provide without running short on resources.
set(QEMU_MEMORY "1024")
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 command, so
# it can be added to the DTS as reference. Every parameter must be
# a separate string, as CMake will make it a dedicated argument
# passed to QEMU then (e.g. "-machine virt" wont be recognized,
# but "-machine", "vir" is).
set(
QEMU_CMD
"${QEMU_BINARY}"
"-machine"
"${QEMU_MACHINE}"
"-cpu"
"${ARM_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
)
if(QEMU_STDERR_MESSAGE)
message(STATUS "${QEMU_STDERR_MESSAGE}")
endif()
if(error)
message(FATAL_ERROR "Failed to dump DTB using ${QEMU_BINARY}: ${error}")
endif()

endif()

# At this point there is a DTB file, either it was passed or dumped from
# QEMU. Create a DTS and store it in QEMU_DTS_DATA.
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's DTB ${QEMU_DTB}: ${error}")
endif()

set(QEMU_DTS_INFO "converted from ${QEMU_DTB}")
if(QEMU_CMD)
# Lists are just strings with ";" as item separator, so we can
# simply replace them with something else. The cleaner way is a
# CMake 3.12 feature: list(JOIN QEMU_CMD "\n * " QEMU_DTS_INFO)
string(
REPLACE
";"
"\n * "
QEMU_DTS_INFO
"DTS of QEMU v${QEMU_VERSION} for:;${QEMU_CMD}"
)
endif()
file(
WRITE
"${QEMU_DTS}"
"/*\n"
" * ${QEMU_DTS_INFO}\n"
" */\n"
"\n"
"${QEMU_DTS_DATA}"
)

endif()
if(KernelMaxNumNodes)
set(QEMU_SMP_OPTION "${KernelMaxNumNodes}")
else()
set(QEMU_SMP_OPTION "1")
endif()
find_program(QEMU_BINARY qemu-system-${QEMU_ARCH})
execute_process(
COMMAND
${QEMU_BINARY} -machine virt,dumpdtb=${DTBPath},${QEMU_VIRT_OPTION} -m ${QEMU_MEMORY}
-cpu ${ARM_CPU} -smp ${QEMU_SMP_OPTION} -nographic
ERROR_VARIABLE QEMU_OUTPUT_MESSAGE
RESULT_VARIABLE error
)
if(${QEMU_OUTPUT_MESSAGE})
string(STRIP ${QEMU_OUTPUT_MESSAGE} QEMU_OUTPUT_MESSAGE)
endif()
message(STATUS ${QEMU_OUTPUT_MESSAGE})
if(error)
message(FATAL_ERROR "Failed to dump DTB using ${QEMU_BINARY})")
endif()
execute_process(
COMMAND
dtc -q -I dtb -O dts ${DTBPath}
OUTPUT_FILE ${DTSPath}
RESULT_VARIABLE error
)
if(error)
message(FATAL_ERROR "Failed to convert DTB to DTS (${DTBPath})")
endif()
list(APPEND KernelDTSList "${DTSPath}")
list(APPEND KernelDTSList "src/plat/qemu-arm-virt/overlay-qemu-arm-virt.dts")

list(APPEND KernelDTSList "${QEMU_DTS}" "${CMAKE_CURRENT_LIST_DIR}/overlay-qemu-arm-virt.dts")

if(KernelArmHypervisorSupport OR KernelSel4ArchArmHyp)
list(APPEND KernelDTSList "src/plat/qemu-arm-virt/overlay-reserve-vm-memory.dts")
list(APPEND KernelDTSList "${CMAKE_CURRENT_LIST_DIR}/overlay-reserve-vm-memory.dts")
endif()

declare_default_headers(
TIMER_FREQUENCY 62500000
MAX_IRQ 159
Expand All @@ -124,6 +233,7 @@ if(KernelPlatformQEMUArmVirt)
CLK_SHIFT 58u
KERNEL_WCET 10u
)

endif()

add_sources(
Expand Down
Loading