1# Copyright (c) 2015, Intel Corporation 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# 7# * Redistributions of source code must retain the above copyright notice, 8# this list of conditions and the following disclaimer. 9# * Redistributions in binary form must reproduce the above copyright notice, 10# this list of conditions and the following disclaimer in the documentation 11# and/or other materials provided with the distribution. 12# * Neither the name of Intel Corporation nor the names of its contributors 13# may be used to endorse or promote products derived from this software 14# without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 27"""Tests for ACPI""" 28 29import acpi 30import bits 31import bits.mwait 32import struct 33import testutil 34import testsuite 35import time 36 37def register_tests(): 38 testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests") 39# testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests") 40# testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests") 41 testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests") 42 testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests") 43 testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests") 44 testsuite.add_test("ACPI MADT (Multiple APIC Description Table)", test_apic, submenu="ACPI Tests") 45 testsuite.add_test("ACPI MPST (Memory Power State Table)", test_mpst, submenu="ACPI Tests") 46 testsuite.add_test("ACPI RSDP (Root System Description Pointer Structure)", test_rsdp, submenu="ACPI Tests") 47 testsuite.add_test("ACPI XSDT (Extended System Description Table)", test_xsdt, submenu="ACPI Tests") 48 49def test_mat(): 50 cpupaths = acpi.get_cpupaths() 51 apic = acpi.parse_apic() 52 procid_apicid = apic.procid_apicid 53 uid_x2apicid = apic.uid_x2apicid 54 for cpupath in cpupaths: 55 # Find the ProcId defined by the processor object 56 processor = acpi.evaluate(cpupath) 57 # Find the UID defined by the processor object's _UID method 58 uid = acpi.evaluate(cpupath + "._UID") 59 mat_buffer = acpi.evaluate(cpupath + "._MAT") 60 if mat_buffer is None: 61 continue 62 # Process each _MAT subtable 63 mat = acpi._MAT(mat_buffer) 64 for index, subtable in enumerate(mat): 65 if subtable.subtype == acpi.MADT_TYPE_LOCAL_APIC: 66 if subtable.flags.bits.enabled: 67 testsuite.test("{} Processor declaration ProcId = _MAT ProcId".format(cpupath), processor.ProcId == subtable.proc_id) 68 testsuite.print_detail("{} ProcId ({:#02x}) != _MAT ProcId ({:#02x})".format(cpupath, processor.ProcId, subtable.proc_id)) 69 testsuite.print_detail("Processor Declaration: {}".format(processor)) 70 testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) 71 if testsuite.test("{} with local APIC in _MAT has local APIC in MADT".format(cpupath), processor.ProcId in procid_apicid): 72 testsuite.test("{} ApicId derived using Processor declaration ProcId = _MAT ApicId".format(cpupath), procid_apicid[processor.ProcId] == subtable.apic_id) 73 testsuite.print_detail("{} ApicId derived from MADT ({:#02x}) != _MAT ApicId ({:#02x})".format(cpupath, procid_apicid[processor.ProcId], subtable.apic_id)) 74 testsuite.print_detail("Processor Declaration: {}".format(processor)) 75 testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) 76 if subtable.subtype == acpi.MADT_TYPE_LOCAL_X2APIC: 77 if subtable.flags.bits.enabled: 78 if testsuite.test("{} with x2Apic in _MAT has _UID".format(cpupath), uid is not None): 79 testsuite.test("{}._UID = _MAT UID".format(cpupath), uid == subtable.uid) 80 testsuite.print_detail("{}._UID ({:#x}) != _MAT UID ({:#x})".format(cpupath, uid, subtable.uid)) 81 testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) 82 if testsuite.test("{} with _MAT x2Apic has x2Apic in MADT".format(cpupath), subtable.uid in uid_x2apicid): 83 testsuite.test("{} x2ApicId derived from MADT using UID = _MAT x2ApicId".format(cpupath), uid_x2apicid[subtable.uid] == subtable.x2apicid) 84 testsuite.print_detail("{} x2ApicId derived from MADT ({:#02x}) != _MAT x2ApicId ({:#02x})".format(cpupath, uid_x2apicid[subtable.uid], subtable.x2apicid)) 85 testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) 86 87def test_pss(): 88 uniques = acpi.parse_cpu_method("_PSS") 89 # We special-case None here to avoid a double-failure for CPUs without a _PSS 90 testsuite.test("_PSS must be identical for all CPUs", len(uniques) <= 1 or (len(uniques) == 2 and None in uniques)) 91 for pss, cpupaths in uniques.iteritems(): 92 if not testsuite.test("_PSS must exist", pss is not None): 93 testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) 94 testsuite.print_detail('No _PSS exists') 95 continue 96 97 if not testsuite.test("_PSS must not be empty", pss.pstates): 98 testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) 99 testsuite.print_detail('_PSS is empty') 100 continue 101 102 testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) 103 for index, pstate in enumerate(pss.pstates): 104 testsuite.print_detail("P[{}]: {}".format(index, pstate)) 105 106 testsuite.test("_PSS must contain at most 16 Pstates", len(pss.pstates) <= 16) 107 testsuite.test("_PSS must have no duplicate Pstates", len(pss.pstates) == len(set(pss.pstates))) 108 109 frequencies = [p.core_frequency for p in pss.pstates] 110 testsuite.test("_PSS must list Pstates in descending order of frequency", frequencies == sorted(frequencies, reverse=True)) 111 112 testsuite.test("_PSS must have Pstates with no duplicate frequencies", len(frequencies) == len(set(frequencies))) 113 114 dissipations = [p.power for p in pss.pstates] 115 testsuite.test("_PSS must list Pstates in descending order of power dissipation", dissipations == sorted(dissipations, reverse=True)) 116 117def test_pstates(): 118 """Execute and verify frequency for each Pstate in the _PSS""" 119 IA32_PERF_CTL = 0x199 120 with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL): 121 cpupath_procid = acpi.find_procid() 122 cpupath_uid = acpi.find_uid() 123 apic = acpi.parse_apic() 124 procid_apicid = apic.procid_apicid 125 uid_x2apicid = apic.uid_x2apicid 126 def cpupath_apicid(cpupath): 127 if procid_apicid is not None: 128 procid = cpupath_procid.get(cpupath, None) 129 if procid is not None: 130 apicid = procid_apicid.get(procid, None) 131 if apicid is not None: 132 return apicid 133 if uid_x2apicid is not None: 134 uid = cpupath_uid.get(cpupath, None) 135 if uid is not None: 136 apicid = uid_x2apicid.get(uid, None) 137 if apicid is not None: 138 return apicid 139 return bits.cpus()[0] 140 141 bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000 142 143 uniques = acpi.parse_cpu_method("_PSS") 144 for pss, cpupaths in uniques.iteritems(): 145 if not testsuite.test("_PSS must exist", pss is not None): 146 testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) 147 testsuite.print_detail('No _PSS exists') 148 continue 149 150 for n, pstate in enumerate(pss.pstates): 151 for cpupath in cpupaths: 152 apicid = cpupath_apicid(cpupath) 153 if apicid is None: 154 print 'Failed to find apicid for cpupath {}'.format(cpupath) 155 continue 156 bits.wrmsr(apicid, IA32_PERF_CTL, pstate.control) 157 158 # Detecting Turbo frequency requires at least 2 pstates 159 # since turbo frequency = max non-turbo frequency + 1 160 turbo = False 161 if len(pss.pstates) >= 2: 162 turbo = (n == 0 and pstate.core_frequency == (pss.pstates[1].core_frequency + 1)) 163 if turbo: 164 # Needs to busywait, not sleep 165 start = time.time() 166 while (time.time() - start < 2): 167 pass 168 169 for duration in (0.1, 1.0): 170 frequency_data = bits.cpu_frequency(duration) 171 # Abort the test if no cpu frequency is not available 172 if frequency_data is None: 173 continue 174 aperf = frequency_data[1] 175 aperf = testutil.adjust_to_nearest(aperf, bclk/2) 176 aperf = int(aperf / 1000000) 177 if turbo: 178 if aperf >= pstate.core_frequency: 179 break 180 else: 181 if aperf == pstate.core_frequency: 182 break 183 184 if turbo: 185 testsuite.test("P{}: Turbo measured frequency {} >= expected {} MHz".format(n, aperf, pstate.core_frequency), aperf >= pstate.core_frequency) 186 else: 187 testsuite.test("P{}: measured frequency {} MHz == expected {} MHz".format(n, aperf, pstate.core_frequency), aperf == pstate.core_frequency) 188 189def test_psd_thread_scope(): 190 uniques = acpi.parse_cpu_method("_PSD") 191 if not testsuite.test("_PSD (P-State Dependency) must exist for each processor", None not in uniques): 192 testsuite.print_detail(acpi.factor_commonprefix(uniques[None])) 193 testsuite.print_detail('No _PSD exists') 194 return 195 unique_num_dependencies = {} 196 unique_num_entries = {} 197 unique_revision = {} 198 unique_domain = {} 199 unique_coordination_type = {} 200 unique_num_processors = {} 201 for value, cpupaths in uniques.iteritems(): 202 unique_num_dependencies.setdefault(len(value.dependencies), []).extend(cpupaths) 203 unique_num_entries.setdefault(value.dependencies[0].num_entries, []).extend(cpupaths) 204 unique_revision.setdefault(value.dependencies[0].revision, []).extend(cpupaths) 205 unique_domain.setdefault(value.dependencies[0].domain, []).extend(cpupaths) 206 unique_coordination_type.setdefault(value.dependencies[0].coordination_type, []).extend(cpupaths) 207 unique_num_processors.setdefault(value.dependencies[0].num_processors, []).extend(cpupaths) 208 def detail(d, fmt): 209 for value, cpupaths in sorted(d.iteritems(), key=(lambda (k,v): v)): 210 testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) 211 testsuite.print_detail(fmt.format(value)) 212 213 testsuite.test('Dependency count for each processor must be 1', unique_num_dependencies.keys() == [1]) 214 detail(unique_num_dependencies, 'Dependency count for each processor = {} (Expected 1)') 215 testsuite.test('_PSD.num_entries must be 5', unique_num_entries.keys() == [5]) 216 detail(unique_num_entries, 'num_entries = {} (Expected 5)') 217 testsuite.test('_PSD.revision must be 0', unique_revision.keys() == [0]) 218 detail(unique_revision, 'revision = {}') 219 testsuite.test('_PSD.coordination_type must be 0xFE (HW_ALL)', unique_coordination_type.keys() == [0xfe]) 220 detail(unique_coordination_type, 'coordination_type = {:#x} (Expected 0xFE HW_ALL)') 221 testsuite.test('_PSD.domain must be unique (thread-scoped) for each processor', len(unique_domain) == len(acpi.get_cpupaths())) 222 detail(unique_domain, 'domain = {:#x} (Expected a unique value for each processor)') 223 testsuite.test('_PSD.num_processors must be 1', unique_num_processors.keys() == [1]) 224 detail(unique_num_processors, 'num_processors = {} (Expected 1)') 225 226def test_table_checksum(data): 227 csum = sum(ord(c) for c in data) % 0x100 228 testsuite.test('ACPI table cumulative checksum must equal 0', csum == 0) 229 testsuite.print_detail("Cumulative checksum = {} (Expected 0)".format(csum)) 230 231def test_apic(): 232 data = acpi.get_table("APIC") 233 if data is None: 234 return 235 test_table_checksum(data) 236 apic = acpi.parse_apic() 237 238def test_dsdt(): 239 data = acpi.get_table("DSDT") 240 if data is None: 241 return 242 test_table_checksum(data) 243 244def test_facp(): 245 data = acpi.get_table("FACP") 246 if data is None: 247 return 248 test_table_checksum(data) 249 facp = acpi.parse_facp() 250 251def test_hpet(): 252 data = acpi.get_table("HPET") 253 if data is None: 254 return 255 test_table_checksum(data) 256 hpet = acpi.parse_hpet() 257 258def test_mpst(): 259 data = acpi.get_table("MPST") 260 if data is None: 261 return 262 test_table_checksum(data) 263 mpst = acpi.MPST(data) 264 265def test_rsdp(): 266 data = acpi.get_table("RSD PTR ") 267 if data is None: 268 return 269 270 # Checksum the first 20 bytes per ACPI 1.0 271 csum = sum(ord(c) for c in data[:20]) % 0x100 272 testsuite.test('ACPI 1.0 table first 20 bytes cummulative checksum must equal 0', csum == 0) 273 testsuite.print_detail("Cummulative checksum = {} (Expected 0)".format(csum)) 274 275 test_table_checksum(data) 276 rsdp = acpi.parse_rsdp() 277 278def test_xsdt(): 279 data = acpi.get_table("XSDT") 280 if data is None: 281 return 282 test_table_checksum(data) 283 xsdt = acpi.parse_xsdt() 284