From patchwork Mon Jun 27 07:28:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896320 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2105EC433EF for ; Mon, 27 Jun 2022 07:34:53 +0000 (UTC) Received: from localhost ([::1]:59454 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jGm-0002eR-7y for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:34:52 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55574) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jBS-0003e7-Iu for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:29:22 -0400 Received: from mail-pj1-x1036.google.com ([2607:f8b0:4864:20::1036]:35535) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jBR-0005eX-5x for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:29:22 -0400 Received: by mail-pj1-x1036.google.com with SMTP id x1-20020a17090abc8100b001ec7f8a51f5so11535995pjr.0 for ; Mon, 27 Jun 2022 00:29:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=W7jXqIdXZQPkgSueqM6O32O53MWeJR4fQ7cpQitnJZY=; b=CMpZOq43vBg/0vs7NaZ0tLCN7YsXZei4OIiSCmJOb+2FFxojACQ1R6uOtNLwK2E7d9 IxNcZu8DS5TI4d8pAIgu1/XK70158VhtHNW10kaS6Rt3O8TyPXD2bRvQBvpX2h2pwAsq VcRpu4ZJLfA/NX6o3C/oe1v2ANei7aPBMX6AGyV8KbbfY/R5SzvFv7OoozHrNfh2IGnY J+V5ktAaHDCpvDsxDNLBv98NLxqI+tU/6x6JEd0p3Uvf2IpOaRYJhiLi0SLHtfQ1GLZR jEaFzL/AS0P+CGQIaRtwCC8INU1kWBCJOs50DQPVA1O7JastRrV/omM15ob59MD41f3z 135A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=W7jXqIdXZQPkgSueqM6O32O53MWeJR4fQ7cpQitnJZY=; b=siUzLbvhnjpNkSVpvkyIFJy1nE8Xm1F9y+sbb9TFpEnl/R5w+cy5xf92RiMCi735sI Ka3uKBmKM46C4OMDFRu5GDX658Hogb6RDmcagifkrJjMSyszZ+5UkXwWsXGq9DSkUIE8 PXh289fX9pX5UI+DLR9psijleT+Ij0Wo9AfVrjQo0HIf/Lwa2ed16vvuemXVLUAKIxKM rWCHC6GtJFMCz/AY9N9f9bIdu6IzEWZ+Nin8WHmGlb4Xq4CBY3SoQodAEYVovDlP1Erk W+yoFoE/EONOGCQErwaBMjonGoQIu0FnEjsEsqxP3AGSl7ZLTKnvXCTZc57rsUbiHgr8 x/0g== X-Gm-Message-State: AJIora/JMKO9Bm2/nCNVGygtko8YUvRGKVYV9qvkFiPCVKp1ckQKso/3 YULFv43+mX6TG9fPfqhHq2NiJHYCxonEt6Xp7xc= X-Google-Smtp-Source: AGRyM1sxGuqkQEjBjo0laBdPIWY7bRaCKlbVyrBheyWr/hloKfS08n0m0SslNzaT3WkzsGM6dD3IiA== X-Received: by 2002:a17:902:cec4:b0:16a:16d6:f67f with SMTP id d4-20020a170902cec400b0016a16d6f67fmr12855360plg.139.1656314958693; Mon, 27 Jun 2022 00:29:18 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.29.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:29:18 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 01/12] qtest: meson.build changes required to integrate python based qtests Date: Mon, 27 Jun 2022 12:58:45 +0530 Message-Id: <20220627072856.1529357-2-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::1036; envelope-from=ani@anisinha.ca; helo=mail-pj1-x1036.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" These are some basic changes required in meson.build file in order to incorporate python based qtests later on. No new qtests have been added in this change. Signed-off-by: Ani Sinha --- tests/qtest/meson.build | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 31287a9173..ad52f1c81b 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -310,6 +310,8 @@ qtests += {'dbus-display-test': [dbus_display1, gio]} endif qtest_executables = {} +other_deps = [] + foreach dir : target_dirs if not dir.endswith('-softmmu') continue @@ -327,6 +329,7 @@ foreach dir : target_dirs endif qtest_env.set('G_TEST_DBUS_DAEMON', meson.project_source_root() / 'tests/dbus-vmstate-daemon.sh') qtest_env.set('QTEST_QEMU_BINARY', './qemu-system-' + target_base) + qtest_env.set('QTEST_SOURCE_ROOT', meson.project_source_root()) if have_tools and have_vhost_user_blk_server qtest_env.set('QTEST_QEMU_STORAGE_DAEMON_BINARY', './storage-daemon/qemu-storage-daemon') test_deps += [qsd] @@ -351,7 +354,7 @@ foreach dir : target_dirs endif test('qtest-@0@/@1@'.format(target_base, test), qtest_executables[test], - depends: [test_deps, qtest_emulator, emulator_modules], + depends: [test_deps, qtest_emulator, emulator_modules, other_deps], env: qtest_env, args: ['--tap', '-k'], protocol: 'tap', From patchwork Mon Jun 27 07:28:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896340 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5CC43C43334 for ; Mon, 27 Jun 2022 07:42:19 +0000 (UTC) Received: from localhost ([::1]:46068 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jNy-0004Qz-9t for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:42:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55930) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCY-00054l-QR for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:30 -0400 Received: from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035]:35541) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCU-0005yG-A5 for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:30 -0400 Received: by mail-pj1-x1035.google.com with SMTP id x1-20020a17090abc8100b001ec7f8a51f5so11538541pjr.0 for ; Mon, 27 Jun 2022 00:30:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=X5BPFgbaCrYTpJYhceeVqQEocIj0KdTdNfpslHR6prU=; b=oMtA2t61GCOP8ZX0CEwIZwtnMMLBEigTW4SZz4WtrOsyDUuOlKcDuoRJIHRj07nJeS XKKtz6c6tigEg+AEyjXR+hNc8GmVCHy/ARWTK5xro4dbL/EoT0gjYd2j/XX4MZTto2la fnTKvCn0q0a03l+cL6KDwm7tHZ8l3Pyr6yBEmeL1OkCocZWkcVg0mLBD9y/Pf5HTZMJ5 GJ5bpr7VUK5VxnOLotFd1WUucSSwR7GH9X4dsQatrRQL9pK8ukX6sfjXepU0tJL57qWz IV6kkR/oNZrK5DDMgsE3SSRV/lqaW8I/1yxjGdTZWiUAjS+Z5C3sIp+QTBZm46kwwbkN ezZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=X5BPFgbaCrYTpJYhceeVqQEocIj0KdTdNfpslHR6prU=; b=uPdxnzwbJhZDtxQXeMGvVKXHrwC5+Flq4krtffcaoLgvzvXDxiuW12M2hDqBCAufYm LUH4T3/CPgM2YuRoEMvLW3K9gcwnPxjrYBjVsNjb21kRx6IFyNIrsSmjyI+doi1ei9LB /sjXe35wJHe0ktcWh0fm+d7O+rpKpfBtenWSH+ARlxQh6KV6GXmgSduZFP36UG8MxMp3 xgaLkuXliqC0BC7DHk99nvSaHWs4UvPEt2XjM1y6uDXkjhbOHXF0YCT+Iyozl2Z3lI5y SjRXpHEFmxxe0PnZS65gLJOzfSnNSkZzCnJEp116ZHdP7hzB7F7NWBgWFzfeScZ7GVbs 5L7w== X-Gm-Message-State: AJIora/fKUYy4slpx4rsnV2zk8iU2n67M09/wShDYXpzbGmDEwP4wL4v xA8I6UNghW0WoThFDZwhEVWm+kGlzppw+rdwOoc= X-Google-Smtp-Source: AGRyM1s1D7soANI3G5zxf/0s/A6mKILMMHGJils1urZV6XjFlqfDe+RXhun/gYkkqxkLO5EUrf6jFw== X-Received: by 2002:a17:902:7c0d:b0:16b:7dd2:626c with SMTP id x13-20020a1709027c0d00b0016b7dd2626cmr3853099pll.152.1656315023591; Mon, 27 Jun 2022 00:30:23 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:23 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 04/12] acpi/tests/bits: initial commit of test scripts that are run by biosbits Date: Mon, 27 Jun 2022 12:58:48 +0530 Message-Id: <20220627072856.1529357-5-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::1035; envelope-from=ani@anisinha.ca; helo=mail-pj1-x1035.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This is initial commit of cpuid, acpi and smbios python test scripts for biosbits to execute. No change has been made to them from the original code written by the biosbits author Josh Triplett. They are required to be installed into the bits iso file and then run from within the virtual machine booted off with biosbits iso. The original location of these tests are here: https://github.com/biosbits/bits/blob/master/python/testacpi.py https://github.com/biosbits/bits/blob/master/python/smbios.py https://github.com/biosbits/bits/blob/master/python/testcpuid.py Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/bits-tests/meson.build | 11 + tests/qtest/acpi-bits/bits-tests/smbios.py | 2430 +++++++++++++++++ tests/qtest/acpi-bits/bits-tests/testacpi.py | 283 ++ tests/qtest/acpi-bits/bits-tests/testcpuid.py | 83 + 4 files changed, 2807 insertions(+) create mode 100644 tests/qtest/acpi-bits/bits-tests/meson.build create mode 100644 tests/qtest/acpi-bits/bits-tests/smbios.py create mode 100644 tests/qtest/acpi-bits/bits-tests/testacpi.py create mode 100644 tests/qtest/acpi-bits/bits-tests/testcpuid.py diff --git a/tests/qtest/acpi-bits/bits-tests/meson.build b/tests/qtest/acpi-bits/bits-tests/meson.build new file mode 100644 index 0000000000..3056731a53 --- /dev/null +++ b/tests/qtest/acpi-bits/bits-tests/meson.build @@ -0,0 +1,11 @@ +test_files = ['smbios.py', 'testacpi.py', 'testcpuid.py'] + +copytestfiles = custom_target('copy test files', + input : test_files, + output : test_files, + command : ['cp', '@INPUT@', '@OUTDIR@'], + install : true, + install_dir : 'bits-tests', + build_by_default : true) + +other_deps += copytestfiles diff --git a/tests/qtest/acpi-bits/bits-tests/smbios.py b/tests/qtest/acpi-bits/bits-tests/smbios.py new file mode 100644 index 0000000000..9667d0542c --- /dev/null +++ b/tests/qtest/acpi-bits/bits-tests/smbios.py @@ -0,0 +1,2430 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""SMBIOS/DMI module.""" + +import bits +import bitfields +import ctypes +import redirect +import struct +import uuid +import unpack +import ttypager +import sys + +class SMBIOS(unpack.Struct): + def __new__(cls): + if sys.platform == "BITS-EFI": + import efi + sm_ptr = efi.system_table.ConfigurationTableDict.get(efi.SMBIOS_TABLE_GUID) + else: + address = 0xF0000 + mem = bits.memory(0xF0000, 0x10000) + for offset in range(0, len(mem), 16): + signature = (ctypes.c_char * 4).from_address(address + offset).value + if signature == "_SM_": + entry_point_length = ctypes.c_ubyte.from_address(address + offset + 5).value + csum = sum(map(ord, mem[offset:offset + entry_point_length])) & 0xff + if csum == 0: + sm_ptr = address + offset + break + else: + return None + + if not sm_ptr: + return None + + sm = super(SMBIOS, cls).__new__(cls) + sm._header_memory = bits.memory(sm_ptr, 0x1f) + return sm + + def __init__(self): + super(SMBIOS, self).__init__() + u = unpack.Unpackable(self._header_memory) + self.add_field('header', Header(u)) + self._structure_memory = bits.memory(self.header.structure_table_address, self.header.structure_table_length) + u = unpack.Unpackable(self._structure_memory) + self.add_field('structures', unpack.unpack_all(u, _smbios_structures, self), unpack.format_each("\n\n{!r}")) + + def structure_type(self, num): + '''Dumps structure of given Type if present''' + try: + types_present = [self.structures[x].smbios_structure_type for x in range(len(self.structures))] + matrix = dict() + for index in range(len(types_present)): + if types_present.count(types_present[index]) == 1: + matrix[types_present[index]] = self.structures[index] + else: # if multiple structures of the same type, return a list of structures for the type number + if matrix.has_key(types_present[index]): + matrix[types_present[index]].append(self.structures[index]) + else: + matrix[types_present[index]] = [self.structures[index]] + return matrix[num] + except: + print "Failure: Type {} - not found".format(num) + +class Header(unpack.Struct): + def __new__(cls, u): + return super(Header, cls).__new__(cls) + + def __init__(self, u): + super(Header, self).__init__() + self.raw_data = u.unpack_rest() + u = unpack.Unpackable(self.raw_data) + self.add_field('anchor_string', u.unpack_one("4s")) + self.add_field('checksum', u.unpack_one("B")) + self.add_field('length', u.unpack_one("B")) + self.add_field('major_version', u.unpack_one("B")) + self.add_field('minor_version', u.unpack_one("B")) + self.add_field('max_structure_size', u.unpack_one(" len(self.strings): + return "(error: string index out of range)" + return self.strings[i - 1] + +class BIOSInformation(SmbiosBaseStructure): + smbios_structure_type = 0 + + def __init__(self, u, sm): + super(BIOSInformation, self).__init__(u, sm) + u = self.u + try: + self.add_field('vendor', u.unpack_one("B"), self.fmtstr) + self.add_field('version', u.unpack_one("B"), self.fmtstr) + self.add_field('starting_address_segment', u.unpack_one("= (2,"4"): + characteristic_bytes = 2 + else: + characteristic_bytes = self.length - 0x12 + self.add_field('characteristics_extensions', [u.unpack_one("B") for b in range(characteristic_bytes)]) + if (sm.header.major_version, minor_version_str) >= (2,"4"): + self.add_field('major_release', u.unpack_one("B")) + self.add_field('minor_release', u.unpack_one("B")) + self.add_field('ec_major_release', u.unpack_one("B")) + self.add_field('ec_minor_release', u.unpack_one("B")) + except: + self.decode_failure = True + print "Error parsing BIOSInformation" + import traceback + traceback.print_exc() + self.fini() + +class SystemInformation(SmbiosBaseStructure): + smbios_structure_type = 1 + + def __init__(self, u, sm): + super(SystemInformation, self).__init__(u, sm) + u = self.u + try: + self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) + self.add_field('product_name', u.unpack_one("B"), self.fmtstr) + self.add_field('version', u.unpack_one("B"), self.fmtstr) + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x8: + self.add_field('uuid', uuid.UUID(bytes_le=u.unpack_one("16s"))) + wakeup_types = { + 0: 'Reserved', + 1: 'Other', + 2: 'Unknown', + 3: 'APM Timer', + 4: 'Modem Ring', + 5: 'LAN Remote', + 6: 'Power Switch', + 7: 'PCI PME#', + 8: 'AC Power Restored' + } + self.add_field('wakeup_type', u.unpack_one("B"), unpack.format_table("{}", wakeup_types)) + if self.length > 0x19: + self.add_field('sku_number', u.unpack_one("B"), self.fmtstr) + self.add_field('family', u.unpack_one("B"), self.fmtstr) + except: + self.decode_failure = True + print "Error parsing SystemInformation" + import traceback + traceback.print_exc() + self.fini() + +_board_types = { + 1: 'Unknown', + 2: 'Other', + 3: 'Server Blade', + 4: 'Connectivity Switch', + 5: 'System Management Module', + 6: 'Processor Module', + 7: 'I/O Module', + 8: 'Memory Module', + 9: 'Daughter Board', + 0xA: 'Motherboard', + 0xB: 'Processor/Memory Module', + 0xC: 'Processor/IO Module', + 0xD: 'Interconnect Board' +} + +class BaseboardInformation(SmbiosBaseStructure): + smbios_structure_type = 2 + + def __init__(self, u, sm): + super(BaseboardInformation, self).__init__(u, sm) + u = self.u + try: + self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) + self.add_field('product', u.unpack_one("B"), self.fmtstr) + self.add_field('version', u.unpack_one("B"), self.fmtstr) + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + + if self.length > 0x8: + self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) + + if self.length > 0x9: + self.add_field('feature_flags', u.unpack_one("B")) + self.add_field('hosting_board', bool(bitfields.getbits(self.feature_flags, 0)), "feature_flags[0]={}") + self.add_field('requires_daughter_card', bool(bitfields.getbits(self.feature_flags, 1)), "feature_flags[1]={}") + self.add_field('removable', bool(bitfields.getbits(self.feature_flags, 2)), "feature_flags[2]={}") + self.add_field('replaceable', bool(bitfields.getbits(self.feature_flags, 3)), "feature_flags[3]={}") + self.add_field('hot_swappable', bool(bitfields.getbits(self.feature_flags, 4)), "feature_flags[4]={}") + + if self.length > 0xA: + self.add_field('location', u.unpack_one("B"), self.fmtstr) + + if self.length > 0xB: + self.add_field('chassis_handle', u.unpack_one(" 0xD: + self.add_field('board_type', u.unpack_one("B"), unpack.format_table("{}", _board_types)) + + if self.length > 0xE: + self.add_field('handle_count', u.unpack_one("B")) + if self.handle_count > 0: + self.add_field('contained_object_handles', tuple(u.unpack_one(" 9: + chassis_states = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Safe', + 0x04: 'Warning', + 0x05: 'Critical', + 0x06: 'Non-recoverable', + } + self.add_field('bootup_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) + self.add_field('power_supply_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) + self.add_field('thermal_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) + security_states = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'None', + 0x04: 'External interface locked out', + 0x05: 'External interface enabled', + } + self.add_field('security_status', u.unpack_one("B"), unpack.format_table("{}", security_states)) + if self.length > 0xd: + self.add_field('oem_defined', u.unpack_one(" 0x11: + self.add_field('height', u.unpack_one("B")) + self.add_field('num_power_cords', u.unpack_one("B")) + self.add_field('contained_element_count', u.unpack_one("B")) + self.add_field('contained_element_length', u.unpack_one("B")) + if getattr(self, 'contained_element_count', 0): + self.add_field('contained_elements', tuple(SystemEnclosureContainedElement(u, self.contained_element_length) for i in range(self.contained_element_count))) + if self.length > (0x15 + (getattr(self, 'contained_element_count', 0) * getattr(self, 'contained_element_length', 0))): + self.add_field('sku_number', u.unpack_one("B"), self.fmtstr) + except: + self.decode_failure = True + print "Error parsing SystemEnclosure" + import traceback + traceback.print_exc() + self.fini() + +class SystemEnclosureContainedElement(unpack.Struct): + def __init__(self, u, length): + super(SystemEnclosureContainedElement, self).__init__() + self.start_offset = u.offset + self.raw_data = u.unpack_raw(length) + self.u = unpack.Unpackable(self.raw_data) + u = self.u + self.add_field('contained_element_type', u.unpack_one("B")) + type_selections = { + 0: 'SMBIOS baseboard type enumeration', + 1: 'SMBIOS structure type enumeration', + } + self.add_field('type_select', bitfields.getbits(self.contained_element_type, 7), unpack.format_table("contained_element_type[7]={}", type_selections)) + self.add_field('type', bitfields.getbits(self.contained_element_type, 6, 0)) + if self.type_select == 0: + self.add_field('smbios_board_type', self.type, unpack.format_table("{}", _board_types)) + else: + self.add_field('smbios_structure_type', self.type) + self.add_field('minimum', u.unpack_one("B")) + self.add_field('maximum', u.unpack_one("B")) + if not u.at_end(): + self.add_field('data', u.unpack_rest()) + del self.u + +class ProcessorInformation(SmbiosBaseStructure): + smbios_structure_type = 4 + + def __init__(self, u, sm): + super(ProcessorInformation, self).__init__(u, sm) + u = self.u + try: + self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr) + processor_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Central Processor', + 0x04: 'Math Processor', + 0x05: 'DSP Processor', + 0x06: 'Video Processor', + } + self.add_field('processor_type', u.unpack_one("B"), unpack.format_table("{}", processor_types)) + self.add_field('processor_family', u.unpack_one("B")) + self.add_field('processor_manufacturer', u.unpack_one("B"), self.fmtstr) + self.add_field('processor_id', u.unpack_one(" 0x1A: + self.add_field('l1_cache_handle', u.unpack_one(" 0x20: + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) + self.add_field('part_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x24: + self.add_field('core_count', u.unpack_one("B")) + self.add_field('core_enabled', u.unpack_one("B")) + self.add_field('thread_count', u.unpack_one("B")) + self.add_field('processor_characteristics', u.unpack_one(" 0x28: + self.add_field('processor_family_2', u.unpack_one(" 0x2A: + self.add_field('core_count2', u.unpack_one(" 0x0F: + self.add_field('cache_speed', u.unpack_one("B")) + if self.length > 0x10: + _error_correction = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'None', + 0x04: 'Parity', + 0x05: 'Single-bit ECC', + 0x06: 'Multi-bit ECC' + } + self.add_field('error_correction', u.unpack_one("B"), unpack.format_table("{}", _error_correction)) + if self.length > 0x10: + _system_cache_type = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Instruction', + 0x04: 'Data', + 0x05: 'Unified' + } + self.add_field('system_cache_type', u.unpack_one("B"), unpack.format_table("{}", _system_cache_type)) + if self.length > 0x12: + _associativity = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Direct Mapped', + 0x04: '2-way Set-Associative', + 0x05: '4-way Set-Associative', + 0x06: 'Fully Associative', + 0x07: '8-way Set-Associative', + 0x08: '16-way Set-Associative', + 0x09: '12-way Set-Associative', + 0x0A: '24-way Set-Associative', + 0x0B: '32-way Set-Associative', + 0x0C: '48-way Set-Associative', + 0x0D: '64-way Set-Associative', + 0x0E: '20-way Set-Associative' + } + self.add_field('associativity', u.unpack_one("B"), unpack.format_table("{}", _associativity)) + + except: + self.decode_failure = True + print "Error parsing CacheInformation" + import traceback + traceback.print_exc() + self.fini() + +class PortConnectorInfo(SmbiosBaseStructure): + smbios_structure_type = 8 + + def __init__(self, u, sm): + super(PortConnectorInfo, self).__init__(u, sm) + u = self.u + try: + self.add_field('internal_reference_designator', u.unpack_one("B"), self.fmtstr) + connector_types = { + 0x00: 'None', + 0x01: 'Centronics', + 0x02: 'Mini Centronics', + 0x03: 'Proprietary', + 0x04: 'DB-25 pin male', + 0x05: 'DB-25 pin female', + 0x06: 'DB-15 pin male', + 0x07: 'DB-15 pin female', + 0x08: 'DB-9 pin male', + 0x09: 'DB-9 pin female', + 0x0A: 'RJ-11', + 0x0B: 'RJ-45', + 0x0C: '50-pin MiniSCSI', + 0x0D: 'Mini-DIN', + 0x0E: 'Micro-DIN', + 0x0F: 'PS/2', + 0x10: 'Infrared', + 0x11: 'HP-HIL', + 0x12: 'Access Bus (USB)', + 0x13: 'SSA SCSI', + 0x14: 'Circular DIN-8 male', + 0x15: 'Circular DIN-8 female', + 0x16: 'On Board IDE', + 0x17: 'On Board Floppy', + 0x18: '9-pin Dual Inline (pin 10 cut)', + 0x19: '25-pin Dual Inline (pin 26 cut)', + 0x1A: '50-pin Dual Inline', + 0x1B: '68-pin Dual Inline', + 0x1C: 'On Board Sound Input from CD-ROM', + 0x1D: 'Mini-Centronics Type-14', + 0x1E: 'Mini-Centronics Type-26', + 0x1F: 'Mini-jack (headphones)', + 0x20: 'BNC', + 0x21: '1394', + 0x22: 'SAS/SATA Plug Receptacle', + 0xA0: 'PC-98', + 0xA1: 'PC-98Hireso', + 0xA2: 'PC-H98', + 0xA3: 'PC-98Note', + 0xA4: 'PC-98Full', + 0xFF: 'Other', + } + self.add_field('internal_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types)) + self.add_field('external_reference_designator', u.unpack_one("B"), self.fmtstr) + self.add_field('external_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types)) + port_types = { + 0x00: 'None', + 0x01: 'Parallel Port XT/AT Compatible', + 0x02: 'Parallel Port PS/2', + 0x03: 'Parallel Port ECP', + 0x04: 'Parallel Port EPP', + 0x05: 'Parallel Port ECP/EPP', + 0x06: 'Serial Port XT/AT Compatible', + 0x07: 'Serial Port 16450 Compatible', + 0x08: 'Serial Port 16550 Compatible', + 0x09: 'Serial Port 16550A Compatible', + 0x0A: 'SCSI Port', + 0x0B: 'MIDI Port', + 0x0C: 'Joy Stick Port', + 0x0D: 'Keyboard Port', + 0x0E: 'Mouse Port', + 0x0F: 'SSA SCSI', + 0x10: 'USB', + 0x11: 'FireWire (IEEE P1394)', + 0x12: 'PCMCIA Type I2', + 0x13: 'PCMCIA Type II', + 0x14: 'PCMCIA Type III', + 0x15: 'Cardbus', + 0x16: 'Access Bus Port', + 0x17: 'SCSI II', + 0x18: 'SCSI Wide', + 0x19: 'PC-98', + 0x1A: 'PC-98-Hireso', + 0x1B: 'PC-H98', + 0x1C: 'Video Port', + 0x1D: 'Audio Port', + 0x1E: 'Modem Port', + 0x1F: 'Network Port', + 0x20: 'SATA', + 0x21: 'SAS', + 0xA0: '8251 Compatible', + 0xA1: '8251 FIFO Compatible', + 0xFF: 'Other', + } + self.add_field('port_type', u.unpack_one("B"), unpack.format_table("{}", port_types)) + except: + self.decodeFailure = True + print "Error parsing PortConnectorInfo" + import traceback + traceback.print_exc() + self.fini() + +class SystemSlots(SmbiosBaseStructure): + smbios_structure_type = 9 + + def __init__(self, u, sm): + super(SystemSlots, self).__init__(u, sm) + u = self.u + try: + self.add_field('designation', u.unpack_one("B"), self.fmtstr) + _slot_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'ISA', + 0x04: 'MCA', + 0x05: 'EISA', + 0x06: 'PCI', + 0x07: 'PC Card (PCMCIA)', + 0x08: 'VL-VESA', + 0x09: 'Proprietary', + 0x0A: 'Processor Card Slot', + 0x0B: 'Proprietary Memory Card Slot', + 0x0C: 'I/O Riser Card Slot', + 0x0D: 'NuBus', + 0x0E: 'PCI 66MHz Capable', + 0x0F: 'AGP', + 0x10: 'AGP 2X', + 0x11: 'AGP 4X', + 0x12: 'PCI-X', + 0x13: 'AGP 8X', + 0xA0: 'PC-98/C20', + 0xA1: 'PC-98/C24', + 0xA2: 'PC-98/E', + 0xA3: 'PC-98/Local Bus', + 0xA4: 'PC-98/Card', + 0xA5: 'PCI Express', + 0xA6: 'PCI Express x1', + 0xA7: 'PCI Express x2', + 0xA8: 'PCI Express x4', + 0xA9: 'PCI Express x8', + 0xAA: 'PCI Express x16', + 0xAB: 'PCI Express Gen 2', + 0xAC: 'PCI Express Gen 2 x1', + 0xAD: 'PCI Express Gen 2 x2', + 0xAE: 'PCI Express Gen 2 x4', + 0xAF: 'PCI Express Gen 2 x8', + 0xB0: 'PCI Express Gen 2 x16', + 0xB1: 'PCI Express Gen 3', + 0xB2: 'PCI Express Gen 3 x1', + 0xB3: 'PCI Express Gen 3 x2', + 0xB4: 'PCI Express Gen 3 x4', + 0xB5: 'PCI Express Gen 3 x8', + 0xB6: 'PCI Express Gen 3 x16', + } + self.add_field('slot_type', u.unpack_one("B"), unpack.format_table("{}", _slot_types)) + _slot_data_bus_widths = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: '8 bit', + 0x04: '16 bit', + 0x05: '32 bit', + 0x06: '64 bit', + 0x07: '128 bit', + 0x08: '1x or x1', + 0x09: '2x or x2', + 0x0A: '4x or x4', + 0x0B: '8x or x8', + 0x0C: '12x or x12', + 0x0D: '16x or x16', + 0x0E: '32x or x32', + } + self.add_field('slot_data_bus_width', u.unpack_one('B'), unpack.format_table("{}", _slot_data_bus_widths)) + _current_usages = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Available', + 0x04: 'In use', + } + self.add_field('current_usage', u.unpack_one('B'), unpack.format_table("{}", _current_usages)) + _slot_lengths = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Short Length', + 0x04: 'Long Length', + } + self.add_field('slot_length', u.unpack_one('B'), unpack.format_table("{}", _slot_lengths)) + self.add_field('slot_id', u.unpack_one(' 0x0C: + self.add_field('characteristics2', u.unpack_one('B')) + self.add_field('supports_PME', bool(bitfields.getbits(self.characteristics2, 0)), "characteristics2[0]={}") + self.add_field('supports_hot_plug', bool(bitfields.getbits(self.characteristics2, 1)), "characteristics2[1]={}") + self.add_field('supports_smbus', bool(bitfields.getbits(self.characteristics2, 2)), "characteristics2[2]={}") + if self.length > 0x0D: + self.add_field('segment_group_number', u.unpack_one(' 0x05: + self.add_field('flags', u.unpack_one('B')) + self.add_field('abbreviated_format', bool(bitfields.getbits(self.flags, 0)), "flags[0]={}") + if self.length > 0x6: + u.skip(15) + self.add_field('current_language', u.unpack_one('B'), self.fmtstr) + except: + self.decodeFailure = True + print "Error parsing BIOSLanguageInformation" + import traceback + traceback.print_exc() + self.fini() + +class GroupAssociations(SmbiosBaseStructure): + smbios_structure_type = 14 + + def __init__(self, u, sm): + super(GroupAssociations, self).__init__(u, sm) + u = self.u + try: + self.add_field('group_name', u.unpack_one("B"), self.fmtstr) + self.add_field('item_type', u.unpack_one('B')) + self.add_field('item_handle', u.unpack_one(' 0x14: + _log_header_formats = { + 0: 'No header', + 1: 'Type 1 log header', + xrange(2, 0x7f): 'Available for future assignment', + xrange(0x80, 0xff): 'BIOS vendor or OEM-specific format' + } + self.add_field('log_header_format', u.unpack_one("B"), unpack.format_table("{}", _log_header_formats)) + if self.length > 0x15: + self.add_field('num_supported_log_type_descriptors', u.unpack_one('B')) + if self.length > 0x16: + self.add_field('length_log_type_descriptor', u.unpack_one('B')) + if self.length != (0x17 + (self.num_supported_log_type_descriptors * self.length_log_type_descriptor)): + print "Error: structure length ({}) != 0x17 + (num_supported_log_type_descriptors ({}) * length_log_type_descriptor({}))".format(self.length, self.num_supported_log_type_descriptors, self.length_log_type_descriptor) + print "structure length = {}".format(self.length) + print "num_supported_log_type_descriptors = {}".format(self.num_supported_log_type_descriptors) + print "length_log_type_descriptor = {}".format(self.length_log_type_descriptor) + self.decodeFailure = True + self.add_field('descriptors', tuple(EventLogDescriptor.unpack(u) for i in range(self.num_supported_log_type_descriptors)), unpack.format_each("\n{!r}")) + except: + self.decodeFailure = True + print "Error parsing SystemEventLog" + import traceback + traceback.print_exc() + self.fini() + +class EventLogDescriptor(unpack.Struct): + @staticmethod + def _unpack(u): + _event_log_type_descriptors = { + 0x00: 'Reserved', + 0x01: 'Single-bit ECC memory error', + 0x02: 'Multi-bit ECC memory error', + 0x03: 'Parity memory error', + 0x04: 'Bus time-out', + 0x05: 'I/O Channel Check', + 0x06: 'Software NMI', + 0x07: 'POST Memory Resize', + 0x08: 'POST Error', + 0x09: 'PCI Parity Error', + 0x0A: 'PCI System Error', + 0x0B: 'CPU Failure', + 0x0C: 'EISA FailSafe Timer time-out', + 0x0D: 'Correctable memory log disabled', + 0x0E: 'Logging disabled for a specific Event Type - too many errors of the same type received in a short amount of time', + 0x0F: 'Reserved', + 0x10: 'System Limit Exceeded', + 0x11: 'Asynchronous hardware timer expired and issued a system reset', + 0x12: 'System configuration information', + 0x13: 'Hard-disk information', + 0x14: 'System reconfigured', + 0x15: 'Uncorrectable CPU-complex error', + 0x16: 'Log Area Reset/Cleared', + 0x17: 'System boot', + xrange(0x18, 0x7F): 'Unused, available for assignment', + xrange(0x80, 0xFE): 'Availalbe for system- and OEM-specific assignments', + 0xFF: 'End of log' + } + yield 'log_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_type_descriptors) + _event_log_format = { + 0x00: 'None', + 0x01: 'Handle', + 0x02: 'Multiple-Event', + 0x03: 'Multiple-Event Handle', + 0x04: 'POST Results Bitmap', + 0x05: 'System Management Type', + 0x06: 'Multiple-Event System Management Type', + xrange(0x80, 0xFF): 'OEM assigned' + } + yield 'variable_data_format_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_format) + +class PhysicalMemoryArray(SmbiosBaseStructure): + smbios_structure_type = 16 + + def __init__(self, u, sm): + super(PhysicalMemoryArray, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + _location_field = { + 0x01: "Other", + 0x02: "Unknown", + 0x03: "System board or motherboard", + 0x04: "ISA add-on card", + 0x05: "EISA add-on card", + 0x06: "PCI add-on card", + 0x07: "MCA add-on card", + 0x08: "PCMCIA add-on card", + 0x09: "Proprietary add-on card", + 0x0A: "NuBus", + 0xA0: "PC-98/C20 add-on card", + 0xA1: "PC-98/C24 add-on card", + 0xA2: "PC-98/E add-on card", + 0xA3: "PC-98/Local bus add-on card" + } + self.add_field('location', u.unpack_one("B"), unpack.format_table("{}", _location_field)) + if self.length > 0x05: + _use = { + 0x01: "Other", + 0x02: "Unknown", + 0x03: "System memory", + 0x04: "Video memory", + 0x05: "Flash memory", + 0x06: "Non-volatile RAM", + 0x07: "Cache memory" + } + self.add_field('use', u.unpack_one('B'), unpack.format_table("{}", _use)) + if self.length > 0x06: + _error_correction = { + 0x01: "Other", + 0x02: "Unknown", + 0x03: "None", + 0x04: "Parity", + 0x05: "Single-bit ECC", + 0x06: "Multi-bit ECC", + 0x07: "CRC" + } + self.add_field('memory_error_correction', u.unpack_one('B'), unpack.format_table("{}", _error_correction)) + if self.length > 0x07: + self.add_field('maximum_capacity', u.unpack_one(' 0x0B: + self.add_field('memory_error_information_handle', u.unpack_one(' 0x0D: + self.add_field('num_memory_devices', u.unpack_one(' 0x0F: + self.add_field('extended_maximum_capacity', u.unpack_one(' 0x4: + self.add_field('physical_memory_array_handle', u.unpack_one(" 0x6: + self.add_field('memory_error_information_handle', u.unpack_one(" 0x8: + self.add_field('total_width', u.unpack_one(" 0xA: + self.add_field('data_width', u.unpack_one(" 0xC: + self.add_field('size', u.unpack_one(" 0xE: + _form_factors = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'SIMM', + 0x04: 'SIP', + 0x05: 'Chip', + 0x06: 'DIP', + 0x07: 'ZIP', + 0x08: 'Proprietary Card', + 0x09: 'DIMM', + 0x0A: 'TSOP', + 0x0B: 'Row of chips', + 0x0C: 'RIMM', + 0x0D: 'SODIMM', + 0x0E: 'SRIMM', + 0x0F: 'FB-DIMM' + } + self.add_field('form_factor', u.unpack_one("B"), unpack.format_table("{}", _form_factors)) + if self.length > 0xF: + self.add_field('device_set', u.unpack_one("B")) + if self.length > 0x10: + self.add_field('device_locator', u.unpack_one("B"), self.fmtstr) + if self.length > 0x11: + self.add_field('bank_locator', u.unpack_one("B"), self.fmtstr) + if self.length > 0x12: + _memory_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'DRAM', + 0x04: 'EDRAM', + 0x05: 'VRAM', + 0x06: 'SRAM', + 0x07: 'RAM', + 0x08: 'ROM', + 0x09: 'FLASH', + 0x0A: 'EEPROM', + 0x0B: 'FEPROM', + 0x0C: 'EPROM', + 0x0D: 'CDRAM', + 0x0E: '3DRAM', + 0x0F: 'SDRAM', + 0x10: 'SGRAM', + 0x11: 'RDRAM', + 0x12: 'DDR', + 0x13: 'DDR2', + 0x14: 'DDR2 FB-DIMM', + xrange(0x15, 0x17): 'Reserved', + 0x18: 'DDR3', + 0x19: 'FBD2' + } + self.add_field('memory_type', u.unpack_one("B"), unpack.format_table("{}", _memory_types)) + if self.length > 0x13: + self.add_field('type_detail', u.unpack_one(' 0x15: + self.add_field('speed', u.unpack_one(" 0x17: + self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) + if self.length > 0x18: + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x19: + self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) + if self.length > 0x1A: + self.add_field('part_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x1B: + self.add_field('attributes', u.unpack_one("B")) + self.add_field('rank', bitfields.getbits(self.attributes, 3, 0), "attributes[3:0]={}") + if self.length > 0x1C: + if self.size == 0x7FFF: + self.add_field('extended_size', u.unpack_one(' 0x20: + self.add_field('configured_memory_clock_speed', u.unpack_one(" 0x22: + self.add_field('minimum_voltage', u.unpack_one(" 0x24: + self.add_field('maximum_voltage', u.unpack_one(" 0x26: + self.add_field('configured_voltage', u.unpack_one(" 0x4: + _error_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'OK', + 0x04: 'Bad read', + 0x05: 'Parity error', + 0x06: 'Single-bit error', + 0x07: 'Double-bit error', + 0x08: 'Multi-bit error', + 0x09: 'Nibble error', + 0x0A: 'Checksum error', + 0x0B: 'CRC error', + 0x0C: 'Corrected single-bit error', + 0x0D: 'Corrected error', + 0x0E: 'Uncorrectable error' + } + self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types)) + if self.length > 0x5: + _error_granularity_field = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Device level', + 0x04: 'Memory partition level' + } + self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field)) + if self.length > 0x6: + _error_operation_field = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Read', + 0x04: 'Write', + 0x05: 'Partial write' + } + self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field)) + if self.length > 0x7: + self.add_field('vendor_syndrome', u.unpack_one(" 0xB: + self.add_field('memory_array_error_address', u.unpack_one(" 0xF: + self.add_field('device_error_address', u.unpack_one(" 0x13: + self.add_field('error_resolution', u.unpack_one(" 0x4: + self.add_field('starting_address', u.unpack_one(" 0x8: + self.add_field('ending_address', u.unpack_one(" 0xC: + self.add_field('memory_array_handle', u.unpack_one(" 0xE: + self.add_field('partition_width', u.unpack_one("B")) + if self.length > 0xF: + # valid if starting_address = FFFF FFFF + if self.starting_address == 0xFFFFFFFF: + self.add_field('extended_starting_address', u.unpack_one(" 0x17: + self.add_field('extended_ending_address', u.unpack_one(" 0x4: + self.add_field('starting_address', u.unpack_one(" 0x8: + self.add_field('ending_address', u.unpack_one(" 0xC: + self.add_field('memory_device_handle', u.unpack_one(" 0xE: + self.add_field('memory_array_mapped_address_handle', u.unpack_one(" 0x10: + self.add_field('partition_row_position', u.unpack_one("B")) + if self.length > 0x11: + self.add_field('interleave_position', u.unpack_one("B")) + if self.length > 0x12: + self.add_field('interleave_data_depth', u.unpack_one("B")) + if self.length > 0x13: + # valid if starting_address = FFFF FFFF + if self.starting_address == 0xFFFFFFFF: + self.add_field('extended_starting_address', u.unpack_one(" 0x1B: + self.add_field('extended_ending_address', u.unpack_one(" 0x4: + _pointing_device_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Mouse', + 0x04: 'Track Ball', + 0x05: 'Track Point', + 0x06: 'Glide Point', + 0x07: 'Touch Pad', + 0x08: 'Touch Screen', + 0x09: 'Optical Sensor' + } + self.add_field('pointing_device_type', u.unpack_one("B"), unpack.format_table("{}", _pointing_device_types)) + if self.length > 0x5: + _interfaces = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Serial', + 0x04: 'PS/2', + 0x05: 'Infared', + 0x06: 'HP-HIL', + 0x07: 'Bus mouse', + 0x08: 'ADB (Apple Desktop Bus)', + 0x09: 'Bus mouse DB-9', + 0x0A: 'Bus mouse micro-DIN', + 0x0B: 'USB' + } + self.add_field('interface', u.unpack_one("B"), unpack.format_table("{}", _interfaces)) + if self.length > 0x6: + self.add_field('num_buttons', u.unpack_one("B")) + except: + self.decodeFailure = True + print "Error parsing BuiltInPointingDevice" + import traceback + traceback.print_exc() + self.fini() + +class PortableBattery(SmbiosBaseStructure): + smbios_structure_type = 22 + + def __init__(self, u, sm): + super(PortableBattery, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + self.add_field('location', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) + if self.length > 0x6: + self.add_field('manufacturer_date', u.unpack_one("B"), self.fmtstr) + if self.length > 0x7: + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x8: + self.add_field('device_name', u.unpack_one("B"), self.fmtstr) + if self.length > 0x9: + _device_chemistry = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Lead Acid', + 0x04: 'Nickel Cadmium', + 0x05: 'Nickel metal hydride', + 0x06: 'Lithium-ion', + 0x07: 'Zinc air', + 0x08: 'Lithium Polymer' + } + self.add_field('device_chemistry', u.unpack_one("B"), unpack.format_table("{}", _device_chemistry)) + if self.length > 0xA: + self.add_field('design_capacity', u.unpack_one(" 0xC: + self.add_field('design_voltage', u.unpack_one(" 0xE: + self.add_field('sbds_version_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0xF: + self.add_field('max_error_battery_data', u.unpack_one("B"), self.fmtstr) + if self.length > 0x10: + if self.serial_number == 0: + self.add_field('sbds_serial_number', u.unpack_one(" 0x12: + if self.manufacturer_date == 0: + self.add_field('sbds_manufacture_date', u.unpack_one(" 0x14: + if self.device_chemistry == 0x02: + self.add_field('sbds_device_chemistry', u.unpack_one("B"), self.fmtstr) + else: + u.skip(1) + if self.length > 0x15: + self.add_field('design_capacity_multiplier', u.unpack_one("B")) + if self.length > 0x16: + self.add_field('oem_specific', u.unpack_one(" 0x4: + self.add_field('capabilities', u.unpack_one("B")) + self.add_field('contains_watchdog_timer', bool(bitfields.getbits(self.capabilities, 5)), "capabilities[5]={}") + _boot_option = { + 0b00: 'Reserved, do not use', + 0b01: 'Operating System', + 0b10: 'System utilities', + 0b11: 'Do not reboot' + } + self.add_field('boot_option_on_limit', bitfields.getbits(self.capabilities, 4, 3), unpack.format_table("capabilities[4:3]={}", _boot_option)) + self.add_field('boot_option_after_watchdog_reset', bitfields.getbits(self.capabilities, 2, 1), unpack.format_table("capabilities[2:1]={}", _boot_option)) + self.add_field('system_reset_enabled_by_user', bool(bitfields.getbits(self.capabilities, 0)), "capabilities[0]={}") + if self.length > 0x5: + self.add_field('reset_count', u.unpack_one(" 0x5: + self.add_field('reset_limit', u.unpack_one(" 0x9: + self.add_field('timer_interval', u.unpack_one(" 0xB: + self.add_field('timeout', u.unpack_one(" 0x4: + self.add_field('hardware_security_settings', u.unpack_one("B")) + _status = { + 0x00: 'Disabled', + 0x01: 'Enabled', + 0x02: 'Not Implemented', + 0x03: 'Unknown' + } + self.add_field('power_on_password_status', bitfields.getbits(self.hardware_security_settings, 7, 6), unpack.format_table("hardware_security_settings[7:6]={}", _status)) + self.add_field('keyboard_password_status', bitfields.getbits(self.hardware_security_settings, 5, 4), unpack.format_table("hardware_security_settings[5:4]={}", _status)) + self.add_field('admin_password_status', bitfields.getbits(self.hardware_security_settings, 3, 2), unpack.format_table("hardware_security_settings0[3:2]={}", _status)) + self.add_field('front_panel_reset_status', bitfields.getbits(self.hardware_security_settings, 1, 0), unpack.format_table("hardware_security_settings[1:0]={}", _status)) + except: + self.decodeFailure = True + print "Error parsing HardwareSecurity" + import traceback + traceback.print_exc() + self.fini() + +class SystemPowerControls(SmbiosBaseStructure): + smbios_structure_type = 25 + + def __init__(self, u, sm): + super(SystemPowerControls, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + self.add_field('next_scheduled_poweron_month', u.unpack_one("B")) + self.add_field('next_scheduled_poweron_day_of_month', u.unpack_one("B")) + self.add_field('next_scheduled_poweron_hour', u.unpack_one("B")) + self.add_field('next_scheduled_poweron_minute', u.unpack_one("B")) + self.add_field('next_scheduled_poweron_second', u.unpack_one("B")) + except: + self.decodeFailure = True + print "Error parsing SystemPowerControls" + import traceback + traceback.print_exc() + self.fini() + +class VoltageProbe(SmbiosBaseStructure): + smbios_structure_type = 26 + + def __init__(self, u, sm): + super(VoltageProbe, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('location_and_status', u.unpack_one("B")) + _status = { + 0b001: 'Other', + 0b010: 'Unknown', + 0b011: 'OK', + 0b100: 'Non-critical', + 0b101: 'Critical', + 0b110: 'Non-recoverable' + } + _location = { + 0b00001: 'Other', + 0b00010: 'Unknown', + 0b00011: 'Processor', + 0b00100: 'Disk', + 0b00101: 'Peripheral Bay', + 0b00110: 'System Management Module', + 0b00111: 'Motherboard', + 0b01000: 'Memory Module', + 0b01001: 'Processor Module', + 0b01010: 'Power Unit', + 0b01011: 'Add-in Card' + } + self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) + self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) + if self.length > 0x6: + self.add_field('max_value', u.unpack_one(" 0x8: + self.add_field('min_value', u.unpack_one(" 0xA: + self.add_field('resolution', u.unpack_one(" 0xC: + self.add_field('tolerance', u.unpack_one(" 0xE: + self.add_field('accuracy', u.unpack_one(" 0x10: + self.add_field('oem_defined', u.unpack_one(" 0x14: + self.add_field('nominal_value', u.unpack_one(" 0x4: + self.add_field('temperature_probe_handle', u.unpack_one(" 0x6: + self.add_field('device_type_and_status', u.unpack_one("B")) + _status = { + 0b001: 'Other', + 0b010: 'Unknown', + 0b011: 'OK', + 0b100: 'Non-critical', + 0b101: 'Critical', + 0b110: 'Non-recoverable' + } + _type = { + 0b00001: 'Other', + 0b00010: 'Unknown', + 0b00011: 'Fan', + 0b00100: 'Centrifugal Blower', + 0b00101: 'Chip Fan', + 0b00110: 'Cabinet Fan', + 0b00111: 'Power Supply Fan', + 0b01000: 'Heat Pipe', + 0b01001: 'Integrated Refrigeration', + 0b10000: 'Active Cooling', + 0b10001: 'Passive Cooling' + } + self.add_field('status', bitfields.getbits(self.device_type_and_status, 7, 5), unpack.format_table("device_type_and_status[7:5]={}", _status)) + self.add_field('device_type', bitfields.getbits(self.device_type_and_status, 4, 0), unpack.format_table("device_type_and_status[4:0]={}", _type)) + if self.length > 0x7: + self.add_field('cooling_unit_group', u.unpack_one("B")) + if self.length > 0x8: + self.add_field('OEM_defined', u.unpack_one(" 0xC: + self.add_field('nominal_speed', u.unpack_one(" 0xE: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + except: + self.decodeFailure = True + print "Error parsing CoolingDevice" + import traceback + traceback.print_exc() + self.fini() + +class TemperatureProbe(SmbiosBaseStructure): + smbios_structure_type = 28 + + def __init__(self, u, sm): + super(TemperatureProbe, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('location_and_status', u.unpack_one("B")) + _status = { + 0b001: 'Other', + 0b010: 'Unknown', + 0b011: 'OK', + 0b100: 'Non-critical', + 0b101: 'Critical', + 0b110: 'Non-recoverable' + } + _location = { + 0b00001: 'Other', + 0b00010: 'Unknown', + 0b00011: 'Processor', + 0b00100: 'Disk', + 0b00101: 'Peripheral Bay', + 0b00110: 'System Management Module', + 0b00111: 'Motherboard', + 0b01000: 'Memory Module', + 0b01001: 'Processor Module', + 0b01010: 'Power Unit', + 0b01011: 'Add-in Card', + 0b01100: 'Front Panel Board', + 0b01101: 'Back Panel Board', + 0b01110: 'Power System Board', + 0b01111: 'Drive Back Plane' + } + self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) + self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) + if self.length > 0x6: + self.add_field('maximum_value', u.unpack_one(" 0x8: + self.add_field('minimum_value', u.unpack_one(" 0xA: + self.add_field('resolution', u.unpack_one(" 0xC: + self.add_field('tolerance', u.unpack_one(" 0xE: + self.add_field('accuracy', u.unpack_one(" 0x10: + self.add_field('OEM_defined', u.unpack_one(" 0x14: + self.add_field('nominal_value', u.unpack_one(" 0x4: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('location_and_status', u.unpack_one("B")) + _status = { + 0b001: 'Other', + 0b010: 'Unknown', + 0b011: 'OK', + 0b100: 'Non-critical', + 0b101: 'Critical', + 0b110: 'Non-recoverable' + } + _location = { + 0b00001: 'Other', + 0b00010: 'Unknown', + 0b00011: 'Processor', + 0b00100: 'Disk', + 0b00101: 'Peripheral Bay', + 0b00110: 'System Management Module', + 0b00111: 'Motherboard', + 0b01000: 'Memory Module', + 0b01001: 'Processor Module', + 0b01010: 'Power Unit', + 0b01011: 'Add-in Card', + 0b01100: 'Front Panel Board', + 0b01101: 'Back Panel Board', + 0b01110: 'Power System Board', + 0b01111: 'Drive Back Plane' + } + self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) + self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) + if self.length > 0x6: + self.add_field('maximum_value', u.unpack_one(" 0x8: + self.add_field('minimum_value', u.unpack_one(" 0xA: + self.add_field('resolution', u.unpack_one(" 0xC: + self.add_field('tolerance', u.unpack_one(" 0xE: + self.add_field('accuracy', u.unpack_one(" 0x10: + self.add_field('OEM_defined', u.unpack_one(" 0x14: + self.add_field('nominal_value', u.unpack_one(" 0x4: + self.add_field('manufacturer_name', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('connections', u.unpack_one("B")) + self.add_field('outbound_connection_enabled', bool(bitfields.getbits(self.connections, 1)), "connections[1]={}") + self.add_field('inbound_connection_enabled', bool(bitfields.getbits(self.connections, 0)), "connections[0]={}") + except: + self.decodeFailure = True + print "Error parsing OutOfBandRemoteAccess" + import traceback + traceback.print_exc() + self.fini() + +class BootIntegrityServicesEntryPoint(SmbiosBaseStructure): + smbios_structure_type = 31 + +class SystemBootInformation(SmbiosBaseStructure): + smbios_structure_type = 32 + + def __init__(self, u, sm): + super(SystemBootInformation, self).__init__(u, sm) + u = self.u + try: + if self.length > 0xA: + u.skip(6) + _boot_status = { + 0: 'No errors detected', + 1: 'No bootable media', + 2: '"normal" operating system failed to load', + 3: 'Firmware-detected hardware failure, including "unknown" failure types', + 4: 'Operating system-detected hardware failure', + 5: 'User-requested boot, usually through a keystroke', + 6: 'System security violation', + 7: 'Previously-requested image', + 8: 'System watchdog timer expired, causing the system to reboot', + xrange(9,127): 'Reserved for future assignment', + xrange(128, 191): 'Vendor/OEM-specific implementations', + xrange(192, 255): 'Product-specific implementations' + } + self.add_field('boot_status', u.unpack_one("B"), unpack.format_table("{}", _boot_status)) + except: + self.decodeFailure = True + print "Error parsing SystemBootInformation" + import traceback + traceback.print_exc() + self.fini() + +class MemoryErrorInfo64Bit(SmbiosBaseStructure): + smbios_structure_type = 33 + + def __init__(self, u, sm): + super(MemoryErrorInfo64Bit, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + _error_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'OK', + 0x04: 'Bad read', + 0x05: 'Parity error', + 0x06: 'Single-bit error', + 0x07: 'Double-bit error', + 0x08: 'Multi-bit error', + 0x09: 'Nibble error', + 0x0A: 'Checksum error', + 0x0B: 'CRC error', + 0x0C: 'Corrected single-bit error', + 0x0D: 'Corrected error', + 0x0E: 'Uncorrectable error' + } + self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types)) + if self.length > 0x5: + _error_granularity_field = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Device level', + 0x04: 'Memory partition level' + } + self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field)) + if self.length > 0x6: + _error_operation_field = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Read', + 0x04: 'Write', + 0x05: 'Partial write' + } + self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field)) + if self.length > 0x7: + self.add_field('vendor_syndrome', u.unpack_one(" 0xB: + self.add_field('memory_array_error_address', u.unpack_one(" 0xF: + self.add_field('device_error_address', u.unpack_one(" 0x13: + self.add_field('error_resolution', u.unpack_one(" 0x4: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + _type = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'National Semiconductor LM75', + 0x04: 'National Semiconductor LM78', + 0x05: 'National Semiconductor LM79', + 0x06: 'National Semiconductor LM80', + 0x07: 'National Semiconductor LM81', + 0x08: 'Analog Devices ADM9240', + 0x09: 'Dallas Semiconductor DS1780', + 0x0A: 'Maxim 1617', + 0x0B: 'Genesys GL518SM', + 0x0C: 'Winbond W83781D', + 0x0D: 'Holtek HT82H791' + } + self.add_field('device_type', u.unpack_one("B"), unpack.format_table("{}", _type)) + if self.length > 0x6: + self.add_field('address', u.unpack_one(" 0xA: + _address_type = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'I/O Port', + 0x04: 'Memory', + 0x05: 'SM Bus' + } + self.add_field('address_type', u.unpack_one("B"), unpack.format_table("{}", _address_type)) + except: + self.decodeFailure = True + print "Error parsing ManagementDevice" + import traceback + traceback.print_exc() + self.fini() + +class ManagementDeviceComponent(SmbiosBaseStructure): + smbios_structure_type = 35 + + def __init__(self, u, sm): + super(ManagementDeviceComponent, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + self.add_field('description', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('management_device_handle', u.unpack_one(" 0x7: + self.add_field('component_handle', u.unpack_one(" 0x9: + self.add_field('threshold_handle', u.unpack_one(" 0x4: + self.add_field('lower_threshold_noncritical', u.unpack_one(" 0x6: + self.add_field('upper_threshold_noncritical', u.unpack_one(" 0x8: + self.add_field('lower_threshold_critical', u.unpack_one(" 0xA: + self.add_field('upper_threshold_critical', u.unpack_one(" 0xC: + self.add_field('lower_threshold_nonrecoverable', u.unpack_one(" 0xE: + self.add_field('upper_threshold_nonrecoverable', u.unpack_one(" 0x4: + _channel_type = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'RamBus', + 0x04: 'SyncLink' + } + self.add_field('channel_type', u.unpack_one("B"), unpack.format_table("{}", _channel_type)) + if self.length > 0x6: + self.add_field('max_channel_load', u.unpack_one("B")) + if self.length > 0x8: + self.add_field('memory_device_count', u.unpack_one("B")) + if self.length > 0xA: + self.add_field('memory_device_load', u.unpack_one("B")) + if self.length > 0xC: + self.add_field('memory_device_handle', u.unpack_one(" 0x4: + self.add_field('power_unit_group', u.unpack_one("B")) + if self.length > 0x5: + self.add_field('location', u.unpack_one("B"), self.fmtstr) + if self.length > 0x6: + self.add_field('device_name', u.unpack_one("B"), self.fmtstr) + if self.length > 0x7: + self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) + if self.length > 0x8: + self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0x9: + self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) + if self.length > 0xA: + self.add_field('model_part_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0xB: + self.add_field('revision_level', u.unpack_one("B"), self.fmtstr) + if self.length > 0xC: + self.add_field('max_power_capacity', u.unpack_one(" 0xE: + self.add_field('power_supply_characteristics', u.unpack_one(" 0x10: + self.add_field('input_voltage_probe_handle', u.unpack_one(" 0x12: + self.add_field('cooling_device_handle', u.unpack_one(" 0x14: + self.add_field('input_current_probe_handle', u.unpack_one(" 0x4: + self.add_field('num_additional_information_entries', u.unpack_one("B")) + if self.length > 0x5: + self.add_field('additional_information_entry_length', u.unpack_one("B")) + self.add_field('referenced_handle', u.unpack_one(" 0x4: + self.add_field('reference_designation', u.unpack_one("B"), self.fmtstr) + if self.length > 0x5: + self.add_field('device_type', u.unpack_one("B")) + self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}") + _device_types = { + 0x01: 'Other', + 0x02: 'Unknown', + 0x03: 'Video', + 0x04: 'SCSI Controller', + 0x05: 'Ethernet', + 0x06: 'Token Ring', + 0x07: 'Sound', + 0x08: 'PATA Controller', + 0x09: 'SATA Controller', + 0x0A: 'SAS Controller' + } + self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types)) + if self.length > 0x6: + self.add_field('device_type_instance', u.unpack_one("B")) + if self.length > 0x7: + self.add_field('segment_group_number', u.unpack_one(" 0x9: + self.add_field('bus_number', u.unpack_one("B"), self.fmtstr) + if self.length > 0xA: + self.add_field('device_and_function_number', u.unpack_one("B")) + self.add_field('device_number', bitfields.getbits(self.device_type, 7, 3), "device_and_function_number[7:3]={}") + self.add_field('function_number', bitfields.getbits(self.device_type, 2, 0), "device_and_function_number[2:0]={}") + except: + self.decodeFailure = True + print "Error parsing OnboardDevicesExtendedInformation" + import traceback + traceback.print_exc() + self.fini() + +class ManagementControllerHostInterface(SmbiosBaseStructure): + smbios_structure_type = 42 + + def __init__(self, u, sm): + super(ManagementControllerHostInterface, self).__init__(u, sm) + u = self.u + try: + if self.length > 0x4: + _interface_types = { + 0x00: 'Reserved', + 0x01: 'Reserved', + 0x02: 'KCS: Keyboard Controller Style', + 0x03: '8250 UART Register Compatible', + 0x04: '16450 UART Register Compatible', + 0x05: '16550/16550A UART Register Compatible', + 0x06: '16650/16650A UART Register Compatible', + 0x07: '16750/16750A UART Register Compatible', + 0x08: '16850/16850A UART Register Compatible', + 0xF0: 'OEM' + } + self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_types)) + if self.length > 0x5: + self.add_field('mc_host_interface_data', u.unpack_rest(), self.fmtstr) + except: + self.decodeFailure = True + print "Error parsing ManagementControllerHostInterface" + import traceback + traceback.print_exc() + self.fini() + +class Inactive(SmbiosBaseStructure): + smbios_structure_type = 126 + + def __init__(self, u, sm): + super(Inactive, self).__init__(u, sm) + self.fini() + +class EndOfTable(SmbiosBaseStructure): + smbios_structure_type = 127 + + def __init__(self, u, sm): + super(EndOfTable, self).__init__(u, sm) + self.fini() + +class SmbiosStructureUnknown(SmbiosBaseStructure): + smbios_structure_type = None + + def __init__(self, u, sm): + super(SmbiosStructureUnknown, self).__init__(u, sm) + self.fini() + +_smbios_structures = [ + BIOSInformation, + SystemInformation, + BaseboardInformation, + SystemEnclosure, + ProcessorInformation, + MemoryControllerInformation, + MemoryModuleInformation, + CacheInformation, + PortConnectorInfo, + SystemSlots, + OnBoardDevicesInformation, + OEMStrings, + SystemConfigOptions, + BIOSLanguageInformation, + GroupAssociations, + SystemEventLog, + PhysicalMemoryArray, + MemoryDevice, + MemoryErrorInfo32Bit, + MemoryArrayMappedAddress, + MemoryDeviceMappedAddress, + BuiltInPointingDevice, + PortableBattery, + SystemReset, + HardwareSecurity, + SystemPowerControls, + VoltageProbe, + CoolingDevice, + TemperatureProbe, + ElectricalCurrentProbe, + OutOfBandRemoteAccess, + BootIntegrityServicesEntryPoint, + SystemBootInformation, + MemoryErrorInfo64Bit, + ManagementDevice, + ManagementDeviceComponent, + ManagementDeviceThresholdData, + MemoryChannel, + IPMIDeviceInformation, + SystemPowerSupply, + AdditionalInformation, + OnboardDevicesExtendedInformation, + ManagementControllerHostInterface, + Inactive, + EndOfTable, + SmbiosStructureUnknown, # Must always come last +] + +def log_smbios_info(): + with redirect.logonly(): + try: + sm = SMBIOS() + print + if sm is None: + print "No SMBIOS structures found" + return + output = {} + known_types = (0, 1) + for sm_struct in sm.structures: + if sm_struct.type in known_types: + output.setdefault(sm_struct.type, []).append(sm_struct) + if len(output) == len(known_types): + break + + print "SMBIOS information:" + for key in sorted(known_types): + for s in output.get(key, ["No structure of type {} found".format(key)]): + print ttypager._wrap("{}: {}".format(key, s)) + except: + print "Error parsing SMBIOS information:" + import traceback + traceback.print_exc() + +def dump_raw(): + try: + sm = SMBIOS() + if sm: + s = "SMBIOS -- Raw bytes and structure decode.\n\n" + + s += str(sm.header) + '\n' + s += bits.dumpmem(sm._header_memory) + '\n' + + s += "Raw bytes for the SMBIOS structures\n" + s += bits.dumpmem(sm._structure_memory) + '\n' + + for sm_struct in sm.structures: + s += str(sm_struct) + '\n' + s += bits.dumpmem(sm_struct.raw_data) + + s += "Strings:\n" + for n in range(1, len(getattr(sm_struct, "strings", [])) + 1): + s += str(sm_struct.fmtstr(n)) + '\n' + s += bits.dumpmem(sm_struct.raw_strings) + '\n' + else: + s = "No SMBIOS structures found" + ttypager.ttypager_wrap(s, indent=False) + except: + print "Error parsing SMBIOS information:" + import traceback + traceback.print_exc() + +def dump(): + try: + sm = SMBIOS() + if sm: + s = str(sm) + else: + s = "No SMBIOS structures found" + ttypager.ttypager_wrap(s, indent=False) + except: + print "Error parsing SMBIOS information:" + import traceback + traceback.print_exc() + +def annex_a_conformance(): + try: + sm = SMBIOS() + + # check: 1. The table anchor string "_SM_" is present in the address range 0xF0000 to 0xFFFFF on a 16-byte bound + + def table_entry_point_verification(): + ''' Verify table entry-point''' + if (sm.header.length < 0x1F): + print "Failure: Table entry-point - The entry-point Length must be at least 0x1F" + if sm.header.checksum != 0: + print "Failure: Table entry-point - The entry-point checksum must evaluate to 0" + if ((sm.header.major_version < 2) and (sm.header.minor_version < 4)): + print "Failure: Table entry-point - SMBIOS version must be at least 2.4" + if (sm.header.intermediate_anchor_string == '_DMI_'): + print "Failure: Table entry-point - The Intermediate Anchor String must be '_DMI_'" + if (sm.header.intermediate_checksum != 0): + print "Failure: Table entry-point - The Intermediate checksum must evaluate to 0" + + #check: 3. The structure-table is traversable and conforms to the entry-point specifications: + + def req_structures(): + '''Checks for required structures and corresponding data''' + types_present = [sm.structures[x].smbios_structure_type for x in range(len(sm.structures))] + required = [0, 1, 4, 7, 9, 16, 17, 19, 31, 32] + for s in required: + if s not in set(types_present): + print "Failure: Type {} required but not found".format(s) + + else: + if s == 0: + if types_present.count(s) > 1: + print "Failure: Type {} - One and only one structure of this type must be present.".format(s) + if sm.structure_type(s).length < 0x18: + print "Failure: Type {} - The structure Length field must be at least 0x18".format(s) + if sm.structure_type(s).version is None: + print "Failure: Type {} - BIOS Version string must be present and non-null.".format(s) + if sm.structure_type(s).release_date is None: + print "Failure: Type {} - BIOS Release Date string must be present, non-null, and include a 4-digit year".format(s) + if bitfields.getbits(sm.structure_type(s).characteristics, 3, 0) != 0 or bitfields.getbits(sm.structure_type(s).characteristics, 31, 4) == 0: + print "Failure: Type {} - BIOS Characteristics: bits 3:0 must all be 0, and at least one of bits 31:4 must be set to 1.".format(s) + elif s == 1: + if types_present.count(s) > 1: + print "Failure: Type {} - One and only one structure of this type must be present.".format(s) + if sm.structure_type(s).length < 0x1B: + print "Failure: Type {} - The structure Length field must be at least 0x1B".format(s) + if sm.structure_type(s).manufacturer == None: + print "Failure: Type {} - Manufacturer string must be present and non-null.".format(s) + if sm.structure_type(s).product_name == None: + print "Failure: Type {} - Product Name string must be present and non-null".format(s) + if sm.structure_type(s).uuid == '00000000 00000000' and sm.structure_type(s).uuid == 'FFFFFFFF FFFFFFFF': + print "Failure: Type {} - UUID field must be neither 00000000 00000000 nor FFFFFFFF FFFFFFFF.".format(s) + if sm.structure_type(s).wakeup_type == 00 and sm.structure_type(s).wakeup_type == 0x02: + print "Failure: Type {} - Wake-up Type field must be neither 00h (Reserved) nor 02h (Unknown).".format(s) + # continue for remaining required types + + # check remaining conformance guidelines + + table_entry_point_verification() + req_structures() + except: + print "Error checking ANNEX A conformance guidelines" + import traceback + traceback.print_exc() diff --git a/tests/qtest/acpi-bits/bits-tests/testacpi.py b/tests/qtest/acpi-bits/bits-tests/testacpi.py new file mode 100644 index 0000000000..9ec452f330 --- /dev/null +++ b/tests/qtest/acpi-bits/bits-tests/testacpi.py @@ -0,0 +1,283 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests for ACPI""" + +import acpi +import bits +import bits.mwait +import struct +import testutil +import testsuite +import time + +def register_tests(): + testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests") + testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests") + testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests") + testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests") + testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests") + testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests") + testsuite.add_test("ACPI MADT (Multiple APIC Description Table)", test_apic, submenu="ACPI Tests") + testsuite.add_test("ACPI MPST (Memory Power State Table)", test_mpst, submenu="ACPI Tests") + testsuite.add_test("ACPI RSDP (Root System Description Pointer Structure)", test_rsdp, submenu="ACPI Tests") + testsuite.add_test("ACPI XSDT (Extended System Description Table)", test_xsdt, submenu="ACPI Tests") + +def test_mat(): + cpupaths = acpi.get_cpupaths() + apic = acpi.parse_apic() + procid_apicid = apic.procid_apicid + uid_x2apicid = apic.uid_x2apicid + for cpupath in cpupaths: + # Find the ProcId defined by the processor object + processor = acpi.evaluate(cpupath) + # Find the UID defined by the processor object's _UID method + uid = acpi.evaluate(cpupath + "._UID") + mat_buffer = acpi.evaluate(cpupath + "._MAT") + if mat_buffer is None: + continue + # Process each _MAT subtable + mat = acpi._MAT(mat_buffer) + for index, subtable in enumerate(mat): + if subtable.subtype == acpi.MADT_TYPE_LOCAL_APIC: + if subtable.flags.bits.enabled: + testsuite.test("{} Processor declaration ProcId = _MAT ProcId".format(cpupath), processor.ProcId == subtable.proc_id) + testsuite.print_detail("{} ProcId ({:#02x}) != _MAT ProcId ({:#02x})".format(cpupath, processor.ProcId, subtable.proc_id)) + testsuite.print_detail("Processor Declaration: {}".format(processor)) + testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) + if testsuite.test("{} with local APIC in _MAT has local APIC in MADT".format(cpupath), processor.ProcId in procid_apicid): + testsuite.test("{} ApicId derived using Processor declaration ProcId = _MAT ApicId".format(cpupath), procid_apicid[processor.ProcId] == subtable.apic_id) + testsuite.print_detail("{} ApicId derived from MADT ({:#02x}) != _MAT ApicId ({:#02x})".format(cpupath, procid_apicid[processor.ProcId], subtable.apic_id)) + testsuite.print_detail("Processor Declaration: {}".format(processor)) + testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) + if subtable.subtype == acpi.MADT_TYPE_LOCAL_X2APIC: + if subtable.flags.bits.enabled: + if testsuite.test("{} with x2Apic in _MAT has _UID".format(cpupath), uid is not None): + testsuite.test("{}._UID = _MAT UID".format(cpupath), uid == subtable.uid) + testsuite.print_detail("{}._UID ({:#x}) != _MAT UID ({:#x})".format(cpupath, uid, subtable.uid)) + testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) + if testsuite.test("{} with _MAT x2Apic has x2Apic in MADT".format(cpupath), subtable.uid in uid_x2apicid): + testsuite.test("{} x2ApicId derived from MADT using UID = _MAT x2ApicId".format(cpupath), uid_x2apicid[subtable.uid] == subtable.x2apicid) + testsuite.print_detail("{} x2ApicId derived from MADT ({:#02x}) != _MAT x2ApicId ({:#02x})".format(cpupath, uid_x2apicid[subtable.uid], subtable.x2apicid)) + testsuite.print_detail("_MAT entry[{}]: {}".format(index, subtable)) + +def test_pss(): + uniques = acpi.parse_cpu_method("_PSS") + # We special-case None here to avoid a double-failure for CPUs without a _PSS + testsuite.test("_PSS must be identical for all CPUs", len(uniques) <= 1 or (len(uniques) == 2 and None in uniques)) + for pss, cpupaths in uniques.iteritems(): + if not testsuite.test("_PSS must exist", pss is not None): + testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) + testsuite.print_detail('No _PSS exists') + continue + + if not testsuite.test("_PSS must not be empty", pss.pstates): + testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) + testsuite.print_detail('_PSS is empty') + continue + + testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) + for index, pstate in enumerate(pss.pstates): + testsuite.print_detail("P[{}]: {}".format(index, pstate)) + + testsuite.test("_PSS must contain at most 16 Pstates", len(pss.pstates) <= 16) + testsuite.test("_PSS must have no duplicate Pstates", len(pss.pstates) == len(set(pss.pstates))) + + frequencies = [p.core_frequency for p in pss.pstates] + testsuite.test("_PSS must list Pstates in descending order of frequency", frequencies == sorted(frequencies, reverse=True)) + + testsuite.test("_PSS must have Pstates with no duplicate frequencies", len(frequencies) == len(set(frequencies))) + + dissipations = [p.power for p in pss.pstates] + testsuite.test("_PSS must list Pstates in descending order of power dissipation", dissipations == sorted(dissipations, reverse=True)) + +def test_pstates(): + """Execute and verify frequency for each Pstate in the _PSS""" + IA32_PERF_CTL = 0x199 + with bits.mwait.use_hint(), bits.preserve_msr(IA32_PERF_CTL): + cpupath_procid = acpi.find_procid() + cpupath_uid = acpi.find_uid() + apic = acpi.parse_apic() + procid_apicid = apic.procid_apicid + uid_x2apicid = apic.uid_x2apicid + def cpupath_apicid(cpupath): + if procid_apicid is not None: + procid = cpupath_procid.get(cpupath, None) + if procid is not None: + apicid = procid_apicid.get(procid, None) + if apicid is not None: + return apicid + if uid_x2apicid is not None: + uid = cpupath_uid.get(cpupath, None) + if uid is not None: + apicid = uid_x2apicid.get(uid, None) + if apicid is not None: + return apicid + return bits.cpus()[0] + + bclk = testutil.adjust_to_nearest(bits.bclk(), 100.0/12) * 1000000 + + uniques = acpi.parse_cpu_method("_PSS") + for pss, cpupaths in uniques.iteritems(): + if not testsuite.test("_PSS must exist", pss is not None): + testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) + testsuite.print_detail('No _PSS exists') + continue + + for n, pstate in enumerate(pss.pstates): + for cpupath in cpupaths: + apicid = cpupath_apicid(cpupath) + if apicid is None: + print 'Failed to find apicid for cpupath {}'.format(cpupath) + continue + bits.wrmsr(apicid, IA32_PERF_CTL, pstate.control) + + # Detecting Turbo frequency requires at least 2 pstates + # since turbo frequency = max non-turbo frequency + 1 + turbo = False + if len(pss.pstates) >= 2: + turbo = (n == 0 and pstate.core_frequency == (pss.pstates[1].core_frequency + 1)) + if turbo: + # Needs to busywait, not sleep + start = time.time() + while (time.time() - start < 2): + pass + + for duration in (0.1, 1.0): + frequency_data = bits.cpu_frequency(duration) + # Abort the test if no cpu frequency is not available + if frequency_data is None: + continue + aperf = frequency_data[1] + aperf = testutil.adjust_to_nearest(aperf, bclk/2) + aperf = int(aperf / 1000000) + if turbo: + if aperf >= pstate.core_frequency: + break + else: + if aperf == pstate.core_frequency: + break + + if turbo: + testsuite.test("P{}: Turbo measured frequency {} >= expected {} MHz".format(n, aperf, pstate.core_frequency), aperf >= pstate.core_frequency) + else: + testsuite.test("P{}: measured frequency {} MHz == expected {} MHz".format(n, aperf, pstate.core_frequency), aperf == pstate.core_frequency) + +def test_psd_thread_scope(): + uniques = acpi.parse_cpu_method("_PSD") + if not testsuite.test("_PSD (P-State Dependency) must exist for each processor", None not in uniques): + testsuite.print_detail(acpi.factor_commonprefix(uniques[None])) + testsuite.print_detail('No _PSD exists') + return + unique_num_dependencies = {} + unique_num_entries = {} + unique_revision = {} + unique_domain = {} + unique_coordination_type = {} + unique_num_processors = {} + for value, cpupaths in uniques.iteritems(): + unique_num_dependencies.setdefault(len(value.dependencies), []).extend(cpupaths) + unique_num_entries.setdefault(value.dependencies[0].num_entries, []).extend(cpupaths) + unique_revision.setdefault(value.dependencies[0].revision, []).extend(cpupaths) + unique_domain.setdefault(value.dependencies[0].domain, []).extend(cpupaths) + unique_coordination_type.setdefault(value.dependencies[0].coordination_type, []).extend(cpupaths) + unique_num_processors.setdefault(value.dependencies[0].num_processors, []).extend(cpupaths) + def detail(d, fmt): + for value, cpupaths in sorted(d.iteritems(), key=(lambda (k,v): v)): + testsuite.print_detail(acpi.factor_commonprefix(cpupaths)) + testsuite.print_detail(fmt.format(value)) + + testsuite.test('Dependency count for each processor must be 1', unique_num_dependencies.keys() == [1]) + detail(unique_num_dependencies, 'Dependency count for each processor = {} (Expected 1)') + testsuite.test('_PSD.num_entries must be 5', unique_num_entries.keys() == [5]) + detail(unique_num_entries, 'num_entries = {} (Expected 5)') + testsuite.test('_PSD.revision must be 0', unique_revision.keys() == [0]) + detail(unique_revision, 'revision = {}') + testsuite.test('_PSD.coordination_type must be 0xFE (HW_ALL)', unique_coordination_type.keys() == [0xfe]) + detail(unique_coordination_type, 'coordination_type = {:#x} (Expected 0xFE HW_ALL)') + testsuite.test('_PSD.domain must be unique (thread-scoped) for each processor', len(unique_domain) == len(acpi.get_cpupaths())) + detail(unique_domain, 'domain = {:#x} (Expected a unique value for each processor)') + testsuite.test('_PSD.num_processors must be 1', unique_num_processors.keys() == [1]) + detail(unique_num_processors, 'num_processors = {} (Expected 1)') + +def test_table_checksum(data): + csum = sum(ord(c) for c in data) % 0x100 + testsuite.test('ACPI table cumulative checksum must equal 0', csum == 0) + testsuite.print_detail("Cumulative checksum = {} (Expected 0)".format(csum)) + +def test_apic(): + data = acpi.get_table("APIC") + if data is None: + return + test_table_checksum(data) + apic = acpi.parse_apic() + +def test_dsdt(): + data = acpi.get_table("DSDT") + if data is None: + return + test_table_checksum(data) + +def test_facp(): + data = acpi.get_table("FACP") + if data is None: + return + test_table_checksum(data) + facp = acpi.parse_facp() + +def test_hpet(): + data = acpi.get_table("HPET") + if data is None: + return + test_table_checksum(data) + hpet = acpi.parse_hpet() + +def test_mpst(): + data = acpi.get_table("MPST") + if data is None: + return + test_table_checksum(data) + mpst = acpi.MPST(data) + +def test_rsdp(): + data = acpi.get_table("RSD PTR ") + if data is None: + return + + # Checksum the first 20 bytes per ACPI 1.0 + csum = sum(ord(c) for c in data[:20]) % 0x100 + testsuite.test('ACPI 1.0 table first 20 bytes cummulative checksum must equal 0', csum == 0) + testsuite.print_detail("Cummulative checksum = {} (Expected 0)".format(csum)) + + test_table_checksum(data) + rsdp = acpi.parse_rsdp() + +def test_xsdt(): + data = acpi.get_table("XSDT") + if data is None: + return + test_table_checksum(data) + xsdt = acpi.parse_xsdt() diff --git a/tests/qtest/acpi-bits/bits-tests/testcpuid.py b/tests/qtest/acpi-bits/bits-tests/testcpuid.py new file mode 100644 index 0000000000..ac55d912e1 --- /dev/null +++ b/tests/qtest/acpi-bits/bits-tests/testcpuid.py @@ -0,0 +1,83 @@ +# Copyright (c) 2012, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests and helpers for CPUID.""" + +import bits +import testsuite +import testutil + +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 test_cpuid_consistency(text, function, index=None, shift=0, mask=~0, eax_mask=~0, ebx_mask=~0, ecx_mask=~0, edx_mask=~0): + uniques, desc = cpuid_helper(function, index, shift, mask, eax_mask, ebx_mask, ecx_mask, edx_mask) + desc[0] += " Consistency Check" + if text: + desc.insert(0, text) + status = testsuite.test(desc[0], len(uniques) == 1) + for line in desc[1:]: + testsuite.print_detail(line) + return status From patchwork Mon Jun 27 07:28:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896338 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4C636C43334 for ; Mon, 27 Jun 2022 07:38:17 +0000 (UTC) Received: from localhost ([::1]:39976 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jK4-0000Dn-4O for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:38:16 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55948) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCa-00059w-M2 for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:32 -0400 Received: from mail-pg1-x535.google.com ([2607:f8b0:4864:20::535]:35784) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCZ-0005yY-2b for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:32 -0400 Received: by mail-pg1-x535.google.com with SMTP id r66so8336476pgr.2 for ; Mon, 27 Jun 2022 00:30:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=cAmHc2wPxluOD0WIjk4hh88cF39rdcDgc3wYDsEpLas=; b=bfHFqXCZNG/2+ZNR9XL1JWVzqQCoxs2bZN3kQ+VwPa8ZkmLiFJdg+GY8LlnmibC3SO N+t43is3PTKOsSO0h7yrIJoVpOww5OyTvTNF35KiSoUJ96Snu/O9HZzeKbHCoSVfHXMi MXbz2IlfQmtb3S+V8xc25KtQqpDIuDPazYeltIf62bynNmMSHynbvHRA9BKU7wE7CGF8 QPOhhrmat0WwNPDg3KHSJ5B007pKCzyIL72TdQTxO3NSYRibhz+zsuQp7GhqNrlvwh1J YaILGPjMfp1tZz0gEob2ksikFyIn6aEElxguRBzsdH5OB/Oy3TtXdKzFR3LyeiPWh8U6 mFAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cAmHc2wPxluOD0WIjk4hh88cF39rdcDgc3wYDsEpLas=; b=mSOQzuHuWEgRKZJSqAOloWGfrsjUUORrStHrIY075T20hgv7OIkvZYZNSkwGc4CAIr SUmQFt8JFkVRrBOqexlRDfRGmA3p2o17FCgxc2kT8j2vBPoTYfO6kBKM2osAAnrCMhcL a7hvi1W5ZQx4GSSLsKjiFu/xIigAewTqC2Bb7XtlDHmm8LoN6t7L30Pg4PpMeuvweWG8 WxbQjZWEpCj++k3zHTmxxswqTac5VE51qjhfjbeFdK9Ad/TPxIEMs0SX+qT70B7jQ16w vSBiwB5/1v1/Gpg3lXr/JUUoh2Bsb7wPbE1dcyGxYNu74aMzABtVJs6rsX2qeVpMbURu xqig== X-Gm-Message-State: AJIora/YjbiM/wi0Uu4zm8eRCehVTtl8+xw5Lg0x6XxjTS/licUFHCfS kk3oFev7aP0GXlCfsQ8vdmDOqeVncALuskus6Uo= X-Google-Smtp-Source: AGRyM1vT0uAKqqaHtx8ncLVCvSWfp6CNUR6oR7tCk5eDPG8jd2fFS0ljxvXXsvuflM7rMrBXT6vXxg== X-Received: by 2002:a05:6a00:114e:b0:51b:8ff5:e05a with SMTP id b14-20020a056a00114e00b0051b8ff5e05amr13497282pfm.37.1656315029394; Mon, 27 Jun 2022 00:30:29 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:29 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 05/12] acpi/tests/bits: disable acpi PSS tests that are failing in biosbits Date: Mon, 27 Jun 2022 12:58:49 +0530 Message-Id: <20220627072856.1529357-6-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::535; envelope-from=ani@anisinha.ca; helo=mail-pg1-x535.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" PSS tests in acpi test suite seems to be failing in biosbits. This is because the test is unable to find PSS support in QEMU bios. Let us disable them for now so that make check does not fail. We can fix the tests and re-enable them later. Example failure: ---- ACPI _PSS (Pstate) table conformance tests ---- [assert] _PSS must exist FAIL \_SB_.CPUS.C000 No _PSS exists Summary: 1 passed, 1 failed ---- ACPI _PSS (Pstate) runtime tests ---- [assert] _PSS must exist FAIL \_SB_.CPUS.C000 No _PSS exists Summary: 0 passed, 1 failed Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/bits-tests/testacpi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/acpi-bits/bits-tests/testacpi.py b/tests/qtest/acpi-bits/bits-tests/testacpi.py index 9ec452f330..dbc150076e 100644 --- a/tests/qtest/acpi-bits/bits-tests/testacpi.py +++ b/tests/qtest/acpi-bits/bits-tests/testacpi.py @@ -36,8 +36,8 @@ def register_tests(): testsuite.add_test("ACPI _MAT (Multiple APIC Table Entry) under Processor objects", test_mat, submenu="ACPI Tests") - testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests") - testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests") +# testsuite.add_test("ACPI _PSS (Pstate) table conformance tests", test_pss, submenu="ACPI Tests") +# testsuite.add_test("ACPI _PSS (Pstate) runtime tests", test_pstates, submenu="ACPI Tests") testsuite.add_test("ACPI DSDT (Differentiated System Description Table)", test_dsdt, submenu="ACPI Tests") testsuite.add_test("ACPI FACP (Fixed ACPI Description Table)", test_facp, submenu="ACPI Tests") testsuite.add_test("ACPI HPET (High Precision Event Timer Table)", test_hpet, submenu="ACPI Tests") From patchwork Mon Jun 27 07:28:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896339 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0998AC433EF for ; Mon, 27 Jun 2022 07:41:08 +0000 (UTC) Received: from localhost ([::1]:45226 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jMo-0003l6-UE for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:41:06 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55978) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCh-0005Jf-2N for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:40 -0400 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]:41603) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCe-0005zI-3L for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:37 -0400 Received: by mail-pf1-x42a.google.com with SMTP id i64so8177881pfc.8 for ; Mon, 27 Jun 2022 00:30:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Fh1ZoyGzwA4iqvZSNk0dn7iRIAjcMEjp8nc1fuCg7M4=; b=lu3X575LrTy/mZ4/GxTok9RbZ2FXgD6wFaZnbQavu5KwbNI5qj5jcRUgrias/kDtvD yP7WV93biVwN4jDnQHAPJbgSxYLTi8/Enib6jxnalEPlZniHT2YANxLv+Lw7lYFjfCa8 39jfV661BbnOvBlhGWud2GL01n+zuP0WdLtgcBqoCbuOewaz1zHiHnE+57IRl62E2Nkm qpUVcJUYbWGVjJS3jugk2bVm0KfxxDbSOzJEKsySToXej4dWOeVvUMPzmX+GijnHAFDy 8/unAl0Et4CO1iB/y+dCFMAxFGe/MD/dWe79kuQgacXOw3rNFQNvaTGhsLi+Zrmc6ZJ3 yc4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Fh1ZoyGzwA4iqvZSNk0dn7iRIAjcMEjp8nc1fuCg7M4=; b=kW1jVfFjwVJbMxHGERsNVpyCmAXAcoS8tOAxnqKJpgrddsB8XvFvH+ALLcQ2DkCkfd cYnUK0JbmLr73CRuqmF/7/BneTgpgprIS7uJI0D1iydi3HrmXHw4a3DZy768xQGJ3eB1 uQI56HRLizDlWgSjpqc6SbA81bnZOFHJcR214JNxkBH+f4juDfELN+8twT2s9/+2IccI 3Wz04P3rlRfU2OhoXW/s5zb5aMJP8qoSvh6G/F0yy3IRk3j21sDy86HBNe1vsEsiIiPl fOQep4Nu4gSd/keD06T9Zpqpk2C0/pjHyKmLZxkzanFWA6ucSociw1d9C0Q3n3xGMUAQ LVrw== X-Gm-Message-State: AJIora+ziGZspSfxU56v28yjsgeqrqYRhbvUpn/wtsDZmAaHli4xqkcp nlKoT+xPqWY7YjlSQdIuGpl5dsKSOAs3N6r1s+M= X-Google-Smtp-Source: AGRyM1sWo55qYl2+JAZ+f/CIg/PoJ0eMCEE0okhrIfe+ay7CzCgkhgxB9mXO9wRrhrp5MsAqqWuMKw== X-Received: by 2002:a63:371e:0:b0:40c:f411:6768 with SMTP id e30-20020a63371e000000b0040cf4116768mr11738470pga.471.1656315034300; Mon, 27 Jun 2022 00:30:34 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:33 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 06/12] acpi/tests/bits: add smilatency test suite from bits in order to disable it Date: Mon, 27 Jun 2022 12:58:50 +0530 Message-Id: <20220627072856.1529357-7-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::42a; envelope-from=ani@anisinha.ca; helo=mail-pf1-x42a.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" smilatency tests does not reliably pass every time it is run from QEMU. This change adds the test file unchanged from bits so that the next change can disable the test. Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/bits-tests/meson.build | 2 +- .../qtest/acpi-bits/bits-tests/smilatency.py | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/acpi-bits/bits-tests/smilatency.py diff --git a/tests/qtest/acpi-bits/bits-tests/meson.build b/tests/qtest/acpi-bits/bits-tests/meson.build index 3056731a53..06bca75d99 100644 --- a/tests/qtest/acpi-bits/bits-tests/meson.build +++ b/tests/qtest/acpi-bits/bits-tests/meson.build @@ -1,4 +1,4 @@ -test_files = ['smbios.py', 'testacpi.py', 'testcpuid.py'] +test_files = ['smbios.py', 'smilatency.py', 'testacpi.py', 'testcpuid.py'] copytestfiles = custom_target('copy test files', input : test_files, diff --git a/tests/qtest/acpi-bits/bits-tests/smilatency.py b/tests/qtest/acpi-bits/bits-tests/smilatency.py new file mode 100644 index 0000000000..fb1b7228e3 --- /dev/null +++ b/tests/qtest/acpi-bits/bits-tests/smilatency.py @@ -0,0 +1,102 @@ +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Intel Corporation nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""SMI latency test.""" + +import bits +from collections import namedtuple +import testsuite +import time +import usb + +def register_tests(): + testsuite.add_test("SMI latency test", smi_latency); + testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False); + +def smi_latency(): + MSR_SMI_COUNT = 0x34 + + print "Warning: touching the keyboard can affect the results of this test." + + tsc_per_sec = bits.tsc_per_sec() + tsc_per_usec = tsc_per_sec / (1000 * 1000) + bins = [long(tsc_per_usec * 10**i) for i in range(9)] + bin_descs = [ + "0 < t <= 1us", + "1us < t <= 10us", + "10us < t <= 100us", + "100us < t <= 1ms", + "1ms < t <= 10ms", + "10ms < t <= 100ms", + "100ms < t <= 1s ", + "1s < t <= 10s ", + "10s < t <= 100s ", + "100s < t ", + ] + + print "Starting test. Wait here, I will be back in 15 seconds." + (max_latency, smi_count_delta, bins) = bits.smi_latency(long(15 * tsc_per_sec), bins) + BinType = namedtuple('BinType', ("max", "total", "count", "times")) + bins = [BinType(*b) for b in bins] + + testsuite.test("SMI latency < 150us to minimize risk of OS timeouts", max_latency / tsc_per_usec <= 150) + if not testsuite.show_detail(): + return + + for bin, desc in zip(bins, bin_descs): + if bin.count == 0: + continue + testsuite.print_detail("{}; average = {}; count = {}".format(desc, bits.format_tsc(bin.total/bin.count), bin.count)) + deltas = (bits.format_tsc(t2 - t1) for t1,t2 in zip(bin.times, bin.times[1:])) + testsuite.print_detail(" Times between first few observations: {}".format(" ".join("{:>6}".format(delta) for delta in deltas))) + + if smi_count_delta is not None: + testsuite.print_detail("{} SMI detected using MSR_SMI_COUNT (MSR {:#x})".format(smi_count_delta, MSR_SMI_COUNT)) + + testsuite.print_detail("Summary of impact: observed maximum latency = {}".format(bits.format_tsc(max_latency))) + +def test_with_usb_disabled(): + if usb.handoff_to_os(): + smi_latency() + +def average_io_smi(port, value, count): + def f(): + tsc_start = bits.rdtsc() + bits.outb(port, value) + return bits.rdtsc() - tsc_start + counts = [f() for i in range(count)] + return sum(counts)/len(counts) + +def time_io_smi(port=0xb2, value=0, count=1000): + count_for_estimate = 10 + start = time.time() + average_io_smi(port, value, count_for_estimate) + avg10 = time.time() - start + estimate = avg10 * count/count_for_estimate + if estimate > 1: + print "Running test, estimated time: {}s".format(int(estimate)) + average = average_io_smi(port, value, count) + print "Average of {} SMIs (via outb, port={:#x}, value={:#x}): {}".format(count, port, value, bits.format_tsc(average)) From patchwork Mon Jun 27 07:28:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896343 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 19703C433EF for ; Mon, 27 Jun 2022 07:44:48 +0000 (UTC) Received: from localhost ([::1]:51082 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jQL-0007lw-G2 for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:44:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56012) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCj-0005Lf-J0 for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:42 -0400 Received: from mail-pg1-x535.google.com ([2607:f8b0:4864:20::535]:35784) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCh-0005yY-MX for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:41 -0400 Received: by mail-pg1-x535.google.com with SMTP id r66so8336476pgr.2 for ; Mon, 27 Jun 2022 00:30:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7yaooi/YX0N1Ovq8r6H8DlJjBpFlIStDURKxX0nntKs=; b=FEjgd0+bMAo5JEYusqi9u9bkfUx8jDL03q4hSpLrLnAwRU7KFwYUBvX60wfRt/4JaH kSPOt57C5INgUsXUnQkQUGFUMCm+nXW5EHctVjQ6rnBfW4uK6yzbcfqW0mFeba8I3bRE 7ZPNaKlpEXm49XGZzGPgbDKhTyLI/UyGhyMr2Fohm+6xzR7wKHu8Ka+cTXSSRITNyEPy xDH4w6n4lkCc50PlNeAeTmZ4qsL7c93xrfZ3umZDDGlfAzhvVeYnsE/xA/Vz4KYMYNxD j8uSXD1Xv0+0oRIMRtQp+1TK9ELv6syOMX8Jaof66MJ0OhQymUPD9gYnpeSJq7d3PX7D ZbCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7yaooi/YX0N1Ovq8r6H8DlJjBpFlIStDURKxX0nntKs=; b=TOkH5R58LfB4ZyVufcVnEQmqNBfXAVmbmKQZhLJ1Qe1EKt1fiV8KZp6qnzzqo9thtD R9zyAMBQ3SAPdC8D7OvVt2nI/HnXF/KB71oU4jO9oUJaMJ44pB0pURg+5q0lBEineICk esfoVne/9bHdvEjGGcAs7+fMvclP5qE4GtmX4vdj2MPqKancNAEJpkae8QoAfoevAuCa amoGcuyXdRRk51Dnuv+O0n1FfU5JzFaG0FNAiOZ6fXzGQ15n0fhp361qYSpqrxHlZr53 y5BS42fiEE62O8dG8bpiWuN7m2HNJJyqwaut05aI9XuEiwQReU+qFZL67OJnX5IfYvvd rVyg== X-Gm-Message-State: AJIora+oPSQCaWDTAfGPC0YnoWS5XLcBdpKDtr/1h8FfIQ13F6dquUba FZO5aQ/FJaE9tcG17wUlw2szI52lSDfFqWgoHqg= X-Google-Smtp-Source: AGRyM1vgPO5xrzfq3AgcoS+CYyohXG4vF4/wsb8J3nabhkO613ZCKf4B+9Cz73w1CbWv9OB7WIgZDA== X-Received: by 2002:a63:4407:0:b0:40d:f0c7:8277 with SMTP id r7-20020a634407000000b0040df0c78277mr4291360pga.163.1656315038630; Mon, 27 Jun 2022 00:30:38 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:38 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 07/12] acpi/tests/bits: disable smilatency test since it does not pass everytime Date: Mon, 27 Jun 2022 12:58:51 +0530 Message-Id: <20220627072856.1529357-8-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::535; envelope-from=ani@anisinha.ca; helo=mail-pg1-x535.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" smilatency test is latency sensitive and does not pass deterministically when run in QEMU environment under biosbits. Disable the test suite for now. Example failure: ==== SMI latency test ==== Warning: touching the keyboard can affect the results of this test. Starting test. Wait here, I will be back in 15 seconds. [assert] SMI latency < 150us to minimize risk of OS timeouts FAIL 1us < t <= 10us; average = 1372ns; count = 10912449 Times between first few observations: 176us 1646ns 1441ns 1450ns 1462ns 10us < t <= 100us; average = 16us; count = 1187 Times between first few observations: 15ms 3148us 5856us 49ms 33ms 100us < t <= 1ms; average = 259us; count = 8 Times between first few observations: 111ms 2227ms 1779ms 999ms 219ms 0 SMI detected using MSR_SMI_COUNT (MSR 0x34) Summary of impact: observed maximum latency = 298us Summary: 0 passed, 1 failed Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/bits-tests/smilatency.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/qtest/acpi-bits/bits-tests/smilatency.py b/tests/qtest/acpi-bits/bits-tests/smilatency.py index fb1b7228e3..53b5f820a5 100644 --- a/tests/qtest/acpi-bits/bits-tests/smilatency.py +++ b/tests/qtest/acpi-bits/bits-tests/smilatency.py @@ -33,8 +33,9 @@ import usb def register_tests(): - testsuite.add_test("SMI latency test", smi_latency); - testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False); + pass + # testsuite.add_test("SMI latency test", smi_latency); + # testsuite.add_test("SMI latency test with USB disabled via BIOS handoff", test_with_usb_disabled, runall=False); def smi_latency(): MSR_SMI_COUNT = 0x34 From patchwork Mon Jun 27 07:28:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896321 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BADEBC43334 for ; Mon, 27 Jun 2022 07:38:03 +0000 (UTC) Received: from localhost ([::1]:39468 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jJq-0008JG-Mp for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:38:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56034) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCn-0005Ow-Tp for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:48 -0400 Received: from mail-pf1-x431.google.com ([2607:f8b0:4864:20::431]:36446) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCm-000629-DS for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:45 -0400 Received: by mail-pf1-x431.google.com with SMTP id x138so5511451pfc.3 for ; Mon, 27 Jun 2022 00:30:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=NdMMt5pJjReoNXvd1kwyatt4oEzdoKgFGcBXEqCNEn0=; b=K3J9+2sUWCNPqOq5vsMhq7HtVENUUdcyFm4t1OYwvG+UAConGgDGmOTuaAV4gw8508 SXj7BFsE1ZtzJDtttc0HX0yrZBEHw1qrOTUexNUXUzmx/903VQ7IZHRf5UbsFR/dL2Ah 31/mLuJqXsaxiY5LIXcM8NUp6Hpd0Je9nW2iMc0DSLDy978/+JX424BXG/toloPd1pDD zAU1DZ4QRf2hcVmd4rnBbc5kiIUdBAwHBfl06HCOMd7Cidks2LWFVnTOZrbLRQwWFk7M 75uMmC0UNNzmerT/nLiyk/8Y8uVIJQ5kbHT7dEAfzsf9EdSBgybB0nXgs8gC3MvSf5ET Y0Pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=NdMMt5pJjReoNXvd1kwyatt4oEzdoKgFGcBXEqCNEn0=; b=bERiZvVwqsa15SQJObIPosqCP3DNldlRqLFOFRrIRabDny7jOWfpqNnp+o++DeeCtX z3OwW2agXJeHss+B10UuHDmKlVKBOiE3tR7Y4L+9FkaoBPci8EfcSm7plWOnETaocrzu 94etdxOJs2eoB3VS5ifKEUy5QPz0oJ+CLfjN5VkaIMN8YAYjzQPR9OjPIROBo5OuabtE eP3J1reKq42nfMKMzSUqtqDuT6XByStqXm4LQQtdmECga1cNx59+P66kMfztlutbPV7e aCcCfrG2B2Ddzz/d2wyJr8U2ya5eHiipsMeScpr1RF0MUxSYXvn2nAevMe7NJZJV9ZYy A/QA== X-Gm-Message-State: AJIora/DFN4AvUQhIbjbR9hbgp/bhjPRkrg5+hd21+6BEx57Jv7Qtcy/ BICcaABEBMkexBJYPJ3DSbQYSKxTQdXq2Amwk0o= X-Google-Smtp-Source: AGRyM1vPybhhkFSCIFtiLlLsciZXKHuGnooWnfA8hRwKq8qXqNq/XOUe/zWkO3e8fwLoEUt2GhfJrw== X-Received: by 2002:a62:6dc2:0:b0:525:43c8:79f7 with SMTP id i185-20020a626dc2000000b0052543c879f7mr13197205pfc.49.1656315042870; Mon, 27 Jun 2022 00:30:42 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:42 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 08/12] acpi/tests/bits: add biosbits config file for running bios tests Date: Mon, 27 Jun 2022 12:58:52 +0530 Message-Id: <20220627072856.1529357-9-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::431; envelope-from=ani@anisinha.ca; helo=mail-pf1-x431.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This change adds initial biosbits config file that instructs biosbits to run bios test suits in batch mode. Additionally acpi and smbios structures are also dumped. Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/bits-config/bits-cfg.txt | 18 ++++++++++++++++++ tests/qtest/acpi-bits/bits-config/meson.build | 11 +++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/qtest/acpi-bits/bits-config/bits-cfg.txt create mode 100644 tests/qtest/acpi-bits/bits-config/meson.build diff --git a/tests/qtest/acpi-bits/bits-config/bits-cfg.txt b/tests/qtest/acpi-bits/bits-config/bits-cfg.txt new file mode 100644 index 0000000000..8010804453 --- /dev/null +++ b/tests/qtest/acpi-bits/bits-config/bits-cfg.txt @@ -0,0 +1,18 @@ +# BITS configuration file +[bits] + +# To run BITS in batch mode, set batch to a list of one or more of the +# following keywords; BITS will then run all of the requested operations, then +# save the log file to disk. +# +# test: Run the full BITS testsuite. +# acpi: Dump all ACPI structures. +# smbios: Dump all SMBIOS structures. +# +# Leave batch set to an empty string to disable batch mode. +# batch = + +# Uncomment the following to run all available batch operations +# please take a look at boot/python/init.py in bits zip file +# to see how these options are parsed and used. +batch = test acpi smbios diff --git a/tests/qtest/acpi-bits/bits-config/meson.build b/tests/qtest/acpi-bits/bits-config/meson.build new file mode 100644 index 0000000000..bbd7a940dc --- /dev/null +++ b/tests/qtest/acpi-bits/bits-config/meson.build @@ -0,0 +1,11 @@ +config_files = ['bits-cfg.txt'] + +copycfgfiles = custom_target('copy cfg files', + input : config_files, + output : config_files, + command : ['cp', '@INPUT@', '@OUTPUT@'], + install : true, + install_dir : 'bits-config', + build_by_default : true) + +other_deps += copycfgfiles From patchwork Mon Jun 27 07:28:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896344 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EF852C433EF for ; Mon, 27 Jun 2022 07:45:43 +0000 (UTC) Received: from localhost ([::1]:53052 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jRG-0000fL-WF for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:45:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56060) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jCx-0005VI-Bc for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:55 -0400 Received: from mail-pl1-x630.google.com ([2607:f8b0:4864:20::630]:43551) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCu-000655-57 for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:30:54 -0400 Received: by mail-pl1-x630.google.com with SMTP id r1so7391552plo.10 for ; Mon, 27 Jun 2022 00:30:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=EB/Bt8Qjj35xoDj6iBfFFp6H1rhYmFpRvyg3Y4Mq7rk=; b=hiryN9IRJtAoacWPkatwYX9KhIAF3imkKqkDH6WHUgHCsbXu2bFIt0yyDNtzu563R/ s9lpMZ9B8wsoLuilijMlmatyZtQBh4GRVz+2Rv/OeIXEyLl/uQ16koNRPcxcvkkHGaZc dHiPBT9GyTyTNFKnK12kg2781OEOP/T4/tJgIknBXX20hy8hLFqaLvNYBNCS8em8QqwC Tai6iY6uJqOEvmUyuogAj60MCsyIpkmQ9mjDkFr2GfEd0XiJ3e/qhSURkInsBh7l3a+N 0XUDx+Q6Bb3rkoirLt1Esr/UteR/J9XU/N6vX98VXc85yVH1GQChJQbHUjEFHKFIIonW 1iZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=EB/Bt8Qjj35xoDj6iBfFFp6H1rhYmFpRvyg3Y4Mq7rk=; b=GToldp4Nqjp4faeiTJ/1HRuGnbVyXU1oOPm7EphOC1YtTWkBJbPaKoVYgxhFhMMdj7 nJu1I94V4vdcArton6Ok+ZH5hw21UXDSUWIINU8bqaI8itaTDL0rtw+yCjIDR3u6BrTC xSNdkj0Ae2GSBLpXCj2ZtGbFVtBOKiDuufQlntLpKsBj3pMbLH1sKoylVknx3ogjmMNl jBZw2aoEQrpyD1nkwhtz0pf6NY1DUmw2BFEprj6tCFbZYpFOayrbzy/gW3+2bXmcGtBx aUK6HvVnN/Tr9aG4wVbGwUDkcyt/FbdQgYc3l8pwrFaMsj5CFtfkZym1sLzS0q2qe0ge TKOg== X-Gm-Message-State: AJIora8TfCrcT+hd/wuzUsZqzlas6QbXQKmjs2BCNO479CFI2p2xCrA0 ftSR6U06BnDmeN1z6OUsVqP/yQxjrJcFbj1++/Y= X-Google-Smtp-Source: AGRyM1vHQZ4bBVqm5ZXf/BQguBxEXz4QMCj/kx9prFIKqOKtS7NYk002n9bJid85DRH4oG/X7iocVQ== X-Received: by 2002:a17:903:2452:b0:16a:3b58:48fd with SMTP id l18-20020a170903245200b0016a3b5848fdmr12856420pls.67.1656315049503; Mon, 27 Jun 2022 00:30:49 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:49 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Ani Sinha , Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com Subject: [PATCH 09/12] acpi/tests/bits: add acpi and smbios python tests that uses biosbits Date: Mon, 27 Jun 2022 12:58:53 +0530 Message-Id: <20220627072856.1529357-10-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::630; envelope-from=ani@anisinha.ca; helo=mail-pl1-x630.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" This change adds python based qtest framework that can be used to run qtests from within a virtual environment. A bash script creates the virtual environment and then runs the python based tests from within that environment. All dependent python packages are installed in the virtual environment using pip module. QEMU python test modules are also available in the environment for spawning the QEMU based VMs. It also introduces QEMU acpi/smbios biosbits python test script which is run from within the python virtual environment. Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/acpi-bits-test-venv.sh | 59 ++++ tests/qtest/acpi-bits/acpi-bits-test.py | 327 +++++++++++++++++++ tests/qtest/acpi-bits/meson.build | 39 +++ tests/qtest/acpi-bits/requirements.txt | 1 + 4 files changed, 426 insertions(+) create mode 100644 tests/qtest/acpi-bits/acpi-bits-test-venv.sh create mode 100644 tests/qtest/acpi-bits/acpi-bits-test.py create mode 100644 tests/qtest/acpi-bits/meson.build create mode 100644 tests/qtest/acpi-bits/requirements.txt diff --git a/tests/qtest/acpi-bits/acpi-bits-test-venv.sh b/tests/qtest/acpi-bits/acpi-bits-test-venv.sh new file mode 100644 index 0000000000..124e03ce18 --- /dev/null +++ b/tests/qtest/acpi-bits/acpi-bits-test-venv.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# Generates a python virtual environment for the test to run. +# Then runs python test scripts from within that virtual environment. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Ani Sinha + +set -e + +MYPATH=$(realpath ${BASH_SOURCE:-$0}) +MYDIR=$(dirname $MYPATH) + +if [ -z "$QTEST_SOURCE_ROOT" ]; then + echo -n "Please set QTEST_SOURCE_ROOT env pointing" + echo " to the root of the qemu source tree." + echo -n "This is required so that the test can find the " + echo "python modules that it needs for execution." + exit 1 +fi +SRCDIR=$QTEST_SOURCE_ROOT +TESTSCRIPTS=("acpi-bits-test.py") +PIPCMD="-m pip -q --disable-pip-version-check" +# we need to save the old value of PWD before we do a change-dir later +QTEST_PWD=$PWD + +TESTS_PYTHON=/usr/bin/python3 +TESTS_VENV_REQ=requirements.txt + +# sadly for pip -e and -t options do not work together. +# please see https://github.com/pypa/pip/issues/562 +cd $MYDIR + +$TESTS_PYTHON -m venv . +$TESTS_PYTHON $PIPCMD install -e $SRCDIR/python/ +[ -f $TESTS_VENV_REQ ] && \ + $TESTS_PYTHON $PIPCMD install -r $TESTS_VENV_REQ + +# venv is activated at this point. + +# run the test +for testscript in ${TESTSCRIPTS[@]} ; do + export QTEST_PWD; python3 $testscript +done + +cd $QTEST_PWD + +exit 0 diff --git a/tests/qtest/acpi-bits/acpi-bits-test.py b/tests/qtest/acpi-bits/acpi-bits-test.py new file mode 100644 index 0000000000..673567bf8e --- /dev/null +++ b/tests/qtest/acpi-bits/acpi-bits-test.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python3 +# group: rw quick +# Exercize QEMU generated ACPI/SMBIOS tables using biosbits, +# https://biosbits.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Some parts are slightly taken from qtest.py and iotests.py +# +# Authors: +# Ani Sinha + +# pylint: disable=invalid-name + +""" +QEMU bios tests using biosbits available at +https://biosbits.org/. +""" + +import logging +import os +import re +import shutil +import subprocess +import sys +import tarfile +import tempfile +import time +import unittest +import zipfile +from typing import ( + List, + Optional, + Sequence, +) +from tap import TAPTestRunner +from qemu.machine import QEMUMachine + +QTESTQEMUPROG = os.getenv('QTEST_QEMU_BINARY') +QTEST_PWD = os.getenv('QTEST_PWD') + +def get_arch(): + """finds the arch from the qemu binary name""" + match = re.search('.*qemu-system-(.*)', QTESTQEMUPROG) + if match: + return match.group(1) + return 'x86_64' + +ARCH = get_arch() + +class QEMUBitsMachine(QEMUMachine): + """ + A QEMU VM, with isa-debugcon enabled and bits iso passed + using -cdrom to QEMU commandline. + """ + def __init__(self, + binary: str, + args: Sequence[str] = (), + wrapper: Sequence[str] = (), + name: Optional[str] = None, + base_temp_dir: str = "/var/tmp", + debugcon_log: str = "debugcon-log.txt", + debugcon_addr: str = "0x403", + sock_dir: Optional[str] = None, + qmp_timer: Optional[float] = None): + # pylint: disable=too-many-arguments + + if name is None: + name = "qemu-bits-%d" % os.getpid() + if sock_dir is None: + sock_dir = base_temp_dir + super().__init__(binary, args, wrapper=wrapper, name=name, + base_temp_dir=base_temp_dir, + sock_dir=sock_dir, qmp_timer=qmp_timer) + self.debugcon_log = debugcon_log + self.debugcon_addr = debugcon_addr + self.base_temp_dir = base_temp_dir + + @property + def _base_args(self) -> List[str]: + args = super()._base_args + args.extend([ + '-chardev', + 'file,path=%s,id=debugcon' %os.path.join(self.base_temp_dir, + self.debugcon_log), + '-device', + 'isa-debugcon,iobase=%s,chardev=debugcon' %self.debugcon_addr, + ]) + return args + + def base_args(self): + """return the base argument to QEMU binary""" + return self._base_args + +class AcpiBitsTest(unittest.TestCase): + """ACPI and SMBIOS tests using biosbits.""" + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._vm = None + self._workdir = None + self._bitsver = 2095 + self._debugcon_addr = '0x403' + self._debugcon_log = 'debugcon-log.txt' + logging.basicConfig(level=logging.INFO) + + def copy_bits_config(self): + """ copies the bios bits config file into bits. + """ + config_file = 'bits-cfg.txt' + qemu_bits_config_dir = os.path.join(os.getcwd(), 'bits-config') + target_config_dir = os.path.join(self._workdir, + 'bits-%d' %self._bitsver, 'boot') + self.assertTrue(os.path.exists(qemu_bits_config_dir)) + self.assertTrue(os.path.exists(target_config_dir)) + self.assertTrue(os.access(os.path.join(qemu_bits_config_dir, + config_file), os.R_OK)) + shutil.copy2(os.path.join(qemu_bits_config_dir, config_file), + target_config_dir) + logging.info('copied config file %s to %s', + config_file, target_config_dir) + + def copy_test_scripts(self): + """copies the python test scripts into bits. """ + qemu_test_dir = os.path.join(os.getcwd(), 'bits-tests') + target_test_dir = os.path.join(self._workdir, 'bits-%d' %self._bitsver, + 'boot', 'python') + + self.assertTrue(os.path.exists(qemu_test_dir)) + self.assertTrue(os.path.exists(target_test_dir)) + + for filename in os.listdir(qemu_test_dir): + if os.path.isfile(os.path.join(qemu_test_dir, filename)) and \ + filename.endswith('.py'): + shutil.copy2(os.path.join(qemu_test_dir, filename), + target_test_dir) + logging.info('copied test file %s to %s', + filename, target_test_dir) + + # now remove the pyc test file if it exists, otherwise the + # changes in the python test script won't be executed. + testfile_pyc = os.path.splitext(filename)[0] + '.pyc' + if os.access(os.path.join(target_test_dir, testfile_pyc), + os.R_OK): + os.remove(os.path.join(target_test_dir, testfile_pyc)) + logging.info('removed compiled file %s', + os.path.join(target_test_dir, testfile_pyc)) + + def fix_mkrescue(self, mkrescue): + """ grub-mkrescue is a bash script with two variables, 'prefix' and + 'libdir'. They must be pointed to the right location so that the + iso can be generated appropriately. We point the two variables to + the directory where we have extracted our pre-built bits grub + tarball. + """ + grub_x86_64_mods = os.path.join(self._workdir, 'bits-grub', + 'grub-inst-x86_64-efi') + grub_i386_mods = os.path.join(self._workdir, 'bits-grub', + 'grub-inst') + + self.assertTrue(os.path.exists(grub_x86_64_mods)) + self.assertTrue(os.path.exists(grub_i386_mods)) + + new_script = "" + with open(mkrescue, 'r') as filehandle: + orig_script = filehandle.read() + new_script = re.sub('(^prefix=)(.*)', + r'\1"%s"' %grub_x86_64_mods, + orig_script, flags=re.M) + new_script = re.sub('(^libdir=)(.*)', r'\1"%s/lib"' %grub_i386_mods, + new_script, flags=re.M) + + with open(mkrescue, 'w') as filehandle: + filehandle.write(new_script) + + def generate_bits_iso(self): + """ Uses grub-mkrescue to generate a fresh bits iso with the python + test scripts + """ + bits_dir = os.path.join(self._workdir, 'bits-%d' %self._bitsver) + iso_file = os.path.join(self._workdir, 'bits-%d.iso' %self._bitsver) + mkrescue_script = os.path.join(self._workdir, + 'bits-grub', 'grub-inst-x86_64-efi', + 'bin', 'grub-mkrescue') + + self.assertTrue(os.access(mkrescue_script, os.R_OK | os.W_OK)) + + self.fix_mkrescue(mkrescue_script) + + logging.info('calling grub-mkrescue to generate the biosbits iso ...') + + if os.getenv('V'): + subprocess.check_call([mkrescue_script, '-o', iso_file, bits_dir], + stdout=subprocess.DEVNULL) + else: + subprocess.check_call([mkrescue_script, '-o', iso_file, bits_dir], + stderr=subprocess.DEVNULL, + stdout=subprocess.DEVNULL) + + self.assertTrue(os.access(iso_file, os.R_OK)) + + logging.info('iso file %s successfully generated.', iso_file) + + def setUp(self): + self._workdir = tempfile.mkdtemp(prefix='acpi-bits-', + suffix='.tmp') + + logging.info('generated working dir: %s', self._workdir) + + # extract the bits software in the temp working directory + bits_zip_file = os.path.join(os.getcwd(), 'prebuilt', 'bits-%d.zip' + %self._bitsver) + grub_tar_file = os.path.join(os.getcwd(), 'prebuilt', + 'bits-%d-grub.tar.gz' %self._bitsver) + + with zipfile.ZipFile(bits_zip_file, 'r') as zref: + zref.extractall(self._workdir) + + with tarfile.open(grub_tar_file, 'r') as tarball: + tarball.extractall(self._workdir) + + self.copy_test_scripts() + self.copy_bits_config() + self.generate_bits_iso() + + def parse_log(self): + """parse the log generated by running bits tests and + check for failures. + """ + debugconf = os.path.join(self._workdir, self._debugcon_log) + log = "" + with open(debugconf, 'r') as filehandle: + log = filehandle.read() + + if os.getenv('V'): + print('\nlogs from biosbits follows:') + print('==========================================\n\n') + print(log) + print('\n==========================================\n') + + matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*', + log) + for match in matchiter: + # verify that no test cases failed. + self.assertEqual(match.group(3).split()[0], '0', + 'Some bits tests seems to have failed. ' \ + 'Set V=1 in the environment to get the entire ' \ + 'log from bits.') + + def tearDown(self): + if self._vm: + self.assertFalse(not self._vm.is_running) + logging.info('removing the work directory %s', self._workdir) + shutil.rmtree(self._workdir) + + def test_acpi_smbios_bits(self): + """The main test case implementaion.""" + + qemu_bin = QTESTQEMUPROG + iso_file = os.path.join(self._workdir, 'bits-%d.iso' %self._bitsver) + + # QTESTQEMUPROG could be relative to the current directory + if not os.access(QTESTQEMUPROG, os.X_OK): + qemu_bin = os.path.join(QTEST_PWD, QTESTQEMUPROG) + + logging.info('QEMU binary used: %s', qemu_bin) + + self.assertTrue(os.access(qemu_bin, os.X_OK)) + self.assertTrue(os.access(iso_file, os.R_OK)) + + self._vm = QEMUBitsMachine(binary=qemu_bin, + base_temp_dir=self._workdir, + debugcon_log=self._debugcon_log, + debugcon_addr=self._debugcon_addr) + + self._vm.add_args('-cdrom', '%s' %iso_file) + + args = " ".join(str(arg) for arg in self._vm.base_args()) + \ + " " + " ".join(str(arg) for arg in self._vm.args) + + logging.info("launching QEMU vm with the following arguments: %s", + args) + + self._vm.launch() + # biosbits has been configured to run all the specified test suites + # in batch mode and then automatically initiate a vm shutdown. + # sleep for maximum of one minute + max_sleep_time = time.monotonic() + 60 + while self._vm.is_running() and time.monotonic() < max_sleep_time: + time.sleep(1) + + self.assertFalse(time.monotonic() > max_sleep_time, + 'The VM seems to have failed to shutdown in time') + + self.parse_log() + +def execute_unittest(argv: List[str], debug: bool = False, + runner: TAPTestRunner = None) -> None: + """Executes unittests within the calling module.""" + + unittest.main(argv=argv, + testRunner=runner, + verbosity=2 if debug else 1, + warnings=None if sys.warnoptions else 'ignore') + +def main(): + """ The main function where execution begins. """ + + assert QTESTQEMUPROG is not None, \ + "Environment variable QTEST_QEMU_BINARY required." + + runner = TAPTestRunner() + runner.set_stream(True) + runner.set_format("%s/acpi-bits-test" %ARCH) + execute_unittest(sys.argv, False, runner) + +main() diff --git a/tests/qtest/acpi-bits/meson.build b/tests/qtest/acpi-bits/meson.build new file mode 100644 index 0000000000..95c096914f --- /dev/null +++ b/tests/qtest/acpi-bits/meson.build @@ -0,0 +1,39 @@ +xorriso = find_program('xorriso', required: true) +if not xorriso.found() + message('xorriso not found ... disabled bits acpi tests.') + subdir_done() +endif + +# biosbits qtests are currenly only supported on x86_64 platforms. +qtests_x86_64 += ['acpi-bits-test'] +qtests += {'acpi-bits-test' : files('acpi-bits-test.py'),} +slow_qtests += {'acpi-bits-test': 120, } + +subdir('prebuilt') +subdir('bits-tests') +subdir('bits-config') + +test_files = ['acpi-bits-test.py'] +requirements = 'requirements.txt' + +copytestfiles = custom_target('copy test files', + input : test_files, + output : test_files, + command : ['cp', '@INPUT@', '@OUTPUT@'], + install : false, + build_by_default : true) + +requirementsfiles = custom_target('copy py req files', + input : requirements, + output : requirements, + command : ['cp', '@INPUT@', '@OUTPUT@'], + install : false, + build_by_default : true) + +other_deps += [copytestfiles,requirementsfiles] + +qtest_executables += { + 'acpi-bits-test': configure_file(copy:true, + input:'acpi-bits-test-venv.sh', + output:'acpi-bits-test') +} diff --git a/tests/qtest/acpi-bits/requirements.txt b/tests/qtest/acpi-bits/requirements.txt new file mode 100644 index 0000000000..00cdad09ef --- /dev/null +++ b/tests/qtest/acpi-bits/requirements.txt @@ -0,0 +1 @@ +tap.py From patchwork Mon Jun 27 07:28:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896347 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 08E97C433EF for ; Mon, 27 Jun 2022 07:51:58 +0000 (UTC) Received: from localhost ([::1]:33714 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jXI-0006lY-V3 for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:51:56 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56128) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jDE-00061I-An for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:12 -0400 Received: from mail-pf1-x42d.google.com ([2607:f8b0:4864:20::42d]:34502) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jCz-00066F-2b for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:12 -0400 Received: by mail-pf1-x42d.google.com with SMTP id t21so8211279pfq.1 for ; Mon, 27 Jun 2022 00:30:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5EYrTNa6kHbbxzTm4ZvyO8emxTLy6z3Jg/Aga853dec=; b=wNIlDfVNS4SUvO4+UpTt+UgY8N86Z6GEOh46129s2J+y/KQ/bfn1xYH9P3vaHp6uDu 4OlFV/7yPXcvzMslcfqb6FsJSvMhUZx+cHqNshsDW9yICOMFkkGEZlRFs6y3wW7iYAG4 nraG4UWTFrvddVdrkzvUHOt16hX5wvshHG3Z9dOXj8JG/DcEtPPFT1DfeHp3v4vfeL6M 1lEslkRhqvGxnpp6LVWrEsSUc1v+Fh3RmZ8IpkVnoDQ/5jDk5Z/PI9jclVQ3yk3SVP9Q udRTXkejZhBDWewcrHA2XAuFT4ZSxNECr2eR1tAlT3GH8zBgnljvitDHKijZyjoQSTKj FneQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5EYrTNa6kHbbxzTm4ZvyO8emxTLy6z3Jg/Aga853dec=; b=irT9eNmGF+Td35vD1qIHDWaxfDt3jV4sPvYkF5RL/RkaX48Sk26wkhYJDSC+Jd7Erk mLHHuB1D2q1/xzEG1k94KDTDDlzab7VQFpBbtbTZraT2L4R3avyIhhIgXuyfaOBn2zcb QFuLzVPN7oBlajlMxBfYyaUmm0wBoRwUOBrMN2wmByofHRNjWAT8YX2bak96cPeFaq/x 3vUbPAsWq77ATwQpncGKWVPNMsLW4dRNpUYy/Uil0wgHWyMx7s9CAH25Qoc43VPQXi/2 Wz+UoxElRCOcYrAABkboSQMSMVA50d3QyDc5qZMp9vp7rRqxppPle41PZTcsswafxKoO 35fg== X-Gm-Message-State: AJIora8Fcrc/jwuYU+FexHvhkmJqcQAyA7ueyHYuajxbwRguwcgNsteG mf1Kc1Lt8bR1lMWX3RaIGtpSoXnkobdlQ/cuwi8= X-Google-Smtp-Source: AGRyM1uQor/LkWLQ3SFg9tTPZS8x4XBXqK/dabTvh/y4bA869BD2L8671BnjTrkaXKgjE6xP2mtwwg== X-Received: by 2002:a63:5c56:0:b0:3fc:824d:fc57 with SMTP id n22-20020a635c56000000b003fc824dfc57mr11426093pgm.561.1656315055527; Mon, 27 Jun 2022 00:30:55 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:55 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Ani Sinha , Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com Subject: [PATCH 10/12] acpi/tests/bits: add acpi bits qtest directory in meson for running tests Date: Mon, 27 Jun 2022 12:58:54 +0530 Message-Id: <20220627072856.1529357-11-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::42d; envelope-from=ani@anisinha.ca; helo=mail-pf1-x42d.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" added acpi-bits subdirectory in meson.build so that the tests in that subdirectory can be run as a part of make check. Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/acpi-bits-test.py | 4 ++-- tests/qtest/meson.build | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/qtest/acpi-bits/acpi-bits-test.py b/tests/qtest/acpi-bits/acpi-bits-test.py index 673567bf8e..ef4ace8028 100644 --- a/tests/qtest/acpi-bits/acpi-bits-test.py +++ b/tests/qtest/acpi-bits/acpi-bits-test.py @@ -244,9 +244,9 @@ def parse_log(self): if os.getenv('V'): print('\nlogs from biosbits follows:') - print('==========================================\n\n') + print('==========================================\n') print(log) - print('\n==========================================\n') + print('==========================================\n') matchiter = re.finditer(r'(.*Summary: )(\d+ passed), (\d+ failed).*', log) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index ad52f1c81b..2c72c42933 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -312,6 +312,8 @@ endif qtest_executables = {} other_deps = [] +subdir('acpi-bits') + foreach dir : target_dirs if not dir.endswith('-softmmu') continue From patchwork Mon Jun 27 07:28:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896345 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E75CBCCA473 for ; Mon, 27 Jun 2022 07:47:44 +0000 (UTC) Received: from localhost ([::1]:57010 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jTE-0003RR-1Z for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:47:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56092) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jD5-0005fp-IA for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:03 -0400 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]:42840) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jD3-00066f-8U for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:03 -0400 Received: by mail-pl1-x62f.google.com with SMTP id jb13so7393385plb.9 for ; Mon, 27 Jun 2022 00:31:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qy9AWsz8rYWaNTIyJpEsyqxUHWXGXQepnsbPdWDlZLE=; b=G1V1+zuDp/8Tt4m8RxS6ZYv2GU0lJ4Nxiq/untohxAhCzeHSImhkaBXgx7vWj8La5W iyvj7xqSX13NNEX07pTW1VjM7sy4KSOqBNEFpNAiAe+tQZsH35SJ0RKCGTBQqMUZ3dW/ mu+fpwwXXFBroJPFkVkitXV91yCkNGLxNpysIYm8cB8VGRe2j4GiD+uhVszdDWf+Bj/E Hc8KM2iw/L+/uQiHtUkYv/mF96NhZPs61yX0quswtUteUwju8I0w6NZNnb65HAoDa0xE rXakCvYylr+9JZMWf/cyUDbJ+kJgxN+TVXIyQcP3oc4Z2xTFgmp5tng+kN5SdVzKOfIg O+fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qy9AWsz8rYWaNTIyJpEsyqxUHWXGXQepnsbPdWDlZLE=; b=b8n1L+H1jNUcAwkv2nNAiUATAS7RC8/cBZIwFdNSdlcw4+4ki3JDIAxWk70WT3zsEb TWWyTdr0X58yRexWN7zx9YmxEw49L+VEcOs3ek08llTAexH2AmNVzqIlobrp7DPEntO7 6aZ69W7/yPdnQWmHjOWCMKyr1Lw8cJDf3B3FjV4dh/9+A89o/Wx6hspOz7wiTHE8yoE2 Lu9LKPhApJpgCVFvyAt7B8hSBs0jNLul3CrsNorltQL3wLu/mw8hU+WF6S2rAVNnEkwr l6vuCCDsKcf98ZcZgRvIwbpb5V/ZAMjj5TsjVlH7+JYtkBIeLHH+zDOUQqSl9pfi5ltg EQbQ== X-Gm-Message-State: AJIora+ES1FJMcLboxAtuuTRcTEY6uswksBbIgdAURu0sVK1kf98D5wV CtPAokzNsCbMfB4lF6QmXiMuL+3B7uHwA+PU7vs= X-Google-Smtp-Source: AGRyM1uHGfQK7qyvKoVDAtyR0nUxj9A1t4n3QWXB4xGLuPANairn/fLDA985OPPFK3/BaY48fRZaOA== X-Received: by 2002:a17:903:18f:b0:16a:5c43:9a85 with SMTP id z15-20020a170903018f00b0016a5c439a85mr13097035plg.122.1656315059548; Mon, 27 Jun 2022 00:30:59 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.30.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:30:59 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org, Ani Sinha , Thomas Huth , Laurent Vivier , Paolo Bonzini Cc: imammedo@redhat.com, mst@redhat.com Subject: [PATCH 11/12] acpi/tests/bits: add README file for bits qtests Date: Mon, 27 Jun 2022 12:58:55 +0530 Message-Id: <20220627072856.1529357-12-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::62f; envelope-from=ani@anisinha.ca; helo=mail-pl1-x62f.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" The README file is added describing the directory structure and the purpose of every file it contains. It also describes how to add new tests, make changes to existing tests or bits config files or regenerate the bits software. Signed-off-by: Ani Sinha --- tests/qtest/acpi-bits/README | 168 +++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 tests/qtest/acpi-bits/README diff --git a/tests/qtest/acpi-bits/README b/tests/qtest/acpi-bits/README new file mode 100644 index 0000000000..97b15f1665 --- /dev/null +++ b/tests/qtest/acpi-bits/README @@ -0,0 +1,168 @@ +============================================================================= +ACPI/SMBIOS QTESTS USING BIOSBITS +============================================================================= + +Biosbits is a software written by Josh Triplett that can be downloaded by +visiting https://biosbits.org/. The github codebase can be found here: +https://github.com/biosbits/bits/tree/master. It is a software that exercizes +the bios components such as acpi and smbios tables directly through acpica +bios interpreter (a freely available C based library written by Intel, +downloadable from https://acpica.org/ and is included with biosbits) without an +operating system getting involved in between. +There are several advantages to directly testing the bios in a real physical +machine or VM as opposed to indirectly discovering bios issues through the +operating system. For one thing, the OSes tend to hide bios problems from the +end user. The other is that we have more control of what we wanted to test +and how by directly using acpica interpreter on top of the bios on a running +system. More details on the inspiration for developing biosbits and its real +life uses can be found in (a) and (b). +This directory contains QEMU qtests written in python that exercizes the QEMU +bios components using biosbits and reports test failures. + +These tests use python virtual environment. In debian/ubuntu system, the tests +would require python3.8-venv and python3-pip packages to be installed. + +A brief description of the contents of this directory follows: + +├── acpi-bits-test.py +├── acpi-bits-test-venv.sh +├── bits-config +│ ├── bits-cfg.txt +│ └── meson.build +├── bits-tests +│ ├── meson.build +│ ├── smbios.py +│ ├── smilatency.py +│ ├── testacpi.py +│ └── testcpuid.py +├── meson.build +├── prebuilt +│ ├── bits-2095-grub.tar.gz +│ ├── bits-2095.zip +│ └── meson.build +├── README +└── requirements.txt + +acpi-bits: + - acpi-bits-test-venv.sh: This is a shell script that sets up the virtual + environment necessary for the actual python test script to run. Amongst + other things, it makes sure that QEMU python library is available within + that venv so that QEMU machines can be forked. QEMU python library can be + found within python/ directory in QEMU source. + After setting up the virtual environment, it runs the python test script + from within that environment. + If you want to enable verbose mode only for bits test and run make check, + one trick is to add V=1 before the call to execute the python script in + this file. + - acpi-bits-test.py: This is the main python test script that generates a + biosbits iso. It then spawns a QEMU VM with it, collects the logs and reports + test failures. This is the script one would be interested in if they wanted + to add or change some component of the log parsing, add a new commandline to + how QEMU is spawned etc. Test writers typically would not need to modify + this script unless they wanted to enhance or change the log parsing for + their tests. + - requirements.txt: This text file contains the dependent python libraries + needed for the tests to run. If a new dependent library is needed, it would + be added here as a new entry and then acpi-bits-test-venv.sh would install + it when setting up the python virtual environment using pip. + - README: This text file. + +acpi-bits/bits-config: + This location contains biosbits config files that determine how the software + runs the tests. + - bits-config.txt: this is the biosbits config file that determines what tests + or actions are performed by bits. The description of the config options are + provided in the file itself. + +acpi-bits/prebuilt: + This location contains prebuilt biosbits binaries that are used to generate + the bits iso file for testing. + - bits-2095.zip: The contents from this zip archive are the main contents of + the iso file that are used for testing. This binary zip archive also + contains the full source of the bits software including the full text of + the license agreement listed here: + https://github.com/biosbits/bits/blob/master/COPYING + The source tarball can be found in this location in the zip file: + boot/src/bits-2095.tar.gz + The additional changes beyond those that are present in the official + biosbits github repository can be found here: + https://github.com/ani-sinha/bits/tree/bits-qemu-logging + + Basically these changes can be categorized into the following: + (a) changes to make sure biosbits builds with the latest gcc compiler + (gcc 9.4). + (b) upgrade of acpica to the latest version (march 2022). + (c) send bits logs to the debug IO port at addresss 0x403 so that isa + debugcon can be used to collect the logs. + (d) send a gub halt command to shutdown the VM once all the tests have been + executed. + + This zip file is automatically generated by the bits build system. It can + be found in the bits build directory and it is suffixed by the bits build + number. + Normally, there is no need to make any alteration to this zip archive + unless one wanted to change the bits software itself (for example to add + a new config option or change actions of existing options or change the + debug IO port etc). When such changes are made and a new biosbits software + is needed to be generated, please refresh this zip archive as well as the + grub tarball at the same time. Tests will break if changes are made to bits + that are incompatible with existing behavior. So care must be taken to make + sure that the change is compatible with existing bits software as much as + possible. When a new config option is introduced for example, bits must + be upadated here first before introducing the new config option through + a later commit. + - prebuilt/bits-2095-grub.tar.gz: This tarbball contains bits generated grub + scripts and modules to the prebuilt directory. These prebuilt grub + artifacts are required in order to generate a bootable bits iso file that + can run tests. + In order to generate this tar archive, please put the following two + directories that can be found in the bits build directory in a single + tar archive file named as bits--grub.tar.gz where n is the version of + bits that generated the archive: + + grub-inst-x86_64-efi + grub-inst + + This version should be the same as the version number of bits that generated + bits-.zip file. In other words, the two files must be in sync and should + come from the same build of biosbits of the same version. Things may still + work if they come from different versions but mixing version numbers are + not recommended. + There is normally no need to regenerate this archive unless some fixes or + changes have gone into the grub that are part of biosbits. + +acpi-bits/bits-tests: + This directory contains biosbits python based tests that are run from within + the biosbits environment in the spawned VM. New additions of test cases can + be made in the appropriate test file. For example, new acpi tests can go + into testacpi.py and one would call testsuite.add_test() to register the new + test so that it gets executed as a part of the ACPI tests. + It might be occassionally necessary to disable some subtests or add a new + test that belongs to a test suite not already present in this directory. To + do this, please extract the bits source from the zip file mentioned above. + Copy the test suite/script that needs modification (addition of new tests + or disabling them) from boot/python location of the extracted directory + into this directory. + + step (a): copy unmodified test script to this directory. + step (b): update meson.build and add this file to the list. + Commit (a) and (b) together in the same commit. + + step (c): perform modifications to the test. + Commit (c) in a separate commit. + + The test framework will then use your modified test script to run the test. + No further changes would be needed. Please check the logs to make sure that + appropriate changes have taken effect. + +meson.build files makes sure that the bits qtests are appropriately integrated +into the QEMU qtest framework and are run with "make check-qtest". +Currently, the bits test is configured to run only for x86_64 architectures. Bits +has been built only for this architecture. + + +Author: Ani Sinha + +References: +(a) https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/867/original/bits.pdf +(b) https://www.youtube.com/watch?v=36QIepyUuhg From patchwork Mon Jun 27 07:28:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ani Sinha X-Patchwork-Id: 12896346 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 81667C433EF for ; Mon, 27 Jun 2022 07:48:29 +0000 (UTC) Received: from localhost ([::1]:58394 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o5jTw-0004M1-CW for qemu-devel@archiver.kernel.org; Mon, 27 Jun 2022 03:48:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56110) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o5jD7-0005jj-RH for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:05 -0400 Received: from mail-pl1-x62e.google.com ([2607:f8b0:4864:20::62e]:46624) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o5jD6-00066r-6h for qemu-devel@nongnu.org; Mon, 27 Jun 2022 03:31:05 -0400 Received: by mail-pl1-x62e.google.com with SMTP id q18so7376181pld.13 for ; Mon, 27 Jun 2022 00:31:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anisinha-ca.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=20lVU+EpbDxJuAdyQsiOYYC0OZmHffv28Q74qBm9xiE=; b=Yf1PvkZmq0TU2/3xY9QUCMjYKbm02JHmX5cQRbkXGYCHooVhBSvYBLNXtKCzkbKXTQ jZvxgoG5Ml8wsXyF1aCJVv+/UXXzP8NIBW2euNd9Qx09K3HA5d2mE7RK1dsPI5UvyqD9 jz0zrRyLIBDbWnVdbw6Mzcb/HBBQdowEe2keFSUXhS5+jRCbdC0n/eVqx/h7f0PPEDT5 NkyUxfRRhajuFtw9fAFzwLeBhuTJzdFBH4PflHBAB4LOrCpLk3Vwj/mngAzfxNPUoorr DxCohq37Zg9YRsFMeVXpYZG+eE+lvSv+KEWBqVAxQkvb+r/m6A+IdmTqIFyabVKdjCS7 lTRw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=20lVU+EpbDxJuAdyQsiOYYC0OZmHffv28Q74qBm9xiE=; b=fZhM9HMftxTEFIVaQ0wrNYVlFcO0ZYUcWWnfbxoaef56loB7exQl4bh5hHuNikksgC 1Tpii7vmxJW4ugyQrGX3mwYRAVLcFuHsX0HZagt1gtSnafDiFQiVlRhcj62NjDQJqwgO J2OJe1Wg/tw13bpgIF0jgJwFtj0LytTG9IfL5aelLNGWNI/bxbI5swDnjLVrdGQwddyT 6Amol+h9YTJayrkWec0a1xdAqf0rsWFgG/NiGRD7f3kfPvCfN6M631vBXpAD7s4EeA7j kf0+eKWHZX8kW5c2b245G5QmlYfhtiN3NCpKo+sdURKTMp7IbXOBjeWLOcgYcrfSPi2E 5hJQ== X-Gm-Message-State: AJIora9N97mGF9rt99/QpVtq/dq/Am3a4DgwrGoenwcfAjTO+m0Mhm0i nZQj18dCGTTxGJQf4+drSL4lysbEO7YDeJj5FFs= X-Google-Smtp-Source: AGRyM1vYDm36l0GUWNcEtidYle3tHDupoWbhcpn8rRwkYukDf/lCEQ7FB0XyquAicfFJHyEBJW20UQ== X-Received: by 2002:a17:90b:1d04:b0:1ec:f898:d863 with SMTP id on4-20020a17090b1d0400b001ecf898d863mr19558587pjb.79.1656315062636; Mon, 27 Jun 2022 00:31:02 -0700 (PDT) Received: from anisinha-lenovo.ba.nuagenetworks.net ([115.96.136.66]) by smtp.googlemail.com with ESMTPSA id h6-20020a170902680600b00163ffe73300sm6420928plk.137.2022.06.27.00.31.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jun 2022 00:31:02 -0700 (PDT) From: Ani Sinha To: qemu-devel@nongnu.org Cc: imammedo@redhat.com, mst@redhat.com, Ani Sinha Subject: [PATCH 12/12] MAINTAINERS: add myself as the maintainer for acpi biosbits qtests Date: Mon, 27 Jun 2022 12:58:56 +0530 Message-Id: <20220627072856.1529357-13-ani@anisinha.ca> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220627072856.1529357-1-ani@anisinha.ca> References: <20220627072856.1529357-1-ani@anisinha.ca> MIME-Version: 1.0 Received-SPF: none client-ip=2607:f8b0:4864:20::62e; envelope-from=ani@anisinha.ca; helo=mail-pl1-x62e.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" I wrote the biosbits test framework, the qtest for testing QEMU with biosbits and all the related changes. Making myself as the maintainer for biosbits related files and test scripts. Signed-off-by: Ani Sinha --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index aaa649a50d..f5358a1f96 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1860,6 +1860,11 @@ S: Supported F: hw/acpi/viot.c F: hw/acpi/viot.h +ACPI/QTEST/BIOSBITS +M: Ani Sinha +S: Supported +F: tests/qtest/acpi-bits/* + ACPI/HEST/GHES R: Dongjiu Geng L: qemu-arm@nongnu.org