Skip to content

Commit

Permalink
cmake: extend qemu-arm-virt script
Browse files Browse the repository at this point in the history
- makes setting more generic an allow overriding parameters
- save QEMU parameters in DTS as comment

Signed-off-by: Axel Heider <[email protected]>
  • Loading branch information
Axel Heider committed Nov 11, 2022
1 parent ca869cc commit 2ce4b83
Showing 1 changed file with 162 additions and 68 deletions.
230 changes: 162 additions & 68 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,8 +9,6 @@ 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)
Expand Down Expand Up @@ -57,79 +56,173 @@ if(KernelPlatformQEMUArmVirt)
setup_qemu_armv8()
set(KernelArmCortexA72 ON)
else()
message(FATAL_ERROR "Unsupported ARM_CPU for QEMU: '${ARM_CPU}'")
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})
# Run QEMU to get the device tree binary. QEMU prints a status message to
# stderr (and not stdout), we capture it and then print it to stdout to
# avoid polluting stderr unnecessarily.
execute_process(
COMMAND
${QEMU_BINARY} -machine virt,dumpdtb=${DTBPath},${QEMU_VIRT_OPTION} -m ${QEMU_MEMORY}
-cpu ${ARM_CPU} -smp ${QEMU_SMP_OPTION} -nographic
ERROR_STRIP_TRAILING_WHITESPACE
ERROR_VARIABLE QEMU_OUTPUT_MESSAGE
RESULT_VARIABLE error
)
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 @@ -140,6 +233,7 @@ if(KernelPlatformQEMUArmVirt)
CLK_SHIFT 58u
KERNEL_WCET 10u
)

endif()

add_sources(
Expand Down

0 comments on commit 2ce4b83

Please sign in to comment.