From nobody Thu May 16 05:10:16 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1693502387; cv=pass; d=zohomail.com; s=zohoarc; b=OAKu7kegxB/5aV1s5SmlHehHnlXpXFweeXFQwkmAIxIlZgpLXKOJ+0K6MENm8QIzcCF5auUk23BTdcRAeetne5zmokYInFpsaVOQai1RxTEL6QNvaCp9sgzOEE65SltuAsuae0By1MWzAd4AlKxrK0n3bKYQcRE40R1IDvBM8uk= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1693502387; h=Content-Type:Content-Transfer-Encoding:Cc: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=QIitgnyEDhzpN1C1j0AIPzHqTjVDAK8thbAOhHLHLS8=; b=Pt0lYQOV2eEyw5droid2vkRLjFkVW12QKaRF7MrqSQsjlPtWj0vB46kv02KlLDzMd063aQSgpvWvqSecbj310+NRHyI9jqS0fkJ+zjBzup1+ZaqxInN95zl8Te1BGuEpRwzSe+1dURBG3pJk81W//vORBtnV92+YNia3TDHUfSQ= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1693502387747707.1974003813372; Thu, 31 Aug 2023 10:19:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qblK0-0001v7-Q1; Thu, 31 Aug 2023 13:19:08 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJx-0001sj-9x; Thu, 31 Aug 2023 13:19:05 -0400 Received: from mail-bn8nam04on2062e.outbound.protection.outlook.com ([2a01:111:f400:7e8d::62e] helo=NAM04-BN8-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJq-0005tu-Vm; Thu, 31 Aug 2023 13:19:05 -0400 Received: from DS7PR03CA0047.namprd03.prod.outlook.com (2603:10b6:5:3b5::22) by MW4PR12MB7285.namprd12.prod.outlook.com (2603:10b6:303:22e::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.35; Thu, 31 Aug 2023 17:18:52 +0000 Received: from CY4PEPF0000E9D5.namprd05.prod.outlook.com (2603:10b6:5:3b5:cafe::8b) by DS7PR03CA0047.outlook.office365.com (2603:10b6:5:3b5::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.21 via Frontend Transport; Thu, 31 Aug 2023 17:18:51 +0000 Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D5.mail.protection.outlook.com (10.167.241.76) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6745.17 via Frontend Transport; Thu, 31 Aug 2023 17:18:51 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 31 Aug 2023 12:18:51 -0500 Received: from xsjtongh40.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Thu, 31 Aug 2023 12:18:50 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Q5702gFz1lG5pBqZ0g/hN4+Nf+i8T53d3kiwKSh6TB6l/kZk9YPpiCV2c5V+OBHURb13xF/Mk8IK0j8JsS4H5HzQdO/Txy3HJmcTdiHNpuJlMalme3yL5Hco1/ZrAdCWgjsRAIQ3juZg4b3yH1QFYmQg6/fvLHMuftiyR7qq4qr/eX4gvMx3ggvVc6GhnubT2lfsHMJ6IgBIkXOaYSE2EtJsg2JP0ul+QeFR9JlmxDie14ZH90ZtNI+KBtM/CN1dAw2TTvITschM6JVytwbSDvmWdlMdwv1pqzIIkj9tOok7KtL+trtO5AsaBYXeUr5PCJpzA8UdYibhDgwIifVLrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=QIitgnyEDhzpN1C1j0AIPzHqTjVDAK8thbAOhHLHLS8=; b=HE85/BvVTvFIakradywbv/Ljw5Dzt3hTp1tg78RSQFKy0kC0jrqiBJNlNxMzPrj2p/QPu9BBxsGz8Wgly6TukHoFECMAxCHxOMB3k5/5L9N6hHymcZifgk3re7s8PHI1YxndUICqUQ8BJDJ00zSI2nBPc7rNqvUkjdtWgY9iauYCV+wTxF64Z4SEEE4SxxkBfIAhiXdlzanPzCV5IRVVQYt6gzRM57dmUEzmKugM7NZwcaaEIewhlzZbvCVtR9cMFkWp0QkA7llyaeOhAqaDa6soY2mxRUNRH8jw6eQbjZVjMvbpmJPYFsCzzOoCSMQkfGocWtmXGE/Xz3ycDdEIZA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=QIitgnyEDhzpN1C1j0AIPzHqTjVDAK8thbAOhHLHLS8=; b=Du7JWAqwyPb7ot+1uI2mALnc8nSDFfsNsN+NOiNkyCq4grQAixu7t9mqJOjrTu3T34s8XtLCITXh1LsPqWNnm3k2hMF51sq7RJhvMFm1v3Wp8XFQijM03mp/r7S2nL4lM81emztlNvtYUTazjtdtJFW5SpgKBSGDwTUvVf8iZQ8= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C From: Tong Ho To: CC: , , , , Subject: [PATCH 1/3] hw/misc: Introduce AMD/Xilix Versal TRNG device Date: Thu, 31 Aug 2023 10:18:47 -0700 Message-ID: <20230831171849.3297497-2-tong.ho@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230831171849.3297497-1-tong.ho@amd.com> References: <20230831171849.3297497-1-tong.ho@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D5:EE_|MW4PR12MB7285:EE_ X-MS-Office365-Filtering-Correlation-Id: e76726cd-6df0-4321-5f95-08dbaa4658d9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kHPD6F4dxprkH43mK13Wi25gJz61RrrhRGOgtgqVSIOCGxgWJdFceW8GEwii0wzDBUo5d6JFtzyLcLuuJ62J2ddII5it8EuaEPkmRFECE25Rf3OtU9W3+z/B27autZtL3gn8Ze5e7CvO1Zw61hEZ1Ga9zD0t6KcTqilJGFfbRszsTJGf1s3vZ4MD3BRCzCXazF/Pm8ITWq4OfAVn/EVLwUZUF0ArtSzuibEJPoeXP5ovOZ0++nZeZG+tIdqKdhExcYwbTb9uKII4CvvbMCHbMenSyC8DPtG/te4zu2FhL+E6XpEg6mqvkDh3WU8f5WzellKJzui9R95oj9SIR97xGYeXCpxAkBNGj6iRnDL8Rs3emJl0K/fGHLn3kFqXwdJFdBWE3FpOCGwceFHhAe2tJVeGrK2shPin+EFBd6hqa4Rjo270RiXunhV93EmzQH9u/0W7D6kFmzkDmlJeuqQcARENDvfLKfmnuev5BxSDuMdmrdep5ZR1IKUjH9ifYLglwie2bjTQ39tWedrGvg3O6Rg8aNLYYE6eKenpdy9K/hQrlQxXXwCQh47LEjGpDesFvl8e7d7Gy+I4MqHrn/aZcV6b1MqdgPx67HN7tqbrLNZqVdxjdpcv8IN3YOAPKO8uPfKpwqVmhF4OGjm+RqxSzz2FGMRZN1JR+hyxBgsQjNmzbPjoX1NPVL1znafQsrF1kRVDh2sBoP5IRMXelI3ly1CjowSa6qTFmDKvXU33B671L+FqbMVGsxAd6xf7qgjOPzwIJoV7SA0QUUP/38etppJ0wEEEckP5/7LAwDRsfJA= X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB03.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(4636009)(346002)(396003)(376002)(136003)(39860400002)(451199024)(82310400011)(186009)(1800799009)(36840700001)(40470700004)(46966006)(8936002)(66899024)(82740400003)(6666004)(4326008)(47076005)(356005)(40460700003)(40480700001)(36756003)(86362001)(81166007)(2906002)(19273905006)(36860700001)(426003)(54906003)(1076003)(336012)(30864003)(8676002)(26005)(966005)(83380400001)(41300700001)(478600001)(5660300002)(70586007)(44832011)(70206006)(6916009)(2616005)(316002)(36900700001)(563064011); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Aug 2023 17:18:51.7193 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: e76726cd-6df0-4321-5f95-08dbaa4658d9 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D5.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW4PR12MB7285 Received-SPF: softfail client-ip=2a01:111:f400:7e8d::62e; envelope-from=tong.ho@amd.com; helo=NAM04-BN8-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1693502389156100007 Content-Type: text/plain; charset="utf-8" This adds a non-cryptographic grade implementation of the model for the True Random Number Generator (TRNG) component in AMD/Xilinx Versal device family. This model is only intended for non-real world testing of guest software, where cryptographically strong TRNG is not needed. This model supports versions 1 & 2 of the Versal TRNG, with default to be version 2; the 'hw-version' uint32 property can be set to 0x0100 to override the default. Other implemented properties: - 'forced-prng', uint64 When set to non-zero, "true random reseed" is replaced by deterministic reseed based on the given value and other deterministic parameters, even when guest software has configured the TRNG as "true random reseed". This option allows guest software to reproduce data-dependent defects. - 'fips-fault-events', uint32, bit-mask bit 3: Triggers the SP800-90B entropy health test fault irq bit 1: Triggers the FIPS 140-2 continuous test fault irq Signed-off-by: Tong Ho --- hw/misc/Kconfig | 3 + hw/misc/meson.build | 3 + hw/misc/xlnx-versal-trng.c | 725 +++++++++++++++++++++++++++++ include/hw/misc/xlnx-versal-trng.h | 58 +++ 4 files changed, 789 insertions(+) create mode 100644 hw/misc/xlnx-versal-trng.c create mode 100644 include/hw/misc/xlnx-versal-trng.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 6996d265e4..6b6105dcbf 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -186,4 +186,7 @@ config AXP2XX_PMU bool depends on I2C =20 +config XLNX_VERSAL_TRNG + bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index d9a370c1de..2425187c51 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -99,6 +99,9 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-xramc.c', 'xlnx-versal-pmc-iou-slcr.c', )) +system_ss.add(when: 'CONFIG_XLNX_VERSAL_TRNG', if_true: files( + 'xlnx-versal-trng.c', +)) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_s= yscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_s= yscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_EXTI', if_true: files('stm32f4xx_ext= i.c')) diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c new file mode 100644 index 0000000000..8835e78dda --- /dev/null +++ b/hw/misc/xlnx-versal-trng.c @@ -0,0 +1,725 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-versal-trng.h" + +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "qemu/timer.h" +#include "qapi/visitor.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" + +#ifndef XLNX_VERSAL_TRNG_ERR_DEBUG +#define XLNX_VERSAL_TRNG_ERR_DEBUG 0 +#endif + +REG32(INT_CTRL, 0x0) + FIELD(INT_CTRL, CERTF_RST, 5, 1) + FIELD(INT_CTRL, DTF_RST, 4, 1) + FIELD(INT_CTRL, DONE_RST, 3, 1) + FIELD(INT_CTRL, CERTF_EN, 2, 1) + FIELD(INT_CTRL, DTF_EN, 1, 1) + FIELD(INT_CTRL, DONE_EN, 0, 1) +REG32(STATUS, 0x4) + FIELD(STATUS, QCNT, 9, 3) + FIELD(STATUS, EAT, 4, 5) + FIELD(STATUS, CERTF, 3, 1) + FIELD(STATUS, DTF, 1, 1) + FIELD(STATUS, DONE, 0, 1) +REG32(CTRL, 0x8) + FIELD(CTRL, PERSODISABLE, 10, 1) + FIELD(CTRL, SINGLEGENMODE, 9, 1) + FIELD(CTRL, EUMODE, 8, 1) + FIELD(CTRL, PRNGMODE, 7, 1) + FIELD(CTRL, TSTMODE, 6, 1) + FIELD(CTRL, PRNGSTART, 5, 1) + FIELD(CTRL, EATAU, 4, 1) + FIELD(CTRL, PRNGXS, 3, 1) + FIELD(CTRL, TRSSEN, 2, 1) + FIELD(CTRL, QERTUEN, 1, 1) + FIELD(CTRL, PRNGSRST, 0, 1) +REG32(CTRL_2, 0xc) + FIELD(CTRL_2, REPCOUNTTESTCUTOFF, 8, 9) + FIELD(CTRL_2, RESERVED_7_5, 5, 3) + FIELD(CTRL_2, DIT, 0, 5) +REG32(CTRL_3, 0x10) + FIELD(CTRL_3, ADAPTPROPTESTCUTOFF, 8, 10) + FIELD(CTRL_3, DLEN, 0, 8) +REG32(CTRL_4, 0x14) + FIELD(CTRL_4, SINGLEBITRAW, 0, 1) +REG32(EXT_SEED_0, 0x40) +REG32(EXT_SEED_1, 0x44) +REG32(EXT_SEED_2, 0x48) +REG32(EXT_SEED_3, 0x4c) +REG32(EXT_SEED_4, 0x50) +REG32(EXT_SEED_5, 0x54) +REG32(EXT_SEED_6, 0x58) +REG32(EXT_SEED_7, 0x5c) +REG32(EXT_SEED_8, 0x60) +REG32(EXT_SEED_9, 0x64) +REG32(EXT_SEED_10, 0x68) +REG32(EXT_SEED_11, 0x6c) +REG32(PER_STRNG_0, 0x80) +REG32(PER_STRNG_1, 0x84) +REG32(PER_STRNG_2, 0x88) +REG32(PER_STRNG_3, 0x8c) +REG32(PER_STRNG_4, 0x90) +REG32(PER_STRNG_5, 0x94) +REG32(PER_STRNG_6, 0x98) +REG32(PER_STRNG_7, 0x9c) +REG32(PER_STRNG_8, 0xa0) +REG32(PER_STRNG_9, 0xa4) +REG32(PER_STRNG_10, 0xa8) +REG32(PER_STRNG_11, 0xac) +REG32(CORE_OUTPUT, 0xc0) +REG32(RESET, 0xd0) + FIELD(RESET, VAL, 0, 1) +REG32(OSC_EN, 0xd4) + FIELD(OSC_EN, VAL, 0, 1) +REG32(TRNG_ISR, 0xe0) + FIELD(TRNG_ISR, SLVERR, 1, 1) + FIELD(TRNG_ISR, CORE_INT, 0, 1) +REG32(TRNG_IMR, 0xe4) + FIELD(TRNG_IMR, SLVERR, 1, 1) + FIELD(TRNG_IMR, CORE_INT, 0, 1) +REG32(TRNG_IER, 0xe8) + FIELD(TRNG_IER, SLVERR, 1, 1) + FIELD(TRNG_IER, CORE_INT, 0, 1) +REG32(TRNG_IDR, 0xec) + FIELD(TRNG_IDR, SLVERR, 1, 1) + FIELD(TRNG_IDR, CORE_INT, 0, 1) +REG32(SLV_ERR_CTRL, 0xf0) + FIELD(SLV_ERR_CTRL, ENABLE, 0, 1) + +#define R_MAX (R_SLV_ERR_CTRL + 1) + +QEMU_BUILD_BUG_ON(R_MAX * 4 !=3D sizeof_field(XlnxVersalTRng, regs)); + +#define TRNG_GUEST_ERROR(D, FMT, ...) \ + do { \ + g_autofree char *p =3D object_get_canonical_path(OBJECT(D)); \ + qemu_log_mask(LOG_GUEST_ERROR, "%s: " FMT, p, ## __VA_ARGS__); \ + } while (0) + +#define TRNG_WARN(D, FMT, ...) \ + do { \ + g_autofree char *p =3D object_get_canonical_path(OBJECT(D)); \ + warn_report("%s: " FMT, p, ## __VA_ARGS__); \ + } while (0) + +static bool trng_older_than_v2(XlnxVersalTRng *s) +{ + return s->hw_version < 0x0200; +} + +static bool trng_in_reset(XlnxVersalTRng *s) +{ + if (ARRAY_FIELD_EX32(s->regs, RESET, VAL)) { + return true; + } + if (ARRAY_FIELD_EX32(s->regs, CTRL, PRNGSRST)) { + return true; + } + + return false; +} + +static bool trng_test_enabled(XlnxVersalTRng *s) +{ + return ARRAY_FIELD_EX32(s->regs, CTRL, TSTMODE); +} + +static bool trng_trss_enabled(XlnxVersalTRng *s) +{ + if (trng_in_reset(s)) { + return false; + } + if (!ARRAY_FIELD_EX32(s->regs, CTRL, TRSSEN)) { + return false; + } + if (!ARRAY_FIELD_EX32(s->regs, OSC_EN, VAL)) { + return false; + } + + return true; +} + +static uint64_t trng_fnv1a_64(uint64_t h64, const void *buf, size_t len) +{ + size_t i; + + for (i =3D 0; i < len; i++) { + uint64_t octet =3D *(const uint8_t *)(buf + i); + + /* See http://www.isthe.com/chongo/tech/comp/fnv */ + h64 ^=3D octet; + h64 *=3D 0x100000001b3ULL; + } + + return h64; +} + +static void trng_reseed(XlnxVersalTRng *s) +{ + bool ext_seed =3D ARRAY_FIELD_EX32(s->regs, CTRL, PRNGXS); + bool pers_disabled =3D ARRAY_FIELD_EX32(s->regs, CTRL, PERSODISABLE); + + enum { + U384_U8 =3D 384 / 8, + }; + + uint64_t h64 =3D 0; + + /* + * Use 64-bit FNV-1a to create a 64-bit seed from all input sources. + * + * Use little-endian to ensure guest sequence being indepedent of + * host endian. + */ + if (ext_seed) { + h64 =3D trng_fnv1a_64(h64, &s->regs[R_EXT_SEED_0], U384_U8); + } else if (trng_test_enabled(s)) { + uint64_t tr[2]; + + tr[0] =3D cpu_to_le64(s->tst_seed[0]); + tr[1] =3D cpu_to_le64(s->tst_seed[1]); + h64 =3D trng_fnv1a_64(h64, tr, sizeof(tr)); + } else if (s->forced_prng_seed) { + uint64_t pr[2]; + + s->forced_prng_count++; + pr[0] =3D cpu_to_le64(s->forced_prng_count); + pr[1] =3D cpu_to_le64(s->forced_prng_seed); + h64 =3D trng_fnv1a_64(h64, pr, sizeof(pr)); + } else { + uint64_t er[2]; + + er[0] =3D cpu_to_le64(qemu_clock_get_ns(QEMU_CLOCK_HOST)); + er[1] =3D cpu_to_le64(getpid()); + h64 =3D trng_fnv1a_64(h64, er, sizeof(er)); + } + + /* + * Personalized string disabled should be the same as string + * with all zeros. + */ + if (pers_disabled) { + static const uint8_t zero[U384_U8] =3D { 0 }; + h64 =3D trng_fnv1a_64(h64, zero, U384_U8); + } else { + h64 =3D trng_fnv1a_64(h64, &s->regs[R_PER_STRNG_0], U384_U8); + } + + s->rand_rdout =3D 0; + s->rand_count =3D 0; + s->rand_state =3D h64; + s->rand_reseed =3D 1ULL << 48; +} + +static void trng_regen(XlnxVersalTRng *s) +{ + if (s->rand_reseed =3D=3D 0) { + TRNG_GUEST_ERROR(s, "Too many generations without a reseed"); + trng_reseed(s); + } + s->rand_reseed--; + + /* + * In real hardware, each regen creates 256 bits, but QCNT + * reports a max of 4. + */ + ARRAY_FIELD_DP32(s->regs, STATUS, QCNT, 4); + s->rand_count =3D 256 / 32; +} + +static uint32_t trng_rdout(XlnxVersalTRng *s) +{ + uint32_t nr; + + if (s->rand_count =3D=3D 0) { + s->rand_rdout =3D 0; + } + + while (!s->rand_rdout) { + union { + uint64_t u64; + uint32_t u32[2]; + } x; + + /* + * A simple 64-bit linear congruential generator. See: + * https://nuclear.llnl.gov/CNP/rng/rngman/node4.html + * + * Reject states with all 0s or all 1s in each 32-bit half. + */ + s->rand_state =3D 2862933555777941757ULL * s->rand_state + 3037000= 493ULL; + + x.u64 =3D s->rand_state; + if (x.u32[0] && x.u32[0] !=3D UINT32_MAX && + x.u32[1] && x.u32[1] !=3D UINT32_MAX) { + s->rand_rdout =3D x.u64; + break; + } + } + + s->rand_count--; + if (s->rand_count < 4) { + ARRAY_FIELD_DP32(s->regs, STATUS, QCNT, s->rand_count); + } + + nr =3D (uint32_t)s->rand_rdout; + s->rand_rdout >>=3D 32; + + return nr; +} + +static void trng_irq_update(XlnxVersalTRng *s) +{ + bool pending =3D s->regs[R_TRNG_ISR] & ~s->regs[R_TRNG_IMR]; + qemu_set_irq(s->irq, pending); +} + +static void trng_isr_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + trng_irq_update(s); +} + +static uint64_t trng_ier_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + uint32_t val =3D val64; + + s->regs[R_TRNG_IMR] &=3D ~val; + trng_irq_update(s); + return 0; +} + +static uint64_t trng_idr_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + uint32_t val =3D val64; + + s->regs[R_TRNG_IMR] |=3D val; + trng_irq_update(s); + return 0; +} + +static void trng_core_int_update(XlnxVersalTRng *s) +{ + bool pending =3D false; + uint32_t st =3D s->regs[R_STATUS]; + uint32_t en =3D s->regs[R_INT_CTRL]; + + if (FIELD_EX32(st, STATUS, CERTF) && FIELD_EX32(en, INT_CTRL, CERTF_EN= )) { + pending =3D true; + } + + if (FIELD_EX32(st, STATUS, DTF) && FIELD_EX32(en, INT_CTRL, DTF_EN)) { + pending =3D true; + } + + if (FIELD_EX32(st, STATUS, DONE) && FIELD_EX32(en, INT_CTRL, DONE_EN))= { + pending =3D true; + } + + ARRAY_FIELD_DP32(s->regs, TRNG_ISR, CORE_INT, pending); + trng_irq_update(s); +} + +static void trng_int_ctrl_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + uint32_t v32 =3D val64; + uint32_t clr_mask =3D 0; + + if (FIELD_EX32(v32, INT_CTRL, CERTF_RST)) { + clr_mask |=3D R_STATUS_CERTF_MASK; + } + if (FIELD_EX32(v32, INT_CTRL, DTF_RST)) { + clr_mask |=3D R_STATUS_DTF_MASK; + } + if (FIELD_EX32(v32, INT_CTRL, DONE_RST)) { + clr_mask |=3D R_STATUS_DONE_MASK; + } + + s->regs[R_STATUS] &=3D ~clr_mask; + trng_core_int_update(s); +} + +static void trng_done(XlnxVersalTRng *s) +{ + ARRAY_FIELD_DP32(s->regs, STATUS, DONE, true); + trng_core_int_update(s); +} + +static void trng_fault_event_set(XlnxVersalTRng *s, uint32_t events) +{ + bool pending =3D false; + + /* Disabled TRSS cannot generate any fault event */ + if (!trng_trss_enabled(s)) { + return; + } + + if (FIELD_EX32(events, STATUS, CERTF)) { + /* In older version, ERTU must be enabled explicitly to get CERTF = */ + if (trng_older_than_v2(s) && + !ARRAY_FIELD_EX32(s->regs, CTRL, QERTUEN)) { + TRNG_WARN(s, "CERTF injection ignored: ERTU disabled"); + } else { + ARRAY_FIELD_DP32(s->regs, STATUS, CERTF, true); + pending =3D true; + } + } + + if (FIELD_EX32(events, STATUS, DTF)) { + ARRAY_FIELD_DP32(s->regs, STATUS, DTF, true); + pending =3D true; + } + + if (pending) { + trng_core_int_update(s); + } +} + +static void trng_soft_reset(XlnxVersalTRng *s) +{ + s->rand_rdout =3D 0; + s->rand_count =3D 0; + s->regs[R_STATUS] =3D 0; + + ARRAY_FIELD_DP32(s->regs, TRNG_ISR, CORE_INT, 0); +} + +static void trng_ctrl_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + + if (trng_in_reset(s)) { + return; + } + + if (FIELD_EX32(val64, CTRL, PRNGSRST)) { + trng_soft_reset(s); + trng_irq_update(s); + return; + } + + if (!FIELD_EX32(val64, CTRL, PRNGSTART)) { + return; + } + + if (FIELD_EX32(val64, CTRL, PRNGMODE)) { + trng_regen(s); + } else { + trng_reseed(s); + } + + trng_done(s); +} + +static void trng_ctrl4_postw(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + + if (trng_older_than_v2(s)) { + return; + } + + /* Only applies to test mode with TRSS enabled */ + if (!trng_test_enabled(s) || !trng_trss_enabled(s)) { + return; + } + + /* Shift in a single bit. */ + s->tst_seed[1] <<=3D 1; + s->tst_seed[1] |=3D s->tst_seed[0] >> 63; + s->tst_seed[0] <<=3D 1; + s->tst_seed[0] |=3D val64 & 1; + + trng_reseed(s); + trng_regen(s); +} + +static uint64_t trng_core_out_postr(RegisterInfo *reg, uint64_t val) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + bool oneshot =3D ARRAY_FIELD_EX32(s->regs, CTRL, SINGLEGENMODE); + bool start =3D ARRAY_FIELD_EX32(s->regs, CTRL, PRNGSTART); + uint32_t r =3D 0xbad; + + if (trng_in_reset(s)) { + TRNG_GUEST_ERROR(s, "Reading random number while in reset!"); + return r; + } + + if (s->rand_count =3D=3D 0) { + TRNG_GUEST_ERROR(s, "Reading random number when unavailable!"); + return r; + } + + r =3D trng_rdout(s); + + /* Automatic mode regenerates when half the output reg is empty. */ + if (!oneshot && start && s->rand_count <=3D 3) { + trng_regen(s); + } + + return r; +} + +static void trng_reset(DeviceState *dev) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(dev); + unsigned int i; + + s->forced_prng_count =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(s->regs_info); ++i) { + register_reset(&s->regs_info[i]); + } + trng_soft_reset(s); + trng_irq_update(s); +} + +static uint64_t trng_reset_prew(RegisterInfo *reg, uint64_t val64) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg->opaque); + + if (!ARRAY_FIELD_EX32(s->regs, RESET, VAL) && + FIELD_EX32(val64, RESET, VAL)) { + trng_reset(DEVICE(s)); + } + + return val64; +} + +static uint64_t trng_register_read(void *opaque, hwaddr addr, unsigned siz= e) +{ + /* + * Guest provided seed and personalized strings cannot be + * read back, and read attempts return value of A_STATUS. + */ + switch (addr) { + case A_EXT_SEED_0 ... A_PER_STRNG_11: + addr =3D A_STATUS; + break; + } + + return register_read_memory(opaque, addr, size); +} + +static void trng_register_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + RegisterInfoArray *reg_array =3D opaque; + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(reg_array->r[0]->opaque); + + if (trng_older_than_v2(s)) { + switch (addr) { + case A_CTRL: + value =3D FIELD_DP64(value, CTRL, PERSODISABLE, 0); + value =3D FIELD_DP64(value, CTRL, SINGLEGENMODE, 0); + break; + case A_CTRL_2: + case A_CTRL_3: + case A_CTRL_4: + return; + } + } else { + switch (addr) { + case A_CTRL: + value =3D FIELD_DP64(value, CTRL, EATAU, 0); + value =3D FIELD_DP64(value, CTRL, QERTUEN, 0); + break; + } + } + + register_write_memory(opaque, addr, value, size); +} + +static RegisterAccessInfo trng_regs_info[] =3D { + { .name =3D "INT_CTRL", .addr =3D A_INT_CTRL, + .post_write =3D trng_int_ctrl_postw, + },{ .name =3D "STATUS", .addr =3D A_STATUS, + .ro =3D 0xfff, + },{ .name =3D "CTRL", .addr =3D A_CTRL, + .post_write =3D trng_ctrl_postw, + },{ .name =3D "CTRL_2", .addr =3D A_CTRL_2, + .reset =3D 0x210c, + },{ .name =3D "CTRL_3", .addr =3D A_CTRL_3, + .reset =3D 0x26f09, + },{ .name =3D "CTRL_4", .addr =3D A_CTRL_4, + .post_write =3D trng_ctrl4_postw, + },{ .name =3D "EXT_SEED_0", .addr =3D A_EXT_SEED_0, + },{ .name =3D "EXT_SEED_1", .addr =3D A_EXT_SEED_1, + },{ .name =3D "EXT_SEED_2", .addr =3D A_EXT_SEED_2, + },{ .name =3D "EXT_SEED_3", .addr =3D A_EXT_SEED_3, + },{ .name =3D "EXT_SEED_4", .addr =3D A_EXT_SEED_4, + },{ .name =3D "EXT_SEED_5", .addr =3D A_EXT_SEED_5, + },{ .name =3D "EXT_SEED_6", .addr =3D A_EXT_SEED_6, + },{ .name =3D "EXT_SEED_7", .addr =3D A_EXT_SEED_7, + },{ .name =3D "EXT_SEED_8", .addr =3D A_EXT_SEED_8, + },{ .name =3D "EXT_SEED_9", .addr =3D A_EXT_SEED_9, + },{ .name =3D "EXT_SEED_10", .addr =3D A_EXT_SEED_10, + },{ .name =3D "EXT_SEED_11", .addr =3D A_EXT_SEED_11, + },{ .name =3D "PER_STRNG_0", .addr =3D A_PER_STRNG_0, + },{ .name =3D "PER_STRNG_1", .addr =3D A_PER_STRNG_1, + },{ .name =3D "PER_STRNG_2", .addr =3D A_PER_STRNG_2, + },{ .name =3D "PER_STRNG_3", .addr =3D A_PER_STRNG_3, + },{ .name =3D "PER_STRNG_4", .addr =3D A_PER_STRNG_4, + },{ .name =3D "PER_STRNG_5", .addr =3D A_PER_STRNG_5, + },{ .name =3D "PER_STRNG_6", .addr =3D A_PER_STRNG_6, + },{ .name =3D "PER_STRNG_7", .addr =3D A_PER_STRNG_7, + },{ .name =3D "PER_STRNG_8", .addr =3D A_PER_STRNG_8, + },{ .name =3D "PER_STRNG_9", .addr =3D A_PER_STRNG_9, + },{ .name =3D "PER_STRNG_10", .addr =3D A_PER_STRNG_10, + },{ .name =3D "PER_STRNG_11", .addr =3D A_PER_STRNG_11, + },{ .name =3D "CORE_OUTPUT", .addr =3D A_CORE_OUTPUT, + .ro =3D 0xffffffff, + .post_read =3D trng_core_out_postr, + },{ .name =3D "RESET", .addr =3D A_RESET, + .reset =3D 0x1, + .pre_write =3D trng_reset_prew, + },{ .name =3D "OSC_EN", .addr =3D A_OSC_EN, + },{ .name =3D "TRNG_ISR", .addr =3D A_TRNG_ISR, + .w1c =3D 0x3, + .post_write =3D trng_isr_postw, + },{ .name =3D "TRNG_IMR", .addr =3D A_TRNG_IMR, + .reset =3D 0x3, + .ro =3D 0x3, + },{ .name =3D "TRNG_IER", .addr =3D A_TRNG_IER, + .pre_write =3D trng_ier_prew, + },{ .name =3D "TRNG_IDR", .addr =3D A_TRNG_IDR, + .pre_write =3D trng_idr_prew, + },{ .name =3D "SLV_ERR_CTRL", .addr =3D A_SLV_ERR_CTRL, + } +}; + +static const MemoryRegionOps trng_ops =3D { + .read =3D trng_register_read, + .write =3D trng_register_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 4, + }, +}; + +static void trng_init(Object *obj) +{ + XlnxVersalTRng *s =3D XLNX_VERSAL_TRNG(obj); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + RegisterInfoArray *reg_array; + + reg_array =3D + register_init_block32(DEVICE(obj), trng_regs_info, + ARRAY_SIZE(trng_regs_info), + s->regs_info, s->regs, + &trng_ops, + XLNX_VERSAL_TRNG_ERR_DEBUG, + R_MAX * 4); + + sysbus_init_mmio(sbd, ®_array->mem); + sysbus_init_irq(sbd, &s->irq); +} + +static void trng_prop_fault_event_set(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) +{ + uint32_t events =3D 0; + + visit_type_uint32(v, name, &events, errp); + if (*errp) { + return; + } + + trng_fault_event_set(XLNX_VERSAL_TRNG(obj), events); +} + +static const PropertyInfo trng_prop_fault_events =3D { + .name =3D "uint32:bits", + .description =3D "Set to trigger TRNG fault events", + .set =3D trng_prop_fault_event_set, + .realized_set_allowed =3D true, +}; + +static PropertyInfo trng_prop_uint64; /* to extend qdev_prop_uint64 */ + +static Property trng_props[] =3D { + DEFINE_PROP_UINT64("forced-prng", XlnxVersalTRng, forced_prng_seed, 0), + DEFINE_PROP_UINT32("hw-version", XlnxVersalTRng, hw_version, 0x0200), + { .name =3D "fips-fault-events", .info =3D &trng_prop_fault_events, }, + + DEFINE_PROP_END_OF_LIST(), +}; + +static const VMStateDescription vmstate_trng =3D { + .name =3D TYPE_XLNX_VERSAL_TRNG, + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT64(rand_state, XlnxVersalTRng), + VMSTATE_UINT32_ARRAY(regs, XlnxVersalTRng, R_MAX), + VMSTATE_END_OF_LIST(), + } +}; + +static void trng_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D trng_reset; + dc->vmsd =3D &vmstate_trng; + + /* Clone uint64 proper with set allowed after realized */ + trng_prop_uint64 =3D qdev_prop_uint64; + trng_prop_uint64.realized_set_allowed =3D true; + trng_props[0].info =3D &trng_prop_uint64; + + device_class_set_props(dc, trng_props); +} + +static const TypeInfo trng_info =3D { + .name =3D TYPE_XLNX_VERSAL_TRNG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(XlnxVersalTRng), + .class_init =3D trng_class_init, + .instance_init =3D trng_init, +}; + +static void trng_register_types(void) +{ + type_register_static(&trng_info); +} + +type_init(trng_register_types) diff --git a/include/hw/misc/xlnx-versal-trng.h b/include/hw/misc/xlnx-vers= al-trng.h new file mode 100644 index 0000000000..d23730c271 --- /dev/null +++ b/include/hw/misc/xlnx-versal-trng.h @@ -0,0 +1,58 @@ +/* + * Non-crypto strength model of the True Random Number Generator + * in the AMD/Xilinx Versal device family. + * + * Copyright (c) 2017-2020 Xilinx Inc. + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a= copy + * of this software and associated documentation files (the "Software"), t= o deal + * in the Software without restriction, including without limitation the r= ights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or se= ll + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included= in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS= OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OT= HER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING= FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS = IN + * THE SOFTWARE. + */ +#ifndef XLNX_VERSAL_TRNG_H +#define XLNX_VERSAL_TRNG_H + +#include "hw/irq.h" +#include "hw/sysbus.h" +#include "hw/register.h" + +#define TYPE_XLNX_VERSAL_TRNG "xlnx.versal-trng" +OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalTRng, XLNX_VERSAL_TRNG); + +#define RMAX_XLNX_VERSAL_TRNG ((0xf0 / 4) + 1) + +typedef struct XlnxVersalTRng { + SysBusDevice parent_obj; + qemu_irq irq; + + uint32_t hw_version; + + uint32_t rand_count; + uint64_t rand_rdout; + uint64_t rand_state; + uint64_t rand_reseed; + + uint64_t forced_prng_seed; + uint64_t forced_prng_count; + uint64_t tst_seed[2]; + + uint32_t regs[RMAX_XLNX_VERSAL_TRNG]; + RegisterInfo regs_info[RMAX_XLNX_VERSAL_TRNG]; +} XlnxVersalTRng; + +#undef RMAX_XLNX_VERSAL_TRNG +#endif --=20 2.25.1 From nobody Thu May 16 05:10:16 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1693502397; cv=pass; d=zohomail.com; s=zohoarc; b=bWI+mYyJFK+6FYOwRZnYCH6vd4o/98s0wjH0ZYrtcik4wq0NjwvLX9HW1hbSqfvmGBfoFWOSrE8GqJ+OlA9o7u9Wo+vlWdUAwRZnb3B0xwdvHfX7QA5JGJ84afNwhLIoUgUiqlt5Cu3A/BlW+as8D3XW9X2EQng0m59IypiBmx0= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1693502397; h=Content-Type:Content-Transfer-Encoding:Cc: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=O7tuUNi+bgqUFHnJ+Rl3ddXSdLMaoX10zW01xm0s1jQ=; b=iMepm9WyNz9i7t+LVBUTA6T9LEuH151NIfWP+vCsSWxkU6+qrPFpFy3Ue8M5WLaxHNqAky2zPwqeTo3NfItFrv06H86SO1HrhzjgKW4+tbdWaF+vydfeOqZPWu1Uo17XGH7zSqvNbKoAC2qQJksEeSTfTBtNUeoiEbdH542gx1Q= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1693502397984777.23185248919; Thu, 31 Aug 2023 10:19:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qblJv-0001sC-7V; Thu, 31 Aug 2023 13:19:03 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJt-0001rg-Er; Thu, 31 Aug 2023 13:19:01 -0400 Received: from mail-dm6nam10on20618.outbound.protection.outlook.com ([2a01:111:f400:7e88::618] helo=NAM10-DM6-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJq-0005ua-7T; Thu, 31 Aug 2023 13:19:01 -0400 Received: from DS7PR03CA0034.namprd03.prod.outlook.com (2603:10b6:5:3b5::9) by DM6PR12MB4121.namprd12.prod.outlook.com (2603:10b6:5:220::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.20; Thu, 31 Aug 2023 17:18:52 +0000 Received: from CY4PEPF0000E9D5.namprd05.prod.outlook.com (2603:10b6:5:3b5:cafe::9e) by DS7PR03CA0034.outlook.office365.com (2603:10b6:5:3b5::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.21 via Frontend Transport; Thu, 31 Aug 2023 17:18:52 +0000 Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D5.mail.protection.outlook.com (10.167.241.76) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6745.17 via Frontend Transport; Thu, 31 Aug 2023 17:18:52 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 31 Aug 2023 12:18:51 -0500 Received: from xsjtongh40.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Thu, 31 Aug 2023 12:18:51 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iSmPxkW7+MeqKawOG3JLio3jt9lrxKXpE9ia0IPhJUUFJstbVP2e2zpzpkB9N3SkHBx2V+pZmNO4nl9/bOUqRTBPIFS1wmvyx9DWybmGa3xUtc63FgGpoTeAMS8AY6RG93WwhXHQxHy+LqfyKp1Lbipn6lnhGHebHDyb9xYVyWRmb5KSSPg7l1XCctMlGKdcd5m4UiWlQu1lyHDaWxcE5wTaMqmP5MWT27ttbVmLW/neivJQiLkS1uExj/HB1XsgqW597o3E3AnZ6+h7UAVa9Hw0gkchqSYg3+i171pRHeHUTxUW2WEftodm3o973Ga6XiVvLFYkaQ08J4I1b+4XiQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=O7tuUNi+bgqUFHnJ+Rl3ddXSdLMaoX10zW01xm0s1jQ=; b=EasgZmSOZP7ttBmNN4p9HJciY4ctWJT5So4GGeGw9WX3HGF5e6+DNlhLctFQ4xRpBvhY6a6aRyYRev7JZ+88C9PVhNIWWHN0dk9Yoqa9hy+8zLrcXFuj+gCJuDAY3cvNZCaZdv0jR8kCbKqhXRMRILKYqVbtWA0EEyqtr0I47FiFAuVxr+noecnDsZQfdylQ3hV5AvJxIqakzBKTPuSNmDYqSMMg8EHN4bEgYFicq+3fJ/3RLBSZV1t0GKi8Yo/YJaEn1sSEBR65X4ksEAa62XnWiOSxGj9f8nsjl0oXUkXoQrTGisF+LD+FzyNP97ikJf4cwHm368X+2bEW5leKoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=O7tuUNi+bgqUFHnJ+Rl3ddXSdLMaoX10zW01xm0s1jQ=; b=3nnZ3BzG7oKfeBAkydO9/fKbdMUq9uqszL+WBtUhEjvtGBWwuAQSlmbnx3KiOTN/HgGANa2QSwGiiZp9Y2B51p4ALpeG2Go9N8y5KmUuwv9CE4arlfz+LSGCtEQBdRKPXhD0C0KdBhOIUgVGtYisM8IwGZomrQakWO6+1cOP38g= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C From: Tong Ho To: CC: , , , , Subject: [PATCH 2/3] hw/arm: xlnx-versal-virt: Add AMD/Xilinx TRNG device Date: Thu, 31 Aug 2023 10:18:48 -0700 Message-ID: <20230831171849.3297497-3-tong.ho@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230831171849.3297497-1-tong.ho@amd.com> References: <20230831171849.3297497-1-tong.ho@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D5:EE_|DM6PR12MB4121:EE_ X-MS-Office365-Filtering-Correlation-Id: b9878fbc-18ae-462b-477f-08dbaa465942 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: dgs670kd+5b5x6599okR5vSXNkz4Z6LqOhQ+xfRDF57bgLYhr7tKUDaDyDM28Ru3Z6ULMNf1JDjNJlFHc87xBsjR5Bm6NvUJUtPniZVGIEjVqN6sNvqEiyKGbSOwg6f0CkYC7pSef3glDumm2RV2u67CFIoMoKZrxlBs1/c9neBc1mltab8EHgVCq+W/Mzv0SXaWrsU0UD+xA9pQKi1oiGHTkIGoWPFAnOxSqmDplFU3ukEZ5ARU/MT2jg98232ljwe28H7lFNbZCIA5cXQXd0vQ5y8GIUZR/PU+kyT9XEhT38FRO0N3WTcdTfKI1ai1gAklRQKCiwybE4pQ/ZXLPAbL7P7A84KVaVycP2vFpQf/tXzj+cizRlD5imsu2Otulr5rjgfB2jvJClCoAu9WXU0YlmUYIH5JP8N7JognfZ6z0ew3GGyDl4u0Ue4FlZQBWOOn3rlJ5wnMjoVqNJ3MCzh2vOWvb6gKtlRiqpeLevZH7xISUS7rJSYW+O9ZaroQo+hih8l/CKxhmmSfyv+zijX3Fs5/ORtfDuRUNcnag58ZnBh8ndXO5mmMibxNqlEkHjjgx2pT+L5hAGusAcBCR6fTT9yasLlMvS7gLM+049GkGK2wD6x6AcWQqejJzI4NclzAM6KdCt/28TG5Ftf2c4DBHCbBxRaOZDIAQXG00DeJF+KqEVy+EUhHue8dvpRgSlCFbPtxQJtiA6450iurPnDJtcYpPfjxVzwao2xW0WL0IAFvX3U/tsH9jSzx/tvEjHi3s8T/drgFQBnoXLmWNw== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB03.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(4636009)(396003)(136003)(376002)(39860400002)(346002)(1800799009)(82310400011)(451199024)(186009)(36840700001)(40470700004)(46966006)(70206006)(2906002)(36756003)(40460700003)(5660300002)(86362001)(44832011)(356005)(82740400003)(81166007)(40480700001)(4326008)(8676002)(47076005)(36860700001)(336012)(41300700001)(8936002)(83380400001)(426003)(1076003)(2616005)(316002)(26005)(54906003)(6666004)(478600001)(70586007)(6916009)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Aug 2023 17:18:52.4068 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b9878fbc-18ae-462b-477f-08dbaa465942 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D5.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR12MB4121 Received-SPF: softfail client-ip=2a01:111:f400:7e88::618; envelope-from=tong.ho@amd.com; helo=NAM10-DM6-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1693502399301100003 Content-Type: text/plain; charset="utf-8" Connect the support for Versal True Random Number Generator (TRNG) device. Warning: unlike the TRNG component in a real device from the Versal device familiy, the connected TRNG model is not of cryptographic grade and is not intended for use cases when cryptograpically strong TRNG is needed. Signed-off-by: Tong Ho --- hw/arm/Kconfig | 1 + hw/arm/xlnx-versal-virt.c | 20 ++++++++++++++++++++ hw/arm/xlnx-versal.c | 16 ++++++++++++++++ include/hw/arm/xlnx-versal.h | 5 +++++ 4 files changed, 42 insertions(+) diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 7e68348440..0a3ff6748d 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -482,6 +482,7 @@ config XLNX_VERSAL select XLNX_BBRAM select XLNX_EFUSE_VERSAL select XLNX_USB_SUBSYS + select XLNX_VERSAL_TRNG =20 config NPCM7XX bool diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c index 1ee2b8697f..c0704f416e 100644 --- a/hw/arm/xlnx-versal-virt.c +++ b/hw/arm/xlnx-versal-virt.c @@ -391,6 +391,25 @@ static void fdt_add_rtc_node(VersalVirt *s) g_free(name); } =20 +static void fdt_add_trng_node(VersalVirt *s) +{ + const char compat[] =3D TYPE_XLNX_VERSAL_TRNG; + const char interrupt_names[] =3D "trng"; + g_autofree char *name =3D g_strdup_printf("/trng@%x", MM_PMC_TRNG); + + qemu_fdt_add_subnode(s->fdt, name); + + qemu_fdt_setprop_cells(s->fdt, name, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, VERSAL_TRNG_IRQ, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); + qemu_fdt_setprop(s->fdt, name, "interrupt-names", + interrupt_names, sizeof(interrupt_names)); + qemu_fdt_setprop_sized_cells(s->fdt, name, "reg", + 2, MM_PMC_TRNG, + 2, MM_PMC_TRNG_SIZE); + qemu_fdt_setprop(s->fdt, name, "compatible", compat, sizeof(compat)); +} + static void fdt_add_bbram_node(VersalVirt *s) { const char compat[] =3D TYPE_XLNX_BBRAM; @@ -690,6 +709,7 @@ static void versal_virt_init(MachineState *machine) fdt_add_usb_xhci_nodes(s); fdt_add_sd_nodes(s); fdt_add_rtc_node(s); + fdt_add_trng_node(s); fdt_add_bbram_node(s); fdt_add_efuse_ctrl_node(s); fdt_add_efuse_cache_node(s); diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 60bf5fe657..4fd1924cf6 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -372,6 +372,21 @@ static void versal_create_rtc(Versal *s, qemu_irq *pic) qdev_get_gpio_in(DEVICE(&s->pmc.apb_irq_orgate), 0)= ); } =20 +static void versal_create_trng(Versal *s, qemu_irq *pic) +{ + SysBusDevice *sbd; + MemoryRegion *mr; + + object_initialize_child(OBJECT(s), "trng", &s->pmc.trng, + TYPE_XLNX_VERSAL_TRNG); + sbd =3D SYS_BUS_DEVICE(&s->pmc.trng); + sysbus_realize(sbd, &error_fatal); + + mr =3D sysbus_mmio_get_region(sbd, 0); + memory_region_add_subregion(&s->mr_ps, MM_PMC_TRNG, mr); + sysbus_connect_irq(sbd, 0, pic[VERSAL_TRNG_IRQ]); +} + static void versal_create_xrams(Versal *s, qemu_irq *pic) { int nr_xrams =3D ARRAY_SIZE(s->lpd.xram.ctrl); @@ -757,6 +772,7 @@ static void versal_realize(DeviceState *dev, Error **er= rp) versal_create_sds(s, pic); versal_create_pmc_apb_irq_orgate(s, pic); versal_create_rtc(s, pic); + versal_create_trng(s, pic); versal_create_xrams(s, pic); versal_create_bbram(s, pic); versal_create_efuse(s, pic); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 39ee31185c..159ee26aad 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -31,6 +31,7 @@ #include "hw/dma/xlnx_csu_dma.h" #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" +#include "hw/misc/xlnx-versal-trng.h" #include "hw/net/xlnx-versal-canfd.h" =20 #define TYPE_XLNX_VERSAL "xlnx-versal" @@ -113,6 +114,7 @@ struct Versal { } iou; =20 XlnxZynqMPRTC rtc; + XlnxVersalTRng trng; XlnxBBRam bbram; XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; @@ -151,6 +153,7 @@ struct Versal { #define VERSAL_OSPI_IRQ 124 #define VERSAL_SD0_IRQ_0 126 #define VERSAL_EFUSE_IRQ 139 +#define VERSAL_TRNG_IRQ 141 #define VERSAL_RTC_ALARM_IRQ 142 #define VERSAL_RTC_SECONDS_IRQ 143 =20 @@ -244,4 +247,6 @@ struct Versal { #define MM_PMC_CRP_SIZE 0x10000 #define MM_PMC_RTC 0xf12a0000 #define MM_PMC_RTC_SIZE 0x10000 +#define MM_PMC_TRNG 0xf1230000 +#define MM_PMC_TRNG_SIZE 0x10000 #endif --=20 2.25.1 From nobody Thu May 16 05:10:16 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass(p=quarantine dis=none) header.from=amd.com ARC-Seal: i=2; a=rsa-sha256; t=1693502387; cv=pass; d=zohomail.com; s=zohoarc; b=Mv3XzcVn9rPWDPqkrYDnYJ3ls3ymDJDbrfsYdh0lPPxqgaeQ7Y3FwPykSbwHZQ/oKDGpNKffJPdkR7xhmZWO+cisp04dzX9xyKzXu0fCkgUJ8HnZ6kWBTWrNu09A4zHrFCwAKUboTj7X4P1ExIGE+wNmA7SAU4sJW8t8hCc5ZfY= ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1693502387; h=Content-Type:Content-Transfer-Encoding:Cc: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=wqvYOrsneLsaPElTOYC/tsMCioYPAeLauARE1zjCjjE=; b=c5tphWRtRad5S5Zxi+tCmBpy/03aCtmIAibNmGEURisyEIxn2f9v57pikJvoopBUgn9JC1I7moxhAStTDdCKqVtsT4JKaWyhzAhjCOuEVjCnUbdRw6rJLUIgrIZqJ88GflvjcmdXcAdsRwUiSdDXRytpfK8H48L5Rfae+J5gk50= ARC-Authentication-Results: i=2; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; arc=pass (i=1 dmarc=pass fromdomain=amd.com); dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1693502387692161.33412347781007; Thu, 31 Aug 2023 10:19:47 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qblJx-0001sm-GR; Thu, 31 Aug 2023 13:19:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJw-0001sV-4h; Thu, 31 Aug 2023 13:19:04 -0400 Received: from mail-bn8nam12on2060a.outbound.protection.outlook.com ([2a01:111:f400:fe5b::60a] helo=NAM12-BN8-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qblJq-0005uh-GM; Thu, 31 Aug 2023 13:19:03 -0400 Received: from DS7PR03CA0052.namprd03.prod.outlook.com (2603:10b6:5:3b5::27) by BN9PR12MB5276.namprd12.prod.outlook.com (2603:10b6:408:101::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.21; Thu, 31 Aug 2023 17:18:53 +0000 Received: from CY4PEPF0000E9D5.namprd05.prod.outlook.com (2603:10b6:5:3b5:cafe::52) by DS7PR03CA0052.outlook.office365.com (2603:10b6:5:3b5::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.22 via Frontend Transport; Thu, 31 Aug 2023 17:18:53 +0000 Received: from SATLEXMB03.amd.com (165.204.84.17) by CY4PEPF0000E9D5.mail.protection.outlook.com (10.167.241.76) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6745.17 via Frontend Transport; Thu, 31 Aug 2023 17:18:53 +0000 Received: from SATLEXMB04.amd.com (10.181.40.145) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 31 Aug 2023 12:18:52 -0500 Received: from xsjtongh40.xilinx.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Thu, 31 Aug 2023 12:18:52 -0500 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=k04ygMGr5sViVK29IOszG8s3UHLYKNSMuQJlOpIj9YhHW/HvjE/J1XxEdOtzoUsh6mRwS1riRtg7QxvWCFOtieUNhE3Hj3K/viI77WhR1/9XZAXUv8EVysHTRg8m13iE1wdPeliPlnxTSZxHZJmL8cFqW8k9Bf9+IlIvbgPCN25qp4pL3PteuxcUvxpDwRW3gCHdICYsxKQCyn7k+f+Qq0X7l2aD2CnWjCDNheCygc/OIAcplApwjgPJV0wnodbfpg5N0gSF1Zn6LTroqE6+93BGmffmau+eqr5rs0iBadUxsV+iYMcAHoPoz3aM82CAuBVTik5/ocV/T27w847gpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=wqvYOrsneLsaPElTOYC/tsMCioYPAeLauARE1zjCjjE=; b=F753p2PVIEso2B1Kx7xBXNHAwjpoIku1NPXd0BtfPWmAUjGtEt4dR6NYShj7C8NDPp+GFTFSxyIVXAHIleP47dXf2lLsOqEy1ud+hF7+ed4ROLf5Bpi5dY+Tao461Oy8RMo7Lw3CX9FOmEIBZzGNwX6K9ZrXu2qrUUiq/FF4FZ5tJK6DulNA3skTkxhJiloy8RXuLXbkXzOQ838GZPHeWZgBJbKuYbNxgpPZj6s8llxrxg8lVay/x5+X4PyBlH/hRNhnj9UXbr6j9MERFCjA5WNHtoF1kKUW6Pk1szJ3qIUB2PjwqiUeewqJm5RUZdiJAltgngGEEGt8pDRjY4i9EA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=nongnu.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wqvYOrsneLsaPElTOYC/tsMCioYPAeLauARE1zjCjjE=; b=srx0HzgEBO+OnL3SfqaZ6wMV84eAtBTVXEjVjAjOFblInD6wyggbeRsdp3ZVUhOBGy3Ak/4gxamhZ6NEf4X4tszwfkpRs9K6F1c52+hZA+AFXTCg+KR2W4FhYjq/wHbuvb0dqfIZyj2NPh4fAxY+JpwQ7YrVjbNGJwV7L9mDoNY= X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C From: Tong Ho To: CC: , , , , Subject: [PATCH 3/3] tests/qtest: Introduce tests for AMD/Xilinx Versal TRNG device Date: Thu, 31 Aug 2023 10:18:49 -0700 Message-ID: <20230831171849.3297497-4-tong.ho@amd.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230831171849.3297497-1-tong.ho@amd.com> References: <20230831171849.3297497-1-tong.ho@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000E9D5:EE_|BN9PR12MB5276:EE_ X-MS-Office365-Filtering-Correlation-Id: aa3495b0-4d60-4ea1-197c-08dbaa4659d6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sy/wwkL64rYTrzZFZ1W8NFuiw7Ukf/VLFgmvmEftiS6PBbuRu4qJhgMKpwSdK8QQ53+33Df/SWghbgAaVhSVpPVQUEmQXfwFmtCby+XzibfNr9dfGzbXM9QlXZ1Sr5X6yzxfFN/rR3pqqXS8Z4TK7pt8GpgJRU5V7xw2Rd6k8FVR+/RXb+3SorR+zAm08EHbs6QNS+DbNJZMBfYhVGMBxAWHFO0SYTpVwUAmKwtNCGO3lGgYqlMp1Zosjg0FbkPGtmZ6ZpXiXeCYs0dzH5IF4z97Vao/YkFZpV9SjNMSmlEANJoBXqwZwtF9H46CjEbvcmQDAf29zG/wJEvzHAJy2wYwNdeVOhvWhRO1avHMwj56yyju8nMXZ+qDI+CQhieUHDk0hhQ2FAH3i4Lh9LcP3uB8Ogs307y0z0cMtJpuGt0Jt/RirmXxRjwkTlx90O1tdZ+uawL5b4fqLibKMkFv6wT/ZLsz93smCP05TV19XPGEatLF5dwKZqJvNmQRYL3ppkz6ldw9Z8Xucj/fuNAFAg7irrpSdgguekBs2M0S3r5uNSz29mR508+ciWcpkwFLL+ef0sIN40b8fC5983ZDHnLyDpeGEQm9cjnjH7BfXFubFMERBDbxBPwGpGcxGwc9nu+QidJ9vLO96Mx/hUMnEfeCAGv5c5cwrUh89jk4kHM4aOqOf7d+GeNk52yzCtvvlvo/HpbIDVM2bMNc9rdAQdVVVAHer/AoViF8rkYDqQKZ5+Yl6zRI+8Ez07NCytzNCltnw49FbjkeTr3cOSdf4Q== X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB03.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(4636009)(136003)(396003)(376002)(346002)(39860400002)(1800799009)(186009)(82310400011)(451199024)(46966006)(40470700004)(36840700001)(82740400003)(356005)(6666004)(40460700003)(36756003)(81166007)(86362001)(47076005)(40480700001)(36860700001)(2616005)(1076003)(2906002)(336012)(426003)(30864003)(26005)(83380400001)(478600001)(8936002)(70586007)(70206006)(8676002)(4326008)(54906003)(5660300002)(41300700001)(44832011)(6916009)(316002)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Aug 2023 17:18:53.3443 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: aa3495b0-4d60-4ea1-197c-08dbaa4659d6 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000E9D5.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN9PR12MB5276 Received-SPF: softfail client-ip=2a01:111:f400:fe5b::60a; envelope-from=tong.ho@amd.com; helo=NAM12-BN8-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @amd.com) X-ZM-MESSAGEID: 1693502389000100005 Content-Type: text/plain; charset="utf-8" Signed-off-by: Tong Ho --- tests/qtest/meson.build | 2 +- tests/qtest/xlnx-versal-trng-test.c | 490 ++++++++++++++++++++++++++++ 2 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/xlnx-versal-trng-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index b071d400b3..af060d9e5b 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -216,7 +216,7 @@ qtests_aarch64 =3D \ (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG= _TPM_TIS_SYSBUS') ? \ ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) + = \ (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test'= , 'fuzz-xlnx-dp-test'] : []) + \ - (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test'] = : []) + \ + (config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', = 'xlnx-versal-trng-test'] : []) + \ (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : [])= + \ (config_all.has_key('CONFIG_TCG') and = \ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test']= : []) + \ diff --git a/tests/qtest/xlnx-versal-trng-test.c b/tests/qtest/xlnx-versal-= trng-test.c new file mode 100644 index 0000000000..6aff00c7fc --- /dev/null +++ b/tests/qtest/xlnx-versal-trng-test.c @@ -0,0 +1,490 @@ +/* + * QTests for the Xilinx Versal True Random Number Generator device + * + * Copyright (c) 2023 Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: MIT + */ + +#include "qemu/osdep.h" +#include "libqtest-single.h" + +/* Base Address */ +#define TRNG_BASEADDR (0xf1230000) + +/* TRNG_INT_CTRL */ +#define R_TRNG_INT_CTRL (0x0000) +#define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) +#define TRNG_INT_CTRL_DTF_RST_MASK (1 << 4) +#define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) +#define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) +#define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) +#define TRNG_INT_CTRL_DONE_EN_MASK (1) + +/* TRNG_STATUS */ +#define R_TRNG_STATUS (0x0004) +#define TRNG_STATUS_QCNT_SHIFT (9) +#define TRNG_STATUS_QCNT_MASK (7 << TRNG_STATUS_QCNT_SHIFT) +#define TRNG_STATUS_CERTF_MASK (1 << 3) +#define TRNG_STATUS_DTF_MASK (1 << 1) +#define TRNG_STATUS_DONE_MASK (1) + +/* TRNG_CTRL */ +#define R_TRNG_CTRL (0x0008) +#define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) +#define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) +#define TRNG_CTRL_PRNGMODE_MASK (1 << 7) +#define TRNG_CTRL_TSTMODE_MASK (1 << 6) +#define TRNG_CTRL_PRNGSTART_MASK (1 << 5) +#define TRNG_CTRL_PRNGXS_MASK (1 << 3) +#define TRNG_CTRL_TRSSEN_MASK (1 << 2) +#define TRNG_CTRL_QERTUEN_MASK (1 << 1) +#define TRNG_CTRL_PRNGSRST_MASK (1) + +/* TRNG_EXT_SEED_0 ... _11 */ +#define R_TRNG_EXT_SEED_0 (0x0040) +#define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) + +/* TRNG_PER_STRNG_0 ... 11 */ +#define R_TRNG_PER_STRNG_0 (0x0080) +#define R_TRNG_PER_STRNG_11 (R_TRNG_PER_STRNG_0 + 4 * 11) + +/* TRNG_CORE_OUTPUT */ +#define R_TRNG_CORE_OUTPUT (0x00c0) + +/* TRNG_RESET */ +#define R_TRNG_RESET (0x00d0) +#define TRNG_RESET_VAL_MASK (1) + +/* TRNG_OSC_EN */ +#define R_TRNG_OSC_EN (0x00d4) +#define TRNG_OSC_EN_VAL_MASK (1) + +/* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ +#define R_TRNG_ISR (0x00e0) +#define R_TRNG_IMR (0x00e4) +#define R_TRNG_IER (0x00e8) +#define R_TRNG_IDR (0x00ec) +#define TRNG_IRQ_SLVERR_MASK (1 << 1) +#define TRNG_IRQ_CORE_INT_MASK (1) + +#define FAILED(FMT, ...) g_error("%s(): " FMT, __func__, ## __VA_ARGS__) + +static const uint32_t prng_seed[12] =3D { + 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, + 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, +}; + +static const uint32_t pers_str[12] =3D { + 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, + 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, +}; + +static void trng_test_start(void) +{ + qtest_start("-machine xlnx-versal-virt"); +} + +static void trng_test_stop(void) +{ + qtest_end(); +} + +static void trng_test_set_uint_prop(const char *name, uint64_t value) +{ + const char *path =3D "/machine/xlnx-versal/trng"; + QDict *response; + + response =3D qmp("{ 'execute': 'qom-set'," + " 'arguments': {" + " 'path': %s," + " 'property': %s," + " 'value': %llu" + "} }", path, + name, (unsigned long long)value); + g_assert(qdict_haskey(response, "return")); + qobject_unref(response); +} + +static void trng_write(unsigned ra, uint32_t val) +{ + writel(TRNG_BASEADDR + ra, val); +} + +static uint32_t trng_read(unsigned ra) +{ + return readl(TRNG_BASEADDR + ra); +} + +static void trng_bit_set(unsigned ra, uint32_t bits) +{ + trng_write(ra, (trng_read(ra) | bits)); +} + +static void trng_bit_clr(unsigned ra, uint32_t bits) +{ + trng_write(ra, (trng_read(ra) & ~bits)); +} + +static void trng_ctrl_set(uint32_t bits) +{ + trng_bit_set(R_TRNG_CTRL, bits); +} + +static void trng_ctrl_clr(uint32_t bits) +{ + trng_bit_clr(R_TRNG_CTRL, bits); +} + +static uint32_t trng_status(void) +{ + return trng_read(R_TRNG_STATUS); +} + +static unsigned trng_qcnt(void) +{ + uint32_t sta =3D trng_status(); + + return (sta & TRNG_STATUS_QCNT_MASK) >> TRNG_STATUS_QCNT_SHIFT; +} + +static const char *trng_info(void) +{ + uint32_t sta =3D trng_status(); + uint32_t ctl =3D trng_read(R_TRNG_CTRL); + + static char info[64]; + + snprintf(info, sizeof(info), "; status=3D0x%x, ctrl=3D0x%x", sta, ctl); + return info; +} + +static void trng_wait(uint32_t wait_mask, bool on, const char *act) +{ + time_t tmo =3D time(NULL) + 2; /* at most 2 seconds */ + uint32_t event_mask =3D 0; + uint32_t clear_mask =3D 0; + + /* + * Only selected bits are events in R_TRNG_STATUS, and + * clear them needs to go through R_INT_CTRL. + */ + if (wait_mask & TRNG_STATUS_CERTF_MASK) { + event_mask |=3D TRNG_STATUS_CERTF_MASK; + clear_mask |=3D TRNG_INT_CTRL_CERTF_RST_MASK; + } + if (wait_mask & TRNG_STATUS_DTF_MASK) { + event_mask |=3D TRNG_STATUS_DTF_MASK; + clear_mask |=3D TRNG_INT_CTRL_DTF_RST_MASK; + } + if (wait_mask & TRNG_STATUS_DONE_MASK) { + event_mask |=3D TRNG_STATUS_DONE_MASK; + clear_mask |=3D TRNG_INT_CTRL_DONE_RST_MASK; + } + + for (;;) { + bool sta =3D !!(trng_status() & event_mask); + + if ((on ^ sta) =3D=3D 0) { + break; + } + + if (time(NULL) >=3D tmo) { + FAILED("%s: Timed out waiting for event 0x%x to be %d%s", + act, event_mask, (int)on, trng_info()); + } + + g_usleep(10000); + } + + /* Remove event */ + trng_bit_set(R_TRNG_INT_CTRL, clear_mask); + + if (!!(trng_read(R_TRNG_STATUS) & event_mask)) { + FAILED("%s: Event 0x%0x stuck at 1 after clear: %s", + act, event_mask, trng_info()); + } +} + +static void trng_wait_done(const char *act) +{ + trng_wait(TRNG_STATUS_DONE_MASK, true, act); +} + +static void trng_wait_dtf(void) +{ + trng_wait(TRNG_STATUS_DTF_MASK, true, "DTF injection"); +} + +static void trng_wait_certf(void) +{ + trng_wait(TRNG_STATUS_CERTF_MASK, true, "CERTF injection"); +} + +static void trng_reset(void) +{ + trng_write(R_TRNG_RESET, TRNG_RESET_VAL_MASK); + trng_write(R_TRNG_RESET, 0); +} + +static void trng_load(unsigned r0, const uint32_t *b384) +{ + static const uint32_t zero[12] =3D { 0 }; + unsigned k; + + if (!b384) { + b384 =3D zero; + } + + for (k =3D 0; k < 12; k++) { + trng_write(r0 + 4 * k, b384[k]); + } +} + +static void trng_reseed(const uint32_t *seed) +{ + const char *act; + uint32_t ctl; + + ctl =3D TRNG_CTRL_PRNGSTART_MASK | + TRNG_CTRL_PRNGXS_MASK | + TRNG_CTRL_TRSSEN_MASK; + + trng_ctrl_clr(ctl | TRNG_CTRL_PRNGMODE_MASK); + + if (seed) { + trng_load(R_TRNG_EXT_SEED_0, seed); + act =3D "Reseed PRNG"; + ctl &=3D ~TRNG_CTRL_TRSSEN_MASK; + } else { + trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); + act =3D "Reseed TRNG"; + ctl &=3D ~TRNG_CTRL_PRNGXS_MASK; + } + + trng_ctrl_set(ctl); + trng_wait_done(act); + trng_ctrl_clr(TRNG_CTRL_PRNGSTART_MASK); +} + +static void trng_generate(bool auto_enb) +{ + uint32_t ctl; + + ctl =3D TRNG_CTRL_PRNGSTART_MASK | TRNG_CTRL_SINGLEGENMODE_MASK; + trng_ctrl_clr(ctl); + + if (auto_enb) { + ctl &=3D ~TRNG_CTRL_SINGLEGENMODE_MASK; + } + + trng_ctrl_set(ctl | TRNG_CTRL_PRNGMODE_MASK); + + trng_wait_done("Generate"); + g_assert(trng_qcnt() !=3D 7); +} + +static size_t trng_collect(uint32_t *rnd, size_t cnt) +{ + size_t i; + + for (i =3D 0; i < cnt; i++) { + if (trng_qcnt() =3D=3D 0) { + return i; + } + + rnd[i] =3D trng_read(R_TRNG_CORE_OUTPUT); + } + + return i; +} + +static void trng_test_autogen(void) +{ + const size_t cnt =3D 512 / 32; + uint32_t rng[cnt], prng[cnt]; + size_t n; + + trng_reset(); + + /* PRNG run #1 */ + trng_reseed(prng_seed); + trng_generate(true); + + n =3D trng_collect(prng, cnt); + if (n !=3D cnt) { + FAILED("PRNG_1 Auto-gen test failed: expected =3D %u, got =3D %u", + (unsigned)cnt, (unsigned)n); + } + + /* TRNG, should not match PRNG */ + trng_reseed(NULL); + trng_generate(true); + + n =3D trng_collect(rng, cnt); + if (n !=3D cnt) { + FAILED("TRNG Auto-gen test failed: expected =3D %u, got =3D %u", + (unsigned)cnt, (unsigned)n); + } + + if (!memcmp(rng, prng, sizeof(rng))) { + FAILED("TRNG test failed: matching PRNG"); + } + + /* PRNG #2: should matches run #1 */ + trng_reseed(prng_seed); + trng_generate(true); + + n =3D trng_collect(rng, cnt); + if (n !=3D cnt) { + FAILED("PRNG_2 Auto-gen test failed: expected =3D %u, got =3D %u", + (unsigned)cnt, (unsigned)n); + } + + if (memcmp(rng, prng, sizeof(rng))) { + FAILED("PRNG_2 Auto-gen test failed: does not match PRNG_1"); + } +} + +static void trng_test_oneshot(void) +{ + const size_t cnt =3D 512 / 32; + uint32_t rng[cnt]; + size_t n; + + trng_reset(); + + /* PRNG run #1 */ + trng_reseed(prng_seed); + trng_generate(false); + + n =3D trng_collect(rng, cnt); + if (n =3D=3D cnt) { + FAILED("PRNG_1 One-shot gen test failed"); + } + + /* TRNG, should not match PRNG */ + trng_reseed(NULL); + trng_generate(false); + + n =3D trng_collect(rng, cnt); + if (n =3D=3D cnt) { + FAILED("TRNG One-shot test failed"); + } +} + +static void trng_test_per_str(void) +{ + const size_t cnt =3D 512 / 32; + uint32_t rng[cnt], prng[cnt]; + size_t n; + + trng_reset(); + + /* #1: disabled */ + trng_ctrl_set(TRNG_CTRL_PERSODISABLE_MASK); + trng_reseed(prng_seed); + trng_ctrl_clr(TRNG_CTRL_PERSODISABLE_MASK); + + trng_generate(true); + n =3D trng_collect(prng, cnt); + g_assert_cmpuint(n, =3D=3D, cnt); + + /* #2: zero string should match personalization disabled */ + trng_load(R_TRNG_PER_STRNG_0, NULL); + trng_reseed(prng_seed); + + trng_generate(true); + n =3D trng_collect(rng, cnt); + g_assert_cmpuint(n, =3D=3D, cnt); + + if (memcmp(rng, prng, sizeof(rng))) { + FAILED("Failed: PER_DISABLE !=3D PER_STRNG_ALL_ZERO"); + } + + /* #3: non-zero string should not match personalization disabled */ + trng_load(R_TRNG_PER_STRNG_0, pers_str); + trng_reseed(prng_seed); + + trng_generate(true); + n =3D trng_collect(rng, cnt); + g_assert_cmpuint(n, =3D=3D, cnt); + + if (!memcmp(rng, prng, sizeof(rng))) { + FAILED("Failed: PER_DISABLE =3D=3D PER_STRNG_NON_ZERO"); + } +} + +static void trng_test_forced_prng(void) +{ + const char *prop =3D "forced-prng"; + const uint64_t seed =3D 0xdeadbeefbad1bad0ULL; + + trng_reset(); + const size_t cnt =3D 512 / 32; + uint32_t rng[cnt], prng[cnt]; + size_t n; + + trng_test_set_uint_prop(prop, seed); + + /* TRNG run #1 */ + trng_reset(); + trng_reseed(NULL); + trng_generate(true); + + n =3D trng_collect(prng, cnt); + g_assert_cmpuint(n, =3D=3D, cnt); + + /* TRNG run #2 should match run #1 */ + trng_reset(); + trng_reseed(NULL); + trng_generate(true); + + n =3D trng_collect(rng, cnt); + g_assert_cmpuint(n, =3D=3D, cnt); + + if (memcmp(rng, prng, sizeof(rng))) { + FAILED("Forced-prng test failed: results do not match"); + } +} + +static void trng_test_fault_events(void) +{ + const char *prop =3D "fips-fault-events"; + + trng_reset(); + + /* Fault events only when TRSS is enabled */ + trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); + trng_ctrl_set(TRNG_CTRL_TRSSEN_MASK); + + trng_test_set_uint_prop(prop, TRNG_STATUS_CERTF_MASK); + trng_wait_certf(); + + trng_test_set_uint_prop(prop, TRNG_STATUS_DTF_MASK); + trng_wait_dtf(); + + trng_reset(); +} + +int main(int argc, char **argv) +{ + int rc; + + g_test_init(&argc, &argv, NULL); + + #define TRNG_TEST_ADD(n) \ + qtest_add_func("/hw/misc/xlnx-versal-trng/" #n, trng_test_ ## = n); + TRNG_TEST_ADD(autogen); + TRNG_TEST_ADD(oneshot); + TRNG_TEST_ADD(per_str); + TRNG_TEST_ADD(forced_prng); + TRNG_TEST_ADD(fault_events); + #undef TRNG_TEST_ADD + + trng_test_start(); + rc =3D g_test_run(); + trng_test_stop(); + + return rc; +} --=20 2.25.1