1fc7c144bSAni Sinha# Copyright (c) 2015, Intel Corporation 2fc7c144bSAni Sinha# All rights reserved. 3fc7c144bSAni Sinha# 4fc7c144bSAni Sinha# SPDX-License-Identifier: BSD-3-Clause 5fc7c144bSAni Sinha 6fc7c144bSAni Sinha# Redistribution and use in source and binary forms, with or without 7fc7c144bSAni Sinha# modification, are permitted provided that the following conditions are met: 8fc7c144bSAni Sinha# 9fc7c144bSAni Sinha# * Redistributions of source code must retain the above copyright notice, 10fc7c144bSAni Sinha# this list of conditions and the following disclaimer. 11fc7c144bSAni Sinha# * Redistributions in binary form must reproduce the above copyright notice, 12fc7c144bSAni Sinha# this list of conditions and the following disclaimer in the documentation 13fc7c144bSAni Sinha# and/or other materials provided with the distribution. 14fc7c144bSAni Sinha# * Neither the name of Intel Corporation nor the names of its contributors 15fc7c144bSAni Sinha# may be used to endorse or promote products derived from this software 16fc7c144bSAni Sinha# without specific prior written permission. 17fc7c144bSAni Sinha# 18fc7c144bSAni Sinha# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19fc7c144bSAni Sinha# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20fc7c144bSAni Sinha# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21fc7c144bSAni Sinha# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 22fc7c144bSAni Sinha# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23fc7c144bSAni Sinha# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24fc7c144bSAni Sinha# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25fc7c144bSAni Sinha# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26fc7c144bSAni Sinha# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27fc7c144bSAni Sinha# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28fc7c144bSAni Sinha 29fc7c144bSAni Sinha# This script runs only from the biosbits VM. 30fc7c144bSAni Sinha 31fc7c144bSAni Sinha"""SMI latency test.""" 32fc7c144bSAni Sinha 33fc7c144bSAni Sinhaimport bits 34fc7c144bSAni Sinhafrom collections import namedtuple 35fc7c144bSAni Sinhaimport testsuite 36fc7c144bSAni Sinhaimport time 37fc7c144bSAni Sinhaimport usb 38fc7c144bSAni Sinha 39fc7c144bSAni Sinhadef register_tests(): 40*b345ffadSAni Sinha pass 41*b345ffadSAni Sinha# testsuite.add_test("SMI latency test", smi_latency); 42*b345ffadSAni Sinha# testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False); 43fc7c144bSAni Sinha 44fc7c144bSAni Sinhadef smi_latency(): 45fc7c144bSAni Sinha MSR_SMI_COUNT = 0x34 46fc7c144bSAni Sinha 47fc7c144bSAni Sinha print "Warning: touching the keyboard can affect the results of this test." 48fc7c144bSAni Sinha 49fc7c144bSAni Sinha tsc_per_sec = bits.tsc_per_sec() 50fc7c144bSAni Sinha tsc_per_usec = tsc_per_sec / (1000 * 1000) 51fc7c144bSAni Sinha bins = [long(tsc_per_usec * 10**i) for i in range(9)] 52fc7c144bSAni Sinha bin_descs = [ 53fc7c144bSAni Sinha "0 < t <= 1us", 54fc7c144bSAni Sinha "1us < t <= 10us", 55fc7c144bSAni Sinha "10us < t <= 100us", 56fc7c144bSAni Sinha "100us < t <= 1ms", 57fc7c144bSAni Sinha "1ms < t <= 10ms", 58fc7c144bSAni Sinha "10ms < t <= 100ms", 59fc7c144bSAni Sinha "100ms < t <= 1s ", 60fc7c144bSAni Sinha "1s < t <= 10s ", 61fc7c144bSAni Sinha "10s < t <= 100s ", 62fc7c144bSAni Sinha "100s < t ", 63fc7c144bSAni Sinha ] 64fc7c144bSAni Sinha 65fc7c144bSAni Sinha print "Starting test. Wait here, I will be back in 15 seconds." 66fc7c144bSAni Sinha (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins) 67fc7c144bSAni Sinha BinType = namedtuple('BinType', ("max", "total", "count", "times")) 68fc7c144bSAni Sinha bins = [BinType(*b) for b in bins] 69fc7c144bSAni Sinha 70fc7c144bSAni Sinha testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150) 71fc7c144bSAni Sinha if not testsuite.show_detail(): 72fc7c144bSAni Sinha return 73fc7c144bSAni Sinha 74fc7c144bSAni Sinha for bin, desc in zip(bins, bin_descs): 75fc7c144bSAni Sinha if bin.count == 0: 76fc7c144bSAni Sinha continue 77fc7c144bSAni Sinha testsuite.print_detail("{}; average = {}; count = {}".format(desc, bits.format_tsc(bin.total/bin.count), bin.count)) 78fc7c144bSAni Sinha deltas = (bits.format_tsc(t2 - t1) for t1,t2 in zip(bin.times, bin.times[1:])) 79fc7c144bSAni Sinha testsuite.print_detail(" Times between first few observations: {}".format(" ".join("{:>6}".format(delta) for delta in deltas))) 80fc7c144bSAni Sinha 81fc7c144bSAni Sinha if smi_count_delta is not None: 82fc7c144bSAni Sinha testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format(smi_count_delta, MSR_SMI_COUNT)) 83fc7c144bSAni Sinha 84fc7c144bSAni Sinha testsuite.print_detail("Summary of impact: observed maximum latency = {}".format(bits.format_tsc(max_latency))) 85fc7c144bSAni Sinha 86fc7c144bSAni Sinhadef test_with_usb_disabled(): 87fc7c144bSAni Sinha if usb.handoff_to_os(): 88fc7c144bSAni Sinha smi_latency() 89fc7c144bSAni Sinha 90fc7c144bSAni Sinhadef average_io_smi(port, value, count): 91fc7c144bSAni Sinha def f(): 92fc7c144bSAni Sinha tsc_start = bits.rdtsc() 93fc7c144bSAni Sinha bits.outb(port, value) 94fc7c144bSAni Sinha return bits.rdtsc() - tsc_start 95fc7c144bSAni Sinha counts = [f() for i in range(count)] 96fc7c144bSAni Sinha return sum(counts)/len(counts) 97fc7c144bSAni Sinha 98fc7c144bSAni Sinhadef time_io_smi(port=0xb2, value=0, count=1000): 99fc7c144bSAni Sinha count_for_estimate = 10 100fc7c144bSAni Sinha start = time.time() 101fc7c144bSAni Sinha average_io_smi(port, value, count_for_estimate) 102fc7c144bSAni Sinha avg10 = time.time() - start 103fc7c144bSAni Sinha estimate = avg10 * count/count_for_estimate 104fc7c144bSAni Sinha if estimate > 1: 105fc7c144bSAni Sinha print "Running test, estimated time: {}s".format(int(estimate)) 106fc7c144bSAni Sinha average = average_io_smi(port, value, count) 107fc7c144bSAni Sinha print "Average of {} SMIs (via outb, port={:#x}, value={:#x}): {}".format(count, port, value, bits.format_tsc(average)) 108