From: Oliver Upton <oupton@google.com>
To: Reiji Watanabe <reijiw@google.com>
Cc: kvm@vger.kernel.org, Marc Zyngier <maz@kernel.org>,
Peter Shier <pshier@google.com>, Will Deacon <will@kernel.org>,
Paolo Bonzini <pbonzini@redhat.com>,
kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v6 01/25] KVM: arm64: Introduce a validation function for an ID register
Date: Tue, 22 Mar 2022 07:42:33 +0000 [thread overview]
Message-ID: <Yjl96UQ7lUovKBWD@google.com> (raw)
In-Reply-To: <20220311044811.1980336-2-reijiw@google.com>
[-- Attachment #1: Type: text/plain, Size: 1306 bytes --]
Hi Reiji,
On Thu, Mar 10, 2022 at 08:47:47PM -0800, Reiji Watanabe wrote:
> Introduce arm64_check_features(), which does a basic validity checking
> of an ID register value against the register's limit value, which is
> generally the host's sanitized value.
>
> This function will be used by the following patches to check if an ID
> register value that userspace tries to set for a guest can be supported
> on the host.
>
> The validation is done using arm64_ftr_bits_kvm, which is created from
> arm64_ftr_regs, with some entries overwritten by entries from
> arm64_ftr_bits_kvm_override.
>
> Signed-off-by: Reiji Watanabe <reijiw@google.com>
I have some concerns regarding the API between cpufeature and KVM that's
being proposed here. It would appear that we are adding some of KVM's
implementation details into the cpufeature code. In particular, I see
that KVM's limitations on AA64DFR0 are being copied here.
Additionally, I think it would be preferable to expose this in a manner
that does not require CONFIG_KVM guards in other parts of the kernel.
WDYT about having KVM keep its set of feature overrides and otherwise
rely on the kernel's feature tables? I messed around with the idea a
bit until I could get something workable (attached). I only compile
tested this :)
--
Thanks,
Oliver
[-- Attachment #2: 0001-arm64-cpufeature-Expose-a-helper-for-validating-feat.patch --]
[-- Type: text/x-diff, Size: 4904 bytes --]
From e095ae6f138418bdb0981b6ef2c07930736aa2c2 Mon Sep 17 00:00:00 2001
From: Oliver Upton <oupton@google.com>
Date: Tue, 22 Mar 2022 07:22:28 +0000
Subject: [PATCH] arm64: cpufeature: Expose a helper for validating feature
registers
KVM is another part of the kernel that needs to deal with feature
registers. Subsequent changes to KVM will make the feature ID registers
writable from userspace, allowing VMMs to limit the exposed ISA to its
guests. However, KVM does not have any good constructs for validating
whether a particular register value constitutes a subset of the features
supported by the system.
Add a helper to check that a feature register value is a subset of the
system's safe value. Allow the caller to specify a set of overridden
feature fields for the case where KVM is more restrictive than the
kernel.
Signed-off-by: Oliver Upton <oupton@google.com>
Change-Id: Iffb134b5517d143377832d9236d5840183283e7f
---
arch/arm64/include/asm/cpufeature.h | 8 +++
arch/arm64/kernel/cpufeature.c | 82 +++++++++++++++++++++++++++--
2 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index ef6be92b1921..3cda05f5c0e9 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -63,6 +63,12 @@ struct arm64_ftr_bits {
s64 safe_val; /* safe value for FTR_EXACT features */
};
+/* Terminator for an array of struct arm64_ftr_bits */
+#define ARM64_FTR_END \
+ { \
+ .width = 0, \
+ }
+
/*
* Describe the early feature override to the core override code:
*
@@ -632,6 +638,8 @@ void check_local_cpu_capabilities(void);
u64 read_sanitised_ftr_reg(u32 id);
u64 __read_sysreg_by_encoding(u32 sys_id);
+bool arm64_ftr_reg_valid(u32 sys_id, u64 val, const struct arm64_ftr_bits *override);
+
static inline bool cpu_supports_mixed_endian_el0(void)
{
return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index e5f23dab1c8d..ba09fbd7b2d0 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -172,11 +172,6 @@ EXPORT_SYMBOL(cpu_hwcap_keys);
#define S_ARM64_FTR_BITS(VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \
__ARM64_FTR_BITS(FTR_SIGNED, VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL)
-#define ARM64_FTR_END \
- { \
- .width = 0, \
- }
-
static void cpu_enable_cnp(struct arm64_cpu_capabilities const *cap);
static bool __system_matches_cap(unsigned int n);
@@ -751,6 +746,83 @@ static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new,
return ret;
}
+static bool arm64_ftr_field_valid(const struct arm64_ftr_bits *ftrp, s64 new,
+ s64 cur)
+{
+ return arm64_ftr_safe_value(ftrp, new, cur) == new;
+}
+
+bool __arm64_ftr_reg_valid(const struct arm64_ftr_bits *ftr_bits, u64 val,
+ u64 safe_val, u64 *mask)
+{
+ const struct arm64_ftr_bits *ftrp;
+ s64 bits, safe_bits;
+ u64 ftr_mask;
+
+ for (ftrp = ftr_bits; ftrp->width; ftrp++) {
+ /*
+ * Skip validation of the field if mask indicates the field has
+ * already been checked.
+ */
+ ftr_mask = arm64_ftr_mask(ftr_bits);
+ if (*mask & ftr_mask)
+ continue;
+
+ *mask |= ftr_mask;
+
+ safe_bits = arm64_ftr_value(ftr_bits, safe_val);
+ bits = arm64_ftr_value(ftr_bits, val);
+
+ /*
+ * Check to see if 'val' attempts to advertise more than is
+ * actually supported.
+ */
+ if (!arm64_ftr_field_valid(ftr_bits, bits, safe_bits))
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * arm64_ftr_reg_valid() - Determines if a feature register value constitutes a
+ * subset of features supported by the system.
+ *
+ * @sys_reg: The encoded feature register ID
+ * @val: The feature value register to check
+ * @override: Pointer to an ARM64_FTR_END terminated array of overrides. Certain
+ * subsystems (such as KVM) are more restrictive than the kernel and
+ * impose tighter limits on certain feature fields.
+ *
+ * Return: true if 'val' is an allowed subset of features w.r.t. the system and
+ * the caller-provided overrides.
+ */
+bool arm64_ftr_reg_valid(u32 sys_reg, u64 val, const struct arm64_ftr_bits *override)
+{
+ const struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg);
+ u64 safe_val;
+ u64 mask = 0;
+
+ if (!reg)
+ return false;
+
+ safe_val = read_sanitised_ftr_reg(sys_reg);
+
+ /*
+ * Use caller overrides for checking field validity, then check what's
+ * remaining with our feature table.
+ */
+ if (!__arm64_ftr_reg_valid(override, val, safe_val, &mask) ||
+ !__arm64_ftr_reg_valid(reg->ftr_bits, val, safe_val, &mask))
+ return false;
+
+ /* Ensure that no unrecognized fields are set */
+ if (val & ~mask)
+ return false;
+
+ return true;
+}
+
static void __init sort_ftr_regs(void)
{
unsigned int i;
--
2.35.1.894.gb6a874cedc-goog
[-- Attachment #3: Type: text/plain, Size: 151 bytes --]
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
next prev parent reply other threads:[~2022-03-22 7:42 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-11 4:47 [PATCH v6 00/25] KVM: arm64: Make CPU ID registers writable by userspace Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 01/25] KVM: arm64: Introduce a validation function for an ID register Reiji Watanabe
2022-03-22 7:42 ` Oliver Upton [this message]
2022-03-23 6:06 ` Reiji Watanabe
2022-03-23 7:05 ` Oliver Upton
2022-03-24 6:00 ` Reiji Watanabe
2022-03-24 7:37 ` Oliver Upton
2022-03-29 1:57 ` Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 02/25] KVM: arm64: Save ID registers' sanitized value per guest Reiji Watanabe
2022-03-23 19:22 ` Oliver Upton
2022-03-24 16:23 ` Reiji Watanabe
2022-03-24 17:54 ` Oliver Upton
2022-03-26 2:35 ` Reiji Watanabe
2022-03-27 22:57 ` Oliver Upton
2022-03-28 0:04 ` Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 03/25] KVM: arm64: Introduce struct id_reg_desc Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 04/25] KVM: arm64: Make ID_AA64PFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 05/25] KVM: arm64: Make ID_AA64PFR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 06/25] KVM: arm64: Make ID_AA64ISAR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 07/25] KVM: arm64: Make ID_AA64ISAR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 08/25] KVM: arm64: Make ID_AA64MMFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 09/25] KVM: arm64: Make ID_AA64DFR0_EL1/ID_DFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 10/25] KVM: arm64: Make MVFR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 11/25] KVM: arm64: Add remaining ID registers to id_reg_desc_table Reiji Watanabe
2022-03-23 19:53 ` Oliver Upton
2022-03-23 20:13 ` Ricardo Koller
2022-03-23 20:44 ` Oliver Upton
2022-03-23 22:22 ` Ricardo Koller
2022-03-23 22:25 ` Oliver Upton
2022-03-24 2:26 ` Oliver Upton
2022-03-24 20:23 ` Reiji Watanabe
2022-03-24 23:01 ` Oliver Upton
2022-03-25 5:15 ` Reiji Watanabe
2022-03-25 8:51 ` Oliver Upton
2022-03-11 4:47 ` [PATCH v6 12/25] KVM: arm64: Use id_reg_desc_table for ID registers Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 13/25] KVM: arm64: Add consistency checking for frac fields of " Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 14/25] KVM: arm64: Introduce KVM_CAP_ARM_ID_REG_CONFIGURABLE capability Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 15/25] KVM: arm64: Add kunit test for ID register validation Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 16/25] KVM: arm64: Use vcpu->arch cptr_el2 to track value of cptr_el2 for VHE Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 17/25] KVM: arm64: Use vcpu->arch.mdcr_el2 to track value of mdcr_el2 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 18/25] KVM: arm64: Introduce framework to trap disabled features Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 19/25] KVM: arm64: Trap disabled features of ID_AA64PFR0_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 20/25] KVM: arm64: Trap disabled features of ID_AA64PFR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 21/25] KVM: arm64: Trap disabled features of ID_AA64DFR0_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 22/25] KVM: arm64: Trap disabled features of ID_AA64MMFR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 23/25] KVM: arm64: Trap disabled features of ID_AA64ISAR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 24/25] KVM: arm64: Add kunit test for trap initialization Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 25/25] KVM: arm64: selftests: Introduce id_reg_test Reiji Watanabe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Yjl96UQ7lUovKBWD@google.com \
--to=oupton@google.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=maz@kernel.org \
--cc=pbonzini@redhat.com \
--cc=pshier@google.com \
--cc=reijiw@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox