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 variable_mtrrs(apicid=bits.bsp_apicid()): assert apicid in bits.cpus() ia32_mtrrcap_msr = IA32_MTRRCAP( bits.rdmsr(apicid, IA32_MTRRCAP_REG) ) ia32_mtrr_def_type_msr = IA32_MTRR_DEF_TYPE(bits.rdmsr(apicid, IA32_MTRR_DEF_TYPE_REG)) with ttypager.page(): print("Summary:") print("Default memory type: {}".format(_memory_type_str(ia32_mtrr_def_type_msr.type))) for i in range(ia32_mtrrcap_msr.VCNT): ia32_mtrr_physbase_msr = IA32_MTRR_PHYSBASE(bits.rdmsr(apicid, IA32_MTRR_PHYSBASEn_REG(i))) ia32_mtrr_physmask_msr = IA32_MTRR_PHYSMASK(bits.rdmsr(apicid, IA32_MTRR_PHYSMASKn_REG(i))) if (ia32_mtrr_physmask_msr.V): print("MTRR{}: type={:20} base={:10} size={:10}".format(i, _memory_type_str(ia32_mtrr_physbase_msr.Type), _physbase_str(ia32_mtrr_physbase_msr.PhysBase), _physmask_str(ia32_mtrr_physmask_msr.PhysMask))) print() print(ia32_mtrrcap_msr, end='\n\n') print(ia32_mtrr_def_type_msr, end='\n\n') for i in range(ia32_mtrrcap_msr.VCNT): msr_num = IA32_MTRR_PHYSBASEn_REG(i) ia32_mtrr_physbase_msr = IA32_MTRR_PHYSBASE( bits.rdmsr(apicid, msr_num) ) print("IA32_MTRR_PHYSBASE[{}] MSR {:#x}".format(i, msr_num)) print(ia32_mtrr_physbase_msr, end='\n\n') msr_num = IA32_MTRR_PHYSMASKn_REG(i) ia32_mtrr_physmask_msr = IA32_MTRR_PHYSMASK( bits.rdmsr(apicid, msr_num) ) print("IA32_MTRR_PHYSMASK[{}] MSR {:#x}".format(i, msr_num)) print(ia32_mtrr_physmask_msr, end='\n\n')
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 rdmsr_helper(msr, cpu=None, shift=0, mask=~0, highbit=63, lowbit=0): """Collate the unique values of an MSR across all CPUs. Returns a dict mapping MSR values to lists of APIC IDs, and a list of strings describing the unique values and the CPUs they occurred on. Each string in the list of descriptions works as an argument to testsuite.print_detail, and the first string also works as a test description for testsuite.test if no more specific description exists.""" if (highbit != 63 or lowbit != 0) and (shift != 0 or mask != ~0): raise ValueError('Input parameter usage is limited to \"highbit and lowbit\" OR \"shift and mask\".') if cpu is None: cpus = bits.cpus() else: cpus = [cpu] uniques = {} for cpu in cpus: value = bits.rdmsr(cpu, msr) if value is not None: if highbit != 63 or lowbit != 0: value = (value & ((1 << (highbit + 1)) - 1)) >> lowbit else: value = (value >> shift) & mask uniques.setdefault(value, []).append(cpu) msr_desc = "MSR {:#x}".format(msr) if shift == 0 and mask == ~0: if highbit == lowbit: msr_desc += " [{:d}]".format(highbit) else: msr_desc += " [{:d}:{:d}]".format(highbit, lowbit) else: if shift != 0: msr_desc += " >> {}".format(shift) if mask != ~0: msr_desc += " & {:#x}".format(mask) test_desc = msr_desc + " = " if len(uniques) > 1: test_desc += "Value Varies" elif value is None: test_desc += "GPF" else: test_desc += "{0:#x}".format(value) desc = [test_desc] if len(uniques) > 1 and (None not in uniques): mask = testutil.find_common_mask(uniques.iterkeys(), 64) desc.append('MSR value is not unique across all logical processors') desc.append("Common bits for all processors = {0:#018x}".format(uniques.keys()[0] & mask)) desc.append("Mask of common bits = {0:#018x}".format(mask)) for value in sorted(uniques.iterkeys()): cpus = uniques[value] desc.append(msr_desc + " = " + ("GPF" if value is None else "{0:#x}".format(value))) desc.append("On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus))) return uniques, desc
def mwait_callback(use_mwait, name="", hint=0): for cpu in bits.cpus(): bits.set_mwait(cpu, use_mwait, hint, int_break_event) with ttypager.page(): if use_mwait: print("MWAIT enabled: {}".format(name)) else: print("MWAIT disabled")
def cmd_brandstring(args): uniques = {} for cpu in bits.cpus(): uniques.setdefault(bits.brandstring(cpu), []).append(cpu) for value in sorted(uniques.iterkeys()): cpus = uniques[value] print 'Brandstring: "{0}"'.format(value) print "On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus))
def dump(): with ttypager.page(): for num, apicid in enumerate(bits.cpus()): heading = "Processor {} -- APIC ID {:#x}".format(num, apicid) cpu = cpus[apicid] print "{}\n{}".format(heading, "="*len(heading)) print "\n\n{}\n".format("".join(str(cpuid) for cpuid in cpu.cpuids)) print "\n\n{}\n".format("".join(str(msr) for msr in cpu.msrs))
def test_hardware_pstates(ratio_to_control_value): IA32_PERF_CTL = 0x199 with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL): MSR_PLATFORM_INFO = 0xce min_ratio = testmsr.MSR("maximum efficiency ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=47, lowbit=40)[0] max_ratio = testmsr.MSR("max non-turbo ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=15, lowbit=8)[0] # Get the Turbo Mode Availability flag turbo_mode_available = bits.cpuid(bits.bsp_apicid(), 0).eax >= 6 and ( bits.cpuid(bits.bsp_apicid(), 6).eax & 0x2) last_ratio = max_ratio if turbo_mode_available: last_ratio += 1 bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0 / 12) * 1000000 for ratio in range(min_ratio, last_ratio + 1): control_value = ratio_to_control_value(ratio, min_ratio, max_ratio) for apicid in bits.cpus(): bits.wrmsr(apicid, IA32_PERF_CTL, control_value) turbo = (ratio == max_ratio + 1) if turbo: # Needs to busywait, not sleep start = time.time() while (time.time() - start < 2): pass expected = int(ratio * bclk / 1000000) for duration in (0.1, 1.0): aperf = bits.cpu_frequency(duration)[1] aperf = testutil.adjust_to_nearest(aperf, bclk / 2) aperf = int(aperf / 1000000) if turbo: if aperf >= expected: break else: if aperf == expected: break if turbo: testsuite.test( "Turbo measured frequency {} >= expected {} MHz".format( aperf, expected), aperf >= expected) else: testsuite.test( "Ratio {} measured frequency {} MHz == expected {} MHz". format(ratio, aperf, expected), aperf == expected)
def dump(): with ttypager.page(): for num, apicid in enumerate(bits.cpus()): heading = "Processor {} -- APIC ID {:#x}".format(num, apicid) cpu = cpus[apicid] print "{}\n{}".format(heading, "=" * len(heading)) print "\n\n{}\n".format("".join( str(cpuid) for cpuid in cpu.cpuids)) print "\n\n{}\n".format("".join(str(msr) for msr in cpu.msrs))
def dump(): s = "" for num, apicid in enumerate(bits.cpus()): heading = "Processor {} -- APIC ID {:#x}".format(num, apicid) cpu = cpus[apicid] s += heading + "\n" + "="*len(heading) + "\n\n" s += "\n\n".join(str(cpuid) for cpuid in cpu.cpuids) + "\n\n" s += "\n\n".join(str(msr) for msr in cpu.msrs) + "\n\n" ttypager.ttypager_wrap(s, indent=False)
def toggle_autodemotion(): value = bits.rdmsr(bits.bsp_apicid(), 0xe2) if bitfields.getbits(value, 26, 25) == 0x3: fieldvalue = 0 else: fieldvalue = 0x3 value = bitfields.setbits(value, fieldvalue, 26, 25) for cpu in bits.cpus(): bits.wrmsr(cpu, 0xe2, value) show_autodemotion()
def each_apicid(cpu): if cpu is None: cpu = os.environ.get("viewpoint", ALL_CPUS) if cpu != ALL_CPUS: cpu = int(cpu, 0) cpus = bits.cpus() if cpu == ALL_CPUS: for apicid in cpus: yield apicid else: yield cpus[cpu]
def rdmsr_helper(msr, shift=0, mask=~0, highbit=63, lowbit=0): """Collate the unique values of an MSR across all CPUs. Returns a dict mapping MSR values to lists of APIC IDs, and a list of strings describing the unique values and the CPUs they occurred on. Each string in the list of descriptions works as an argument to testsuite.print_detail, and the first string also works as a test description for testsuite.test if no more specific description exists.""" if (highbit != 63 or lowbit != 0) and (shift != 0 or mask != ~0): raise ValueError( 'Input parameter usage is limited to \"highbit and lowbit\" OR \"shift and mask\".' ) uniques = {} for cpu in bits.cpus(): value = bits.rdmsr(cpu, msr) if value is not None: if highbit != 63 or lowbit != 0: value = (value & ((1 << (highbit + 1)) - 1)) >> lowbit else: value = (value >> shift) & mask uniques.setdefault(value, []).append(cpu) msr_desc = "MSR {:#x}".format(msr) if shift == 0 and mask == ~0: if highbit == lowbit: msr_desc += " [{:d}]".format(highbit) else: msr_desc += " [{:d}:{:d}]".format(highbit, lowbit) else: if shift != 0: msr_desc += " >> {}".format(shift) if mask != ~0: msr_desc += " & {:#x}".format(mask) desc = [] if len(uniques) > 1 and (None not in uniques): mask = testutil.find_common_mask(uniques.iterkeys(), 64) desc.append('MSR value is not unique across all logical processors') desc.append("Common bits for all processors = {0:#018x}".format( uniques.keys()[0] & mask)) desc.append("Mask of common bits = {0:#018x}".format(mask)) for value in sorted(uniques.iterkeys()): cpus = uniques[value] desc.append(msr_desc + " = " + ("GPF" if value is None else "{0:#x}".format(value))) desc.append("On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus))) return uniques, desc
def test_hardware_pstates(ratio_to_control_value): old_mwait = {} try: MSR_PLATFORM_INFO = 0xce IA32_PERF_CTL = 0x199 min_ratio = testmsr.MSR("maximum efficiency ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=47, lowbit=40)[0] max_ratio = testmsr.MSR("max non-turbo ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=15, lowbit=8)[0] # Get the Turbo Mode Availability flag turbo_mode_available = bits.cpuid(bits.bsp_apicid(),0).eax >= 6 and (bits.cpuid(bits.bsp_apicid(),6).eax & 0x2) last_ratio = max_ratio if turbo_mode_available: last_ratio += 1 duration = last_ratio - min_ratio + 1 if turbo_mode_available: duration += 2 print "Test duration is ~{} seconds...".format(duration) # Force use of MWAIT C3 hint = 0x20 cpus = bits.cpus() for apicid in cpus: old_mwait[apicid] = bits.get_mwait(apicid) bits.set_mwait(apicid, True, hint) bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000 for ratio in range(min_ratio, last_ratio + 1): control_value = ratio_to_control_value(ratio, min_ratio, max_ratio) for apicid in cpus: bits.wrmsr(apicid, IA32_PERF_CTL, control_value) if ratio == max_ratio + 1: # Needs to busywait, not sleep start = time.time() while (time.time() - start < 2): pass aperf = bits.cpu_frequency()[1] aperf = testutil.adjust_to_nearest(aperf, bclk/2) aperf = int(aperf / 1000000) expected = int(ratio * bclk / 1000000) if ratio == max_ratio + 1: testsuite.test("Turbo measured frequency {} >= expected {} MHz".format(aperf, expected), aperf >= expected) else: testsuite.test("Ratio {} measured frequency {} MHz == expected {} MHz".format(ratio, aperf, expected), aperf == expected) finally: for apicid, old_mwait_values in old_mwait.iteritems(): bits.set_mwait(apicid, *old_mwait_values)
def cmd_cpuid32(args): if args.cpu is not None: args.cpu = bits.cpus()[args.cpu] uniques, desc = testcpuid.cpuid_helper(args.function, args.index, args.cpu, args.shift, args.mask, args.eax_mask, args.ebx_mask, args.ecx_mask, args.edx_mask) if args.env: if len(uniques) > 1: print "Setting environment vars eax,ebx,ecx,edx requested; but register values are not unique" return False for regname, regvalue in uniques.keys()[0]._asdict().iteritems(): os.putenv(regname, "{:#x}".format(regvalue)) if not args.quiet: print "\n".join(desc) return True
def cpupath_apicid(cpupath): if procid_apicid is not None: procid = cpupath_procid.get(cpupath, None) if procid is not None: apicid = procid_apicid.get(procid, None) if apicid is not None: return apicid if uid_x2apicid is not None: uid = cpupath_uid.get(cpupath, None) if uid is not None: apicid = uid_x2apicid.get(uid, None) if apicid is not None: return apicid return bits.cpus()[0]
def use_hint(hint=None): """Context manager to temporarily set the mwait hint of all CPUs""" global default_hint if hint is None: hint = default_hint old_mwait = {} try: for apicid in bits.cpus(): old_mwait[apicid] = bits.get_mwait(apicid) bits.set_mwait(apicid, True, hint) yield finally: for apicid, old_mwait_values in old_mwait.iteritems(): bits.set_mwait(apicid, *old_mwait_values)
def cmd_rdmsr(args): if args.cpu is not None: args.cpu = bits.cpus()[args.cpu] uniques, desc = testmsr.rdmsr_helper(msr=args.msr, cpu=args.cpu, shift=args.shift, mask=args.mask) if not args.quiet: print "\n".join(desc) value = uniques.keys()[0] if args.varname is not None: if len(uniques) > 1: print "Variable setting requested but MSR value not unique" return False if value is None: print "Variable setting requested but MSR read caused GPF" return False os.putenv(args.varname, "{0:#x}".format(value)) return len(uniques) == 1 and value is not None
def cpuid_helper(function, index=None, cpu=None, shift=0, mask=~0, eax_mask=~0, ebx_mask=~0, ecx_mask=~0, edx_mask=~0): if cpu is None: cpus = bits.cpus() else: cpus = [cpu] if index is None: index = 0 indexdesc = "" else: indexdesc = " index {0:#x}".format(index) def find_mask(m): if m == ~0: return mask return m masks = map(find_mask, [eax_mask, ebx_mask, ecx_mask, edx_mask]) uniques = {} for cpu in cpus: regs = bits.cpuid_result(*[(r >> shift) & m for r, m in zip(bits.cpuid(cpu, function, index), masks)]) uniques.setdefault(regs, []).append(cpu) desc = ["CPUID function {:#x}{}".format(function, indexdesc)] if shift != 0: desc.append("Register values have been shifted by {}".format(shift)) if mask != ~0 or eax_mask != ~0 or ebx_mask != ~0 or ecx_mask != ~0 or edx_mask != ~0: desc.append("Register values have been masked:") shifted_masks = bits.cpuid_result(*[m << shift for m in masks]) desc.append("Masks: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**shifted_masks._asdict())) if len(uniques) > 1: regvalues = zip(*uniques.iterkeys()) common_masks = bits.cpuid_result(*map(testutil.find_common_mask, regvalues)) common_values = bits.cpuid_result(*[v[0] & m for v, m in zip(regvalues, common_masks)]) desc.append('Register values are not unique across all logical processors') desc.append("Common bits: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**common_values._asdict())) desc.append("Mask of common bits: {eax:#010x} {ebx:#010x} {ecx:#010x} {edx:#010x}".format(**common_masks._asdict())) for regs in sorted(uniques.iterkeys()): cpus = uniques[regs] desc.append("Register value: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**regs._asdict())) desc.append("On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus))) return uniques, desc
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 test_hardware_pstates(ratio_to_control_value): IA32_PERF_CTL = 0x199 with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL): MSR_PLATFORM_INFO = 0xce min_ratio = testmsr.MSR("maximum efficiency ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=47, lowbit=40)[0] max_ratio = testmsr.MSR("max non-turbo ratio", bits.bsp_apicid(), MSR_PLATFORM_INFO, highbit=15, lowbit=8)[0] # Get the Turbo Mode Availability flag turbo_mode_available = bits.cpuid(bits.bsp_apicid(),0).eax >= 6 and (bits.cpuid(bits.bsp_apicid(),6).eax & 0x2) last_ratio = max_ratio if turbo_mode_available: last_ratio += 1 bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000 for ratio in range(min_ratio, last_ratio + 1): control_value = ratio_to_control_value(ratio, min_ratio, max_ratio) for apicid in bits.cpus(): bits.wrmsr(apicid, IA32_PERF_CTL, control_value) turbo = (ratio == max_ratio + 1) if turbo: # Needs to busywait, not sleep start = time.time() while (time.time() - start < 2): pass expected = int(ratio * bclk / 1000000) for duration in (0.1, 1.0): aperf = bits.cpu_frequency(duration)[1] aperf = testutil.adjust_to_nearest(aperf, bclk/2) aperf = int(aperf / 1000000) if turbo: if aperf >= expected: break else: if aperf == expected: break if turbo: testsuite.test("Turbo measured frequency {} >= expected {} MHz".format(aperf, expected), aperf >= expected) else: testsuite.test("Ratio {} measured frequency {} MHz == expected {} MHz".format(ratio, aperf, expected), aperf == expected)
def cmd_cpu(args): cpus = bits.cpus() ncpus = len(cpus) if args.num is not None: if args.num == ALL_CPUS: os.unsetenv("viewpoint") else: os.putenv("viewpoint", str(args.num)) if args.list: print "{} CPUs: 0-{}".format(ncpus, ncpus-1) for i in range(ncpus): # print 4 per line print 'CPU{: <3d} = {: <#10x}'.format(i, cpus[i]), if i == (ncpus - 1) or (i % 4) == 3: print if not args.quiet: print "Assigned CPU number = {}".format(os.environ.get("viewpoint", 'all')) if args.env: os.putenv("apicid_list", " ".join("{:#x}".format(cpu) for cpu in sorted(cpus)))
def cpuid_helper(function, index=None, shift=0, mask=~0, eax_mask=~0, ebx_mask=~0, ecx_mask=~0, edx_mask=~0): if index is None: index = 0 indexdesc = "" else: indexdesc = " index {0:#x}".format(index) def find_mask(m): if m == ~0: return mask return m masks = map(find_mask, [eax_mask, ebx_mask, ecx_mask, edx_mask]) uniques = {} for cpu in bits.cpus(): regs = bits.cpuid_result(*[(r >> shift) & m for r, m in zip(bits.cpuid(cpu, function, index), masks)]) uniques.setdefault(regs, []).append(cpu) desc = ["CPUID function {:#x}{}".format(function, indexdesc)] if shift != 0: desc.append("Register values have been shifted by {}".format(shift)) if mask != ~0 or eax_mask != ~0 or ebx_mask != ~0 or ecx_mask != ~0 or edx_mask != ~0: desc.append("Register values have been masked:") shifted_masks = bits.cpuid_result(*[m << shift for m in masks]) desc.append("Masks: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**shifted_masks._asdict())) if len(uniques) > 1: regvalues = zip(*uniques.iterkeys()) common_masks = bits.cpuid_result(*map(testutil.find_common_mask, regvalues)) common_values = bits.cpuid_result(*[v[0] & m for v, m in zip(regvalues, common_masks)]) desc.append('Register values are not unique across all logical processors') desc.append("Common bits: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**common_values._asdict())) desc.append("Mask of common bits: {eax:#010x} {ebx:#010x} {ecx:#010x} {edx:#010x}".format(**common_masks._asdict())) for regs in sorted(uniques.iterkeys()): cpus = uniques[regs] desc.append("Register value: eax={eax:#010x} ebx={ebx:#010x} ecx={ecx:#010x} edx={edx:#010x}".format(**regs._asdict())) desc.append("On {0} CPUs: {1}".format(len(cpus), testutil.apicid_list(cpus))) return uniques, desc
def topology(): """Return a dictionary relating each socket APIC ID to its cores' APIC IDs, and each core to its threads' APIC IDs. Raises RuntimeError if CPUID leaf 0xb not supported.""" socket_dict = OrderedDict() prev_socket_num = None for apicid in sorted(bits.cpus(), key=_apickey): current_socket_num, current_core_num, apicid = thread(apicid) if current_socket_num != prev_socket_num: core_dict = OrderedDict() socket_dict[apicid] = core_dict prev_core_num = None if current_core_num != prev_core_num: thread_list = [] core_dict[apicid] = thread_list thread_list.append(apicid) prev_socket_num = current_socket_num prev_core_num = current_core_num return socket_dict
def test_smrr(): """Test the SMRR-related configuration""" cpus = sorted(bits.cpus()) if not testmsr.test_msr_consistency( text="IA32_MTRRCAP Bit [11] (SMRR Supported) must be consistent", first_msr=0xFE, shift=11, mask=1 ): return ia32_mtrrcap = bits.rdmsr(cpus[0], 0xFE) if ia32_mtrrcap is not None and not ia32_mtrrcap & (1 << 11): return if testmsr.msr_available(0x1F2) and testmsr.msr_available(0x1F3): MSR_SMRR_PHYS_BASE = 0x1F2 MSR_SMRR_PHYS_MASK = 0x1F3 elif testmsr.msr_available(0xA0) and testmsr.msr_available(0xA1): MSR_SMRR_PHYS_BASE = 0xA0 MSR_SMRR_PHYS_MASK = 0xA1 return else: return testmsr.test_msr_consistency( text="SMRR must be consistent across all processors", first_msr=MSR_SMRR_PHYS_BASE, last_msr=MSR_SMRR_PHYS_MASK ) for apicid in cpus: smrr_physbase, smrr_physbase_str = testmsr.MSR("SMRR Physbase", apicid, MSR_SMRR_PHYS_BASE, 31, 12) smrr_type, smrr_type_str = testmsr.MSR("SMRR Type", apicid, MSR_SMRR_PHYS_BASE, 2, 0) smrr_physmask, smrr_physmask_str = testmsr.MSR("SMRR Physmask", apicid, MSR_SMRR_PHYS_MASK, 31, 12) smrr_valid, smrr_valid_str = testmsr.MSR("SMRR Valid", apicid, MSR_SMRR_PHYS_MASK, 11, 11) testsuite.test("SMRR_PHYSBASE must be aligned on an 8MB boundary", (smrr_physbase % 0x800) == 0) testsuite.print_detail(smrr_physbase_str) testsuite.print_detail("SMRR_PHYSBASE % 0x800 must be 0") testsuite.test("SMRR Type must be Write-Back (Best performance)", smrr_type == 6) testsuite.print_detail(smrr_type_str) testsuite.print_detail("SMRR Type must be 6") testsuite.test("SMRR size must be at least 8MB", smrr_physmask >= 0x800) testsuite.print_detail(smrr_physmask_str) testsuite.print_detail("SMRR Physmask must be >= 0x800") testsuite.test("SMRR Valid bit must be 1", smrr_valid) testsuite.print_detail(smrr_valid_str)
def cmd_wrmsr(args): rd_fail = [] wr_fail = [] success = [] def process_wrmsr(apicid): wr_value = 0 if args.rmw: rd_value = bits.rdmsr(apicid, args.msr) if rd_value is None: rd_fail.append(apicid) return wr_value = rd_value & ~(args.mask << args.shift) wr_value |= (args.value & args.mask) << args.shift if bits.wrmsr(apicid, args.msr, wr_value): success.append(apicid) else: wr_fail.append(apicid) for apicid in bits.cpus(): process_wrmsr(apicid) if rd_fail or wr_fail: if args.rmw: op = "|=" else: op = "=" print "MSR {0:#x} {1} ({2:#x} & {3:#x}) << {4} ({5:#x})".format(args.msr, op, args.value, args.mask, args.shift, (args.value & args.mask) << args.shift) if rd_fail: print "Read MSR fail (GPF) on {} CPUs: {}".format(len(rd_fail), testutil.apicid_list(rd_fail)) if wr_fail: print "Write MSR fail (GPF) on {} CPUs: {}".format(len(wr_fail), testutil.apicid_list(wr_fail)) if success: print "Write MSR pass on {} CPUs: {}".format(len(success), testutil.apicid_list(success)) return not rd_fail and not wr_fail
def test_pstates(): """Execute and verify frequency for each Pstate in the _PSS""" old_mwait = {} try: IA32_PERF_CTL = 0x199 # Force use of MWAIT C3 hint = 0x20 cpus = bits.cpus() for apicid in cpus: old_mwait[apicid] = bits.get_mwait(apicid) bits.set_mwait(apicid, True, hint) cpupath_procid = acpi.find_procid() cpupath_uid = acpi.find_uid() procid_apicid, uid_x2apicid = acpi.parse_apic() def cpupath_apicid(cpupath): if procid_apicid is not None: procid = cpupath_procid.get(cpupath, None) if procid is not None: apicid = procid_apicid.get(procid, None) if apicid is not None: return apicid if uid_x2apicid is not None: uid = cpupath_uid.get(cpupath, None) if uid is not None: apicid = uid_x2apicid.get(uid, None) if apicid is not None: return apicid return bits.cpus()[0] bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000 uniques = acpi.parse_cpu_method("_PSS") for pss, cpupaths in uniques.iteritems(): if not testsuite.test("_PSS must exist", pss is not None): testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) testsuite.print_detail('No _PSS exists') continue print "Test duration is ~{} seconds...".format(len(pss.pstates) + 2) for n, pstate in enumerate(pss.pstates): for cpupath in cpupaths: apicid = cpupath_apicid(cpupath) if apicid is None: print 'Failed to find apicid for cpupath {}'.format(cpupath) continue bits.wrmsr(apicid, IA32_PERF_CTL, pstate.control) # Detecting Turbo frequency requires at least 2 pstates # since turbo frequency = max non-turbo frequency + 1 turbo = False if len(pss.pstates) >= 2: turbo = (n == 0 and pstate.core_frequency == (pss.pstates[1].core_frequency + 1)) if turbo: # Needs to busywait, not sleep start = time.time() while (time.time() - start < 2): pass # Abort the test if no cpu frequency is not available if bits.cpu_frequency() is None: continue aperf = bits.cpu_frequency()[1] aperf = testutil.adjust_to_nearest(aperf, bclk/2) aperf = int(aperf / 1000000) if turbo: testsuite.test("P{}: Turbo measured frequency {} >= expected {} MHz".format(n, aperf, pstate.core_frequency), aperf >= pstate.core_frequency) else: testsuite.test("P{}: measured frequency {} MHz == expected {} MHz".format(n, aperf, pstate.core_frequency), aperf == pstate.core_frequency) finally: for apicid, old_mwait_values in old_mwait.iteritems(): bits.set_mwait(apicid, *old_mwait_values)
def apicid_list(apicids): if len(apicids) == len(bits.cpus()): return "all" else: return " ".join("{0:#x}".format(cpu) for cpu in sorted(apicids))
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """testing module.""" import bits from cpudetect import cpulib import testsuite import unittest def f(x): """Test function in a test module.""" for i in range(x): print ("Hello from a function in a module, for the %dth time" % i) # Save the list of CPUs cpulist = bits.cpus() # Build a reverse mapping from APIC ID to CPU number apicid_index = dict([(apicid, i) for (i, apicid) in enumerate(cpulist)]) def rdmsr_test(): """Test the rdmsr function""" for cpu in cpulist: for msr in [0x10, 0x40000000]: value = bits.rdmsr(cpu, msr) if value is None: print "CPU 0x%x MSR 0x%x: GPF" % (cpu, msr) else: print "CPU 0x%x MSR 0x%x: 0x%x" % (cpu, msr, value) def ppm_test1():
def parse_cpu(s): if s.lower() == 'all': return ALL_CPUS return parse_int(s, "CPU", max_bound = len(bits.cpus())-1)
"""testing module.""" import bits from cpudetect import cpulib import testsuite import unittest def f(x): """Test function in a test module.""" for i in range(x): print("Hello from a function in a module, for the %dth time" % i) # Save the list of CPUs cpulist = bits.cpus() # Build a reverse mapping from APIC ID to CPU number apicid_index = dict([(apicid, i) for (i, apicid) in enumerate(cpulist)]) def rdmsr_test(): """Test the rdmsr function""" for cpu in cpulist: for msr in [0x10, 0x40000000]: value = bits.rdmsr(cpu, msr) if value is None: print "CPU 0x%x MSR 0x%x: GPF" % (cpu, msr) else: print "CPU 0x%x MSR 0x%x: 0x%x" % (cpu, msr, value)
import bits from bits.cpuids import generate_cpuids from bits.msrs import sample_msrs import bits.platformbase import ttypager MSRS = bits.platformbase.make_MSRS(sample_msrs()) class CPU(object): def __init__(self, apicid): self.apicid = apicid self.msrs = MSRS(apicid) CPUIDS = bits.platformbase.make_CPUIDS(generate_cpuids(apicid)) self.cpuids = CPUIDS(apicid) cpus = dict((n, CPU(n)) for n in bits.cpus()) def dump(): with ttypager.page(): for num, apicid in enumerate(bits.cpus()): heading = "Processor {} -- APIC ID {:#x}".format(num, apicid) cpu = cpus[apicid] print "{}\n{}".format(heading, "=" * len(heading)) print "\n\n{}\n".format("".join( str(cpuid) for cpuid in cpu.cpuids)) print "\n\n{}\n".format("".join(str(msr) for msr in cpu.msrs))
def msr_available(msr): """Return True if the specified MSR exists on all CPUs""" return all(bits.rdmsr(cpu_num, msr) is not None for cpu_num in bits.cpus())
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """Hierarchical object-based CPU register (CPUID and MSR) decoding""" import bits from cpuids import generate_cpuids from msrs import sample_msrs import platformbase import ttypager MSRS = platformbase.make_MSRS(sample_msrs()) class CPU(object): def __init__(self, apicid): self.apicid = apicid self.msrs = MSRS(apicid) CPUIDS = platformbase.make_CPUIDS(generate_cpuids(apicid)) self.cpuids = CPUIDS(apicid) cpus = dict((n, CPU(n)) for n in bits.cpus()) def dump(): s = "" for num, apicid in enumerate(bits.cpus()): heading = "Processor {} -- APIC ID {:#x}".format(num, apicid) cpu = cpus[apicid] s += heading + "\n" + "="*len(heading) + "\n\n" s += "\n\n".join(str(cpuid) for cpuid in cpu.cpuids) + "\n\n" s += "\n\n".join(str(msr) for msr in cpu.msrs) + "\n\n" ttypager.ttypager_wrap(s, indent=False)
def cmd_test_msr(args): if args.cpu is not None: args.cpu = bits.cpus()[args.cpu] return testmsr.test_msr(**vars(args))