From nobody Sat Feb 7 07:44:07 2026 Received: from out-178.mta1.migadu.com (out-178.mta1.migadu.com [95.215.58.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0A5061FB8A9 for ; Fri, 25 Oct 2024 18:24:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729880653; cv=none; b=adHTI/U00XpWTv9e7Wt5dPIFv529PVbFPbflg8E9vUYPM3DcfRA8wA0+Vjh8KZaILVQ9EnLyIevRLATFDX5wQs7OCS8y3on9CBD8mxh/AgHWPPNja/uPR70Svx+mZu1w1i2o7RcebnLKTvaFUumlVB0piUe3x5OW3GCeEdalR2o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729880653; c=relaxed/simple; bh=PDCcPrQinjbIXiZ5EARzDQFjXrFM6VDckRuDEtXvSTc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KlfEUmapD98IvMPHfucBg1kkHj11BUpxbMpE/2Y/0dpoA35TtmoMgpnagOc3oqkWIEEWFlHBBcWIupZshDbWsdWZERU/DUT+ljq6FsZk7v7SdtPZs2QOY9jBFknqqzJZyuqZgcFkivejXvzC75aeW5h6YywkNPvOqJsDO0oor5Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=J9K565V5; arc=none smtp.client-ip=95.215.58.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="J9K565V5" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1729880648; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AENT3HV05ZYgfYGtK7xFvzc3fnZN0pfnRLgWILAuZnQ=; b=J9K565V5Mp1DK+wZq8UNE8ZhLwLNylJy4zux1sSKU6e9q/asZkxef2QDlnTmHlez3xIKcR 8Un/4YcuL2+92GFzohCcrXuwYh0sNgMbMX3O8GMiEkZl9zhxqWcZMBNJBwZFh3VzmXrht1 8sHA075HhzvHi20Sxz5ES3vHtFQ0MN4= From: Oliver Upton To: kvmarm@lists.linux.dev Cc: Marc Zyngier , Joey Gouly , Suzuki K Poulose , Zenghui Yu , Catalin Marinas , Will Deacon , Anshuman Khandual , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Oliver Upton Subject: [PATCH v4 01/18] KVM: arm64: Extend masking facility to arbitrary registers Date: Fri, 25 Oct 2024 18:23:36 +0000 Message-ID: <20241025182354.3364124-2-oliver.upton@linux.dev> In-Reply-To: <20241025182354.3364124-1-oliver.upton@linux.dev> References: <20241025182354.3364124-1-oliver.upton@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Marc Zyngier We currently only use the masking (RES0/RES1) facility for VNCR registers, as they are memory-based and thus easy to sanitise. But we could apply the same thing to other registers if we: - split the sanitisation from __VNCR_START__ - apply the sanitisation when reading from a HW register This involves a new "marker" in the vcpu_sysreg enum, which defines the point at which the sanitisation applies (the VNCR registers being of course after this marker). Whle we are at it, rename kvm_vcpu_sanitise_vncr_reg() to kvm_vcpu_apply_reg_masks(), which is vaguely more explicit, and harden set_sysreg_masks() against setting masks for random registers... Signed-off-by: Marc Zyngier Reviewed-by: Joey Gouly Signed-off-by: Oliver Upton --- arch/arm64/include/asm/kvm_host.h | 19 +++++++++++++------ arch/arm64/kvm/nested.c | 12 ++++++++---- arch/arm64/kvm/sys_regs.c | 3 +++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm= _host.h index 94cff508874b..07c7d2b7b3a3 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -367,7 +367,7 @@ struct kvm_arch { =20 u64 ctr_el0; =20 - /* Masks for VNCR-baked sysregs */ + /* Masks for VNCR-backed and general EL2 sysregs */ struct kvm_sysreg_masks *sysreg_masks; =20 /* @@ -401,6 +401,9 @@ struct kvm_vcpu_fault_info { r =3D __VNCR_START__ + ((VNCR_ ## r) / 8), \ __after_##r =3D __MAX__(__before_##r - 1, r) =20 +#define MARKER(m) \ + m, __after_##m =3D m - 1 + enum vcpu_sysreg { __INVALID_SYSREG__, /* 0 is reserved as an invalid value */ MPIDR_EL1, /* MultiProcessor Affinity Register */ @@ -487,7 +490,11 @@ enum vcpu_sysreg { CNTHV_CTL_EL2, CNTHV_CVAL_EL2, =20 - __VNCR_START__, /* Any VNCR-capable reg goes after this point */ + /* Anything from this can be RES0/RES1 sanitised */ + MARKER(__SANITISED_REG_START__), + + /* Any VNCR-capable reg goes after this point */ + MARKER(__VNCR_START__), =20 VNCR(SCTLR_EL1),/* System Control Register */ VNCR(ACTLR_EL1),/* Auxiliary Control Register */ @@ -547,7 +554,7 @@ struct kvm_sysreg_masks { struct { u64 res0; u64 res1; - } mask[NR_SYS_REGS - __VNCR_START__]; + } mask[NR_SYS_REGS - __SANITISED_REG_START__]; }; =20 struct kvm_cpu_context { @@ -995,13 +1002,13 @@ static inline u64 *___ctxt_sys_reg(const struct kvm_= cpu_context *ctxt, int r) =20 #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r)) =20 -u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg); +u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *, enum vcpu_sysreg, u6= 4); #define __vcpu_sys_reg(v,r) \ (*({ \ const struct kvm_cpu_context *ctxt =3D &(v)->arch.ctxt; \ u64 *__r =3D __ctxt_sys_reg(ctxt, (r)); \ - if (vcpu_has_nv((v)) && (r) >=3D __VNCR_START__) \ - *__r =3D kvm_vcpu_sanitise_vncr_reg((v), (r)); \ + if (vcpu_has_nv((v)) && (r) >=3D __SANITISED_REG_START__) \ + *__r =3D kvm_vcpu_apply_reg_masks((v), (r), *__r);\ __r; \ })) =20 diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c index f9e30dd34c7a..b20b3bfb9cae 100644 --- a/arch/arm64/kvm/nested.c +++ b/arch/arm64/kvm/nested.c @@ -908,15 +908,15 @@ static void limit_nv_id_regs(struct kvm *kvm) kvm_set_vm_id_reg(kvm, SYS_ID_AA64DFR0_EL1, val); } =20 -u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *vcpu, enum vcpu_sysr= eg sr) +u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu, + enum vcpu_sysreg sr, u64 v) { - u64 v =3D ctxt_sys_reg(&vcpu->arch.ctxt, sr); struct kvm_sysreg_masks *masks; =20 masks =3D vcpu->kvm->arch.sysreg_masks; =20 if (masks) { - sr -=3D __VNCR_START__; + sr -=3D __SANITISED_REG_START__; =20 v &=3D ~masks->mask[sr].res0; v |=3D masks->mask[sr].res1; @@ -927,7 +927,11 @@ u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *= vcpu, enum vcpu_sysreg sr) =20 static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1) { - int i =3D sr - __VNCR_START__; + int i =3D sr - __SANITISED_REG_START__; + + BUILD_BUG_ON(!__builtin_constant_p(sr)); + BUILD_BUG_ON(sr < __SANITISED_REG_START__); + BUILD_BUG_ON(sr >=3D NR_SYS_REGS); =20 kvm->arch.sysreg_masks->mask[i].res0 =3D res0; kvm->arch.sysreg_masks->mask[i].res1 =3D res1; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index dad88e31f953..30fe940cd5bd 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -165,6 +165,9 @@ u64 vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int = reg) =20 /* Get the current version of the EL1 counterpart. */ WARN_ON(!__vcpu_read_sys_reg_from_cpu(el1r, &val)); + if (reg >=3D __SANITISED_REG_START__) + val =3D kvm_vcpu_apply_reg_masks(vcpu, reg, val); + return val; } =20 --=20 2.47.0.163.g1226f6d8fa-goog