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