Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp462206pxb; Thu, 5 Nov 2020 04:59:41 -0800 (PST) X-Google-Smtp-Source: ABdhPJzQHIx0yBEfEEduyD16xHzmeDcFznVS9btmT/Qc3S8LVJT5Rsxh+5IVlFJIe76KydkptEt0 X-Received: by 2002:a17:906:c1c3:: with SMTP id bw3mr2073127ejb.126.1604581181072; Thu, 05 Nov 2020 04:59:41 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604581181; cv=none; d=google.com; s=arc-20160816; b=vKxIVwHzDqbmenuGcjGWpk9aqxQuuTW0NUXZJ1nTAT2gBfXEpYdO5WGblU1JajZfUT 1AyR8PCnE9D/oaxp3+XGZLs8F4H3Y4pzRs65kFotP7WIMbUjPJwjnFssXM8WSCI48NwX h/Y+jrBgOTQP77bOxb6uaMP4K/+NiSoD27laaYRCRwM744qqTeL6JMThWOgdnKIW8GJd JEh7P+F4HUziAifoYAbAfJl+s58o7iv1HF+p5HJ0H1DgbbyEGbJRerydQvrgRT2QwagW 9IS27S2I2+lWFkmh+skS6qZ2x4wxFb5fNjwZa70/uwdhVDNjSTAvTbfdpY/it5bwMGm9 k1ag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=PjOb5LZ7z5pFoO6vY2KQJPUu8R3k64K5Udzqu3f5+q0=; b=lzSvEdTGdQTsa2GfGGt2osrGFNB0Oeb1/AaeZB4OF+L/5SIHGfWIQH0/IdCFO5IQWQ zg1qHPsAdXXnTC/gu+CqgNhQmH5iJnuoj+BCR4hAnOhyZLHeyoDuaZM1v9UMZD27Z0Uj t5QmHgClLgnGyxVoJiQc2dUU35XqEI4U9aF7qawHSPQv/yjDh1e0tLEgfpFPtHzBTDNn 9nP6zW6pWiH/XUAziM8mFwc7V43Fp4dUpCgka0s2TRZqgZ9la+0B9arS5tx6HHCxp4nl EIsr4YF9cKH6OaY5p0OnIqTref2JRWkskhNgf2zcqQ6DwV0Ina78xgeTm0iasqu5A3mL GOKw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j90si1102385edc.189.2020.11.05.04.59.17; Thu, 05 Nov 2020 04:59:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730959AbgKEM5T (ORCPT + 99 others); Thu, 5 Nov 2020 07:57:19 -0500 Received: from foss.arm.com ([217.140.110.172]:60160 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730975AbgKEM5P (ORCPT ); Thu, 5 Nov 2020 07:57:15 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C46E114BF; Thu, 5 Nov 2020 04:57:14 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.195.35]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 2659D3F719; Thu, 5 Nov 2020 04:57:13 -0800 (PST) From: Andre Przywara To: Will Deacon , Catalin Marinas , Ard Biesheuvel , Russell King Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, linux-kernel@vger.kernel.org, Sudeep Holla , Mark Rutland , Mark Brown , Lorenzo Pieralisi , Linus Walleij Subject: [PATCH v2 5/5] KVM: arm64: implement the TRNG hypervisor call Date: Thu, 5 Nov 2020 12:56:56 +0000 Message-Id: <20201105125656.25259-6-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201105125656.25259-1-andre.przywara@arm.com> References: <20201105125656.25259-1-andre.przywara@arm.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Ard Biesheuvel Provide a hypervisor implementation of the ARM architected TRNG firmware interface described in ARM spec DEN0098. All function IDs are implemented, including both 32-bit and 64-bit versions of the TRNG_RND service, which is the centerpiece of the API. The API is backed by arch_get_unsigned_seed_long(), which is implemented in terms of RNDRRS currently, and will be alternatively backed by a SMC call to the secure firmware using same interface after a future patch. If neither are available, the kernel's entropy pool is used instead. Signed-off-by: Ard Biesheuvel Signed-off-by: Andre Przywara --- arch/arm64/include/asm/kvm_host.h | 2 + arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/hypercalls.c | 6 ++ arch/arm64/kvm/trng.c | 91 +++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/kvm/trng.c diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 781d029b8aa8..615932bacf76 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -652,4 +652,6 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu); #define kvm_arm_vcpu_sve_finalized(vcpu) \ ((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED) +int kvm_trng_call(struct kvm_vcpu *vcpu); + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 1504c81fbf5d..a510037e3270 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -16,7 +16,7 @@ kvm-y := $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o \ inject_fault.o regmap.o va_layout.o handle_exit.o \ guest.o debug.o reset.o sys_regs.o \ vgic-sys-reg-v3.o fpsimd.o pmu.o \ - aarch32.o arch_timer.o \ + aarch32.o arch_timer.o trng.o \ vgic/vgic.o vgic/vgic-init.o \ vgic/vgic-irqfd.o vgic/vgic-v2.o \ vgic/vgic-v3.o vgic/vgic-v4.o \ diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c index 25ea4ecb6449..ead21b98b620 100644 --- a/arch/arm64/kvm/hypercalls.c +++ b/arch/arm64/kvm/hypercalls.c @@ -71,6 +71,12 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) if (gpa != GPA_INVALID) val = gpa; break; + case ARM_SMCCC_TRNG_VERSION: + case ARM_SMCCC_TRNG_FEATURES: + case ARM_SMCCC_TRNG_GET_UUID: + case ARM_SMCCC_TRNG_RND32: + case ARM_SMCCC_TRNG_RND64: + return kvm_trng_call(vcpu); default: return kvm_psci_call(vcpu); } diff --git a/arch/arm64/kvm/trng.c b/arch/arm64/kvm/trng.c new file mode 100644 index 000000000000..5a27b2d99977 --- /dev/null +++ b/arch/arm64/kvm/trng.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2020 Arm Ltd. + +#include +#include + +#include + +#include + +#define ARM_SMCCC_TRNG_VERSION_1_0 0x10000UL + +#define TRNG_SUCCESS 0UL +#define TRNG_NOT_SUPPORTED ((unsigned long)-1) +#define TRNG_INVALID_PARAMETER ((unsigned long)-2) +#define TRNG_NO_ENTROPY ((unsigned long)-3) + +#define MAX_BITS32 96 +#define MAX_BITS64 192 + +static const uuid_t arm_smc_trng_uuid __aligned(4) = UUID_INIT( + 0x023534a2, 0xe0bc, 0x45ec, 0x95, 0xdd, 0x33, 0x34, 0xc1, 0xcc, 0x31, 0x89); + +static int kvm_trng_do_rnd(struct kvm_vcpu *vcpu, int size) +{ + u32 num_bits = smccc_get_arg1(vcpu); + u64 bits[3]; + int i; + + if (num_bits > 3 * size) { + smccc_set_retval(vcpu, TRNG_INVALID_PARAMETER, 0, 0, 0); + return 1; + } + + /* get as many bits as we need to fulfil the request */ + for (i = 0; i < DIV_ROUND_UP(num_bits, 64); i++) + /* use the arm64 specific backend directly if one exists */ + if (!arch_get_random_seed_long((unsigned long *)&bits[i])) + bits[i] = get_random_long(); + + if (num_bits % 64) + bits[i - 1] &= U64_MAX >> (64 - (num_bits % 64)); + + while (i < ARRAY_SIZE(bits)) + bits[i++] = 0; + + if (size == 32) + smccc_set_retval(vcpu, TRNG_SUCCESS, lower_32_bits(bits[1]), + upper_32_bits(bits[0]), lower_32_bits(bits[0])); + else + smccc_set_retval(vcpu, TRNG_SUCCESS, bits[2], bits[1], bits[0]); + + memzero_explicit(bits, sizeof(bits)); + return 1; +} + +int kvm_trng_call(struct kvm_vcpu *vcpu) +{ + const __le32 *u = (__le32 *)arm_smc_trng_uuid.b; + u32 func_id = smccc_get_function(vcpu); + unsigned long val = TRNG_NOT_SUPPORTED; + int size = 64; + + switch (func_id) { + case ARM_SMCCC_TRNG_VERSION: + val = ARM_SMCCC_TRNG_VERSION_1_0; + break; + case ARM_SMCCC_TRNG_FEATURES: + switch (smccc_get_arg1(vcpu)) { + case ARM_SMCCC_TRNG_VERSION: + case ARM_SMCCC_TRNG_FEATURES: + case ARM_SMCCC_TRNG_GET_UUID: + case ARM_SMCCC_TRNG_RND32: + case ARM_SMCCC_TRNG_RND64: + val = TRNG_SUCCESS; + } + break; + case ARM_SMCCC_TRNG_GET_UUID: + smccc_set_retval(vcpu, le32_to_cpu(u[0]), le32_to_cpu(u[1]), + le32_to_cpu(u[2]), le32_to_cpu(u[3])); + return 1; + case ARM_SMCCC_TRNG_RND32: + size = 32; + fallthrough; + case ARM_SMCCC_TRNG_RND64: + return kvm_trng_do_rnd(vcpu, size); + } + + smccc_set_retval(vcpu, val, 0, 0, 0); + return 1; +} -- 2.17.1