blob: b2ee6b1a932a199dbbf4e89fa9f5c93dae90f647 [file]
#
# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
#
# SPDX-License-Identifier: BSD-2-Clause
#
# This module provides a function GenerateSimulateScript which will place a `simulate`
# script in the build directory for running produced images in Qemu.
include_guard(GLOBAL)
include("${KERNEL_HELPERS_PATH}")
RequireFile(SIMULATE_SCRIPT simulate.py PATHS "${CMAKE_CURRENT_LIST_DIR}/../simulate_scripts/")
RequireFile(GDB_SCRIPT launch_gdb.py PATHS "${CMAKE_CURRENT_LIST_DIR}/../simulate_scripts/")
RequireFile(CONFIGURE_FILE_SCRIPT configure_file.cmake PATHS "${CMAKE_CURRENT_LIST_DIR}")
# Help macro for testing a config and appending to a list that is destined for a qemu -cpu line
macro(TestQemuCPUFeature config feature string)
if(${config})
set(${string} "${${string}},+${feature}")
else()
set(${string} "${${string}},-${feature}")
endif()
endmacro(TestQemuCPUFeature)
# Function for the user for configuration the simulation script. Valid values for property are
# 'GRAPHIC' if set to TRUE disables the -nographic flag
# 'MEM_SIZE' if set will override the memory size given to qemu
function(SetSimulationScriptProperty property value)
# define the target if it doesn't already exist
if(NOT (TARGET simulation_script_prop_target))
add_custom_target(simulation_script_prop_target)
endif()
set_property(TARGET simulation_script_prop_target PROPERTY "${property}" "${value}")
endfunction(SetSimulationScriptProperty)
macro(SetDefaultMemSize default)
set(
QemuMemSize
"$<IF:$<BOOL:$<TARGET_PROPERTY:simulation_script_prop_target,MEM_SIZE>>,$<TARGET_PROPERTY:simulation_script_prop_target,MEM_SIZE>,${default}>"
)
endmacro(SetDefaultMemSize)
# Helper function that generates targets that will attempt to generate a ./simulate style script
function(GenerateSimulateScript)
set(error "")
set(KERNEL_IMAGE_NAME "$<TARGET_PROPERTY:rootserver_image,KERNEL_IMAGE_NAME>")
set(IMAGE_NAME "$<TARGET_PROPERTY:rootserver_image,IMAGE_NAME>")
# Define simulation script target if it doesn't exist to simplify the generator expressions
if(NOT (TARGET simulation_script_prop_target))
add_custom_target(simulation_script_prop_target)
endif()
set(
sim_graphic_opt
"$<IF:$<BOOL:$<TARGET_PROPERTY:simulation_script_prop_target,GRAPHIC>>,,-nographic>"
)
set(sim_serial_opt "")
set(sim_cpu "")
set(sim_cpu_opt "")
set(sim_machine "")
set(qemu_sim_extra_args "")
if(KernelArchX86)
# Try and simulate the correct micro architecture and features
if(KernelX86MicroArchNehalem)
set(sim_cpu "Nehalem")
elseif(KernelX86MicroArchGeneric)
if(KernelSel4ArchIA32)
set(sim_cpu "qemu32")
else()
set(sim_cpu "qemu64")
endif()
elseif(KernelX86MicroArchWestmere)
set(sim_cpu "Westmere")
elseif(KernelX86MicroArchSandy)
set(sim_cpu "SandyBridge")
elseif(KernelX86MicroArchIvy)
set(sim_cpu "IvyBridge")
elseif(KernelX86MicroArchHaswell)
set(sim_cpu "Haswell")
elseif(KernelX86MicroArchBroadwell)
set(sim_cpu "Broadwell")
else()
set(error "Unknown x86 micro-architecture for simulation")
endif()
TestQemuCPUFeature(KernelVTX vme sim_cpu_opt)
TestQemuCPUFeature(KernelHugePage pdpe1gb sim_cpu_opt)
TestQemuCPUFeature(KernelFPUXSave xsave sim_cpu_opt)
TestQemuCPUFeature(KernelXSaveXSaveOpt xsaveopt sim_cpu_opt)
TestQemuCPUFeature(KernelXSaveXSaveC xsavec sim_cpu_opt)
TestQemuCPUFeature(KernelFSGSBaseInst fsgsbase sim_cpu_opt)
TestQemuCPUFeature(KernelSupportPCID invpcid sim_cpu_opt)
TestQemuCPUFeature(KernelX86SyscallSyscall syscall sim_cpu_opt)
TestQemuCPUFeature(KernelSel4ArchX86_64 lm sim_cpu_opt)
set(sim_cpu "${sim_cpu}")
set(sim_cpu_opt "${sim_cpu_opt},enforce")
if(KernelSel4ArchIA32)
set(QemuBinaryMachine "qemu-system-i386")
else()
set(QemuBinaryMachine "qemu-system-x86_64")
endif()
set(sim_serial_opt "-serial mon:stdio")
SetDefaultMemSize("512M")
elseif(KernelPlatformSabre)
set(QemuBinaryMachine "qemu-system-arm")
# '-serial null -serial mon:stdio' means connect second UART to
# the terminal and ignore the first UART
set(sim_serial_opt "-serial null -serial mon:stdio")
set(sim_machine "sabrelite")
SetDefaultMemSize("1024M")
elseif(KernelPlatformZynq7000)
set(QemuBinaryMachine "qemu-system-arm")
set(sim_serial_opt "-serial null -serial mon:stdio")
set(sim_machine "xilinx-zynq-a9")
SetDefaultMemSize("1024M")
elseif(KernelPlatformWandQ)
set(QemuBinaryMachine "qemu-system-arm")
set(sim_serial_opt "-serial mon:stdio")
set(sim_machine "sabrelite")
SetDefaultMemSize("2048M")
elseif(KernelPlatformRpi3 AND KernelSel4ArchAarch64)
set(QemuBinaryMachine "qemu-system-aarch64")
set(sim_serial_opt "-serial null -serial mon:stdio")
set(sim_machine "raspi3")
SetDefaultMemSize("1024M")
elseif(KernelPlatformSpike)
if(KernelSel4ArchRiscV32)
set(binary "qemu-system-riscv32")
set(sim_cpu "rv32")
SetDefaultMemSize("2000M")
set(sim_machine "virt")
elseif(KernelSel4ArchRiscV64)
set(binary "qemu-system-riscv64")
set(sim_cpu "rv64")
SetDefaultMemSize("4095M")
set(sim_machine "spike")
endif()
set(QemuBinaryMachine "${binary}")
set(sim_serial_opt "-serial mon:stdio")
elseif(KernelPlatformShodan)
set(binary "qemu-system-riscv32")
SetDefaultMemSize("2000M")
set(sim_machine "spike")
set(QemuBinaryMachine "${binary}")
set(sim_serial_opt "-serial mon:stdio")
set(qemu_sim_extra_args "-bios none")
elseif(KernelPlatformRocketchip)
set(binary "qemu-system-riscv64")
set(sim_cpu "rv64")
SetDefaultMemSize("256M")
set(QemuBinaryMachine "${binary}")
set(sim_serial_opt "-serial mon:stdio")
set(qemu_sim_extra_args "-bios none")
elseif(KernelPlatformQEMUArmVirt)
set(QemuBinaryMachine "qemu-system-${QEMU_ARCH}")
if(KernelArmHypervisorSupport)
set(sim_machine "virt,virtualization=on,highmem=off,secure=off")
else()
set(sim_machine "virt")
endif()
set(sim_graphic_opt "-nographic")
set(sim_cpu "${KernelArmCPU}")
SetDefaultMemSize("${QEMU_MEMORY}")
else()
set(error "Unsupported platform or architecture for simulation")
endif()
set(sim_path "${CMAKE_BINARY_DIR}/simulate")
set(gdb_path "${CMAKE_BINARY_DIR}/launch_gdb")
if(NOT "${error}" STREQUAL "")
set(script "#!/bin/sh\\necho ${error} && exit 1\\n")
add_custom_command(
OUTPUT "${sim_path}" "${gdb_path}"
COMMAND
printf "${script}" > "${sim_path}"
COMMAND
printf "${script}" > "${gdb_path}"
COMMAND
chmod u+x "${sim_path}" "${gdb_path}"
VERBATIM
)
else()
# We assume a x86 host, but will provide options to override the default gdb binary
if(KernelArchX86)
set(GdbBinary "gdb")
else()
set(GdbBinary "gdb-multiarch")
endif()
add_custom_command(
OUTPUT "${sim_path}"
COMMAND
${CMAKE_COMMAND} -DCONFIGURE_INPUT_FILE=${SIMULATE_SCRIPT}
-DCONFIGURE_OUTPUT_FILE=${sim_path} -DQEMU_SIM_BINARY=${QemuBinaryMachine}
-DQEMU_SIM_CPU=${sim_cpu} -DQEMU_SIM_MACHINE=${sim_machine}
-DQEMU_SIM_CPU_OPT=${sim_cpu_opt} -DQEMU_SIM_GRAPHIC_OPT=${sim_graphic_opt}
-DQEMU_SIM_SERIAL_OPT=${sim_serial_opt} -DQEMU_SIM_MEM_SIZE_OPT=${QemuMemSize}
-DQEMU_SIM_KERNEL_FILE=${KERNEL_IMAGE_NAME} -DQEMU_SIM_INITRD_FILE=${IMAGE_NAME}
-DQEMU_SIM_EXTRA_ARGS=${qemu_sim_extra_args} -P ${CONFIGURE_FILE_SCRIPT}
COMMAND chmod u+x "${sim_path}"
VERBATIM COMMAND_EXPAND_LISTS
)
add_custom_command(
OUTPUT "${gdb_path}"
COMMAND
${CMAKE_COMMAND} -DCONFIGURE_INPUT_FILE=${GDB_SCRIPT}
-DCONFIGURE_OUTPUT_FILE=${gdb_path} -DGDB_BINARY=${GdbBinary}
-DQEMU_SIM_KERNEL_FILE=${KERNEL_IMAGE_NAME} -DQEMU_SIM_INITRD_FILE=${IMAGE_NAME} -P
${CONFIGURE_FILE_SCRIPT}
COMMAND chmod u+x "${gdb_path}"
VERBATIM COMMAND_EXPAND_LISTS
)
endif()
add_custom_target(simulate_gen ALL DEPENDS "${sim_path}")
add_custom_target(gdb_gen ALL DEPENDS "${gdb_path}")
endfunction(GenerateSimulateScript)