From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 7454DA3160 for ; Sat, 12 Oct 2019 07:47:43 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4D0771EB83; Sat, 12 Oct 2019 07:47:43 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id C87571EB82 for ; Sat, 12 Oct 2019 07:47:40 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Oct 2019 22:47:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.67,286,1566889200"; d="scan'208";a="346236732" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by orsmga004.jf.intel.com with ESMTP; 11 Oct 2019 22:47:39 -0700 Received: from FMSMSX110.amr.corp.intel.com (10.18.116.10) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 11 Oct 2019 22:47:39 -0700 Received: from shsmsx106.ccr.corp.intel.com (10.239.4.159) by fmsmsx110.amr.corp.intel.com (10.18.116.10) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 11 Oct 2019 22:47:38 -0700 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.96]) by SHSMSX106.ccr.corp.intel.com ([169.254.10.119]) with mapi id 14.03.0439.000; Sat, 12 Oct 2019 13:47:37 +0800 From: "Tu, Lijuan" To: "Mo, YufengX" , "dts@dpdk.org" , "Yao, Lei A" CC: "Mo, YufengX" Thread-Topic: [dts] [PATCH V1 1/1] tests/power_pbf: upload automation script Thread-Index: AQHVdPmvbSRpG8U4H0yTtZt7gpGSIadWlxmw Date: Sat, 12 Oct 2019 05:47:36 +0000 Message-ID: <8CE3E05A3F976642AAB0F4675D0AD20E0BB3EAE4@SHSMSX101.ccr.corp.intel.com> References: <20190927060730.12852-1-yufengx.mo@intel.com> <20190927060730.12852-2-yufengx.mo@intel.com> In-Reply-To: <20190927060730.12852-2-yufengx.mo@intel.com> Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiN2VlZjhjYmQtZmM2OC00MWNiLWFlYWEtYzIwZDZlMWZkZmQ3IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiZ0RcL2lMZHJPR2phTmRwY09ZV0lxTVhtWm41bGdaWGRUR0ZaVDd3ZERYSzlROFM3aXVNUTEwZlBTdXdJNXJMUTgifQ== x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dts] [PATCH V1 1/1] tests/power_pbf: upload automation script X-BeenThere: dts@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: test suite reviews and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dts-bounces@dpdk.org Sender: "dts" Applied, thanks > -----Original Message----- > From: dts [mailto:dts-bounces@dpdk.org] On Behalf Of yufengmx > Sent: Friday, September 27, 2019 2:08 PM > To: dts@dpdk.org; Yao, Lei A > Cc: Mo, YufengX > Subject: [dts] [PATCH V1 1/1] tests/power_pbf: upload automation script >=20 >=20 > Priority Base Frequency is new power feature on some Intel CPU SKU. This > feature can support some core in core list have garenteed higher base > frequency DPDK start support this feafure from 19.05 >=20 > Signed-off-by: yufengmx > --- > tests/TestSuite_power_pbf.py | 620 > +++++++++++++++++++++++++++++++++++ > 1 file changed, 620 insertions(+) > create mode 100644 tests/TestSuite_power_pbf.py >=20 > diff --git a/tests/TestSuite_power_pbf.py b/tests/TestSuite_power_pbf.py > new file mode 100644 index 0000000..fb4cf1a > --- /dev/null > +++ b/tests/TestSuite_power_pbf.py > @@ -0,0 +1,620 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2010-2019 Intel Corporation. All rights reserved. > +# All rights reserved. > +# > +# Redistribution and use in source and binary forms, with or without # > +modification, are permitted provided that the following conditions # > +are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS # > +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > # > +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > FOR # > +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT # > +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, # > +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > NOT # > +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > USE, # > +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND > ON ANY # > +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > # > +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF > THE USE # > +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + > +import os > +import time > +import random > +import json > +import re > +import shutil > +from collections import Counter > +from pprint import pformat > + > +# import dts libs > +from test_case import TestCase > +from utils import create_mask > + > + > +class TestPowerPbf(TestCase): > + > + def timestamp(self): > + curTime =3D time.localtime() > + timestamp =3D "%04d%02d%02d_%02d-%02d-%02d" % ( > + curTime.tm_year, curTime.tm_mon, curTime.tm_mday, > + curTime.tm_hour, curTime.tm_min, curTime.tm_sec) > + return timestamp > + > + @property > + def target_dir(self): > + target_dir =3D '/root' + self.dut.base_dir[1:] \ > + if self.dut.base_dir.startswith('~') else \ > + self.dut.base_dir > + return target_dir > + > + @property > + def output_path(self): > + suiteName =3D self.__class__.__name__[4:].lower() > + if self.logger.log_path.startswith(os.sep): > + output_path =3D os.path.join(self.logger.log_path, suiteName= ) > + else: > + cur_path =3D os.path.dirname( > + os.path.dirname(os.path.realpath(__file__))) > + output_path =3D os.path.join( > + cur_path, self.logger.log_path, suiteName) > + if not os.path.exists(output_path): > + os.makedirs(output_path) > + > + return output_path > + > + def get_console(self, name): > + if name =3D=3D 'dut': > + console =3D self.dut.send_expect > + msg_pipe =3D self.dut.get_session_output > + elif name =3D=3D 'dut_alt': > + console =3D self.dut.alt_session.send_expect > + msg_pipe =3D self.dut.alt_session.session.get_output_all > + return console, msg_pipe > + > + def execute_cmds(self, cmds, con_name=3D'dut'): > + console, msg_pipe =3D self.get_console(con_name) > + if len(cmds) =3D=3D 0: > + return > + if isinstance(cmds, (str, unicode)): > + cmds =3D [cmds, '# ', 5] > + if not isinstance(cmds[0], list): > + cmds =3D [cmds] > + outputs =3D [] if len(cmds) > 1 else '' > + for item in cmds: > + expected_items =3D item[1] > + if expected_items and isinstance(expected_items, (list, tupl= e)): > + check_output =3D True > + expected_str =3D expected_items[0] or '# ' > + else: > + check_output =3D False > + expected_str =3D expected_items or '# ' > + > + try: > + if len(item) =3D=3D 3: > + timeout =3D int(item[2]) > + output =3D console(item[0], expected_str, timeout) > + output =3D msg_pipe() if not output else output > + else: > + output =3D console(item[0], expected_str) > + output =3D msg_pipe() if not output else output > + except Exception as e: > + msg =3D "execute '{0}' timeout".format(item[0]) > + raise Exception(msg) > + time.sleep(1) > + if len(cmds) > 1: > + outputs.append(output) > + else: > + outputs =3D output > + time.sleep(2) > + return outputs > + > + def d_console(self, cmds): > + return self.execute_cmds(cmds, con_name=3D'dut') > + > + def d_a_console(self, cmds): > + return self.execute_cmds(cmds, con_name=3D'dut_alt') > + > + def get_cores_mask(self, config=3D'all'): > + sockets =3D [self.dut.get_numa_id(index) for index in self.dut_p= orts] > + socket_count =3D Counter(sockets) > + port_socket =3D socket_count.keys()[0] if len(socket_count) =3D= =3D 1 else -1 > + mask =3D create_mask(self.dut.get_core_list(config, socket=3Dpor= t_socket)) > + return mask > + > + def prepare_binary(self, name): > + example_dir =3D "examples/" + name > + out =3D self.dut.build_dpdk_apps('./' + example_dir) > + self.verify("Error" not in out, "Compilation error") > + self.verify("No such" not in out, "Compilation error") > + binary_dir =3D os.path.join(self.target_dir, example_dir, 'build= ') > + cmd =3D ["ls -F {0} | grep '*'".format(binary_dir), '# ', 5] > + exec_file =3D self.d_a_console(cmd) > + binary_file =3D os.path.join(binary_dir, exec_file[:-1]) > + return binary_file > + > + def create_powermonitor_folder(self): > + cmd =3D 'mkdir -p {0}; chmod 777 {0}'.format('/tmp/powermonitor'= ) > + self.d_console(cmd) > + > + def init_test_binary_file(self): > + self.create_powermonitor_folder() > + # open debug SW > + cmd =3D ("sed -i -e 's/" > + "CONFIG_RTE_LIBRTE_POWER_DEBUG=3Dn$/" > + "CONFIG_RTE_LIBRTE_POWER_DEBUG=3Dy/" > + "' {0}/config/common_base").format(self.target_dir) > + self.d_a_console(cmd) > + self.dut.skip_setup =3D False > + self.dut.build_install_dpdk(self.target) > + # set up vm power management binary process setting > + self.vm_power_mgr =3D self.prepare_binary('vm_power_manager') > + # set up distributor binary process setting > + self.distributor =3D self.prepare_binary('distributor') > + > + def start_vm_power_mgr(self): > + bin_file =3D os.sep.join([self.target_dir, '']) > + config =3D "1S/4C/1T" > + eal_option =3D '-c {0} -n {1} --file-prefix=3Dvmpower --no-pci'.= format( > + self.get_cores_mask(config), > + self.memory_channels) > + prompt =3D 'vmpower>' > + cmd =3D [' '.join([self.vm_power_mgr, eal_option]), prompt, 30] > + output =3D self.d_console(cmd) > + return output > + > + def close_vm_power_mgr(self): > + output =3D self.d_console('quit') > + return output > + > + def start_distributor(self, high_core_num=3D1): > + cores_mask, high_freq_cores =3D self.get_high_freq_core_mask( > + high_core_num) > + eal_option =3D ' -c {0} -n {1} -- -p 0x1'.format( > + cores_mask, self.memory_channels) > + prompt =3D 'Distributor thread' > + cmd =3D [' '.join([self.distributor, eal_option]), prompt, 30] > + output =3D self.d_console(cmd) > + return high_freq_cores, output > + > + def close_distributor(self): > + cmds =3D ['killall distributor_app', '# ', 10] > + output =3D self.d_a_console(cmds) > + return output > + > + def __preset_single_core_json_cmd(self, core_index, unit, name): > + command =3D { > + "instruction": { > + # name of the vm or host > + "name": name, > + "command": "power", > + "unit": unit, }} > + # generate json data file and scp it to dut target source code f= older > + json_name =3D 'command_{}.json'.format(core_index) > + json_file =3D os.sep.join([self.output_path, json_name]) > + with open(json_file, 'w') as fp: > + json.dump(command, fp, indent=3D4, separators=3D(',', ': '), > + encoding=3D"utf-8", sort_keys=3DTrue) > + fp.write(os.linesep) > + self.dut.session.copy_file_to(json_file, self.target_dir) > + # save a backup json file to retrace test command > + backup_file =3D json_file + self.timestamp() > + shutil.move(json_file, backup_file) > + # send action JSON file to vm_power_mgr's fifo channel > + cmd =3D 'cat {0}/{2} > /tmp/powermonitor/fifo{1}'.format( > + self.target_dir, core_index, json_name) > + > + return cmd > + > + def send_json_command(self, cores, unit, name=3D'policy1'): > + if type(cores) =3D=3D int: > + _cores =3D [cores] > + elif type(cores) =3D=3D list: > + _cores =3D cores[:] > + else: > + msg =3D 'not support input cores type' > + self.verify(False, msg) > + > + cmds =3D [] > + for core_index in _cores: > + cmds.append( > + self.__preset_single_core_json_cmd(core_index, unit, nam= e)) > + self.d_a_console(';'.join(cmds)) > + > + def get_core_cur_freq(self, core_index): > + cpu_attr =3D r'/sys/devices/system/cpu/cpu{0}/cpufreq/scaling_cu= r_freq' > + cmd =3D 'cat ' + cpu_attr.format(core_index) > + output =3D self.d_a_console(cmd) > + return int(output) > + > + def get_core_scaling_max_freq(self, core_index): > + cpu_attr =3D > r'/sys/devices/system/cpu/cpu{0}/cpufreq/scaling_max_freq' > + cmd =3D 'cat ' + cpu_attr.format(core_index) > + output =3D self.d_a_console(cmd) > + return int(output) > + > + def get_core_scaling_min_freq(self, core_index): > + cpu_attr =3D > r'/sys/devices/system/cpu/cpu{0}/cpufreq/scaling_min_freq' > + cmd =3D 'cat ' + cpu_attr.format(core_index) > + output =3D self.d_a_console(cmd) > + return int(output) > + > + def get_core_scaling_base_freq(self, core_index): > + cpu_attr =3D r'/sys/devices/system/cpu/cpu{0}/cpufreq/base_frequ= ency' > + cmd =3D 'cat ' + cpu_attr.format(core_index) > + output =3D self.d_a_console(cmd) > + return int(output) > + > + @property > + def is_support_pbf(self): > + # check if cpu support bpf feature > + cpu_attr =3D r'/sys/devices/system/cpu/cpu0/cpufreq/base_frequen= cy' > + cmd =3D "ls {0}".format(cpu_attr) > + self.d_a_console(cmd) > + cmd =3D "echo $?" > + output =3D self.d_a_console(cmd) > + ret =3D True if output =3D=3D "0" else False > + return ret > + > + def get_sys_power_driver(self): > + drv_file =3D r"/sys/devices/system/cpu/cpu0/cpufreq/scaling_driv= er" > + output =3D self.d_a_console('cat ' + drv_file) > + if not output: > + msg =3D 'unknown power driver' > + self.verify(False, msg) > + drv_name =3D output.splitlines()[0].strip() > + return drv_name > + > + def get_all_cpu_attrs(self): > + ''' get all cpus' base_frequency value ''' > + key_values =3D ['base_frequency', > + 'cpuinfo_max_freq', > + 'cpuinfo_min_freq'] > + freq =3D r'/sys/devices/system/cpu/cpu{0}/cpufreq/{1}'.format > + # use dut alt session to get dut platform cpu base frequency att= ribute > + cpu_topos =3D self.dut.get_all_cores() > + cpu_info =3D {} > + for cpu_topo in cpu_topos: > + cpu_id =3D int(cpu_topo['thread']) > + cpu_info[cpu_id] =3D {} > + cpu_info[cpu_id]['socket'] =3D cpu_topo['socket'] > + cpu_info[cpu_id]['core'] =3D cpu_topo['core'] > + > + for key_value in key_values: > + cmds =3D [] > + for cpu_id in sorted(cpu_info.keys()): > + cmds.append('cat {0}'.format(freq(cpu_id, key_value))) > + output =3D self.d_a_console(';'.join(cmds)) > + freqs =3D [int(item) for item in output.splitlines()] > + for index, cpu_id in enumerate(sorted(cpu_info.keys())): > + cpu_info[cpu_id][key_value] =3D freqs[index] > + > + # get high priority core and normal core > + base_freqs_info =3D {} > + for core_index, value in cpu_info.iteritems(): > + base_frequency =3D value.get('base_frequency') > + base_freqs_info.setdefault(base_frequency, []).append(core_i= ndex) > + base_freqs =3D base_freqs_info.keys() > + # cpu should have high priority core and normal core > + # high priority core frequency is higher than normal core freque= ncy > + if len(base_freqs) <=3D 1 or \ > + not all([len(value) for value in base_freqs_info.values()]): > + msg =3D 'current cpu has no high priority core' > + raise Exception(msg) > + > + return cpu_info, base_freqs_info > + > + def get_normal_cores_index(self): > + ''' get one random normal core index, ignore core 0 ''' > + normal_freq =3D min(self.base_freqs_info.keys()) > + cores_index =3D self.base_freqs_info[normal_freq][1:] \ > + if self.base_freqs_info[normal_freq][0] =3D=3D 0 else \ > + self.base_freqs_info[normal_freq] > + return cores_index > + > + def get_high_freq_cores_index(self, number=3D1): > + ''' get one random high frequency core index, ignore core 0 ''' > + high_freq =3D max(self.base_freqs_info.keys()) > + cores_index =3D self.base_freqs_info[high_freq][1:number] \ > + if self.base_freqs_info[high_freq][0] =3D=3D 0 else \ > + self.base_freqs_info[high_freq][:number] > + return cores_index > + > + def get_high_freq_core_mask(self, number=3D1, min_cores=3D5): > + index_list =3D [] > + # get high frequency core first > + cores_index =3D self.get_high_freq_cores_index(number) > + [index_list.append(core_index) for core_index in cores_index] > + high_freq_cores =3D index_list[:] > + # get normal cores to make sure minimum cores are enough > + cores_index =3D self.get_normal_cores_index() > + for core_index in cores_index: > + if core_index in index_list: > + continue > + index_list.append(core_index) > + if len(index_list) >=3D min_cores: > + break > + # create core mask > + cores_mask =3D create_mask(index_list) > + return cores_mask, high_freq_cores > + > + def parse_vm_power_cores_freq(self, output): > + ''' get vm power management cores frequency ''' > + pat_begin =3D ( > + 'POWER: power_set_governor_performance: Power management ' > + 'governor of lcore (\\d+) is already performance') > + pat_end =3D \ > + 'POWER: Initialized successfully for lcore (\\d+) power mana= gement' > + pat_freq =3D ( > + 'POWER: power_get_available_freqs: ' > + 'sys min (\\d+), sys max (\\d+), base_max (\\d+)') > + cores_info =3D {} > + flag =3D False > + core_id =3D None > + for line in output.splitlines(): > + # if core output begin message > + result =3D re.findall(pat_begin, line) > + if result: > + core_id =3D int(result[0]) > + flag =3D True > + if flag: > + result =3D re.findall(pat_freq, line) > + if result and len(result[0]) =3D=3D 3: > + cores_info[core_id] =3D {} > + cores_info[core_id]['cpuinfo_min_freq'] =3D result[0= ][0] > + cores_info[core_id]['cpuinfo_max_freq'] =3D result[0= ][1] > + cores_info[core_id]['base_frequency'] =3D result[0][= 2] > + # if core output last message > + result =3D re.findall(pat_end, line) > + if result: > + core_id =3D None > + flag =3D False > + return cores_info > + > + def check_core_freq_for_unit(self, unit, core_index, ref_freq_name): > + msg =3D ("begin verify core <{0}> command <{1}> action ...").for= mat( > + core_index, unit) > + self.logger.info(msg) > + self.send_json_command(core_index, unit) > + expected_freq =3D self.cpu_info[core_index].get(ref_freq_name) > + max_freq =3D self.get_core_scaling_max_freq(core_index) > + min_freq =3D self.get_core_scaling_min_freq(core_index) > + msg =3D 'max freq<{0}>/min_freq<{1}>/expected freq<{2}> are not = the > same' > + self.verify( > + max_freq =3D=3D min_freq and max_freq =3D=3D expected_freq, > + msg.format(max_freq, min_freq, expected_freq)) > + msg =3D ("core <{0}> command <{1}> action is ok").format( > + core_index, unit) > + self.logger.info(msg) > + > + def verify_high_priority_core(self): > + # run vm power binary file > + output =3D self.start_vm_power_mgr() > + self.close_vm_power_mgr() > + # parse output message > + cores_info =3D self.parse_vm_power_cores_freq(output) > + # get high priority core and normal core > + base_freqs_info =3D {} > + for core_index, value in cores_info.iteritems(): > + base_frequency =3D value.get('base_frequency') > + base_freqs_info.setdefault(base_frequency, []).append(core_i= ndex) > + base_freqs =3D base_freqs_info.keys() > + # cpu should have high priority core and normal core > + # high priority core frequency is higher than normal core freque= ncy > + if len(base_freqs) <=3D 1 or \ > + not all([len(value) for value in base_freqs_info.values()]): > + msg =3D 'current cpu has no high priority core' > + raise Exception(msg) > + > + def verify_high_priority_core_min_max_freq(self): > + ''' > + random select one high priority core to run testing > + Send different command to power sample: > + Command Steps: > + ENABLE_TURBO > + SCALE_MAX > + SCALE_DOWN > + SCALE_MIN > + Check the CPU frequency is changed accordingly in this list > + ''' > + try: > + self.start_vm_power_mgr() > + # random select one high priority core to run testing > + core_index =3D self.get_high_freq_cores_index()[0] > + # Enable turbo Boost for this core > + self.send_json_command(core_index, 'ENABLE_TURBO') > + # these test items sequence can't changed > + test_items =3D [ > + # Scale frequency of this core to maximum > + ["SCALE_MAX", core_index, 'cpuinfo_max_freq'], > + # Scale down frequency of this core > + ["SCALE_DOWN", core_index, 'base_frequency'], > + # Scale frequency of this core to minimum > + ["SCALE_MIN", core_index, 'cpuinfo_min_freq'], > + ] > + # test cpu core frequency change with unit command > + for test_item in test_items: > + self.check_core_freq_for_unit(*test_item) > + self.close_vm_power_mgr() > + except Exception as e: > + self.close_vm_power_mgr() > + raise Exception(e) > + > + def verify_high_priority_core_turbo_status(self): > + ''' > + Send different command to power sample: > + Command Steps: > + ENABLE_TURBO > + SCALE_MAX > + ENABLE_TURBO > + Check the CPU frequency is changed accordingly in this list > + ''' > + try: > + self.start_vm_power_mgr() > + # random select one high priority core to run testing > + core_index =3D self.get_high_freq_cores_index()[0] > + # Enable Turbo Boost for this core > + self.send_json_command(core_index, 'ENABLE_TURBO') > + # Scale frequency of this core to maximum > + test_items =3D [ > + ["SCALE_MAX", core_index, 'cpuinfo_max_freq'], > + ["DISABLE_TURBO", core_index, 'base_frequency'], ] > + # test cpu core frequency change with unit command > + for test_item in test_items: > + self.check_core_freq_for_unit(*test_item) > + self.close_vm_power_mgr() > + except Exception as e: > + self.close_vm_power_mgr() > + raise Exception(e) > + > + def verify_distributor_high_priority_core(self): > + ''' > + check distributor example use high priority core as distribute c= ore > + ''' > + try: > + high_freq_cores, output =3D self.start_distributor() > + self.close_distributor() > + expected_str =3D "Distributor on priority core {0}".format( > + high_freq_cores[0]) > + self.verify(expected_str in output, > + "'{}' not display".format(expected_str)) > + except Exception as e: > + self.close_distributor() > + raise Exception(e) > + > + def verify_distributor_high_priority_core_txrx(self): > + ''' > + check distributor sample will use high priority core for > + distribute core and rx/tx core > + ''' > + try: > + high_freq_cores, output =3D self.start_distributor(3) > + self.close_distributor() > + # check the high priority core are assigned as rx core in lo= g > + pat =3D 'Core (\\d+) doing packet RX.' > + result =3D re.findall(pat, output, re.M) > + if len(result) =3D=3D 1: > + core_index =3D int(result[0]) > + else: > + msg =3D "haven't catch expected RX core" > + self.verify(False, msg) > + msg =3D "No high frequency core doing packet RX" > + self.verify(core_index in high_freq_cores, msg) > + # Check the high priority core are assigned as tx core in lo= g > + pat =3D 'Core (\\d+) doing packet TX.' > + result =3D re.findall(pat, output, re.M) > + if len(result) =3D=3D 1: > + core_index =3D int(result[0]) > + else: > + msg =3D "haven't catch expected TX core" > + self.verify(False, msg) > + msg =3D "No high frequency core doing packet TX" > + self.verify(core_index in high_freq_cores, msg) > + # check the high priority core is assigned as distributor co= re in > + # log > + pat =3D r'Core (\\d+) acting as distributor core.' > + result =3D re.findall(pat, output, re.M) > + if len(result) =3D=3D 1: > + core_index =3D int(result[0]) > + else: > + msg =3D "haven't catch expected distributor core" > + self.verify(False, msg) > + msg =3D "No high frequency core acting as distributor core" > + self.verify(core_index in high_freq_cores, msg) > + except Exception as e: > + self.close_distributor() > + raise Exception(e) > + > + def verify_pbf_supported(self): > + if self.is_support_pbf: > + return > + msg =3D "dut cpu doesn't support power pbf feature" > + raise Exception(msg) > + > + def verify_power_driver(self): > + power_drv =3D self.get_sys_power_driver() > + msg =3D "power pstate should work with intel_pstate driver" > + self.verify(power_drv =3D=3D 'intel_pstate', msg) > + # > + # Test cases. > + # > + > + def set_up_all(self): > + """ > + Run before each test suite > + """ > + self.verify_power_driver() > + # get ports information > + self.dut_ports =3D self.dut.get_ports() > + self.verify(len(self.dut_ports) >=3D 1, "Insufficient ports") > + # get dut node cores information > + self.d_a_console('modprobe msr') > + self.dut.init_core_list_uncached_linux() > + # check if cpu support bpf feature > + self.verify_pbf_supported() > + self.cpu_info, self.base_freqs_info =3D self.get_all_cpu_attrs() > + self.logger.info(pformat(self.cpu_info)) > + self.logger.info(pformat(self.base_freqs_info)) > + self.memory_channels =3D self.dut.get_memory_channels() > + self.init_test_binary_file() > + > + def set_up(self): > + """ > + Run before each test case. > + """ > + pass > + > + def tear_down(self): > + """ > + Run after each test case. > + """ > + pass > + > + def tear_down_all(self): > + """ > + Run after each test suite. > + """ > + pass > + > + def test_high_priority_core(self): > + ''' > + check high priority core can be recognized by power lib > + ''' > + self.verify_high_priority_core() > + > + def test_high_priority_core_min_max_freq(self): > + ''' > + set cpu min and max frequency test for the high priority core > + ''' > + self.verify_high_priority_core_min_max_freq() > + > + def test_high_priority_core_turbo_status(self): > + ''' > + check "DISABLE_TURBO" Action when core is in turbo status for > + high priority core > + ''' > + self.verify_high_priority_core_turbo_status() > + > + def test_distributor_high_priority_core(self): > + ''' > + check distributor sample use high priority core as distribute co= re > + ''' > + self.verify_distributor_high_priority_core() > + > + def test_distributor_high_priority_core_txrx(self): > + ''' > + check distributor sample will use high priority core for distrib= ute > + core and rx/tx core > + ''' > + self.verify_distributor_high_priority_core_txrx() > -- > 2.21.0