Path: blob/main/tests/integration_tests/functional/test_topology.py
1958 views
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.1# SPDX-License-Identifier: Apache-2.02"""Tests for ensuring correctness of CPU and cache topology in the guest."""34import os5import platform6import pytest7import framework.utils_cpuid as utils89TOPOLOGY_STR = {1: "0", 2: "0,1", 16: "0-15"}10PLATFORM = platform.machine()111213def _check_cpu_topology(test_microvm, expected_cpu_count,14expected_threads_per_core,15expected_cpus_list):16expected_cpu_topology = {17"CPU(s)": str(expected_cpu_count),18"On-line CPU(s) list": expected_cpus_list,19"Thread(s) per core": str(expected_threads_per_core),20"Core(s) per socket": str(21int(expected_cpu_count / expected_threads_per_core)),22"Socket(s)": "1",23"NUMA node(s)": "1"24}2526utils.check_guest_cpuid_output(test_microvm, "lscpu", None, ':',27expected_cpu_topology)282930def _check_cache_topology_x86(test_microvm, num_vcpus_on_lvl_1_cache,31num_vcpus_on_lvl_3_cache):32vm = test_microvm33expected_lvl_1_str = '{} ({})'.format(hex(num_vcpus_on_lvl_1_cache),34num_vcpus_on_lvl_1_cache)35expected_lvl_3_str = '{} ({})'.format(hex(num_vcpus_on_lvl_3_cache),36num_vcpus_on_lvl_3_cache)3738cpu_vendor = utils.get_cpu_vendor()39if cpu_vendor == utils.CpuVendor.AMD:40expected_level_1_topology = {41"level": '0x1 (1)',42"extra cores sharing this cache": expected_lvl_1_str43}44expected_level_3_topology = {45"level": '0x3 (3)',46"extra cores sharing this cache": expected_lvl_3_str47}48elif cpu_vendor == utils.CpuVendor.INTEL:49expected_level_1_topology = {50"cache level": '0x1 (1)',51"extra threads sharing this cache": expected_lvl_1_str,52}53expected_level_3_topology = {54"cache level": '0x3 (3)',55"extra threads sharing this cache": expected_lvl_3_str,56}5758utils.check_guest_cpuid_output(vm, "cpuid -1", "--- cache 0 ---", '=',59expected_level_1_topology)60utils.check_guest_cpuid_output(vm, "cpuid -1", "--- cache 1 ---", '=',61expected_level_1_topology)62utils.check_guest_cpuid_output(vm, "cpuid -1", "--- cache 2 ---", '=',63expected_level_1_topology)64utils.check_guest_cpuid_output(vm, "cpuid -1", "--- cache 3 ---", '=',65expected_level_3_topology)666768def _check_cache_topology_arm(test_microvm, no_cpus):69# We will check the cache topology by looking at what each cpu70# contains as far as cache info.71# For that we are iterating through the hierarchy of folders inside:72# /sys/devices/system/cpu/cpuX/cache/indexY/type - the type of the cache73# (i.e Instruction, Data, Unified)74# /sys/devices/system/cpu/cpuX/cache/indexY/size - size of the cache75# /sys/devices/system/cpu/cpuX/cache/indexY/level - L1, L2 or L3 cache.76# There are 2 types of L1 cache (instruction and data) that is why the77# "cache_info" variable below has 4 items.7879path = "/sys/devices/system/cpu/"8081cache_files = ["level", "type", "size",82"coherency_line_size", "number_of_sets"]8384for i in range(no_cpus):85cpu_path = os.path.join(os.path.join(path, 'cpu{}'.format(i)), "cache")86dirs = os.listdir(cpu_path)87for cache_level in dirs:88if "index" not in os.path.basename(cache_level):89continue90cache_path = os.path.join(cpu_path, cache_level)9192for cache_file in cache_files:93absolute_cache_file = os.path.join(cache_path, cache_file)94with open(absolute_cache_file, 'r') as file:95host_val = file.readline().strip()96guest_val = utils.read_guest_file(97test_microvm, absolute_cache_file98)99assert host_val == guest_val100101102@pytest.mark.skipif(103PLATFORM != "x86_64",104reason="Firecracker supports CPU topology only on x86_64."105)106@pytest.mark.parametrize(107"num_vcpus",108[1, 2, 16],109)110@pytest.mark.parametrize(111"htt",112[True, False],113)114def test_cpu_topology(test_microvm_with_ssh, network_config, num_vcpus, htt):115"""Check the CPU topology for a microvm with the specified config."""116vm = test_microvm_with_ssh117vm.spawn()118vm.basic_config(vcpu_count=num_vcpus, ht_enabled=htt)119_tap, _, _ = vm.ssh_network_config(network_config, '1')120vm.start()121122_check_cpu_topology(vm, num_vcpus, 2 if htt and num_vcpus > 1 else 1,123TOPOLOGY_STR[num_vcpus])124125126@pytest.mark.parametrize(127"num_vcpus",128[1, 2, 16],129)130@pytest.mark.parametrize(131"htt",132[True, False],133)134def test_cache_topology(test_microvm_with_ssh, network_config, num_vcpus, htt):135"""Check the cache topology for a microvm with the specified config."""136vm = test_microvm_with_ssh137vm.spawn()138vm.basic_config(vcpu_count=num_vcpus, ht_enabled=htt)139_tap, _, _ = vm.ssh_network_config(network_config, '1')140vm.start()141if PLATFORM == "x86_64":142_check_cache_topology_x86(vm, 1 if htt and num_vcpus > 1 else 0,143num_vcpus - 1)144elif PLATFORM == "aarch64":145_check_cache_topology_arm(vm, num_vcpus)146else:147raise Exception("This test is not run on this platform!")148149150