187853babSAni Sinha# Copyright (c) 2015, Intel Corporation
287853babSAni Sinha# All rights reserved.
387853babSAni Sinha#
45a373924SAni Sinha# SPDX-License-Identifier: BSD-3-Clause
55a373924SAni Sinha#
687853babSAni Sinha# Redistribution and use in source and binary forms, with or without
787853babSAni Sinha# modification, are permitted provided that the following conditions are met:
887853babSAni Sinha#
987853babSAni Sinha#     * Redistributions of source code must retain the above copyright notice,
1087853babSAni Sinha#       this list of conditions and the following disclaimer.
1187853babSAni Sinha#     * Redistributions in binary form must reproduce the above copyright notice,
1287853babSAni Sinha#       this list of conditions and the following disclaimer in the documentation
1387853babSAni Sinha#       and/or other materials provided with the distribution.
1487853babSAni Sinha#     * Neither the name of Intel Corporation nor the names of its contributors
1587853babSAni Sinha#       may be used to endorse or promote products derived from this software
1687853babSAni Sinha#       without specific prior written permission.
1787853babSAni Sinha#
1887853babSAni Sinha# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1987853babSAni Sinha# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2087853babSAni Sinha# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2187853babSAni Sinha# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
2287853babSAni Sinha# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2387853babSAni Sinha# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2487853babSAni Sinha# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2587853babSAni Sinha# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2687853babSAni Sinha# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2787853babSAni Sinha# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2887853babSAni Sinha
295a373924SAni Sinha# This script runs only from the biosbits VM.
305a373924SAni Sinha
3187853babSAni Sinha"""Tests for ACPI"""
3287853babSAni Sinha
3387853babSAni Sinhaimport acpi
3487853babSAni Sinhaimport bits
3587853babSAni Sinhaimport bits.mwait
3687853babSAni Sinhaimport struct
3787853babSAni Sinhaimport testutil
3887853babSAni Sinhaimport testsuite
3987853babSAni Sinhaimport time
4087853babSAni Sinha
4187853babSAni Sinhadef register_tests():
4287853babSAni Sinha    testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests")
4391cab435SAni Sinha#    testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests")
4491cab435SAni Sinha#    testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests")
4587853babSAni Sinha    testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests")
4687853babSAni Sinha    testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests")
4787853babSAni Sinha    testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests")
4887853babSAni Sinha    testsuite.add_test("ACPI MADT (Multiple APIC Description Table)", test_apic, submenu="ACPI Tests")
4987853babSAni Sinha    testsuite.add_test("ACPI MPST (Memory Power State Table)", test_mpst, submenu="ACPI Tests")
5087853babSAni Sinha    testsuite.add_test("ACPI RSDP (Root System Description Pointer Structure)", test_rsdp, submenu="ACPI Tests")
5187853babSAni Sinha    testsuite.add_test("ACPI XSDT (Extended System Description Table)", test_xsdt, submenu="ACPI Tests")
5287853babSAni Sinha
5387853babSAni Sinhadef test_mat():
5487853babSAni Sinha    cpupaths = acpi.get_cpupaths()
5587853babSAni Sinha    apic = acpi.parse_apic()
5687853babSAni Sinha    procid_apicid = apic.procid_apicid
5787853babSAni Sinha    uid_x2apicid = apic.uid_x2apicid
5887853babSAni Sinha    for cpupath in cpupaths:
5987853babSAni Sinha        # Find the ProcId defined by the processor object
6087853babSAni Sinha        processor = acpi.evaluate(cpupath)
6187853babSAni Sinha        # Find the UID defined by the processor object's _UID method
6287853babSAni Sinha        uid = acpi.evaluate(cpupath + "._UID")
6387853babSAni Sinha        mat_buffer = acpi.evaluate(cpupath + "._MAT")
6487853babSAni Sinha        if mat_buffer is None:
6587853babSAni Sinha            continue
6687853babSAni Sinha        # Process each _MAT subtable
6787853babSAni Sinha        mat = acpi._MAT(mat_buffer)
6887853babSAni Sinha        for index, subtable in enumerate(mat):
6987853babSAni Sinha            if subtable.subtype == acpi.MADT_TYPE_LOCAL_APIC:
7087853babSAni Sinha                if subtable.flags.bits.enabled:
7187853babSAni Sinha                    testsuite.test("{} Processor declaration ProcId = _MAT ProcId".format(cpupath), processor.ProcId == subtable.proc_id)
7287853babSAni Sinha                    testsuite.print_detail("{} ProcId ({:#02x}) != _MAT ProcId ({:#02x})".format(cpupath, processor.ProcId, subtable.proc_id))
7387853babSAni Sinha                    testsuite.print_detail("Processor Declaration: {}".format(processor))
7487853babSAni Sinha                    testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
7587853babSAni Sinha                    if testsuite.test("{} with local APIC in _MAT has local APIC in MADT".format(cpupath), processor.ProcId in procid_apicid):
7687853babSAni Sinha                        testsuite.test("{} ApicId derived using Processor declaration ProcId = _MAT ApicId".format(cpupath), procid_apicid[processor.ProcId] == subtable.apic_id)
7787853babSAni Sinha                        testsuite.print_detail("{} ApicId derived from MADT ({:#02x}) != _MAT ApicId ({:#02x})".format(cpupath, procid_apicid[processor.ProcId], subtable.apic_id))
7887853babSAni Sinha                        testsuite.print_detail("Processor Declaration: {}".format(processor))
7987853babSAni Sinha                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
8087853babSAni Sinha            if subtable.subtype == acpi.MADT_TYPE_LOCAL_X2APIC:
8187853babSAni Sinha                if subtable.flags.bits.enabled:
8287853babSAni Sinha                    if testsuite.test("{} with x2Apic in _MAT has _UID".format(cpupath), uid is not None):
8387853babSAni Sinha                        testsuite.test("{}._UID = _MAT UID".format(cpupath), uid == subtable.uid)
8487853babSAni Sinha                        testsuite.print_detail("{}._UID ({:#x}) != _MAT UID ({:#x})".format(cpupath, uid, subtable.uid))
8587853babSAni Sinha                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
8687853babSAni Sinha                    if testsuite.test("{} with _MAT x2Apic has x2Apic in MADT".format(cpupath), subtable.uid in uid_x2apicid):
8787853babSAni Sinha                        testsuite.test("{} x2ApicId derived from MADT using UID = _MAT x2ApicId".format(cpupath), uid_x2apicid[subtable.uid] == subtable.x2apicid)
8887853babSAni Sinha                        testsuite.print_detail("{} x2ApicId derived from MADT ({:#02x}) != _MAT x2ApicId ({:#02x})".format(cpupath, uid_x2apicid[subtable.uid], subtable.x2apicid))
8987853babSAni Sinha                        testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable))
9087853babSAni Sinha
9187853babSAni Sinhadef test_pss():
9287853babSAni Sinha    uniques = acpi.parse_cpu_method("_PSS")
9387853babSAni Sinha    # We special-case None here to avoid a double-failure for CPUs without a _PSS
9487853babSAni Sinha    testsuite.test("_PSS must be identical for all CPUs", len(uniques) <= 1 or (len(uniques) == 2 and None in uniques))
9587853babSAni Sinha    for pss, cpupaths in uniques.iteritems():
9687853babSAni Sinha        if not testsuite.test("_PSS must exist", pss is not None):
9787853babSAni Sinha            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
9887853babSAni Sinha            testsuite.print_detail('No _PSS exists')
9987853babSAni Sinha            continue
10087853babSAni Sinha
10187853babSAni Sinha        if not testsuite.test("_PSS must not be empty", pss.pstates):
10287853babSAni Sinha            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
10387853babSAni Sinha            testsuite.print_detail('_PSS is empty')
10487853babSAni Sinha            continue
10587853babSAni Sinha
10687853babSAni Sinha        testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
10787853babSAni Sinha        for index, pstate in enumerate(pss.pstates):
10887853babSAni Sinha            testsuite.print_detail("P[{}]: {}".format(index, pstate))
10987853babSAni Sinha
11087853babSAni Sinha        testsuite.test("_PSS must contain at most 16 Pstates", len(pss.pstates) <= 16)
11187853babSAni Sinha        testsuite.test("_PSS must have no duplicate Pstates", len(pss.pstates) == len(set(pss.pstates)))
11287853babSAni Sinha
11387853babSAni Sinha        frequencies = [p.core_frequency for p in pss.pstates]
11487853babSAni Sinha        testsuite.test("_PSS must list Pstates in descending order of frequency", frequencies == sorted(frequencies, reverse=True))
11587853babSAni Sinha
11687853babSAni Sinha        testsuite.test("_PSS must have Pstates with no duplicate frequencies", len(frequencies) == len(set(frequencies)))
11787853babSAni Sinha
11887853babSAni Sinha        dissipations = [p.power for p in pss.pstates]
11987853babSAni Sinha        testsuite.test("_PSS must list Pstates in descending order of power dissipation", dissipations == sorted(dissipations, reverse=True))
12087853babSAni Sinha
12187853babSAni Sinhadef test_pstates():
12287853babSAni Sinha    """Execute and verify frequency for each Pstate in the _PSS"""
12387853babSAni Sinha    IA32_PERF_CTL = 0x199
12487853babSAni Sinha    with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL):
12587853babSAni Sinha        cpupath_procid = acpi.find_procid()
12687853babSAni Sinha        cpupath_uid = acpi.find_uid()
12787853babSAni Sinha        apic = acpi.parse_apic()
12887853babSAni Sinha        procid_apicid = apic.procid_apicid
12987853babSAni Sinha        uid_x2apicid = apic.uid_x2apicid
13087853babSAni Sinha        def cpupath_apicid(cpupath):
13187853babSAni Sinha            if procid_apicid is not None:
13287853babSAni Sinha                procid = cpupath_procid.get(cpupath, None)
13387853babSAni Sinha                if procid is not None:
13487853babSAni Sinha                    apicid = procid_apicid.get(procid, None)
13587853babSAni Sinha                    if apicid is not None:
13687853babSAni Sinha                        return apicid
13787853babSAni Sinha            if uid_x2apicid is not None:
13887853babSAni Sinha                uid = cpupath_uid.get(cpupath, None)
13987853babSAni Sinha                if uid is not None:
14087853babSAni Sinha                    apicid = uid_x2apicid.get(uid, None)
14187853babSAni Sinha                    if apicid is not None:
14287853babSAni Sinha                        return apicid
14387853babSAni Sinha            return bits.cpus()[0]
14487853babSAni Sinha
14587853babSAni Sinha        bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000
14687853babSAni Sinha
14787853babSAni Sinha        uniques = acpi.parse_cpu_method("_PSS")
14887853babSAni Sinha        for pss, cpupaths in uniques.iteritems():
14987853babSAni Sinha            if not testsuite.test("_PSS must exist", pss is not None):
15087853babSAni Sinha                testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
15187853babSAni Sinha                testsuite.print_detail('No _PSS exists')
15287853babSAni Sinha                continue
15387853babSAni Sinha
15487853babSAni Sinha            for n, pstate in enumerate(pss.pstates):
15587853babSAni Sinha                for cpupath in cpupaths:
15687853babSAni Sinha                    apicid = cpupath_apicid(cpupath)
15787853babSAni Sinha                    if apicid is None:
15887853babSAni Sinha                        print 'Failed to find apicid for cpupath {}'.format(cpupath)
15987853babSAni Sinha                        continue
16087853babSAni Sinha                    bits.wrmsr(apicid, IA32_PERF_CTL, pstate.control)
16187853babSAni Sinha
16287853babSAni Sinha                # Detecting Turbo frequency requires at least 2 pstates
16387853babSAni Sinha                # since turbo frequency = max non-turbo frequency + 1
16487853babSAni Sinha                turbo = False
16587853babSAni Sinha                if len(pss.pstates) >= 2:
16687853babSAni Sinha                    turbo = (n == 0 and pstate.core_frequency == (pss.pstates[1].core_frequency + 1))
16787853babSAni Sinha                    if turbo:
16887853babSAni Sinha                        # Needs to busywait, not sleep
16987853babSAni Sinha                        start = time.time()
17087853babSAni Sinha                        while (time.time() - start < 2):
17187853babSAni Sinha                            pass
17287853babSAni Sinha
17387853babSAni Sinha                for duration in (0.1, 1.0):
17487853babSAni Sinha                    frequency_data = bits.cpu_frequency(duration)
17587853babSAni Sinha                    # Abort the test if no cpu frequency is not available
17687853babSAni Sinha                    if frequency_data is None:
17787853babSAni Sinha                        continue
17887853babSAni Sinha                    aperf = frequency_data[1]
17987853babSAni Sinha                    aperf = testutil.adjust_to_nearest(aperf, bclk/2)
18087853babSAni Sinha                    aperf = int(aperf / 1000000)
18187853babSAni Sinha                    if turbo:
18287853babSAni Sinha                        if aperf >= pstate.core_frequency:
18387853babSAni Sinha                            break
18487853babSAni Sinha                    else:
18587853babSAni Sinha                        if aperf == pstate.core_frequency:
18687853babSAni Sinha                            break
18787853babSAni Sinha
18887853babSAni Sinha                if turbo:
18987853babSAni Sinha                    testsuite.test("P{}: Turbo measured frequency {} >= expected {} MHz".format(n, aperf, pstate.core_frequency), aperf >= pstate.core_frequency)
19087853babSAni Sinha                else:
19187853babSAni Sinha                    testsuite.test("P{}: measured frequency {} MHz == expected {} MHz".format(n, aperf, pstate.core_frequency), aperf == pstate.core_frequency)
19287853babSAni Sinha
19387853babSAni Sinhadef test_psd_thread_scope():
19487853babSAni Sinha    uniques = acpi.parse_cpu_method("_PSD")
19587853babSAni Sinha    if not testsuite.test("_PSD (P-State Dependency) must exist for each processor", None not in uniques):
19687853babSAni Sinha        testsuite.print_detail(acpi.factor_commonprefix(uniques[None]))
19787853babSAni Sinha        testsuite.print_detail('No _PSD exists')
19887853babSAni Sinha        return
19987853babSAni Sinha    unique_num_dependencies = {}
20087853babSAni Sinha    unique_num_entries = {}
20187853babSAni Sinha    unique_revision = {}
20287853babSAni Sinha    unique_domain = {}
20387853babSAni Sinha    unique_coordination_type = {}
20487853babSAni Sinha    unique_num_processors = {}
20587853babSAni Sinha    for value, cpupaths in uniques.iteritems():
20687853babSAni Sinha        unique_num_dependencies.setdefault(len(value.dependencies), []).extend(cpupaths)
20787853babSAni Sinha        unique_num_entries.setdefault(value.dependencies[0].num_entries, []).extend(cpupaths)
20887853babSAni Sinha        unique_revision.setdefault(value.dependencies[0].revision, []).extend(cpupaths)
20987853babSAni Sinha        unique_domain.setdefault(value.dependencies[0].domain, []).extend(cpupaths)
21087853babSAni Sinha        unique_coordination_type.setdefault(value.dependencies[0].coordination_type, []).extend(cpupaths)
21187853babSAni Sinha        unique_num_processors.setdefault(value.dependencies[0].num_processors, []).extend(cpupaths)
21287853babSAni Sinha    def detail(d, fmt):
21387853babSAni Sinha        for value, cpupaths in sorted(d.iteritems(), key=(lambda (k,v): v)):
21487853babSAni Sinha            testsuite.print_detail(acpi.factor_commonprefix(cpupaths))
21587853babSAni Sinha            testsuite.print_detail(fmt.format(value))
21687853babSAni Sinha
21787853babSAni Sinha    testsuite.test('Dependency count for each processor must be 1', unique_num_dependencies.keys() == [1])
21887853babSAni Sinha    detail(unique_num_dependencies, 'Dependency count for each processor = {} (Expected 1)')
21987853babSAni Sinha    testsuite.test('_PSD.num_entries must be 5', unique_num_entries.keys() == [5])
22087853babSAni Sinha    detail(unique_num_entries, 'num_entries = {} (Expected 5)')
22187853babSAni Sinha    testsuite.test('_PSD.revision must be 0', unique_revision.keys() == [0])
22287853babSAni Sinha    detail(unique_revision, 'revision = {}')
22387853babSAni Sinha    testsuite.test('_PSD.coordination_type must be 0xFE (HW_ALL)', unique_coordination_type.keys() == [0xfe])
22487853babSAni Sinha    detail(unique_coordination_type, 'coordination_type = {:#x} (Expected 0xFE HW_ALL)')
22587853babSAni Sinha    testsuite.test('_PSD.domain must be unique (thread-scoped) for each processor', len(unique_domain) == len(acpi.get_cpupaths()))
22687853babSAni Sinha    detail(unique_domain, 'domain = {:#x} (Expected a unique value for each processor)')
22787853babSAni Sinha    testsuite.test('_PSD.num_processors must be 1', unique_num_processors.keys() == [1])
22887853babSAni Sinha    detail(unique_num_processors, 'num_processors = {} (Expected 1)')
22987853babSAni Sinha
23087853babSAni Sinhadef test_table_checksum(data):
23187853babSAni Sinha    csum = sum(ord(c) for c in data) % 0x100
23287853babSAni Sinha    testsuite.test('ACPI table cumulative checksum must equal 0', csum == 0)
23387853babSAni Sinha    testsuite.print_detail("Cumulative checksum = {} (Expected 0)".format(csum))
23487853babSAni Sinha
23587853babSAni Sinhadef test_apic():
23687853babSAni Sinha    data = acpi.get_table("APIC")
23787853babSAni Sinha    if data is None:
23887853babSAni Sinha        return
23987853babSAni Sinha    test_table_checksum(data)
24087853babSAni Sinha    apic = acpi.parse_apic()
24187853babSAni Sinha
24287853babSAni Sinhadef test_dsdt():
24387853babSAni Sinha    data = acpi.get_table("DSDT")
24487853babSAni Sinha    if data is None:
24587853babSAni Sinha        return
24687853babSAni Sinha    test_table_checksum(data)
24787853babSAni Sinha
24887853babSAni Sinhadef test_facp():
24987853babSAni Sinha    data = acpi.get_table("FACP")
25087853babSAni Sinha    if data is None:
25187853babSAni Sinha        return
25287853babSAni Sinha    test_table_checksum(data)
25387853babSAni Sinha    facp = acpi.parse_facp()
25487853babSAni Sinha
25587853babSAni Sinhadef test_hpet():
25687853babSAni Sinha    data = acpi.get_table("HPET")
25787853babSAni Sinha    if data is None:
25887853babSAni Sinha        return
25987853babSAni Sinha    test_table_checksum(data)
26087853babSAni Sinha    hpet = acpi.parse_hpet()
26187853babSAni Sinha
26287853babSAni Sinhadef test_mpst():
26387853babSAni Sinha    data = acpi.get_table("MPST")
26487853babSAni Sinha    if data is None:
26587853babSAni Sinha        return
26687853babSAni Sinha    test_table_checksum(data)
26787853babSAni Sinha    mpst = acpi.MPST(data)
26887853babSAni Sinha
26987853babSAni Sinhadef test_rsdp():
27087853babSAni Sinha    data = acpi.get_table("RSD PTR ")
27187853babSAni Sinha    if data is None:
27287853babSAni Sinha        return
27387853babSAni Sinha
27487853babSAni Sinha    # Checksum the first 20 bytes per ACPI 1.0
27587853babSAni Sinha    csum = sum(ord(c) for c in data[:20]) % 0x100
27696420a30SMichael Tokarev    testsuite.test('ACPI 1.0 table first 20 bytes cumulative checksum must equal 0', csum == 0)
27796420a30SMichael Tokarev    testsuite.print_detail("Cumulative checksum = {} (Expected 0)".format(csum))
27887853babSAni Sinha
27987853babSAni Sinha    test_table_checksum(data)
28087853babSAni Sinha    rsdp = acpi.parse_rsdp()
28187853babSAni Sinha
28287853babSAni Sinhadef test_xsdt():
28387853babSAni Sinha    data = acpi.get_table("XSDT")
28487853babSAni Sinha    if data is None:
28587853babSAni Sinha        return
28687853babSAni Sinha    test_table_checksum(data)
28787853babSAni Sinha    xsdt = acpi.parse_xsdt()
288