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