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