1# 2# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 3# 4# SPDX-License-Identifier: BSD-2-Clause 5# 6 7# This module provides a function GenerateSimulateScript which will place a `simulate` 8# script in the build directory for running produced images in Qemu. 9include_guard(GLOBAL) 10include("${KERNEL_HELPERS_PATH}") 11RequireFile(SIMULATE_SCRIPT simulate.py PATHS "${CMAKE_CURRENT_LIST_DIR}/../simulate_scripts/") 12RequireFile(GDB_SCRIPT launch_gdb.py PATHS "${CMAKE_CURRENT_LIST_DIR}/../simulate_scripts/") 13RequireFile(CONFIGURE_FILE_SCRIPT configure_file.cmake PATHS "${CMAKE_CURRENT_LIST_DIR}") 14 15# Help macro for testing a config and appending to a list that is destined for a qemu -cpu line 16macro(TestQemuCPUFeature config feature string) 17 if(${config}) 18 set(${string} "${${string}},+${feature}") 19 else() 20 set(${string} "${${string}},-${feature}") 21 endif() 22endmacro(TestQemuCPUFeature) 23 24# Function for the user for configuration the simulation script. Valid values for property are 25# 'GRAPHIC' if set to TRUE disables the -nographic flag 26# 'MEM_SIZE' if set will override the memory size given to qemu 27function(SetSimulationScriptProperty property value) 28 # define the target if it doesn't already exist 29 if(NOT (TARGET simulation_script_prop_target)) 30 add_custom_target(simulation_script_prop_target) 31 endif() 32 set_property(TARGET simulation_script_prop_target PROPERTY "${property}" "${value}") 33endfunction(SetSimulationScriptProperty) 34 35macro(SetDefaultMemSize default) 36 set( 37 QemuMemSize 38 "$<IF:$<BOOL:$<TARGET_PROPERTY:simulation_script_prop_target,MEM_SIZE>>,$<TARGET_PROPERTY:simulation_script_prop_target,MEM_SIZE>,${default}>" 39 ) 40endmacro(SetDefaultMemSize) 41 42# Helper function that generates targets that will attempt to generate a ./simulate style script 43function(GenerateSimulateScript) 44 set(error "") 45 set(KERNEL_IMAGE_NAME "$<TARGET_PROPERTY:rootserver_image,KERNEL_IMAGE_NAME>") 46 set(IMAGE_NAME "$<TARGET_PROPERTY:rootserver_image,IMAGE_NAME>") 47 # Define simulation script target if it doesn't exist to simplify the generator expressions 48 if(NOT (TARGET simulation_script_prop_target)) 49 add_custom_target(simulation_script_prop_target) 50 endif() 51 set( 52 sim_graphic_opt 53 "$<IF:$<BOOL:$<TARGET_PROPERTY:simulation_script_prop_target,GRAPHIC>>,,-nographic>" 54 ) 55 set(sim_serial_opt "") 56 set(sim_cpu "") 57 set(sim_cpu_opt "") 58 set(sim_machine "") 59 set(qemu_sim_extra_args "") 60 if(KernelArchX86) 61 # Try and simulate the correct micro architecture and features 62 if(KernelX86MicroArchNehalem) 63 set(sim_cpu "Nehalem") 64 elseif(KernelX86MicroArchGeneric) 65 set(sim_cpu "qemu64") 66 elseif(KernelX86MicroArchWestmere) 67 set(sim_cpu "Westmere") 68 elseif(KernelX86MicroArchSandy) 69 set(sim_cpu "SandyBridge") 70 elseif(KernelX86MicroArchIvy) 71 set(sim_cpu "IvyBridge") 72 elseif(KernelX86MicroArchHaswell) 73 set(sim_cpu "Haswell") 74 elseif(KernelX86MicroArchBroadwell) 75 set(sim_cpu "Broadwell") 76 else() 77 set(error "Unknown x86 micro-architecture for simulation") 78 endif() 79 TestQemuCPUFeature(KernelVTX vme sim_cpu_opt) 80 TestQemuCPUFeature(KernelHugePage pdpe1gb sim_cpu_opt) 81 TestQemuCPUFeature(KernelFPUXSave xsave sim_cpu_opt) 82 TestQemuCPUFeature(KernelXSaveXSaveOpt xsaveopt sim_cpu_opt) 83 TestQemuCPUFeature(KernelXSaveXSaveC xsavec sim_cpu_opt) 84 TestQemuCPUFeature(KernelFSGSBaseInst fsgsbase sim_cpu_opt) 85 TestQemuCPUFeature(KernelSupportPCID invpcid sim_cpu_opt) 86 set(sim_cpu "${sim_cpu}") 87 set(sim_cpu_opt "${sim_cpu_opt},enforce") 88 set(QemuBinaryMachine "qemu-system-x86_64") 89 set(sim_serial_opt "-serial mon:stdio") 90 SetDefaultMemSize("512M") 91 elseif(KernelPlatformKZM) 92 set(QemuBinaryMachine "qemu-system-arm") 93 set(sim_machine "kzm") 94 SetDefaultMemSize("128M") 95 elseif(KernelPlatformSabre) 96 set(QemuBinaryMachine "qemu-system-arm") 97 # '-serial null -serial mon:stdio' means connect second UART to 98 # the terminal and ignore the first UART 99 set(sim_serial_opt "-serial null -serial mon:stdio") 100 set(sim_machine "sabrelite") 101 SetDefaultMemSize("1024M") 102 elseif(KernelPlatformZynq7000) 103 set(QemuBinaryMachine "qemu-system-arm") 104 set(sim_serial_opt "-serial null -serial mon:stdio") 105 set(sim_machine "xilinx-zynq-a9") 106 SetDefaultMemSize("1024M") 107 elseif(KernelPlatformWandQ) 108 set(QemuBinaryMachine "qemu-system-arm") 109 set(sim_serial_opt "-serial mon:stdio") 110 set(sim_machine "sabrelite") 111 SetDefaultMemSize("2048M") 112 elseif(KernelPlatformRpi3 AND KernelSel4ArchAarch64) 113 set(QemuBinaryMachine "qemu-system-aarch64") 114 set(sim_serial_opt "-serial null -serial mon:stdio") 115 set(sim_machine "raspi3") 116 SetDefaultMemSize("1024M") 117 elseif(KernelPlatformSpike) 118 if(KernelSel4ArchRiscV32) 119 set(binary "qemu-system-riscv32") 120 set(sim_cpu "rv32") 121 SetDefaultMemSize("2000M") 122 set(sim_machine "virt") 123 elseif(KernelSel4ArchRiscV64) 124 set(binary "qemu-system-riscv64") 125 set(sim_cpu "rv64") 126 SetDefaultMemSize("4095M") 127 set(sim_machine "spike") 128 endif() 129 set(QemuBinaryMachine "${binary}") 130 set(sim_serial_opt "-serial mon:stdio") 131 set(qemu_sim_extra_args "-bios none") 132 elseif(KernelPlatformQEMUArmVirt) 133 set(QemuBinaryMachine "qemu-system-${QEMU_ARCH}") 134 if(KernelArmHypervisorSupport) 135 set(sim_machine "virt,virtualization=on,highmem=off,secure=off") 136 else() 137 set(sim_machine "virt") 138 endif() 139 set(sim_graphic_opt "-nographic") 140 set(sim_cpu "${KernelArmCPU}") 141 SetDefaultMemSize("${QEMU_MEMORY}") 142 else() 143 set(error "Unsupported platform or architecture for simulation") 144 endif() 145 set(sim_path "${CMAKE_BINARY_DIR}/simulate") 146 set(gdb_path "${CMAKE_BINARY_DIR}/launch_gdb") 147 if(NOT "${error}" STREQUAL "") 148 set(script "#!/bin/sh\\necho ${error} && exit 1\\n") 149 add_custom_command( 150 OUTPUT "${sim_path}" "${gdb_path}" 151 COMMAND 152 printf "${script}" > "${sim_path}" 153 COMMAND 154 printf "${script}" > "${gdb_path}" 155 COMMAND 156 chmod u+x "${sim_path}" "${gdb_path}" 157 VERBATIM 158 ) 159 else() 160 # We assume a x86 host, but will provide options to override the default gdb binary 161 if(KernelArchX86) 162 set(GdbBinary "gdb") 163 else() 164 set(GdbBinary "gdb-multiarch") 165 endif() 166 add_custom_command( 167 OUTPUT "${sim_path}" 168 COMMAND 169 ${CMAKE_COMMAND} -DCONFIGURE_INPUT_FILE=${SIMULATE_SCRIPT} 170 -DCONFIGURE_OUTPUT_FILE=${sim_path} -DQEMU_SIM_BINARY=${QemuBinaryMachine} 171 -DQEMU_SIM_CPU=${sim_cpu} -DQEMU_SIM_MACHINE=${sim_machine} 172 -DQEMU_SIM_CPU_OPT=${sim_cpu_opt} -DQEMU_SIM_GRAPHIC_OPT=${sim_graphic_opt} 173 -DQEMU_SIM_SERIAL_OPT=${sim_serial_opt} -DQEMU_SIM_MEM_SIZE_OPT=${QemuMemSize} 174 -DQEMU_SIM_KERNEL_FILE=${KERNEL_IMAGE_NAME} -DQEMU_SIM_INITRD_FILE=${IMAGE_NAME} 175 -DQEMU_SIM_EXTRA_ARGS=${qemu_sim_extra_args} -P ${CONFIGURE_FILE_SCRIPT} 176 COMMAND chmod u+x "${sim_path}" 177 VERBATIM COMMAND_EXPAND_LISTS 178 ) 179 add_custom_command( 180 OUTPUT "${gdb_path}" 181 COMMAND 182 ${CMAKE_COMMAND} -DCONFIGURE_INPUT_FILE=${GDB_SCRIPT} 183 -DCONFIGURE_OUTPUT_FILE=${gdb_path} -DGDB_BINARY=${GdbBinary} 184 -DQEMU_SIM_KERNEL_FILE=${KERNEL_IMAGE_NAME} -DQEMU_SIM_INITRD_FILE=${IMAGE_NAME} -P 185 ${CONFIGURE_FILE_SCRIPT} 186 COMMAND chmod u+x "${gdb_path}" 187 VERBATIM COMMAND_EXPAND_LISTS 188 ) 189 endif() 190 add_custom_target(simulate_gen ALL DEPENDS "${sim_path}") 191 add_custom_target(gdb_gen ALL DEPENDS "${gdb_path}") 192endfunction(GenerateSimulateScript) 193