From nobody Mon Feb 9 01:44:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1680771483; cv=none; d=zohomail.com; s=zohoarc; b=J/lYE+sIYCdWiLzy8Nt0RkGnmYS6kYIjsk2Cn1zhyHirn2OCPsHyC8qWuS+A1H7RNLzdjgq9HCx2Hd8pHpn/hTHFcI1esaQlez1WT2TKIdw2kjbGC94CCC/RAY5KJoHPPQZciQst7OUA09xaI1u6fyfUSZFqyIGRH0/bE8vm1Ts= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1680771483; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=zCwp2+aR/lbHNhxRH0KttKXUDDLd1jw7vzWl41sYM4g=; b=XPxPTTLwBnG6j8pHjGS8a3yDw6cO+4IB7jbmIteEW51AL+UZ2n8TBfil6MGRzzPGEStkuqXf08OYpYmuBRFFxtreFGTLuxnicDjwkaBCbH9SFZnUyUZdq9sqn5aHunJ92DX67LwjSxDFDGmKhzHHYwO5PVodtqFXNWHiJkQ9tHY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1680771483554212.42831440102225; Thu, 6 Apr 2023 01:58:03 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-652-hTplEXTVN3yX-ZfE4-i1lw-1; Thu, 06 Apr 2023 04:57:12 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 57593857FB7; Thu, 6 Apr 2023 08:57:09 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4479D2166B26; Thu, 6 Apr 2023 08:57:09 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 2975019465BD; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 015871946587 for ; Thu, 6 Apr 2023 08:57:07 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id E886B492C3E; Thu, 6 Apr 2023 08:57:06 +0000 (UTC) Received: from localhost.localdomain (unknown [10.43.2.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 74AFC492B01 for ; Thu, 6 Apr 2023 08:57:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1680771482; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=zCwp2+aR/lbHNhxRH0KttKXUDDLd1jw7vzWl41sYM4g=; b=Z7kkeOMbI8Ns9vuvGYKhR7bKYlhfsQWuo9NjcNaPA96bBWQpl1Mhx5aqCQOVEEVvw+iId4 vK5QAiEJHIqfsKT8wOVfZsooCnZdEaqQUXSnVWbLxLhMGlvMv2tTl+DtByrUAl+wKynqhk OLxSmAVLlL5YbeVig54zb0YSG3LWcR4= X-MC-Unique: hTplEXTVN3yX-ZfE4-i1lw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Michal Privoznik To: libvir-list@redhat.com Subject: [PATCH v2 1/3] util: Introduce virAcpi module Date: Thu, 6 Apr 2023 10:57:02 +0200 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1680771485267100001 Content-Type: text/plain; charset="utf-8"; x-default="true" The aim of this new module is to contain code that's parsing ACPI tables. For now, only parsing of IORT table is implemented (it's ARM specific table). And since we only need to check whether the table contains SMMU record, the code is very simplified. I've followed the specification published here: https://developer.arm.com/documentation/den0049/latest/ Signed-off-by: Michal Privoznik --- po/POTFILES | 1 + src/libvirt_private.syms | 7 ++ src/util/meson.build | 1 + src/util/viracpi.c | 226 +++++++++++++++++++++++++++++++++++++++ src/util/viracpi.h | 23 ++++ src/util/viracpipriv.h | 58 ++++++++++ 6 files changed, 316 insertions(+) create mode 100644 src/util/viracpi.c create mode 100644 src/util/viracpi.h create mode 100644 src/util/viracpipriv.h diff --git a/po/POTFILES b/po/POTFILES index fa769a8a95..b122f02818 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -244,6 +244,7 @@ src/storage_file/storage_source.c src/storage_file/storage_source_backingstore.c src/test/test_driver.c src/util/iohelper.c +src/util/viracpi.c src/util/viralloc.c src/util/virarptable.c src/util/viraudit.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index e37373c3c9..1247b67a39 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1829,6 +1829,13 @@ vir_g_strdup_printf; vir_g_strdup_vprintf; =20 =20 +# util/viracpi.c +virAcpiHasSMMU; +virAcpiParseIORT; +virIORTNodeTypeTypeFromString; +virIORTNodeTypeTypeToString; + + # util/viralloc.h virAppendElement; virDeleteElementsN; diff --git a/src/util/meson.build b/src/util/meson.build index c81500ea04..2fe6f7699e 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -1,5 +1,6 @@ util_sources =3D [ 'glibcompat.c', + 'viracpi.c', 'viralloc.c', 'virarch.c', 'virarptable.c', diff --git a/src/util/viracpi.c b/src/util/viracpi.c new file mode 100644 index 0000000000..05a2b29f0f --- /dev/null +++ b/src/util/viracpi.c @@ -0,0 +1,226 @@ +/* + * viracpi.c: ACPI table(s) parser + * + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * . + */ + +#include + +#include +#include + +#define LIBVIRT_VIRACPIPRIV_H_ALLOW +#include "internal.h" +#include "viracpi.h" +#include "viracpipriv.h" +#include "viralloc.h" +#include "virerror.h" +#include "virfile.h" +#include "virlog.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +VIR_LOG_INIT("util.acpi"); + +typedef struct virIORTHeader virIORTHeader; +struct virIORTHeader { + uint32_t signature; + uint32_t length; + uint8_t revision; + uint8_t checksum; + char oem_id[6]; + char oem_table_id[8]; + char oem_revision[4]; + char creator_id[4]; + char creator_revision[4]; + /* Technically, the following are not part of header, but + * they immediately follow the header and are in the table + * exactly once. */ + uint32_t nnodes; + uint32_t nodes_offset; + /* Here follows reserved and padding fields. Ain't nobody's + * interested in that. */ +} ATTRIBUTE_PACKED; + +VIR_ENUM_IMPL(virIORTNodeType, + VIR_IORT_NODE_TYPE_LAST, + "ITS Group", + "Named Component", + "Root Complex", + "SMMUv1 or SMMUv2", + "SMMUv3", + "PMCG", + "Memory range"); + + +static int +virAcpiParseIORTNodeHeader(int fd, + const char *filename, + virIORTNodeHeader *nodeHeader) +{ + g_autofree char *nodeHeaderBuf =3D NULL; + const char *typeStr =3D NULL; + int nodeHeaderLen; + + nodeHeaderLen =3D virFileReadHeaderFD(fd, sizeof(*nodeHeader), &nodeHe= aderBuf); + if (nodeHeaderLen < 0) { + virReportSystemError(errno, + _("cannot read node header '%1$s'"), + filename); + return -1; + } + + if (nodeHeaderLen !=3D sizeof(*nodeHeader)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("IORT table node header ended early")); + return -1; + } + + memcpy(nodeHeader, nodeHeaderBuf, nodeHeaderLen); + + typeStr =3D virIORTNodeTypeTypeToString(nodeHeader->type); + + VIR_DEBUG("IORT node header: type =3D %" PRIu8 " (%s) len =3D %" PRIu1= 6, + nodeHeader->type, NULLSTR(typeStr), nodeHeader->len); + + /* Basic sanity check. While there's a type specific data + * that follows the node header, the node length should be at + * least size of header itself. */ + if (nodeHeader->len < sizeof(*nodeHeader)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("IORT table node type %1$s has invalid length: %2= $u"), + NULLSTR(typeStr), (unsigned int)nodeHeader->len); + return -1; + } + + return 0; +} + + +static ssize_t +virAcpiParseIORTNodes(int fd, + const char *filename, + const virIORTHeader *header, + virIORTNodeHeader **nodesRet) +{ + g_autofree virIORTNodeHeader *nodes =3D NULL; + size_t nnodes =3D 0; + off_t pos; + + /* Firstly, reset position to the start of nodes. */ + if ((pos =3D lseek(fd, header->nodes_offset, SEEK_SET)) < 0) { + virReportSystemError(errno, + _("cannot seek in '%1$s'"), + filename); + return -1; + } + + for (; pos < header->length;) { + virIORTNodeHeader node; + + if (virAcpiParseIORTNodeHeader(fd, filename, &node) < 0) + return -1; + + if ((pos =3D lseek(fd, pos + node.len, SEEK_SET)) < 0) { + virReportSystemError(errno, + _("cannot seek in '%1$s'"), + filename); + return -1; + } + + VIR_APPEND_ELEMENT(nodes, nnodes, node); + } + + *nodesRet =3D g_steal_pointer(&nodes); + return nnodes; +} + + +ssize_t +virAcpiParseIORT(virIORTNodeHeader **nodesRet, + const char *filename) +{ + VIR_AUTOCLOSE fd =3D -1; + g_autofree char *headerBuf =3D NULL; + int headerLen; + virIORTHeader header; + + if ((fd =3D open(filename, O_RDONLY)) < 0) { + virReportSystemError(errno, + _("cannot open '%1$s'"), + filename); + return -1; + } + + headerLen =3D virFileReadHeaderFD(fd, sizeof(header), &headerBuf); + if (headerLen < 0) { + virReportSystemError(errno, + _("cannot read header '%1$s'"), + filename); + return -1; + } + + if (headerLen !=3D sizeof(header)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("IORT table header ended early")); + return -1; + } + + memcpy(&header, headerBuf, headerLen); + + VIR_DEBUG("IORT header: len =3D %" PRIu32 " revision =3D %" PRIu8 + " nnodes =3D %" PRIu32 " OEM =3D %s", + header.length, header.revision, + header.nnodes, header.oem_id); + + return virAcpiParseIORTNodes(fd, filename, &header, nodesRet); +} + + +#define IORT_PATH "/sys/firmware/acpi/tables/IORT" + +/** + * virAcpiHasSMMU: + * + * Parse IORT table trying to find SMMU node entry. + * Since IORT is ARM specific ACPI table, it doesn't make much + * sense to call this function on other platforms and expect + * sensible result. + * + * Returns: 0 if no SMMU node was found, + * 1 if a SMMU node was found (i.e. host supports SMMU), + * -1 otherwise (with error reported). + */ +int +virAcpiHasSMMU(void) +{ + g_autofree virIORTNodeHeader *nodes =3D NULL; + ssize_t nnodes =3D -1; + size_t i; + + if ((nnodes =3D virAcpiParseIORT(&nodes, IORT_PATH)) < 0) + return -1; + + for (i =3D 0; i < nnodes; i++) { + if (nodes[i].type =3D=3D VIR_IORT_NODE_TYPE_SMMUV1_OR_SMMUV2 || + nodes[i].type =3D=3D VIR_IORT_NODE_TYPE_SMMUV3) { + return 1; + } + } + + return 0; +} diff --git a/src/util/viracpi.h b/src/util/viracpi.h new file mode 100644 index 0000000000..5a433b893a --- /dev/null +++ b/src/util/viracpi.h @@ -0,0 +1,23 @@ +/* + * viracpi.h: ACPI table(s) parser + * + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see + * . + */ + +#pragma once + +int virAcpiHasSMMU(void); diff --git a/src/util/viracpipriv.h b/src/util/viracpipriv.h new file mode 100644 index 0000000000..362a192ebf --- /dev/null +++ b/src/util/viracpipriv.h @@ -0,0 +1,58 @@ +/* + * viracpipriv.h: Functions for testing virAcpi APIs + * + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#ifndef LIBVIRT_VIRACPIPRIV_H_ALLOW +# error "viracpipriv.h may only be included by viracpi.c or test suites" +#endif /* LIBVIRT_VIRACPIPRIV_H_ALLOW */ + +#pragma once + +#include + +#include "internal.h" +#include "virenum.h" + +typedef enum { + VIR_IORT_NODE_TYPE_ITS_GROUP =3D 0, + VIR_IORT_NODE_TYPE_NAMED_COMPONENT, + VIR_IORT_NODE_TYPE_ROOT_COMPLEX, + VIR_IORT_NODE_TYPE_SMMUV1_OR_SMMUV2, + VIR_IORT_NODE_TYPE_SMMUV3, + VIR_IORT_NODE_TYPE_PMCG, + VIR_IORT_NODE_TYPE_MEMORY_RANGE, + VIR_IORT_NODE_TYPE_LAST, +} virIORTNodeType; + +VIR_ENUM_DECL(virIORTNodeType); + +typedef struct virIORTNodeHeader virIORTNodeHeader; +struct virIORTNodeHeader { + uint8_t type; /* One of virIORTNodeType */ + uint16_t len; + uint8_t revision; + uint32_t identifier; + uint32_t nmappings; + uint32_t reference_id; +} ATTRIBUTE_PACKED; + +ssize_t +virAcpiParseIORT(virIORTNodeHeader **nodesRet, + const char *filename); --=20 2.39.2 From nobody Mon Feb 9 01:44:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1680771437; cv=none; d=zohomail.com; s=zohoarc; b=YPobfV1hvkE016o8mUNi3e76NWrzhibASlpAyaP4qxE+j/Sx0r0rZnIX3RvQRnQfFzMS/Yv6tBkXJTe4D1D/4F/KUGVaAUi4pEyyZLK7a7I5nVG2bdQhf4TmoyiRLdafbV1CVWN0ev3WfEpZ8n0OBq91Of5Ske+QLaY6DokaisQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1680771437; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=S3sPBfQDuBPTfD+HScCZ6uB4dtVJw1JY35VOyiEif2k=; b=MdT0AaUFzSxilXhBSKlNkZA4RpK2DYpEma7hahMzGQy7Q1h/e9hRd/LL1ipJvvE7S7nlrDMeHdX/Slexv1IYuTGrqHGsy5tV1UxwPwyOjMSLVYEdP0TIWZkVk3NmgeA0x9qL5fjsG6DhbaKr9+9CMEsPqNYhxUHdsYBsuWSHYiU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1680771437916651.1786958204839; Thu, 6 Apr 2023 01:57:17 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-660-ZQTyDZ0KPl2wHiSM9E7isw-1; Thu, 06 Apr 2023 04:57:13 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 612BE2932481; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4B25940C83AC; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 11A57194658F; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 1EA9919465BB for ; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 03171492B01; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) Received: from localhost.localdomain (unknown [10.43.2.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9EA52492B00 for ; Thu, 6 Apr 2023 08:57:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1680771436; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=S3sPBfQDuBPTfD+HScCZ6uB4dtVJw1JY35VOyiEif2k=; b=ZVEPpO7kZX7W4g3yhIcIFJmEKG/9UoeBqL+jowWBFd43gV9kXHXqFe9CnDcFT7QqYAmXqu rRkXb5jiABc+oCzxSfoDsAP2s+GzgWMbT81JH94PYoKN9IhOHr6CNz6+ncxdP7gyLq48xb 1dtV9Mxc4UKYYDFHXIE+xbrDGVB6HRU= X-MC-Unique: ZQTyDZ0KPl2wHiSM9E7isw-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Michal Privoznik To: libvir-list@redhat.com Subject: [PATCH v2 2/3] tests: Introduce viracpitest Date: Thu, 6 Apr 2023 10:57:03 +0200 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1680771438911100003 Content-Type: text/plain; charset="utf-8"; x-default="true" Introduce a test that checks newly introduced virAcpi module. There are three IORT tables from a real HW (IORT_ampere, IORT_gigabyte and IORT_qualcomm), then there's one from a VM (IORT_virt_aarch64) and one that I handcrafted to be empty (IORT_empty). Signed-off-by: Michal Privoznik Reviewed-by: Andrea Bolognani --- build-aux/syntax-check.mk | 2 +- tests/meson.build | 1 + tests/viracpidata/IORT_ampere | Bin 0 -> 2304 bytes tests/viracpidata/IORT_empty | Bin 0 -> 65 bytes tests/viracpidata/IORT_gigabyte | Bin 0 -> 10100 bytes tests/viracpidata/IORT_qualcomm | Bin 0 -> 3560 bytes tests/viracpidata/IORT_virt_aarch64 | Bin 0 -> 128 bytes tests/viracpitest.c | 135 ++++++++++++++++++++++++++++ 8 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 tests/viracpidata/IORT_ampere create mode 100644 tests/viracpidata/IORT_empty create mode 100644 tests/viracpidata/IORT_gigabyte create mode 100644 tests/viracpidata/IORT_qualcomm create mode 100644 tests/viracpidata/IORT_virt_aarch64 create mode 100644 tests/viracpitest.c diff --git a/build-aux/syntax-check.mk b/build-aux/syntax-check.mk index 5829dc9011..64c1e2773e 100644 --- a/build-aux/syntax-check.mk +++ b/build-aux/syntax-check.mk @@ -1370,7 +1370,7 @@ exclude_file_name_regexp--sc_prohibit_close =3D \ (\.p[yl]$$|\.spec\.in$$|^docs/|^(src/util/vir(file|event)\.c|src/libvirt= -stream\.c|tests/(vir.+mock\.c|commandhelper\.c|qemusecuritymock\.c)|tools/= nss/libvirt_nss_(leases|macs)\.c)|tools/virt-qemu-qmp-proxy$$) =20 exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF =3D \ - (^tests/(nodedevmdevctl|virhostcpu|virpcitest|virstoragetest)data/|docs/= js/.*\.js|docs/fonts/.*\.woff|\.diff|tests/virconfdata/no-newline\.conf$$) + (^tests/(nodedevmdevctl|viracpi|virhostcpu|virpcitest|virstoragetest)dat= a/|docs/js/.*\.js|docs/fonts/.*\.woff|\.diff|tests/virconfdata/no-newline\.= conf$$) =20 exclude_file_name_regexp--sc_prohibit_fork_wrappers =3D \ (^(src/(util/(vircommand|virdaemon)|lxc/lxc_controller)|tests/testutils)= \.c$$) diff --git a/tests/meson.build b/tests/meson.build index 24d08e4f97..35adbc2d56 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -269,6 +269,7 @@ tests +=3D [ { 'name': 'storagevolxml2xmltest' }, { 'name': 'sysinfotest' }, { 'name': 'utiltest' }, + { 'name': 'viracpitest' }, { 'name': 'viralloctest' }, { 'name': 'virauthconfigtest' }, { 'name': 'virbitmaptest' }, diff --git a/tests/viracpidata/IORT_ampere b/tests/viracpidata/IORT_ampere new file mode 100644 index 0000000000000000000000000000000000000000..02e7fd98499729025346c6ac3ae= 5cf10b0f1074d GIT binary patch literal 2304 zcmbW1y-EW?6opUzV}1)8%LN4mK`kr-7P4TWg&4%rLXlu$Lg$lfAhAGcZwV=3D;3b8Z6<$$zRpB*-Hx%AfcuV1Jg?AL*&3Um09*JpqZe{?O zqhNo2j#YGkfFbw)ib1ii+>)bWKJ0S3tjuMt`ZLaZB1OlRM%>(tBecBB}{d#$GR#QJ1$|W zYctkW#f#$-rnUxTGHSy)RgsHBpSXT>E n$0ba4UB|lGsLR0_qjZI-uA5j_2Z`enrn>H8U0w7XmoVaAS)q0T literal 0 HcmV?d00001 diff --git a/tests/viracpidata/IORT_empty b/tests/viracpidata/IORT_empty new file mode 100644 index 0000000000000000000000000000000000000000..58b696fe935b432020377aabc76= fe2b95376b48f GIT binary patch literal 65 ucmebD4+?Q$U|?Y6a`g=3DeiDdBcbPDqf3SnRbih&p)8U!4`B$SXqaJT?S&j#KA literal 0 HcmV?d00001 diff --git a/tests/viracpidata/IORT_gigabyte b/tests/viracpidata/IORT_gigab= yte new file mode 100644 index 0000000000000000000000000000000000000000..b18b445b5de0911ba7190dfe396= a72fec3fe6cf5 GIT binary patch literal 10100 zcmeI1OHRWu5Qg2REq(9^AS76TA~tNhV95qiBr266RV`x4f;U?ZP>CaO1rESrH~oNhgq5>JSK2mi4?O{V>;(fI91sY?6o^twN}9A8X^z4OscMJd%Ejt6^< zo$Nrz$NF$>*F_2;#-b&+H51}AsNpZVy_<6t=3Deh}%I??@99|OL|*gKAGch71O=3Dh`F3(vuP5gZKakV%Y~+ zD>13!@}VLoSw2~g{cuiHq~RfsV@ z(9PynpX+p8l*6sikW!lF5}Hcb3_`W*WeOMOMwNiSS{Sk4Ei zh>1=3D0y-jlzF_BX_$HZUO_?VOiGD+%l0c?$20f;fCe6|Kc$o$AQtESLYAp2^S*N^jIFPpwaF5v64&vo11iD#Xe(lq> zk4fD?CP{scJdCCOBI}g*4F~e}0qzlBIzdcYgFrXSq~0N27v*r9G^CVfYY7d1;x0Vr E57fpI9{>OV literal 0 HcmV?d00001 diff --git a/tests/viracpidata/IORT_qualcomm b/tests/viracpidata/IORT_qualc= omm new file mode 100644 index 0000000000000000000000000000000000000000..5364a9968fa024f34b5e911513a= 08e8a7f88cf91 GIT binary patch literal 3560 zcmb7_yK7WI6vk)w?gfdc+XO5}jbI^i_hDy|WN$P9V~9y%A;c$GhzN?HK?NJFM9@YX zTmKYG!TbS&7AXbo*Yn+ZoZX!D-Z=3Dxi^Z3p;bLMyV++Eway1jqI7;|ZJw6SjOW_htc zEDGDArL`;Dm*?|&yF%lFK2~PpYhnO$Ma|k4ZC3tC?blad8 z)4JsI;{czZk6z#9bS9q`KM%?s_r`81d;+7u=3Dbm2>_cy;HAH)c~+o0P9y_nV| zpWg@g{E2*C5tCid<@HQHZNUe-rSS3FnZW0bUl8{A zSHEb~7tPV$Qa;ap-tT=3Ds{oFIb2fL;4$=3Dnf<&lkTS?r-+0eBROdh!HyKi}L-ij{2(8 zQC}0fv9_<$8e|24;sU28c=3DX_M*3CwBCO7w$aiFLPc} zdztgH+RL0rYAa?~@eq_}=3D!+#oS-SQ~fN<#%m$R3ygL--Gw7zX!(+%s=3D~I BN)P}5 literal 0 HcmV?d00001 diff --git a/tests/viracpidata/IORT_virt_aarch64 b/tests/viracpidata/IORT_v= irt_aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..7efd0ce8a6b3928efa7e1373f68= 8ab4c5f50543b GIT binary patch literal 128 zcmebD4+?2uU|?Y0?Bwt45v<@85#X!<1dKp25F11@0kHuPgMkDCNC*yK93~3}W)K^M VRiHGGVg_O`aDdYP|3ers^8jQz3IPBB literal 0 HcmV?d00001 diff --git a/tests/viracpitest.c b/tests/viracpitest.c new file mode 100644 index 0000000000..f5dd542ffb --- /dev/null +++ b/tests/viracpitest.c @@ -0,0 +1,135 @@ +/* + * viracpitest.c: Test ACPI table parsing + * + * Copyright (C) 2023 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * . + * + */ + +#include + +#define LIBVIRT_VIRACPIPRIV_H_ALLOW +#include "testutils.h" +#include "viracpi.h" +#include "viracpipriv.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +typedef struct testAarch64SMMUData testAarch64SMMUData; +struct testAarch64SMMUData { + const char *filename; + ssize_t nnodes; + const virIORTNodeType *node_types; +}; + +static void +printBitmap(virBitmap *types) +{ + size_t i; + + for (i =3D 0; i < VIR_IORT_NODE_TYPE_LAST; i++) { + if (virBitmapIsBitSet(types, i)) { + fprintf(stderr, "%s\n", virIORTNodeTypeTypeToString(i)); + } + } +} + +static int +testAarch64SMMU(const void *opaque) +{ + const testAarch64SMMUData *data =3D opaque; + g_autofree char *path =3D NULL; + g_autofree virIORTNodeHeader *nodes =3D NULL; + ssize_t nnodes =3D 0; + + path =3D g_strdup_printf("%s/viracpidata/%s", + abs_srcdir, data->filename); + + nnodes =3D virAcpiParseIORT(&nodes, path); + + if (nnodes !=3D data->nnodes) { + fprintf(stderr, + "virAcpiParseIORT() returned wrong number of nodes: %zd, e= xpected %zd\n", + nnodes, data->nnodes); + return -1; + } + + if (nnodes > 0) { + g_autoptr(virBitmap) typesSeen =3D virBitmapNew(VIR_IORT_NODE_TYPE= _LAST); + g_autoptr(virBitmap) typesExp =3D virBitmapNew(VIR_IORT_NODE_TYPE_= LAST); + size_t i =3D 0; + + for (i =3D 0; data->node_types[i] !=3D VIR_IORT_NODE_TYPE_LAST; i+= +) { + size_t type =3D data->node_types[i]; + + ignore_value(virBitmapSetBit(typesExp, type)); + } + + for (i =3D 0; i < nnodes; i++) { + virIORTNodeHeader *h =3D &nodes[i]; + + ignore_value(virBitmapSetBit(typesSeen, h->type)); + } + + if (!virBitmapEqual(typesSeen, typesExp)) { + fprintf(stderr, "node types mismatch.\n\nExpected:\n"); + printBitmap(typesExp); + fprintf(stderr, "\nActual:\n"); + printBitmap(typesSeen); + return -1; + } + } + + return 0; +} + + +static int +mymain(void) +{ + int ret =3D 0; + +#define DO_TEST(filename, nnodes, ...) \ + do { \ + const virIORTNodeType node_types[] =3D { __VA_ARGS__, VIR_IORT_NOD= E_TYPE_LAST }; \ + const testAarch64SMMUData data =3D {filename, nnodes, node_types }= ; \ + if (virTestRun("aarch64 SMMU " filename, testAarch64SMMU, &data) <= 0) \ + ret =3D -1; \ + } while (0) + + DO_TEST("IORT_empty", 0, VIR_IORT_NODE_TYPE_LAST); + DO_TEST("IORT_virt_aarch64", 2, + VIR_IORT_NODE_TYPE_ITS_GROUP, + VIR_IORT_NODE_TYPE_ROOT_COMPLEX); + DO_TEST("IORT_ampere", 36, + VIR_IORT_NODE_TYPE_ITS_GROUP, + VIR_IORT_NODE_TYPE_ROOT_COMPLEX, + VIR_IORT_NODE_TYPE_SMMUV3); + DO_TEST("IORT_gigabyte", 30, + VIR_IORT_NODE_TYPE_ITS_GROUP, + VIR_IORT_NODE_TYPE_ROOT_COMPLEX, + VIR_IORT_NODE_TYPE_SMMUV1_OR_SMMUV2); + DO_TEST("IORT_qualcomm", 69, + VIR_IORT_NODE_TYPE_ITS_GROUP, + VIR_IORT_NODE_TYPE_NAMED_COMPONENT, + VIR_IORT_NODE_TYPE_ROOT_COMPLEX, + VIR_IORT_NODE_TYPE_SMMUV3, + VIR_IORT_NODE_TYPE_PMCG); + + return ret =3D=3D 0 ? EXIT_SUCCESS : EXIT_FAILURE; +} + +VIR_TEST_MAIN(mymain) --=20 2.39.2 From nobody Mon Feb 9 01:44:05 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1680771435; cv=none; d=zohomail.com; s=zohoarc; b=f/VZ4ivTijvgzQEUo3e1Ayrihe/YtWhTMLb+LbGanv9s9TDsLj2qqeBXv/+Cb3LDduOkk6w6REmC0/Iya8Tlfrzr07Dla7rHH88LaEnQa9cCjOeHD+8yin6F1d2wchEoJceus6TUF53DBDZ+RVXlPmkGT6d2fyz94qmrnW5OzVQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1680771435; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=s5a3NFDoYu8yOlVSklO870QfQEk6JufRaRBf3sKmMRo=; b=VL8cUlnVi9+2Ki1CAL0SBhd/iZSBowHAmavwv82vFXdPV0SUeBiPVz5j1pPG40Af+embKsGgbHHIFWNN0DoXgZoSZx5DfRIutFYR918OLvduIH5KlFsglxGKbhuZM0f5ayG6Mkozg2RQ1vRVa/C208rgLl8Cl6BDfw2Fwu7Y5G0= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1680771435235247.10870662104753; Thu, 6 Apr 2023 01:57:15 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-35-KR4glfNMPB2SqnXOFZK5OQ-1; Thu, 06 Apr 2023 04:57:13 -0400 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 94BAB3823A17; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (unknown [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E3CE483EC0; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 458AB19465BD; Thu, 6 Apr 2023 08:57:10 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id E1832194658F for ; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id C7BF5492B00; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) Received: from localhost.localdomain (unknown [10.43.2.39]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3A3AF492C3E for ; Thu, 6 Apr 2023 08:57:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1680771434; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=s5a3NFDoYu8yOlVSklO870QfQEk6JufRaRBf3sKmMRo=; b=N9pFB+Z9xW/5am2Dx2vNdCyTjteZNrtfvHIGHwJeNfLfBtHSMjr5tSje2x96cmzjVdhVP5 +csu6jWfGUbslvj9IxQJd1NoFMx/TUBfuTVFOf4EPO8IyMNFQis8OBHmjd7eJR+F8UKolM WeUGKDEN1LcPE+akBB99ChoIKII4LCE= X-MC-Unique: KR4glfNMPB2SqnXOFZK5OQ-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Michal Privoznik To: libvir-list@redhat.com Subject: [PATCH v2 3/3] virt-host-validate: Detect SMMU presence on ARMs by parsing IORT table Date: Thu, 6 Apr 2023 10:57:04 +0200 Message-Id: <2db5ac9fba52b7c774dd6a7954159e54b9302575.1680771337.git.mprivozn@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1680771437439100001 Content-Type: text/plain; charset="utf-8"; x-default="true" In my previous commit v9.2.0-rc1~3 I've made virt-host-validate to report host IOMMU check pass if IORT table is present. This is not sufficient though, because IORT describes much more than just IOMMU (well, it's called SMMU in ARM world). In fact, this can be seen in previous commit which adds test cases: there are tables (IORT_virt_aarch64) which does not contain any SMMU records. But after previous commits, we can parse the table so switch to that. Fixes: 2c13a2a7c9c368ea81eccd4ba12d9cf34bdd331b Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=3D2178885 Signed-off-by: Michal Privoznik Reviewed-by: Andrea Bolognani --- tools/virt-host-validate-common.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-c= ommon.c index e96986bb48..c8a23e2e99 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -26,6 +26,7 @@ #include #include =20 +#include "viracpi.h" #include "viralloc.h" #include "vircgroup.h" #include "virfile.h" @@ -389,13 +390,24 @@ int virHostValidateIOMMU(const char *hvname, } virHostMsgPass(); } else if (ARCH_IS_ARM(arch)) { - if (access("/sys/firmware/acpi/tables/IORT", F_OK) =3D=3D 0) { - virHostMsgPass(); - } else { + if (access("/sys/firmware/acpi/tables/IORT", F_OK) !=3D 0) { virHostMsgFail(level, "No ACPI IORT table found, IOMMU not " "supported by this hardware platform"); return VIR_HOST_VALIDATE_FAILURE(level); + } else { + rc =3D virAcpiHasSMMU(); + if (rc < 0) { + virHostMsgFail(level, + "Failed to parse ACPI IORT table"); + return VIR_HOST_VALIDATE_FAILURE(level); + } else if (rc =3D=3D 0) { + virHostMsgFail(level, + "No SMMU found"); + return VIR_HOST_VALIDATE_FAILURE(level); + } else { + virHostMsgPass(); + } } } else { virHostMsgFail(level, --=20 2.39.2