def test(residency_tests, residency_counter_msr, residency_counters): cpus = bits.cpus() for states, hint in residency_tests: with bits.mwait.use_hint(hint): delta = residency(residency_counters, residency_counter_msr) detail = False for state in states: for apic_id, r in sorted(delta.iteritems()): state_residency = getattr(r, state) testsuite.test( "MWAIT hint {:#x}, socket {} {} residency {:4.0%} (expected >= 85%)" .format(hint, bits.socket_index(apic_id), state.upper(), state_residency), state_residency >= 0.85) detail = detail or testsuite.show_detail() if detail: print testsuite.format_detail( "Full residency for MWAIT hint {:#x}:".format(hint)) print testsuite.format_detail(" SKT APIC" + "".join( "{:>6s}".format(field.upper()) for field in residency_counters._fields)) for apic_id, r in sorted(delta.iteritems()): skt_index = bits.socket_index(apic_id) print testsuite.format_detail( "{:4d} {:#04x} ".format(skt_index, apic_id) + " ".join("{:4.0%}".format(field) for field in r))
def rdmsr_consistent(msr_blacklist=set(), msr_masklist=dict()): """Rdmsr for all CPU and verify consistent value""" cpulist = sorted(bits.cpus()) for r in [range(0, 0x1000), range(0xC0000000, 0xC0001000)]: for msr in r: if msr in msr_blacklist: continue mask = msr_masklist.get(msr, ~0) uniques = {} for cpu in cpulist: value = bits.rdmsr(cpu, msr) if value is not None: value &= mask uniques.setdefault(value, []).append(cpu) testsuite.test("MSR 0x{0:x} consistent".format(msr), len(uniques) == 1) # Avoid doing any extra work formatting output when not necessary if testsuite.show_detail(): testsuite.print_detail("{0} unique values".format(len(uniques))) for value, cpus in uniques.iteritems(): testsuite.print_detail("{0} CPUs: {1}".format(len(cpus), ",".join(str(c) for c in cpus))) if value is None: testsuite.print_detail("MSR 0x{0:x}: GPF".format(msr)) else: testsuite.print_detail("MSR 0x{0:x}: 0x{1:x}".format(msr, value))
def rdmsr_consistent(msr_blacklist=set(), msr_masklist=dict()): """Rdmsr for all CPU and verify consistent value""" cpulist = sorted(bits.cpus()) for r in [range(0, 0x1000), range(0xC0000000, 0xC0001000)]: for msr in r: if msr in msr_blacklist: continue mask = msr_masklist.get(msr, ~0) uniques = {} for cpu in cpulist: value = bits.rdmsr(cpu, msr) if value is not None: value &= mask uniques.setdefault(value, []).append(cpu) testsuite.test("MSR 0x{0:x} consistent".format(msr), len(uniques) == 1) # Avoid doing any extra work formatting output when not necessary if testsuite.show_detail(): testsuite.print_detail("{0} unique values".format( len(uniques))) for value, cpus in uniques.iteritems(): testsuite.print_detail("{0} CPUs: {1}".format( len(cpus), ",".join(str(c) for c in cpus))) if value is None: testsuite.print_detail("MSR 0x{0:x}: GPF".format(msr)) else: testsuite.print_detail("MSR 0x{0:x}: 0x{1:x}".format( msr, value))
def smi_latency(): MSR_SMI_COUNT = 0x34 print "Warning: touching the keyboard can affect the results of this test." tsc_per_sec = bits.tsc_per_sec() tsc_per_usec = tsc_per_sec / (1000 * 1000) bins = [long(tsc_per_usec * 10**i) for i in range(9)] bin_descs = [ "0 < t <= 1us", "1us < t <= 10us", "10us < t <= 100us", "100us < t <= 1ms", "1ms < t <= 10ms", "10ms < t <= 100ms", "100ms < t <= 1s ", "1s < t <= 10s ", "10s < t <= 100s ", "100s < t ", ] print "Starting test. Wait here, I will be back in 15 seconds." (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins) BinType = namedtuple('BinType', ("max", "total", "count", "times")) bins = [BinType(*b) for b in bins] testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150) if not testsuite.show_detail(): return for bin, desc in zip(bins, bin_descs): if bin.count == 0: continue testsuite.print_detail("{}; average = {}; count = {}".format( desc, bits.format_tsc(bin.total / bin.count), bin.count)) deltas = (bits.format_tsc(t2 - t1) for t1, t2 in zip(bin.times, bin.times[1:])) testsuite.print_detail( " Times between first few observations: {}".format(" ".join( "{:>6}".format(delta) for delta in deltas))) if smi_count_delta is not None: testsuite.print_detail( "{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format( smi_count_delta, MSR_SMI_COUNT)) testsuite.print_detail( "Summary of impact: observed maximum latency = {}".format( bits.format_tsc(max_latency)))
def test(residency_tests, residency_counter_msr, residency_counters): cpus = bits.cpus() for states, hint in residency_tests: with bits.mwait.use_hint(hint): delta = residency(residency_counters, residency_counter_msr) detail = False for state in states: for apic_id, r in sorted(delta.iteritems()): state_residency = getattr(r, state) testsuite.test("MWAIT hint {:#x}, socket {} {} residency {:4.0%} (expected >= 85%)".format(hint, bits.socket_index(apic_id), state.upper(), state_residency), state_residency >= 0.85) detail = detail or testsuite.show_detail() if detail: print testsuite.format_detail("Full residency for MWAIT hint {:#x}:".format(hint)) print testsuite.format_detail(" SKT APIC" + "".join("{:>6s}".format(field.upper()) for field in residency_counters._fields)) for apic_id, r in sorted(delta.iteritems()): skt_index = bits.socket_index(apic_id) print testsuite.format_detail("{:4d} {:#04x} ".format(skt_index, apic_id) + " ".join("{:4.0%}".format(field) for field in r))
def smi_latency(): MSR_SMI_COUNT = 0x34 print "Warning: touching the keyboard can affect the results of this test." tsc_per_sec = bits.tsc_per_sec() tsc_per_usec = tsc_per_sec / (1000 * 1000) bins = [long(tsc_per_usec * 10**i) for i in range(9)] bin_descs = [ "0 < t <= 1us", "1us < t <= 10us", "10us < t <= 100us", "100us < t <= 1ms", "1ms < t <= 10ms", "10ms < t <= 100ms", "100ms < t <= 1s ", "1s < t <= 10s ", "10s < t <= 100s ", "100s < t ", ] print "Starting test. Wait here, I will be back in 15 seconds." (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins) BinType = namedtuple('BinType', ("max", "total", "count", "times")) bins = [BinType(*b) for b in bins] testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150) if not testsuite.show_detail(): return for bin, desc in zip(bins, bin_descs): if bin.count == 0: continue testsuite.print_detail("{}; average = {}; count = {}".format(desc, bits.format_tsc(bin.total/bin.count), bin.count)) deltas = (bits.format_tsc(t2 - t1) for t1,t2 in zip(bin.times, bin.times[1:])) testsuite.print_detail(" Times between first few observations: {}".format(" ".join("{:>6}".format(delta) for delta in deltas))) if smi_count_delta is not None: testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format(smi_count_delta, MSR_SMI_COUNT)) testsuite.print_detail("Summary of impact: observed maximum latency = {}".format(bits.format_tsc(max_latency)))
def smi_latency(): IA32_TSC_MSR = 0x10 MSR_SMI_COUNT = 0x34 bsp_apicid = bits.bsp_apicid() if bits.rdmsr(bsp_apicid, IA32_TSC_MSR) is None: raise RuntimeError("Reading of IA32_TSC MSR caused a GPF") print "Warning: touching the keyboard can affect the results of this test." print "Starting pass #1. Calibrating the TSC." start = time.time() tsc1 = bits.rdmsr(bsp_apicid, IA32_TSC_MSR) while time.time() - start < 1: pass stop = time.time() tsc2 = bits.rdmsr(bsp_apicid, IA32_TSC_MSR) tsc_per_sec = (tsc2 - tsc1) / (stop - start) tsc_per_usec = tsc_per_sec / (1000*1000) def show_time(tscs): units = [(1000*1000*1000, "ns"), (1000*1000, "us"), (1000, "ms")] for divisor, unit in units: temp = tscs / (tsc_per_sec / divisor) if temp < 10000: return "{}{}".format(int(temp), unit) return "{}s".format(int(tscs / tsc_per_sec)) bins = [long(tsc_per_usec * 10**i) for i in range(9)] bin_descs = [ "0 < t <= 1us", "1us < t <= 10us", "10us < t <= 100us", "100us < t <= 1ms", "1ms < t <= 10ms", "10ms < t <= 100ms", "100ms < t <= 1s ", "1s < t <= 10s ", "10s < t <= 100s ", "100s < t ", ] print "Starting pass #2. Wait here, I will be back in 15 seconds." (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins) BinType = namedtuple('BinType', ("max", "total", "count", "times")) bins = [BinType(*b) for b in bins] testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150) if not testsuite.show_detail(): return for bin, desc in zip(bins, bin_descs): if bin.count == 0: continue testsuite.print_detail("{}; average = {}; count = {}".format(desc, show_time(bin.total/bin.count), bin.count)) deltas = (show_time(t2 - t1) for t1,t2 in zip(bin.times, bin.times[1:])) testsuite.print_detail(" Times between first few observations: {}".format(" ".join("{:>6}".format(delta) for delta in deltas))) if smi_count_delta is not None: testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format(smi_count_delta, MSR_SMI_COUNT)) testsuite.print_detail("Summary of impact: observed maximum latency = {}".format(show_time(max_latency)))