Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 1 | # |
| 2 | # SPDX-License-Identifier: BSD-3-Clause |
| 3 | # SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| 4 | # |
| 5 | |
| 6 | include(FetchContent) |
| 7 | include("${SOURCE_DIR}/tools/cbmc/SummaryHelpers.cmake") |
| 8 | find_program(RMM_CBMC_PATH "cbmc" |
| 9 | DOC "Path to cbmc.") |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 10 | find_program(RMM_GOTO_CC_PATH "goto-cc" |
| 11 | DOC "Path to goto-cc.") |
| 12 | find_program(RMM_CBMC_VIEWER_PATH "cbmc-viewer" |
| 13 | DOC "Path to cbmc-viewer.") |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 14 | |
Mate Toth-Pal | 7b875ea | 2023-11-15 16:59:19 +0100 | [diff] [blame] | 15 | find_package(Python3 REQUIRED) |
| 16 | find_program(CHECK_CBMC_SUMMARY_EXECUTABLE "compare_summary.py" |
| 17 | PATHS ${CMAKE_SOURCE_DIR} |
| 18 | PATH_SUFFIXES tools/cbmc |
| 19 | DOC "Path to compare_summary.py" |
| 20 | ) |
| 21 | |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 22 | # |
| 23 | # Configure and execute CBMC |
| 24 | # |
| 25 | if(NOT (EXISTS "${RMM_CBMC_PATH}")) |
| 26 | message(FATAL_ERROR "cbmc executable not found. (${RMM_CBMC_PATH})") |
| 27 | endif() |
| 28 | |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 29 | string(TOLOWER "${RMM_CBMC_CONFIGURATION}" CBMC_RESULT_FILE_SUFFIX) |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 30 | |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 31 | if(RMM_CBMC_VIEWER_OUTPUT) |
| 32 | set(CBMC_OUT_FILE_ENDING "xml") |
| 33 | set(CBMC_UI_OPTION "--xml-ui") |
| 34 | else() |
| 35 | set(CBMC_OUT_FILE_ENDING "output") |
| 36 | set(CBMC_UI_OPTION "") |
| 37 | endif() |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 38 | |
| 39 | set(RMM_TESTBENCH_RESULT_DIR "${BINARY_DIR}/cbmc_${CBMC_RESULT_FILE_SUFFIX}_results") |
| 40 | set(SUMMARY_FILE "SUMMARY.${CBMC_RESULT_FILE_SUFFIX}") |
| 41 | set(RMM_CBMC_SUMMARY_FIELD_WIDTH 38) |
| 42 | |
| 43 | # Configurations for the initial state. |
| 44 | set(GRANULE_SHIFT "7") |
| 45 | set(MAX_NUM_OF_GRANULE "8") |
| 46 | set(HOST_MEM_SIZE "1024UL") |
| 47 | |
| 48 | set(MAX_RTT_UNWIND "6") |
| 49 | set(MAX_AUX_REC "2") |
| 50 | set(MAX_ROOT_RTT "3") |
| 51 | set(MAX_UNWIND_FLAGS "") |
| 52 | |
| 53 | # |
| 54 | # Set up cbmc command line |
| 55 | # |
| 56 | set(cbmc_unwinds_list |
Mate Toth-Pal | c751c0d | 2023-11-14 16:56:41 +0100 | [diff] [blame^] | 57 | "--unwindset;find_lock_granules.3:${MAX_ROOT_RTT}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 58 | "--unwindset;find_lock_rd_granules.0:${MAX_RTT_UNWIND}" |
| 59 | "--unwindset;find_lock_rd_granules.1:${MAX_RTT_UNWIND}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 60 | "--unwindset;free_rec_aux_granules.0:${MAX_AUX_REC}" |
Mate Toth-Pal | c751c0d | 2023-11-14 16:56:41 +0100 | [diff] [blame^] | 61 | "--unwindset;free_sl_rtts.0:${MAX_RTT_UNWIND}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 62 | "--unwindset;init_realm_descriptor_page.0:${MAX_ROOT_RTT}" |
Mate Toth-Pal | c751c0d | 2023-11-14 16:56:41 +0100 | [diff] [blame^] | 63 | "--unwindset;init_realm_descriptor_page.1:${MAX_ROOT_RTT}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 64 | "--unwindset;init_rec.0:${MAX_AUX_REC}" |
Mate Toth-Pal | c751c0d | 2023-11-14 16:56:41 +0100 | [diff] [blame^] | 65 | "--unwindset;init_rtt_root_page.0:${MAX_ROOT_RTT}" |
| 66 | "--unwindset;init_walk_path.0:${MAX_RTT_UNWIND}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 67 | "--unwindset;lock_order_invariable.0:21" |
| 68 | "--unwindset;lock_order_invariable.1:11" |
| 69 | "--unwindset;lock_order_invariable.2:" |
Mate Toth-Pal | c751c0d | 2023-11-14 16:56:41 +0100 | [diff] [blame^] | 70 | "--unwindset;RealmIsLive.0:${MAX_ROOT_RTT}" |
| 71 | "--unwindset;RealmIsLive.2:${MAX_ROOT_RTT}" |
| 72 | "--unwindset;rtt_walk_lock_unlock.0:${MAX_RTT_UNWIND}" |
| 73 | "--unwindset;RttWalk.0:${MAX_RTT_UNWIND}" |
| 74 | "--unwindset;smc_realm_create.0:${MAX_RTT_UNWIND}" |
| 75 | "--unwindset;smc_rec_create.0:${MAX_AUX_REC}" |
| 76 | "--unwindset;total_root_rtt_refcount.0:${MAX_RTT_UNWIND}" |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 77 | ) |
| 78 | |
| 79 | set(cbmc_defines_list |
| 80 | "-DCBMC" |
| 81 | "-DDISABLE_COMPILER_ASSERT" |
| 82 | "-DDISABLE_SET_MEMBER" |
| 83 | "-DGRANULE_SHIFT=${GRANULE_SHIFT}" |
| 84 | "-DXLAT_GRANULARITY_SIZE_SHIFT=${GRANULE_SHIFT}" |
| 85 | "-DRMM_MAX_GRANULES=${MAX_NUM_OF_GRANULE}" |
| 86 | "-DMAX_CPUS=1" |
| 87 | "-DMAX_RTT_LEVEL=${MAX_RTT_UNWIND}" |
| 88 | "-DHOST_MEM_SIZE=${HOST_MEM_SIZE}" |
| 89 | "-DNAME=\"RMM\"" |
| 90 | "-DVERSION=\"CBMC\"" |
| 91 | "-DCOMMIT_INFO=\"CBMC\"" |
| 92 | ) |
| 93 | |
| 94 | # CBMC flags for memory safety analysis and undefined behaviour analysis. |
| 95 | set(cbmc_analysis_flags_list |
| 96 | "--bounds-check" |
| 97 | "--pointer-check" |
| 98 | "--div-by-zero-check" |
| 99 | "--signed-overflow-check" |
| 100 | "--unsigned-overflow-check" |
| 101 | "--pointer-overflow-check" |
| 102 | "--conversion-check" |
| 103 | "--undefined-shift-check" |
| 104 | "--float-overflow-check" |
| 105 | "--nan-check" |
| 106 | "--enum-range-check" |
| 107 | "--pointer-primitive-check" |
| 108 | "--memory-leak-check") |
| 109 | |
| 110 | set(cbmc_flags_list |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 111 | "--timestamp;wall" |
| 112 | "--verbosity;9" |
| 113 | # Optimisation flags: |
| 114 | "--drop-unused-functions" |
| 115 | "--reachability-slice" |
| 116 | ) |
| 117 | |
| 118 | if("${RMM_CBMC_CONFIGURATION}" STREQUAL "COVERAGE") |
| 119 | list(APPEND cbmc_flags_list |
| 120 | "--cover;cover" |
| 121 | "--no-assertions") |
| 122 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ASSERT") |
| 123 | list(APPEND cbmc_flags_list |
| 124 | "--unwinding-assertions" |
| 125 | "--trace" |
| 126 | "--trace-show-function-calls") |
| 127 | elseif("${RMM_CBMC_CONFIGURATION}" STREQUAL "ANALYSIS") |
| 128 | list(APPEND cbmc_flags_list |
| 129 | "--unwinding-assertions" |
| 130 | "${cbmc_analysis_flags_list}") |
| 131 | else() |
| 132 | message(FATAL_ERROR "Invalid RMM_CBMC_CONFIGURATION '${RMM_CBMC_CONFIGURATION}'") |
| 133 | endif() |
| 134 | |
| 135 | file(GLOB_RECURSE TESTBENCH_FILES "${TESTBENCH_DIR}/*.c") |
| 136 | |
| 137 | # |
| 138 | # Create semi-colon separated list from white-space seperated ones. |
| 139 | # |
| 140 | separate_arguments(RMM_IMP_SRCS) |
| 141 | separate_arguments(RMM_IMP_INCS) |
| 142 | |
| 143 | # |
| 144 | # Execute CBMC on the testbench files |
| 145 | # |
| 146 | rmm_cbmc_write_summary_header(${RMM_CBMC_SUMMARY_FIELD_WIDTH} |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 147 | ${RMM_TESTBENCH_RESULT_DIR} ${SUMMARY_FILE} ${RMM_CBMC_CONFIGURATION}) |
| 148 | |
| 149 | function(rmm_cbmc_gen_file_names |
| 150 | testbench_file_path |
| 151 | filename_prefix |
| 152 | out_file_ending |
| 153 | cmd_file_var_name |
| 154 | out_file_var_name |
| 155 | err_file_var_name) |
| 156 | get_filename_component(testbench_file_name "${testbench_file_path}" NAME) |
| 157 | get_filename_component(parent "${testbench_file_path}" DIRECTORY) |
| 158 | set("${cmd_file_var_name}" "${parent}/${filename_prefix}_${testbench_file_name}.cmd" PARENT_SCOPE) |
| 159 | set("${out_file_var_name}" "${parent}/${filename_prefix}_${testbench_file_name}.${out_file_ending}" PARENT_SCOPE) |
| 160 | set("${err_file_var_name}" "${parent}/${filename_prefix}_${testbench_file_name}.error" PARENT_SCOPE) |
| 161 | endfunction() |
| 162 | |
| 163 | function(normalise_cmd cmd_str out_var_name) |
| 164 | # replace the ; with space |
| 165 | string (REPLACE ";" " " cmd_str "${cmd_str}") |
| 166 | set("${out_var_name}" "${cmd_str}" PARENT_SCOPE) |
| 167 | endfunction() |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 168 | |
| 169 | foreach(testbench_file ${TESTBENCH_FILES}) |
| 170 | |
| 171 | string(REPLACE ${TESTBENCH_DIR}/ "" testbench_filename ${testbench_file}) |
| 172 | string(REGEX REPLACE "\\.[^\\.]*$" "" entry_point "${testbench_filename}") |
| 173 | |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 174 | set(RMM_GOTO_PROG_NAME "${RMM_TESTBENCH_RESULT_DIR}/rmm_${entry_point}.goto") |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 175 | |
| 176 | # Set the names of output files |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 177 | string(REPLACE ${TESTBENCH_DIR} ${RMM_TESTBENCH_RESULT_DIR} OUT_FILE_NAME_PREFIX "${testbench_file}") |
| 178 | rmm_cbmc_gen_file_names(${OUT_FILE_NAME_PREFIX} "cbmc" "${CBMC_OUT_FILE_ENDING}" |
| 179 | cbmc_cmd_file cbmc_output_file cbmc_error_file) |
| 180 | rmm_cbmc_gen_file_names(${OUT_FILE_NAME_PREFIX} "cbmc_prop" "xml" |
| 181 | cbmc_prop_cmd_file cbmc_prop_output_file cbmc_prop_error_file) |
| 182 | rmm_cbmc_gen_file_names(${OUT_FILE_NAME_PREFIX} "goto_cc" "output" |
| 183 | goto_cc_cmd_file goto_cc_output_file goto_cc_error_file) |
| 184 | rmm_cbmc_gen_file_names(${OUT_FILE_NAME_PREFIX} "cbmc_viewer" "output" |
| 185 | cbmc_viewer_cmd_file cbmc_viewer_output_file cbmc_viewer_error_file) |
| 186 | set(CBMC_VIEWER_REPORT_DIR "${RMM_TESTBENCH_RESULT_DIR}/report_${entry_point}") |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 187 | |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 188 | set(goto_cc_cmd |
| 189 | ${RMM_GOTO_CC_PATH} |
| 190 | ${cbmc_compiler_options} |
| 191 | ${cbmc_defines_list} |
| 192 | "--function;${entry_point}" |
| 193 | "-o;${RMM_GOTO_PROG_NAME}" |
| 194 | ${RMM_IMP_INCS} |
| 195 | ${RMM_IMP_SRCS} |
| 196 | ${testbench_file} |
| 197 | ) |
| 198 | |
| 199 | set(cbmc_cmd |
| 200 | ${RMM_CBMC_PATH} |
| 201 | ${CBMC_UI_OPTION} |
| 202 | ${cbmc_flags_list} |
| 203 | ${cbmc_unwinds_list} |
| 204 | ${RMM_GOTO_PROG_NAME}) |
| 205 | |
| 206 | set(cbmc_prop_cmd |
| 207 | ${RMM_CBMC_PATH} |
| 208 | ${cbmc_flags_list} |
| 209 | "--xml-ui" |
| 210 | "--show-properties" |
| 211 | ${RMM_GOTO_PROG_NAME}) |
| 212 | |
| 213 | set(cbmc_viewer_cmd |
| 214 | "${RMM_CBMC_VIEWER_PATH}" |
| 215 | "--goto;${RMM_GOTO_PROG_NAME}" |
| 216 | "--result;${cbmc_output_file}" |
| 217 | "--property;${cbmc_prop_output_file}" |
| 218 | "--srcdir;${CMAKE_SOURCE_DIR}" |
| 219 | "--reportdir;${CBMC_VIEWER_REPORT_DIR}") |
| 220 | |
| 221 | # remove the absolute path making it relative (shorten the command line) |
| 222 | string (REPLACE "${SOURCE_DIR}/" "" goto_cc_cmd "${goto_cc_cmd}") |
| 223 | |
| 224 | normalise_cmd("${goto_cc_cmd}" GOTO_CC_CMD_STR) |
| 225 | normalise_cmd("${cbmc_cmd}" CBMC_CMD_STR) |
| 226 | |
| 227 | file(WRITE ${goto_cc_cmd_file} "${GOTO_CC_CMD_STR}") |
| 228 | file(WRITE ${cbmc_cmd_file} "${CBMC_CMD_STR}") |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 229 | |
| 230 | execute_process(COMMAND ${CMAKE_COMMAND} -E echo_append "CBMC: ${testbench_file}... ") |
| 231 | execute_process( |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 232 | COMMAND ${goto_cc_cmd} |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 233 | RESULT_VARIABLE res_var |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 234 | OUTPUT_FILE ${goto_cc_output_file} |
| 235 | ERROR_FILE ${goto_cc_error_file}) |
| 236 | if (NOT ${res_var} EQUAL "0") |
| 237 | message(FATAL_ERROR "Compiling testbench with goto-cc failed. For details see: ${goto_cc_error_file}") |
| 238 | endif() |
| 239 | |
| 240 | execute_process( |
| 241 | COMMAND ${cbmc_cmd} |
| 242 | RESULT_VARIABLE res_var |
| 243 | OUTPUT_FILE ${cbmc_output_file} |
| 244 | ERROR_FILE ${cbmc_error_file}) |
| 245 | |
| 246 | if(RMM_CBMC_VIEWER_OUTPUT) |
| 247 | normalise_cmd("${cbmc_prop_cmd}" CBMC_PROP_CMD_STR) |
| 248 | file(WRITE ${cbmc_prop_cmd_file} "${CBMC_PROP_CMD_STR}") |
| 249 | execute_process( |
| 250 | COMMAND ${cbmc_prop_cmd} |
| 251 | RESULT_VARIABLE res_var |
| 252 | OUTPUT_FILE ${cbmc_prop_output_file} |
| 253 | ERROR_FILE ${cbmc_prop_error_file}) |
| 254 | |
| 255 | normalise_cmd("${cbmc_viewer_cmd}" CBMC_VIEWER_CMD_STR) |
| 256 | file(WRITE ${cbmc_viewer_cmd_file} "${CBMC_VIEWER_CMD_STR}") |
| 257 | execute_process( |
| 258 | COMMAND ${cbmc_viewer_cmd} |
| 259 | RESULT_VARIABLE res_var |
| 260 | OUTPUT_FILE ${cbmc_viewer_output_file} |
| 261 | ERROR_FILE ${cbmc_viewer_error_file}) |
| 262 | if (NOT ${res_var} EQUAL "0") |
| 263 | message(FATAL_ERROR "Failed to run cbmc-viewer. For details see: ${goto_cc_error_file}") |
| 264 | endif() |
| 265 | endif() |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 266 | |
| 267 | execute_process(COMMAND ${CMAKE_COMMAND} -E echo "DONE") |
| 268 | |
Mate Toth-Pal | 0361dcb | 2023-11-29 10:20:12 +0100 | [diff] [blame] | 269 | rmm_cbmc_append_summary("${testbench_filename}" "${cbmc_output_file}" |
| 270 | "${CBMC_RESULT_FILE_SUFFIX}-${CBMC_OUT_FILE_ENDING}" |
| 271 | ${RMM_CBMC_SUMMARY_FIELD_WIDTH} ${RMM_TESTBENCH_RESULT_DIR} ${SUMMARY_FILE}) |
Mate Toth-Pal | 83a45bd | 2023-09-01 11:17:19 +0200 | [diff] [blame] | 272 | |
| 273 | endforeach() |
| 274 | message(STATUS "Result in ${RMM_TESTBENCH_RESULT_DIR}") |
Mate Toth-Pal | 7b875ea | 2023-11-15 16:59:19 +0100 | [diff] [blame] | 275 | |
| 276 | execute_process( |
| 277 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} |
| 278 | COMMAND ${CHECK_CBMC_SUMMARY_EXECUTABLE} |
| 279 | ${CMAKE_SOURCE_DIR}/tools/cbmc/testbenches_results/BASELINE.${CBMC_RESULT_FILE_SUFFIX} |
| 280 | ${RMM_TESTBENCH_RESULT_DIR}/${SUMMARY_FILE} |
| 281 | OUTPUT_VARIABLE CHECK_SUMMARY_OUTPUT |
| 282 | ERROR_VARIABLE CHECK_SUMMARY_ERROR |
| 283 | RESULT_VARIABLE CHECK_SUMMARY_RC |
| 284 | OUTPUT_STRIP_TRAILING_WHITESPACE |
| 285 | ) |
| 286 | |
| 287 | if (NOT ${CHECK_SUMMARY_RC} EQUAL "0") |
| 288 | message(WARNING |
| 289 | "cbmc-${CBMC_RESULT_FILE_SUFFIX}: FAILED\n${CHECK_SUMMARY_ERROR}") |
| 290 | else() |
| 291 | message(STATUS "cbmc-${CBMC_RESULT_FILE_SUFFIX}: PASSED") |
| 292 | endif() |