def thread(apicid): """Return the thread APIC ID, and the APIC IDs of the core and socket in which the thread resides. Raises RuntimeError if CPUID leaf 0xb not supported.""" if bits.cpuid(apicid, 0).eax < 0xb: raise RuntimeError("Cannot compute topology; CPUID leaf 0xb not supported.") coreid = apicid >> bitfields.getbits(bits.cpuid(apicid, 0xb, 0).eax, 4, 0) socketid = apicid >> bitfields.getbits(bits.cpuid(apicid, 0xb, 1).eax, 4, 0) return socketid, coreid, apicid
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 thread(apicid): """Return the thread APIC ID, and the APIC IDs of the core and socket in which the thread resides. Raises RuntimeError if CPUID leaf 0xb not supported.""" if bits.cpuid(apicid, 0).eax < 0xb: raise RuntimeError( "Cannot compute topology; CPUID leaf 0xb not supported.") coreid = apicid >> bitfields.getbits(bits.cpuid(apicid, 0xb, 0).eax, 4, 0) socketid = apicid >> bitfields.getbits( bits.cpuid(apicid, 0xb, 1).eax, 4, 0) return socketid, coreid, apicid
def cmd_brandstring(args): uniques = {} for cpu in each_apicid(args.cpu): brand = "" if bits.cpuid(cpu, 0x80000000).eax >= 0x80000004: brand = "".join(struct.pack("<LLLL", *bits.cpuid(cpu, func_num)) for func_num in range(0x80000002, 0x80000005)) brand = brand.rstrip('\0') uniques.setdefault(brand, []).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 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 power_opt_low_power_profile(): # If CPUID.06H:ECX.SETBH[bit 3] is set, then the processor supports # performance-energy bias preference and IA32_ENERGY_PERF_BIAS (1B0H) MSR setbh = (bits.cpuid(bits.bsp_apicid(),6).ecx >> 3) & 1 if not setbh: return testmsr.test_msr_consistency("Energy Performance Bias", 0x1b0, mask=0xf) testmsr.test_msr("Energy Performance Bias 12-15", 0x1b0, expected_value=3, shift=2, mask=3)
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 max_phys_addr(): """Return the max physical address width, in bits. Computed on first call, and cached for subsequent return.""" global max_phys_addr max_extended_leaf = bits.cpuid(bits.bsp_apicid(), 0x80000000).eax if max_extended_leaf >= 0x80000008: # cpuid.(eax=0x80000008).eax[7:0] = max physical-address width supported by the processor local_max_phys_addr = bitfields.getbits(bits.cpuid(bits.bsp_apicid(), 0x80000008).eax, 7, 0) elif bitfields.getbits(bits.cpuid(bits.bsp_apicid(), 1).edx, 6): # PAE supported local_max_phys_addr = 36 else: local_max_phys_addr = 32 old_func = max_phys_addr def max_phys_addr(): return local_max_phys_addr functools.update_wrapper(max_phys_addr, old_func) return local_max_phys_addr
def power_opt_low_power_profile(): # If CPUID.06H:ECX.SETBH[bit 3] is set, then the processor supports # performance-energy bias preference and IA32_ENERGY_PERF_BIAS (1B0H) MSR setbh = (bits.cpuid(bits.bsp_apicid(), 6).ecx >> 3) & 1 if not setbh: return testmsr.test_msr_consistency("Energy Performance Bias", 0x1b0, mask=0xf) testmsr.test_msr("Energy Performance Bias 12-15", 0x1b0, expected_value=3, shift=2, mask=3)
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 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 is_cpu(): return bits.cpuid(bits.bsp_apicid(), 1).eax & ~0xf == 0x106c0
def log_sysinfo(): with redirect.logonly(): signature = bits.cpuid(bits.bsp_apicid(), 1).eax print "Processor signature {:#x}, detected CPU as {}".format( signature, cpulib.name)
def generate_mwait_menu(): global created_mwait_menu global supported_mwaits_msg if created_mwait_menu: return cfg = "" cfg += 'menuentry "Test round-trip latency via MWAIT" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.test_latency()'\n" cfg += '}\n\n' cfg += 'menuentry "MWAIT disable" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.mwait_callback(False)'\n" cfg += '}\n\n' cfg += 'menuentry "MWAIT enable C0" {\n' cfg += """ py 'import mwaitmenu; mwaitmenu.mwait_callback(True, "C0", 0xf)'\n""" cfg += '}\n\n' edx = 0 if bits.cpuid(bits.bsp_apicid(), 0).eax >= 5: edx = bits.cpuid(bits.bsp_apicid(), 5).edx mwait_table = ( ("C1", 0, 4, 1), ("C1E", 1, 4, 2), ("*C2", 0x10, 8, 1), ("*C3", 0x20, 12, 1), ("*C4", 0x30, 16, 1), ("*C5", 0x40, 20, 1), ("*C6", 0x50, 24, 1), ) supported_mwaits_msg = "" for name, hint, shift, n in mwait_table: if ((edx >> shift) & 0xf) >= n: cfg += 'menuentry "MWAIT enable {}" {{\n'.format(name) cfg += """ py 'import mwaitmenu; mwaitmenu.mwait_callback(True, "{}", {})'\n""".format( name, hint) cfg += '}\n\n' supported_mwaits_msg += "MWAIT {} is supported\n".format(name) else: supported_mwaits_msg += "MWAIT {} is not supported\n".format(name) supported_mwaits_msg += "For more information, see the Intel Software Developers Manual, CPUID leaf 5\n" cfg += 'menuentry "* MWAIT C-state naming is per CPUID leaf 5 & not processor-specific!" {' cfg += " py 'import mwaitmenu; mwaitmenu.show_supported_mwaits()'\n" cfg += '}\n\n' cfg += 'menuentry "Current state of Interrupt Break Event" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.show_interrupt_break_event()'\n" cfg += '}\n\n' cfg += 'menuentry "Toggle Interrupt Break Event" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.toggle_interrupt_break_event()'\n" cfg += '}\n\n' try: cfg += cpulib.generate_mwait_menu() except AttributeError as e: pass bits.pyfs.add_static("mwaitmenu.cfg", cfg) created_mwait_menu = True
def is_cpu(): return bits.cpuid(bits.bsp_apicid(),1).eax & ~0xf == 0x106c0
def log_sysinfo(): with redirect.logonly(): signature = bits.cpuid(bits.bsp_apicid(),1).eax print "Processor signature {:#x}, detected CPU as {}".format(signature, cpulib.name)
def is_cpu(): return bits.cpuid(bits.bsp_apicid(), 1).eax & ~0xF == 0x206D0
def read(cls, apicid, subleaf=0): r = cls(bits.cpuid(apicid, cls.leaf, subleaf)) r.apicid = apicid r.subleaf = subleaf return r
def generate_mwait_menu(): global created_mwait_menu global supported_mwaits_msg if created_mwait_menu: return cfg = "" cfg += 'menuentry "Test round-trip latency via MWAIT" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.test_latency()'\n" cfg += '}\n\n' cfg += 'menuentry "MWAIT disable" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.mwait_callback(False)'\n" cfg += '}\n\n' cfg += 'menuentry "MWAIT enable C0" {\n' cfg += """ py 'import mwaitmenu; mwaitmenu.mwait_callback(True, "C0", 0xf)'\n""" cfg += '}\n\n' edx = 0 if bits.cpuid(bits.bsp_apicid(), 0).eax >= 5: edx = bits.cpuid(bits.bsp_apicid(), 5).edx mwait_table = ( ("C1", 0, 4, 1), ("C1E", 1, 4, 2), ("*C2", 0x10, 8, 1), ("*C3", 0x20, 12, 1), ("*C4", 0x30, 16, 1), ("*C5", 0x40, 20, 1), ("*C6", 0x50, 24, 1), ) supported_mwaits_msg = "" for name, hint, shift, n in mwait_table: if ((edx >> shift) & 0xf) >= n: cfg += 'menuentry "MWAIT enable {}" {{\n'.format(name) cfg += """ py 'import mwaitmenu; mwaitmenu.mwait_callback(True, "{}", {})'\n""".format(name, hint) cfg += '}\n\n' supported_mwaits_msg += "MWAIT {} is supported\n".format(name) else: supported_mwaits_msg += "MWAIT {} is not supported\n".format(name) supported_mwaits_msg += "For more information, see the Intel Software Developers Manual, CPUID leaf 5\n" cfg += 'menuentry "* MWAIT C-state naming is per CPUID leaf 5 & not processor-specific!" {' cfg += " py 'import mwaitmenu; mwaitmenu.show_supported_mwaits()'\n" cfg += '}\n\n' cfg += 'menuentry "Current state of Interrupt Break Event" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.show_interrupt_break_event()'\n" cfg += '}\n\n' cfg += 'menuentry "Toggle Interrupt Break Event" {\n' cfg += " py 'import mwaitmenu; mwaitmenu.toggle_interrupt_break_event()'\n" cfg += '}\n\n' try: cfg += cpulib.generate_mwait_menu() except AttributeError as e: pass bits.pyfs.add_static("mwaitmenu.cfg", cfg) created_mwait_menu = True