get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2190209/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "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"
    ]
}