Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2190209/?format=api
{ "id": 2190209, "url": "http://patchwork.ozlabs.org/api/patches/2190209/?format=api", "web_url": "http://patchwork.ozlabs.org/project/fwts/patch/20260129035110.60952-1-ivan.hu@canonical.com/", "project": { "id": 24, "url": "http://patchwork.ozlabs.org/api/projects/24/?format=api", "name": "Firmware Test Suite development", "link_name": "fwts", "list_id": "fwts-devel.lists.ubuntu.com", "list_email": "fwts-devel@lists.ubuntu.com", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260129035110.60952-1-ivan.hu@canonical.com>", "list_archive_url": null, "date": "2026-01-29T03:51:10", "name": "[1/1] smccc: New tests for Arm PSCI functions", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "6f4d26c228d44f1837afc8d62f0cab2ba257ff85", "submitter": { "id": 14061, "url": "http://patchwork.ozlabs.org/api/people/14061/?format=api", "name": "Ivan Hu", "email": "ivan.hu@canonical.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/fwts/patch/20260129035110.60952-1-ivan.hu@canonical.com/mbox/", "series": [ { "id": 490163, "url": "http://patchwork.ozlabs.org/api/series/490163/?format=api", "web_url": "http://patchwork.ozlabs.org/project/fwts/list/?series=490163", "date": "2026-01-29T03:51:10", "name": "[1/1] smccc: New tests for Arm PSCI functions", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/490163/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2190209/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2190209/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<fwts-devel-bounces@lists.ubuntu.com>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (4096-bit key;\n unprotected) header.d=canonical.com header.i=@canonical.com\n header.a=rsa-sha256 header.s=20251003 header.b=YXnz08XB;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com\n (client-ip=185.125.189.65; helo=lists.ubuntu.com;\n envelope-from=fwts-devel-bounces@lists.ubuntu.com;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4f1lYp2QCnz1xsw\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 29 Jan 2026 14:51:25 +1100 (AEDT)", "from localhost ([127.0.0.1] helo=lists.ubuntu.com)\n\tby lists.ubuntu.com with esmtp (Exim 4.86_2)\n\t(envelope-from <fwts-devel-bounces@lists.ubuntu.com>)\n\tid 1vlJ3s-0000ee-Ub; Thu, 29 Jan 2026 03:51:16 +0000", "from smtp-relay-internal-0.internal ([10.131.114.225]\n helo=smtp-relay-internal-0.canonical.com)\n by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.86_2) (envelope-from <ivan.hu@canonical.com>)\n id 1vlJ3q-0000eX-VP\n for fwts-devel@lists.ubuntu.com; Thu, 29 Jan 2026 03:51:15 +0000", "from mail-pf1-f198.google.com (mail-pf1-f198.google.com\n [209.85.210.198])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 953033F887\n for <fwts-devel@lists.ubuntu.com>; Thu, 29 Jan 2026 03:51:14 +0000 (UTC)", "by mail-pf1-f198.google.com with SMTP id\n d2e1a72fcca58-81ecb6279d9so783670b3a.3\n for <fwts-devel@lists.ubuntu.com>; Wed, 28 Jan 2026 19:51:14 -0800 (PST)", "from canonical.com (118-163-61-247.hinet-ip.hinet.net.\n [118.163.61.247]) by smtp.gmail.com with ESMTPSA id\n d2e1a72fcca58-82379bfc72asm4723099b3a.42.2026.01.28.19.51.11\n for <fwts-devel@lists.ubuntu.com>\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 28 Jan 2026 19:51:12 -0800 (PST)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com;\n s=20251003; t=1769658674;\n bh=HDzLSvZdxL/A7iSAKI7y6HiCu+4UtCcyvrsNkkf3qkc=;\n h=From:To:Subject:Date:Message-ID:MIME-Version:Content-Type;\n b=YXnz08XBxOdGhwqBFwNAgaFZQTp4/jkxgNeeSh8Kl6FJ7fKbxcGKYHlDH4HiE6alI\n 3EMx3pk+fpjtl+AlI9U2fBGGbG/Ur4rVhGpNWBG8VRAgIYv+/DJygnEfEXjCGMJjB7\n uAQAe5q7lVkPYupIGGIURC+WBuTDZHQIHCj/oxRx2zHrD7mZFMBFb8q+aEFFd9GrVU\n xozHk97SpE/M0S5fufRnClmOBqI7gzJOMQuKEwEZnLcVDN7lXzNhIQMs0PsGQjdGdu\n RA8xkfPIjYVtRRIKdZDImAmOtMRXdMn9pnhc/2AS7mzAtf7C7e8heAopprhBwXp4h/\n I7DCz/wwsd3M1FecimfbL+68QeigOL4E8D/OS5eVa9IpOiA4X2a3PMWr9xcXclMHma\n dpZ5jM1ltQ7n3E6EHdP3IjqqC//4zcIkU9VYqiS8euwLAvWnYb31sQ9cpqF/nJS1zw\n hS8nlywa3y46EbkQ2YlaJW/ubfOPJslhjYAn6ECTrlWCjZtqVtPhibfExjOo4pSGw9\n DQNlpVGpfpAg373N9zYgxfgms4sHx3BlzD6ANEu/AkIxMZ088SwqwUw8cCTtDxALhT\n kDGg983xqoAzq2zmbG3Kxj8RljXUSGG0gYNvPedYxnAOe6ZH8NLE8GnWJquptZ086L\n MZDsmPiqUWBFrLb6IhAQZy7I=", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1769658673; x=1770263473;\n h=content-transfer-encoding:mime-version:message-id:date:subject:to\n :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=HDzLSvZdxL/A7iSAKI7y6HiCu+4UtCcyvrsNkkf3qkc=;\n b=NG5oGI41enpvINsaJICT8at0Tm54+S54oWkaGf+buU+OL6+5jI7YrJkhNtFQ8+Oinb\n inwmywsn9DHIhDUq6jSFlrgmzoomiB0Rh1HGz9nAQrtv7JTOb6U+3D22paNwS1maN7a8\n atfum9gUhYT3bwkYqN8wnx8r0GyjTxWhcq/aPDoM4cBPqdpQE0khdrx8E4HDpQ1H3PfI\n h42hnJgDQnOLliR/RPxAshuIK/+QNjDiz7SDDK1C0Q3dSaJDbDxHWlAL8XIubxFhy8s8\n PrUPzeY4vdYzEGJ4maH4XxlYoWAxA7QIMApY4LBRV7twRbRaYbxwNptDeFlDbaExwGhd\n UbQA==", "X-Gm-Message-State": "AOJu0YyDzUauydULpomKrlPxDu4dWKJ9G+8MmjKNFB0qee2eWGYgUOIE\n upqhKZKNCW5JJjUKopO3DIeWtkfmcLjjsTj2p1mPLUhFGw7PXqY+oRbZQwzOLcOCDpyYTkw4VNX\n mWa3kbELuvrVTtRuqUV6tgjCoI1CTUXFvfLZOwmaUpoKqIEwkMq2QfzdHR7T9oly2gSJOVOnBdx\n zUHsu602pAVY0p", "X-Gm-Gg": "AZuq6aIRZMwlelO8BEizBOydRJFvh5WwdKKraHwBs5t5ziYIn55IzACGbQIvgV2VtrH\n vG/1GAmRtWMSJoHNS5DavTAvb9wLohvZ93z215IvP3NTj8ff49ebBo34yZ9yRsoJpqz7Z2wlV4M\n EClm+1b8NT2f56wJA8iWE7j6fFcddY/6n1BWmoRjTl4/LN5TtXHADJkocMXzmI1afLwmLDV3can\n Ozzwh/I8tCWW0yRQb+cZjX7wk0fVO7XHYFQuC+OAmczGTZhSbu9bAdlVzK146THvuouPpYWdrU1\n 3BYQ+F0Pu7JE4IuAXVP+qpKmzB/FeLDYKXbAMmaRJFBBsSy011162IOLaKwA5MK9j1Gl/8PyltZ\n +Wa3bIR9AJCciBVg4dvfxSKFgaJAOaC5zCAb3K09/h47ojerwfQ==", "X-Received": [ "by 2002:a05:6a00:7609:b0:81f:4566:ccde with SMTP id\n d2e1a72fcca58-82369173d65mr6197530b3a.20.1769658673116;\n Wed, 28 Jan 2026 19:51:13 -0800 (PST)", "by 2002:a05:6a00:7609:b0:81f:4566:ccde with SMTP id\n d2e1a72fcca58-82369173d65mr6197512b3a.20.1769658672506;\n Wed, 28 Jan 2026 19:51:12 -0800 (PST)" ], "From": "Ivan Hu <ivan.hu@canonical.com>", "To": "fwts-devel@lists.ubuntu.com", "Subject": "[PATCH 1/1] smccc: New tests for Arm PSCI functions", "Date": "Thu, 29 Jan 2026 11:51:10 +0800", "Message-ID": "<20260129035110.60952-1-ivan.hu@canonical.com>", "X-Mailer": "git-send-email 2.43.0", "MIME-Version": "1.0", "X-BeenThere": "fwts-devel@lists.ubuntu.com", "X-Mailman-Version": "2.1.20", "Precedence": "list", "List-Id": "Firmware Test Suite Development <fwts-devel.lists.ubuntu.com>", "List-Unsubscribe": "<https://lists.ubuntu.com/mailman/options/fwts-devel>,\n <mailto:fwts-devel-request@lists.ubuntu.com?subject=unsubscribe>", "List-Archive": "<https://lists.ubuntu.com/archives/fwts-devel>", "List-Post": "<mailto:fwts-devel@lists.ubuntu.com>", "List-Help": "<mailto:fwts-devel-request@lists.ubuntu.com?subject=help>", "List-Subscribe": "<https://lists.ubuntu.com/mailman/listinfo/fwts-devel>,\n <mailto:fwts-devel-request@lists.ubuntu.com?subject=subscribe>", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "fwts-devel-bounces@lists.ubuntu.com", "Sender": "\"fwts-devel\" <fwts-devel-bounces@lists.ubuntu.com>" }, "content": "From: edhay <edhaya.chandran@arm.com>\n\nPower State Coordination Interface (PSCI) is a standard to manage power states in systems\nbased on Arm architectures—especially in multi-core or multi-cluster environments. \nPSCI provides a firmware interface that allows operating systems to control\nthe power states of CPUs and other system components in a standardized way.\nActual implementation of these calls reside in secure firmware like Arm Trusted Firmware.\n\nArm defines these interfaces in\nArm Power State Coordination Interface specification\nhttps://developer.arm.com/documentation/den0022/latest/\n\nFollowing new tests are added:\n 1. Check if PSCI is supported as per ACPI FADT table\n 2. Test for PSCI_VERSION\n 3. Test for PSCI_FEATURES: Check for the implementation of all\n the 22 PSCI functions\n 4. Test for AFFINITY_INFO\n 5. psci_features_bbr_check: Checks if all the mandatory PSCI functions\n according to the Arm BBR specification is implemented.\n enabled only with --sbbr or --ebbr flags\n\n This suite has dependency on smccc_test kernel module and the same\n should loaded\n\n usage\n sudo fwts psci\n sudo fwts psci --sbbr\n sudo fwts psci --ebbr\n\nComments from ivan.hu@canonical.com are rewoked.\n---\n smccc_test/smccc_test.c | 63 +++++\n smccc_test/smccc_test.h | 6 +\n src/Makefile.am | 1 +\n src/smccc/psci.c | 550 ++++++++++++++++++++++++++++++++++++++++\n src/smccc/smccc.c | 15 +-\n 5 files changed, 630 insertions(+), 5 deletions(-)\n create mode 100644 src/smccc/psci.c", "diff": "diff --git a/smccc_test/smccc_test.c b/smccc_test/smccc_test.c\nindex 4262dd9c..6d6b5986 100644\n--- a/smccc_test/smccc_test.c\n+++ b/smccc_test/smccc_test.c\n@@ -85,6 +85,18 @@ MODULE_LICENSE(\"GPL\");\n #define SMCCC_ARCH_SOC_ID\t0x80000002\n #endif\n \n+#ifndef PSCI_VERSION\n+#define PSCI_VERSION\t0x84000000\n+#endif\n+\n+#ifndef PSCI_FEATURES\n+#define PSCI_FEATURES\t0x8400000A\n+#endif\n+\n+#ifndef AFFINITY_INFO\n+#define AFFINITY_INFO\t0x84000004\n+#endif\n+\n /*\n * smccc_test_copy_to_user()\n *\tcopy arm_res a* registers to user space test_arg w array\n@@ -199,6 +211,51 @@ static long smccc_test_arch_soc_id(unsigned long arg)\n \treturn smccc_test_copy_to_user(arg, &arm_res, conduit);\n }\n \n+static long smccc_test_psci_version(unsigned long arg)\n+{\n+\tstruct arm_smccc_res arm_res = { };\n+\tstruct smccc_test_arg test_arg;\n+\tint ret, conduit;\n+\n+\tret = smccc_test_copy_from_user(&test_arg, arg);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tconduit = arm_smccc_1_1_invoke(PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &arm_res);\n+\n+\treturn smccc_test_copy_to_user(arg, &arm_res, conduit);\n+}\n+\n+static long smccc_test_psci_features(unsigned long arg)\n+{\n+\tstruct arm_smccc_res arm_res = { };\n+\tstruct smccc_test_arg test_arg;\n+\tint ret, conduit;\n+\n+\tret = smccc_test_copy_from_user(&test_arg, arg);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tconduit = arm_smccc_1_1_invoke(PSCI_FEATURES, test_arg.w[1], 0, 0, 0, 0, 0, 0, &arm_res);\n+\n+\treturn smccc_test_copy_to_user(arg, &arm_res, conduit);\n+}\n+\n+static long smccc_test_affinity_info(unsigned long arg)\n+{\n+\tstruct arm_smccc_res arm_res = { };\n+\tstruct smccc_test_arg test_arg;\n+\tint ret, conduit;\n+\n+\tret = smccc_test_copy_from_user(&test_arg, arg);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tconduit = arm_smccc_1_1_invoke(AFFINITY_INFO, test_arg.w[1], test_arg.w[2], 0, 0, 0, 0, 0, &arm_res);\n+\n+\treturn smccc_test_copy_to_user(arg, &arm_res, conduit);\n+}\n+\n static long smccc_test_ioctl(struct file *file, unsigned int cmd,\n \t\t\t unsigned long arg)\n {\n@@ -229,6 +286,12 @@ static long smccc_test_ioctl(struct file *file, unsigned int cmd,\n \t\treturn smccc_test_arch_features(arg);\n \tcase SMCCC_TEST_ARCH_SOC_ID:\n \t\treturn smccc_test_arch_soc_id(arg);\n+\tcase SMCCC_TEST_PSCI_VERSION:\n+\t\treturn smccc_test_psci_version(arg);\n+\tcase SMCCC_TEST_PSCI_FEATURES:\n+\t\treturn smccc_test_psci_features(arg);\n+\tcase SMCCC_TEST_AFFINITY_INFO:\n+\t\treturn smccc_test_affinity_info(arg);\n \tdefault:\n \t\tbreak;\n \t}\ndiff --git a/smccc_test/smccc_test.h b/smccc_test/smccc_test.h\nindex 6597d87e..25c83a66 100644\n--- a/smccc_test/smccc_test.h\n+++ b/smccc_test/smccc_test.h\n@@ -45,4 +45,10 @@ struct smccc_test_arg {\n _IOWR('p', 0x07, struct smccc_test_arg)\n #define SMCCC_TEST_ARCH_SOC_ID \\\n _IOWR('p', 0x08, struct smccc_test_arg)\n+#define SMCCC_TEST_PSCI_VERSION \\\n+ _IOWR('p', 0x09, struct smccc_test_arg)\n+#define SMCCC_TEST_PSCI_FEATURES \\\n+ _IOWR('p', 0x0A, struct smccc_test_arg)\n+#define SMCCC_TEST_AFFINITY_INFO \\\n+ _IOWR('p', 0x0B, struct smccc_test_arg)\n #endif\ndiff --git a/src/Makefile.am b/src/Makefile.am\nindex aeb98d57..624e3e78 100644\n--- a/src/Makefile.am\n+++ b/src/Makefile.am\n@@ -209,6 +209,7 @@ fwts_SOURCES = main.c \t\t\t\t\\\n \tpci/crs/crs.c \t\t\t\t\\\n \tpci/maxreadreq/maxreadreq.c \t\t\\\n \tsmccc/smccc.c\t\t\t\t\\\n+\tsmccc/psci.c\t\t\t\t\\\n \ttpm/tpmevlog/tpmevlog.c\t\t\t\\\n \ttpm/tpmevlogdump/tpmevlogdump.c\t\t\\\n \tuefi/csm/csm.c \t\t\t\t\\\ndiff --git a/src/smccc/psci.c b/src/smccc/psci.c\nnew file mode 100644\nindex 00000000..32a6128a\n--- /dev/null\n+++ b/src/smccc/psci.c\n@@ -0,0 +1,550 @@\n+/*\n+ *\n+ * Copyright (C) 2025 Canonical\n+ * Copyright (C) 2025 Arm\n+ *\n+ * This program is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU General Public License\n+ * as published by the Free Software Foundation; either version 2\n+ * of the License, or (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, write to the Free Software\n+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n+ *\n+ */\n+#include \"fwts.h\"\n+\n+#ifdef FWTS_ARCH_AARCH64\n+\n+#include <errno.h>\n+#include <inttypes.h>\n+#include <stdio.h>\n+#include <stddef.h>\n+#include <stdbool.h>\n+#include <string.h>\n+#include <sys/ioctl.h>\n+#include <fcntl.h>\n+\n+#include \"smccc_test.h\"\n+\n+/*\n+ * ARM PSCI tests,\n+ * https://developer.arm.com/documentation/den0022/latest/\n+ */\n+\n+extern int smccc_init(fwts_framework *fw);\n+extern char *smccc_pci_conduit_name(struct smccc_test_arg *arg);\n+extern int smccc_deinit(fwts_framework *fw);\n+extern int smccc_pci_conduit_check(fwts_framework *fw, struct smccc_test_arg *arg);\n+extern int smccc_fd;\n+\n+#define\tPSCI_VERSION 0x84000000\n+#define\tCPU_SUSPEND 0x84000001\n+#define\tCPU_OFF 0x84000002\n+#define\tCPU_ON 0x84000003\n+#define\tAFFINITY_INFO 0x84000004\n+#define\tMIGRATE 0x84000005\n+#define\tMIGRATE_INFO_TYPE 0x84000006\n+#define\tMIGRATE_INFO_UP_CPU 0x84000007\n+#define\tSYSTEM_OFF 0x84000008\n+#define\tSYSTEM_RESET 0x84000009\n+#define\tPSCI_FEATURES 0x8400000A\n+#define\tCPU_FREEZE 0x8400000B\n+#define\tCPU_DEFAULT_SUSPEND 0x8400000C\n+#define\tNODE_HW_STATE 0x8400000D\n+#define\tSYSTEM_SUSPEND 0x8400000E\n+#define\tPSCI_SET_SUSPEND_MODE 0x8400000F\n+#define\tPSCI_STAT_RESIDENCY 0x84000010\n+#define\tPSCI_STAT_COUNT 0x84000011\n+#define\tSYSTEM_RESET2 0x84000012\n+#define\tMEM_PROTECT 0x84000013\n+#define\tMEM_PROTECT_CHECK_RANGE 0x84000014\n+#define\tSYSTEM_OFF2 0x84000015\n+\n+#define PSCI_VERSION_0_2 0x00002\n+#define PSCI_VERSION_1_0 0x10000\n+#define PSCI_VERSION_1_1 0x10001\n+#define PSCI_VERSION_1_2 0x10002\n+\n+enum PSCI_ret_code {\n+ PSCI_SUCCESS = 0,\n+ PSCI_NOT_SUPPORTED = -1\n+};\n+\n+typedef struct {\n+\tconst uint32_t\tPSCI_func_id;\n+\tconst char\t*PSCI_func_id_name;\n+\tbool\t\timplemented;\n+} PSCI_func_id_t;\n+\n+static PSCI_func_id_t PSCI_func_id_list[] = {\n+ { PSCI_VERSION, \"PSCI_VERSION\", false },\n+ { CPU_SUSPEND, \"CPU_SUSPEND\", false },\n+ { CPU_OFF, \"CPU_OFF\", false },\n+ { CPU_ON, \"CPU_ON\", false },\n+ { AFFINITY_INFO, \"AFFINITY_INFO\", false },\n+ { MIGRATE, \"MIGRATE\", false },\n+ { MIGRATE_INFO_TYPE, \"MIGRATE_INFO_TYPE\", false },\n+ { MIGRATE_INFO_UP_CPU, \"MIGRATE_INFO_UP_CPU \", false },\n+ { SYSTEM_OFF, \"SYSTEM_OFF\", false },\n+ { SYSTEM_RESET, \"SYSTEM_RESET\", false },\n+ { PSCI_FEATURES, \"PSCI_FEATURES\", false },\n+ { CPU_FREEZE, \"CPU_FREEZE\", false },\n+ { CPU_DEFAULT_SUSPEND, \"CPU_DEFAULT_SUSPEND\", false },\n+ { NODE_HW_STATE, \"NODE_HW_STATE\", false },\n+ { SYSTEM_SUSPEND, \"SYSTEM_SUSPEND\", false },\n+ { PSCI_SET_SUSPEND_MODE, \"PSCI_SET_SUSPEND_MODE\", false },\n+ { PSCI_STAT_RESIDENCY, \"PSCI_STAT_RESIDENCY\", false },\n+ { PSCI_STAT_COUNT, \"PSCI_STAT_COUNT\", false },\n+ { SYSTEM_RESET2, \"SYSTEM_RESET2\", false },\n+ { MEM_PROTECT, \"MEM_PROTECT\", false },\n+ { MEM_PROTECT_CHECK_RANGE, \"MEM_PROTECT_CHECK_RANGE\", false },\n+ { SYSTEM_OFF2, \"SYSTEM_OFF2\", false }\n+};\n+\n+static uint16_t psci_major_version = 0;\n+static uint16_t psci_minor_version = 0;\n+static uint32_t psci_version = 0;\n+\n+/*\n+ * check_for_psci_support()\n+ * This test checks if PSCI is supported in the system by checking the FADT table\n+ */\n+static int check_for_psci_support(fwts_framework *fw)\n+{\n+ static const fwts_acpi_gas null_gas;\n+ fwts_acpi_table_info *table = NULL;\n+ const fwts_acpi_table_fadt *fadt;\n+ int fadt_size;\n+ bool passed = true;\n+\n+ if (fwts_acpi_find_table(fw, \"FACP\", 0, &table) != FWTS_OK) {\n+ fwts_log_error(fw, \"Cannot read ACPI table FACP.\");\n+ return FWTS_ERROR;\n+ }\n+ if (table == NULL) {\n+ fwts_log_error(fw, \"ACPI table FACP does not exist!\");\n+ return FWTS_ERROR;\n+ }\n+\n+ fadt = (const fwts_acpi_table_fadt *)table->data;\n+ fadt_size = table->length;\n+ if (fadt_size == 0) {\n+ fwts_log_error(fw, \"ACPI table FACP has zero length!\");\n+ return FWTS_ERROR;\n+ }\n+\n+ bool PSCI_compliant = fadt->arm_boot_flags & FWTS_FACP_ARM_BOOT_ARCH_PSCI_COMPLIANT;\n+ if (PSCI_compliant) {\n+ fwts_log_info_verbatim(fw, \"Arm PSCI: FADT ARM_BOOT_ARCH PSCI compliant flag is set\");\n+ } else {\n+ fwts_log_error(fw, \"Arm PSCI: FADT ARM_BOOT_ARCH PSCI compliant flag is not set.\"\n+ \" PSCI is not supported\");\n+ return FWTS_ERROR;\n+ }\n+\n+ bool HVC_Conduit = fadt->arm_boot_flags & FWTS_FACP_ARM_BOOT_ARCH_PSCI_USE_HVC;\n+ if (HVC_Conduit) {\n+ fwts_log_info_verbatim(fw, \"Arm PSCI: PSCI uses HVC conduit\");\n+ } else {\n+ fwts_log_info_verbatim(fw, \"Arm PSCI: PSCI uses SMC conduit\");\n+ }\n+\n+ if (memcmp((const void *)&fadt->sleep_control_reg,\n+ (const void *)&null_gas,\n+ sizeof(fwts_acpi_gas))) {\n+ passed = false;\n+ fwts_log_error(fw, \"Arm PSCI: FADT SLEEP_CONTROL_REG is not zeroed (Recommended)\"\n+ \". Non-zero general register structure detected. Must be coded as all zeros\");\n+ }\n+\n+ if (memcmp((const void *)&fadt->sleep_status_reg,\n+ (const void *)&null_gas,\n+ sizeof(fwts_acpi_gas))) {\n+ passed = false;\n+ fwts_log_error(fw, \"Arm PSCI: FADT SLEEP_STATUS_REG is not zeroed (Recommended)\"\n+ \". Non-zero general register structure detected. Must be coded as all zeros\");\n+ }\n+\n+ if (passed == false)\n+ {\n+ fwts_failed(fw, LOG_LEVEL_MEDIUM, \"SleepNonZero\",\n+ \"FADT SLEEP_* registers field are non-zero.\");\n+ return (FWTS_ERROR);\n+ }\n+\n+ fwts_passed(fw, \"Check for Arm PSCI support test passed\");\n+ return FWTS_OK;\n+}\n+\n+\n+/*\n+ * psci_version_test()\n+ * test PSCI function VERSION\n+ */\n+static int psci_version_test(fwts_framework *fw)\n+{\n+ int ret;\n+ struct smccc_test_arg arg = { };\n+\n+ arg.size = sizeof(arg);\n+ arg.w[0] = PSCI_VERSION;\n+\n+ ret = ioctl(smccc_fd, SMCCC_TEST_PSCI_VERSION, &arg);\n+ if (ret < 0) {\n+ fwts_log_error(fw, \"SMCCC test driver ioctl PSCI_TEST_VERSION \"\n+ \"failed, errno=%d (%s)\\n\", errno, strerror(errno));\n+ return FWTS_ERROR;\n+ }\n+ if (smccc_pci_conduit_check(fw, &arg) != FWTS_OK)\n+ return FWTS_ERROR;\n+\n+ fwts_log_info_verbatim(fw, \" SMCCC conduit type: 0x%\" PRIx32 \" ('%s')\",\n+ arg.conduit, smccc_pci_conduit_name(&arg));\n+\n+ psci_major_version = arg.w[0] >> 16;\n+ psci_minor_version = arg.w[0] & 0x0000ffff;\n+ fwts_log_info_verbatim(fw, \"Arm PSCI: Major version: %\" PRIu16 \" , Minor version: %\" PRIu16 \" \",\n+ psci_major_version, psci_minor_version);\n+\n+ psci_version = (psci_major_version << 16) + psci_minor_version;\n+\n+ fwts_passed(fw, \"Arm PSCI_VERSION test passed\");\n+ return FWTS_OK;\n+}\n+\n+\n+/*\n+ * get_implementation_status()\n+ * Query the implementation status by function_id\n+*/\n+static bool get_implementation_status(const uint32_t func_id)\n+{\n+ int k=0;\n+ for (k=0; k < FWTS_ARRAY_SIZE(PSCI_func_id_list); k++) {\n+ if (PSCI_func_id_list[k].PSCI_func_id == func_id)\n+ return (PSCI_func_id_list[k].implemented);\n+ }\n+\n+ return false;\n+}\n+\n+/*\n+ * psci_features_bbr_check()\n+ * Asserts based on the BBR specification rules in\n+ * Section 4.2 which refers to the table 6.9 in the\n+ * PSCI specification https://developer.arm.com/documentation/den0022/latest/\n+ * This function can be run only if SBBR or EBBR flag is set\n+ * while running FWTS\n+ */\n+\n+ static int psci_features_bbr_check(fwts_framework *fw)\n+ {\n+ bool bbr_check_failed = false;\n+ uint16_t assert_failed_count = 0;\n+ int i=0;\n+\n+ fwts_log_info_verbatim(fw, \"Arm BBR PSCI implementation check - the detected PSCI version is %\" PRIu16 \".%\" PRIu16 \"\",\n+ psci_major_version, psci_minor_version);\n+\n+ for (i=0; i < FWTS_ARRAY_SIZE(PSCI_func_id_list); i++) {\n+ if(PSCI_func_id_list[i].implemented == false) {\n+ switch (PSCI_func_id_list[i].PSCI_func_id) {\n+ case PSCI_VERSION:\n+ case CPU_SUSPEND:\n+ case CPU_OFF:\n+ case CPU_ON:\n+ case AFFINITY_INFO:\n+ case SYSTEM_OFF:\n+ case SYSTEM_RESET: {\n+ /* These PSCI functions are mandatory for all versions */\n+ bbr_check_failed = true;\n+ }\n+ break;\n+\n+ case PSCI_FEATURES: {\n+ /* PSCI_FEATURES is mandatory for all PSCI versions >= 1.0 */\n+ if (psci_version >= PSCI_VERSION_1_0)\n+ {\n+ bbr_check_failed = true;\n+ }\n+ }\n+ break;\n+\n+ default: {\n+ fwts_log_info_verbatim(fw, \"Info: \\\"Optional\\\" Function: 0x%8.8\" PRIx32 \" (%s) is not Implemented.\",\n+ PSCI_func_id_list[i].PSCI_func_id,\n+ PSCI_func_id_list[i].PSCI_func_id_name);\n+ }\n+ }\n+ if (bbr_check_failed == true) {\n+ fwts_log_error(fw, \"failed: As per Arm BBR specifciation, \"\n+ \"the implementation of %s is \\\"Mandatory\\\" in PSCI v%d.%d but is not implemented\"\n+ , PSCI_func_id_list[i].PSCI_func_id_name\n+ , psci_major_version, psci_minor_version);\n+ bbr_check_failed = false;\n+\n+ assert_failed_count++;\n+ }\n+ }\n+\n+ /* Additional checks */\n+ /* Some PSCI functions are mandatory conditionally. Such cases are checked below */\n+ if (PSCI_func_id_list[i].implemented == true) {\n+ switch (PSCI_func_id_list[i].PSCI_func_id) {\n+ case MIGRATE: {\n+ /* If MIGRATE is implemented then MIGRATE_INFO_UP_CPU is mandatory */\n+ if (false == get_implementation_status(MIGRATE_INFO_UP_CPU)) {\n+ fwts_log_error(fw, \"failed: MIGRATE is implemented however MIGRATE_INFO_UP_CPU\"\n+ \" is not implemented\");\n+ assert_failed_count++;\n+ }\n+ }\n+ break;\n+\n+ case PSCI_STAT_RESIDENCY: {\n+ /* If PSCI_STAT_RESIDENCY is implemented then PSCI_STAT_COUNT is mandatory */\n+ if (false == get_implementation_status(PSCI_STAT_COUNT)) {\n+ fwts_log_error(fw, \"failed: PSCI_STAT_RESIDENCY is implemented however PSCI_STAT_COUNT\"\n+ \" is not implemented\");\n+ assert_failed_count++;\n+ }\n+ }\n+ break;\n+\n+ case PSCI_STAT_COUNT: {\n+ /* If PSCI_STAT_COUNT is implemented then PSCI_STAT_RESIDENCY is mandatory */\n+ if (false == get_implementation_status(PSCI_STAT_RESIDENCY)) {\n+ fwts_log_error(fw, \"failed: PSCI_STAT_COUNT is implemented however PSCI_STAT_RESIDENCY\"\n+ \" is not implemented\");\n+ assert_failed_count++;\n+ }\n+ }\n+ break;\n+\n+ case MEM_PROTECT: {\n+ /* If MEM_PROTECT is implemented then MEM_PROTECT_CHECK_RANGE is mandatory */\n+ if (false == get_implementation_status(MEM_PROTECT_CHECK_RANGE)) {\n+ fwts_log_error(fw, \"failed: MEM_PROTECT is implemented however MEM_PROTECT_CHECK_RANGE\"\n+ \" is not implemented\");\n+ assert_failed_count++;\n+ }\n+ }\n+ break;\n+\n+ case MEM_PROTECT_CHECK_RANGE: {\n+ /* If MEM_PROTECT_CHECK_RANGE is implemented then MEM_PROTECT is mandatory */\n+ if (false == get_implementation_status(MEM_PROTECT)) {\n+ fwts_log_error(fw, \"failed: MEM_PROTECT_CHECK_RANGE is implemented however MEM_PROTECT\"\n+ \" is not implemented\");\n+ assert_failed_count++;\n+ }\n+ }\n+ break;\n+ }\n+\n+ }\n+ }\n+\n+ if (assert_failed_count > 0) {\n+ fwts_log_error(fw, \"Arm SBBR check for Arm PSCI_FEATURES failed. %d checks failed\",\n+ assert_failed_count);\n+ return FWTS_ERROR;\n+ }\n+\n+ fwts_log_info_verbatim(fw, \"Arm SBBR check for Arm PSCI_FEATURES test passed\");\n+ return FWTS_OK;\n+ }\n+\n+\n+/*\n+ * psci_features_test()\n+ * test PSCI function PSCI_FEATURES for each PSCI function\n+ */\n+ static int psci_features_test(fwts_framework *fw)\n+ {\n+ int ret;\n+ int i = 0;\n+ struct smccc_test_arg arg = { };\n+ bool feaatures_test_failed = 0;\n+\n+ if (psci_version == PSCI_VERSION_0_2) {\n+ fwts_skipped(fw, \"PSCI_FEATURES is Not Applicable for PSCI version %\" PRIu16 \".%\" PRIu16 \"\",\n+ psci_major_version, psci_minor_version);\n+ return FWTS_SKIP;\n+ }\n+\n+ fwts_log_info_verbatim(fw, \"========================= PSCI_FEATURES query ===========================\");\n+ fwts_log_info_verbatim(fw, \" # Function Name Function ID Implementation Status\");\n+ for (i = 0; i < FWTS_ARRAY_SIZE(PSCI_func_id_list); i++) {\n+ memset(&arg, 0, sizeof(arg));\n+ arg.size = sizeof(arg);\n+ arg.w[0] = PSCI_FEATURES;\n+\n+ /* arg.w[1] should contain, the function id of the\n+ PSCI function to query about */\n+ arg.w[1] = PSCI_func_id_list[i].PSCI_func_id;\n+\n+ ret = ioctl(smccc_fd, SMCCC_TEST_PSCI_FEATURES, &arg);\n+ if (ret < 0) {\n+ fwts_log_error(fw, \"SMCCC test driver ioctl PSCI_FEATURES \"\n+ \"failed, ret=%d, errno=%d (%s)\\n\", ret, errno, strerror(errno));\n+ return FWTS_ERROR;\n+ }\n+ if (smccc_pci_conduit_check(fw, &arg) != FWTS_OK)\n+ return FWTS_ERROR;\n+\n+ int32_t return_value = arg.w[0];\n+\n+ if (return_value == PSCI_NOT_SUPPORTED) {\n+ fwts_log_info_verbatim(fw, \"%2d %-24s 0x%8.8\" PRIx32\" NOT IMPLEMENTED\",\n+ i+1,\n+ PSCI_func_id_list[i].PSCI_func_id_name,\n+ PSCI_func_id_list[i].PSCI_func_id);\n+ PSCI_func_id_list[i].implemented = false;\n+ } else if (((arg.w[0] >> 31) & 0x1) == 0) { /* if bit 31 is 0, then the function is supported */\n+ fwts_log_info_verbatim(fw, \"%2d %-24s 0x%8.8\" PRIx32\" IMPLEMENTED\",\n+ i+1,\n+ PSCI_func_id_list[i].PSCI_func_id_name,\n+ PSCI_func_id_list[i].PSCI_func_id);\n+ PSCI_func_id_list[i].implemented = true;\n+ } else if (((arg.w[0] >> 31) & 0x1) == 1) { /* if bit 31 is 1, then the implementation is incorrect as per spec */\n+ fwts_log_info_verbatim(fw, \"%2d %-24s 0x%8.8\" PRIx32\" \"\n+ \" Error Invalid return - Please check the implementation\",\n+ i+1,\n+ PSCI_func_id_list[i].PSCI_func_id_name,\n+ PSCI_func_id_list[i].PSCI_func_id);\n+ PSCI_func_id_list[i].implemented = false;\n+ feaatures_test_failed = 1;\n+ }\n+ }\n+ fwts_log_nl(fw); \n+ /* if --sbbr flag or --ebbr is set, additionally call the BBR assertions function */\n+ if (fw->flags & FWTS_FLAG_SBBR || fw->flags & FWTS_FLAG_EBBR) {\n+ if (psci_features_bbr_check(fw) == FWTS_ERROR) {\n+ fwts_failed(fw, LOG_LEVEL_HIGH, \"psci_features_bbr_check check \",\n+ \"for Arm BBR specification rules failed.\\n\");\n+ return (FWTS_ERROR);\n+ }\n+ }\n+\n+ if (feaatures_test_failed == 1) {\n+ fwts_failed(fw, LOG_LEVEL_HIGH, \"Arm Arm PSCI_FEATURES test\", \"failed\");\n+ return FWTS_ERROR;\n+ }\n+\n+ fwts_passed(fw, \"Arm PSCI_FEATURES test passed\");\n+ return FWTS_OK;\n+ }\n+\n+static inline uint64_t read_mpidr_el1(void)\n+{\n+ uint64_t mpidr;\n+ asm volatile(\"mrs %0, mpidr_el1\" : \"=r\" (mpidr));\n+ return mpidr;\n+}\n+\n+static int affinity_info_test(fwts_framework *fw)\n+{\n+ int ret;\n+ struct smccc_test_arg arg = { };\n+\n+ uint64_t mpidr = read_mpidr_el1();\n+ fwts_log_info_verbatim(fw, \"Info: mpidr = 0x%16.16\" PRIx64\"\", mpidr);\n+\n+\n+ uint32_t aff0 = mpidr & 0xFF;\n+ uint32_t aff1 = (mpidr >> 8) & 0xFF;\n+ uint32_t aff2 = (mpidr >> 16) & 0xFF;\n+ /* aff3 is unused */\n+\n+ uint32_t target_affinity = 0;\n+ target_affinity |= aff0;\n+ target_affinity |= (aff1 << 8);\n+ target_affinity |= (aff2 << 16);\n+\n+ fwts_log_info_verbatim(fw, \"Info: target_affinity = 0x%8.8\" PRIx32\"\", target_affinity);\n+\n+ uint32_t lowest_affinity_level = 0; /* All affinity levels are valid */\n+\n+ arg.size = sizeof(arg);\n+ arg.w[0] = AFFINITY_INFO;\n+ arg.w[1] = target_affinity;\n+ arg.w[2] = lowest_affinity_level;\n+\n+ ret = ioctl(smccc_fd, SMCCC_TEST_AFFINITY_INFO, &arg);\n+ if (ret < 0) {\n+ fwts_log_error(fw, \"SMCCC test driver ioctl SMCCC_TEST_AFFINITY_INFO \"\n+ \"failed, errno=%d (%s)\\n\", errno, strerror(errno));\n+ return FWTS_ERROR;\n+ }\n+ if (smccc_pci_conduit_check(fw, &arg) != FWTS_OK)\n+ return FWTS_ERROR;\n+\n+ fwts_log_info_verbatim(fw, \" SMCCC conduit type: 0x%x ('%s')\",\n+ arg.conduit, smccc_pci_conduit_name(&arg));\n+\n+ int32_t result = arg.w[0];\n+ switch(result) {\n+ case 2: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d (ON_PENDING)\", result);\n+ }\n+ break;\n+ case 1: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d (OFF)\", result);\n+ }\n+ break;\n+ case 0: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d (ON)\", result);\n+ }\n+ break;\n+ case -2: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d (INVALID_PARAMETERS)\", result);\n+ }\n+ break;\n+ case -8: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d (DISABLED)\", result);\n+ }\n+ break;\n+ default: {\n+ fwts_log_info_verbatim(fw,\n+ \"Test AFFINITY_INFO returned value = %d , an unexpected value\", result);\n+ fwts_failed(fw, LOG_LEVEL_HIGH, \"Arm PSCI AFFINITY_INFO \",\n+ \"test failed\");\n+ return FWTS_ERROR;\n+ }\n+ }\n+\n+ fwts_passed(fw, \"Arm PSCI AFFINITY_INFO test passed\");\n+ return FWTS_OK;\n+}\n+\n+static fwts_framework_minor_test psci_tests[] = {\n+ { check_for_psci_support, \"Check for Arm PSCI support\" },\n+ { psci_version_test, \"Test PSCI_VERSION\" },\n+ { psci_features_test, \"Test PSCI_FEATURES\" },\n+ { affinity_info_test, \"Test AFFINITY_INFO\" },\n+ { NULL, NULL }\n+};\n+\n+static fwts_framework_ops psciops = {\n+ .description = \"ARM64 PSCI tests.\",\n+ .init = smccc_init,\n+ .deinit = smccc_deinit,\n+ .minor_tests = psci_tests\n+};\n+\n+FWTS_REGISTER(\"psci\", &psciops, FWTS_TEST_ANYTIME, FWTS_FLAG_UNSAFE | FWTS_FLAG_ROOT_PRIV)\n+\n+#endif\ndiff --git a/src/smccc/smccc.c b/src/smccc/smccc.c\nindex dda1c3c3..f0b696e4 100644\n--- a/src/smccc/smccc.c\n+++ b/src/smccc/smccc.c\n@@ -84,7 +84,7 @@ static pci_func_id_t pci_func_ids[] = {\n static const char *module_name = \"smccc_test\";\n static const char *dev_name = \"/dev/smccc_test\";\n static bool module_loaded;\n-static int smccc_fd = -1;\n+int smccc_fd = -1;\n \n typedef struct {\n \tconst uint32_t\tSMCCC_func_id;\n@@ -103,7 +103,12 @@ static SMCCC_func_id_t SMCCC_func_id_list[] = {\n static uint16_t smccc_major_version = 0;\n static uint16_t smccc_minor_version = 0;\n \n-static int smccc_init(fwts_framework *fw)\n+int smccc_init(fwts_framework *fw);\n+int smccc_deinit(fwts_framework *fw);\n+char *smccc_pci_conduit_name(struct smccc_test_arg *arg);\n+int smccc_pci_conduit_check(fwts_framework *fw, struct smccc_test_arg *arg);\n+\n+int smccc_init(fwts_framework *fw)\n {\n \tif (fwts_module_load(fw, module_name) != FWTS_OK) {\n \t\tmodule_loaded = false;\n@@ -121,7 +126,7 @@ static int smccc_init(fwts_framework *fw)\n \treturn FWTS_OK;\n }\n \n-static int smccc_deinit(fwts_framework *fw)\n+int smccc_deinit(fwts_framework *fw)\n {\n \tif (smccc_fd >= 0) {\n \t\tclose(smccc_fd);\n@@ -140,7 +145,7 @@ static int smccc_deinit(fwts_framework *fw)\n * smccc_pci_conduit_name()\n *\tmap the conduit number to human readable string\n */\n-static char *smccc_pci_conduit_name(struct smccc_test_arg *arg)\n+char *smccc_pci_conduit_name(struct smccc_test_arg *arg)\n {\n \tstatic char unknown[32];\n \n@@ -163,7 +168,7 @@ static char *smccc_pci_conduit_name(struct smccc_test_arg *arg)\n * smccc_pci_conduit_check()\n *\tcheck if conduit number is valid\n */\n-static int smccc_pci_conduit_check(fwts_framework *fw, struct smccc_test_arg *arg)\n+int smccc_pci_conduit_check(fwts_framework *fw, struct smccc_test_arg *arg)\n {\n \tswitch (arg->conduit) {\n \tcase FWTS_SMCCC_CONDUIT_HVC:\n", "prefixes": [ "1/1" ] }