| #!/usr/bin/env python3 |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Copyright (c) 2025 Intel Corporation |
| # |
| # Test for indirect target selection (ITS) cmdline permutations with other bugs |
| # like spectre_v2 and retbleed. |
| |
| import os, sys, subprocess, itertools, re, shutil |
| |
| test_dir = os.path.dirname(os.path.realpath(__file__)) |
| sys.path.insert(0, test_dir + '/../../kselftest') |
| import ksft |
| import common as c |
| |
| bug = "indirect_target_selection" |
| mitigation = c.get_sysfs(bug) |
| |
| if not mitigation or "Not affected" in mitigation: |
| ksft.test_result_skip("Skipping its_permutations.py: not applicable") |
| ksft.finished() |
| |
| if shutil.which('vng') is None: |
| ksft.test_result_skip("Skipping its_permutations.py: virtme-ng ('vng') not found in PATH.") |
| ksft.finished() |
| |
| TEST = f"{test_dir}/its_sysfs.py" |
| default_kparam = ['clearcpuid=hypervisor', 'panic=5', 'panic_on_warn=1', 'oops=panic', 'nmi_watchdog=1', 'hung_task_panic=1'] |
| |
| DEBUG = " -v " |
| |
| # Install dependencies |
| # https://github.com/arighi/virtme-ng |
| # apt install virtme-ng |
| BOOT_CMD = f"vng --run {test_dir}/../../../../../arch/x86/boot/bzImage " |
| #BOOT_CMD += DEBUG |
| |
| bug = "indirect_target_selection" |
| |
| input_options = { |
| 'indirect_target_selection' : ['off', 'on', 'stuff', 'vmexit'], |
| 'retbleed' : ['off', 'stuff', 'auto'], |
| 'spectre_v2' : ['off', 'on', 'eibrs', 'retpoline', 'ibrs', 'eibrs,retpoline'], |
| } |
| |
| def pretty_print(output): |
| OKBLUE = '\033[94m' |
| OKGREEN = '\033[92m' |
| WARNING = '\033[93m' |
| FAIL = '\033[91m' |
| ENDC = '\033[0m' |
| BOLD = '\033[1m' |
| |
| # Define patterns and their corresponding colors |
| patterns = { |
| r"^ok \d+": OKGREEN, |
| r"^not ok \d+": FAIL, |
| r"^# Testing .*": OKBLUE, |
| r"^# Found: .*": WARNING, |
| r"^# Totals: .*": BOLD, |
| r"pass:([1-9]\d*)": OKGREEN, |
| r"fail:([1-9]\d*)": FAIL, |
| r"skip:([1-9]\d*)": WARNING, |
| } |
| |
| # Apply colors based on patterns |
| for pattern, color in patterns.items(): |
| output = re.sub(pattern, lambda match: f"{color}{match.group(0)}{ENDC}", output, flags=re.MULTILINE) |
| |
| print(output) |
| |
| combinations = list(itertools.product(*input_options.values())) |
| ksft.print_header() |
| ksft.set_plan(len(combinations)) |
| |
| logs = "" |
| |
| for combination in combinations: |
| append = "" |
| log = "" |
| for p in default_kparam: |
| append += f' --append={p}' |
| command = BOOT_CMD + append |
| test_params = "" |
| for i, key in enumerate(input_options.keys()): |
| param = f'{key}={combination[i]}' |
| test_params += f' {param}' |
| command += f" --append={param}" |
| command += f" -- {TEST}" |
| test_name = f"{bug} {test_params}" |
| pretty_print(f'# Testing {test_name}') |
| t = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| t.wait() |
| output, _ = t.communicate() |
| if t.returncode == 0: |
| ksft.test_result_pass(test_name) |
| else: |
| ksft.test_result_fail(test_name) |
| output = output.decode() |
| log += f" {output}" |
| pretty_print(log) |
| logs += output + "\n" |
| |
| # Optionally use tappy to parse the output |
| # apt install python3-tappy |
| with open("logs.txt", "w") as f: |
| f.write(logs) |
| |
| ksft.finished() |