From: Marc Zyngier <maz@kernel.org>
To: Joey Gouly <joey.gouly@arm.com>
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oliver.upton@linux.dev>,
Zenghui Yu <yuzenghui@huawei.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH 03/25] KVM: arm64: nv: Add sanitising to VNCR-backed sysregs
Date: Tue, 23 Jan 2024 17:33:37 +0000 [thread overview]
Message-ID: <86il3k7y4u.wl-maz@kernel.org> (raw)
In-Reply-To: <20240123134857.GB1283334@e124191.cambridge.arm.com>
On Tue, 23 Jan 2024 13:48:57 +0000,
Joey Gouly <joey.gouly@arm.com> wrote:
>
> Hi,
>
> On Mon, Jan 22, 2024 at 08:18:30PM +0000, Marc Zyngier wrote:
> > VNCR-backed "registers" are actually only memory. Which means that
> > there is zero control over what the guest can write, and that it
> > is the hypervisor's job to actually sanitise the content of the
> > backing store. Yeah, this is fun.
> >
> > In order to preserve some form of sanity, add a repainting mechanism
> > that makes use of a per-VM set of RES0/RES1 masks, one pair per VNCR
> > register. These masks get applied on access to the backing store via
> > __vcpu_sys_reg(), ensuring that the state that is consumed by KVM is
> > correct.
> >
> > So far, nothing populates these masks, but stay tuned.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/include/asm/kvm_host.h | 25 +++++++++++++++++++
> > arch/arm64/kvm/arm.c | 1 +
> > arch/arm64/kvm/nested.c | 41 ++++++++++++++++++++++++++++++-
> > 3 files changed, 66 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index c0cf9c5f5e8d..fe35c59214ad 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -238,6 +238,8 @@ static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
> > return index;
> > }
> >
> > +struct kvm_sysreg_masks;
> > +
> > struct kvm_arch {
> > struct kvm_s2_mmu mmu;
> >
> > @@ -312,6 +314,9 @@ struct kvm_arch {
> > #define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
> > u64 id_regs[KVM_ARM_ID_REG_NUM];
> >
> > + /* Masks for VNCR-baked sysregs */
> > + struct kvm_sysreg_masks *sysreg_masks;
> > +
> > /*
> > * For an untrusted host VM, 'pkvm.handle' is used to lookup
> > * the associated pKVM instance in the hypervisor.
> > @@ -474,6 +479,13 @@ enum vcpu_sysreg {
> > NR_SYS_REGS /* Nothing after this line! */
> > };
> >
> > +struct kvm_sysreg_masks {
> > + struct {
> > + u64 res0;
> > + u64 res1;
> > + } mask[NR_SYS_REGS - __VNCR_START__];
> > +};
> > +
> > struct kvm_cpu_context {
> > struct user_pt_regs regs; /* sp = sp_el0 */
> >
> > @@ -868,7 +880,20 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
> >
> > #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r))
> >
> > +#if defined (__KVM_NVHE_HYPERVISOR__)
> > #define __vcpu_sys_reg(v,r) (ctxt_sys_reg(&(v)->arch.ctxt, (r)))
> > +#else
> > +u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
> > +#define __vcpu_sys_reg(v,r) \
> > + (*({ \
> > + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
> > + u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
> > + if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) && \
> > + r >= __VNCR_START__ && ctxt->vncr_array)) \
> > + *__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
> > + __r; \
> > + }))
> > +#endif
>
> Can you not use vcpu_has_nv() here? I see that __ctxt_sys_reg() does a similar
> check, but vcpu_has_nv() covers !__KVM_NVHE_HYPERVISOR__, ARM64_HAS_NESTED_VIRT
> and KVM_ARM_VCPU_HAS_EL2 (which I guess is what the ctxt->vncr_array check is
> doing?) I can see it's defined in kvm_nested.h, which includes kvm_host.h, so
> maybe that's an issue.
>
> #define __vcpu_sys_reg(v,r) \
> (*({ \
> const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
> u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
> if (unlikely(vcpu_has_nv(v) && r >= __VNCR_START__)) \
> *__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
> __r; \
> }))
>
> And since vcpu_has_nv() already checks __KVM_NVHE_HYPERVISOR__, you don't need
> to define __vcpu_sys_reg() twice.
All good points. Now that we only cater for NV2, vncr_array not being
NULL is a given, although we still need it in __ctxt_sys_reg() as we
don't have the full-fat vcpu at this stage (and thus cannot check for
flags).
>
> Also maybe move that derefence into the macro, like: *__r;, instead of being
> after the first (.
Surprisingly, this doesn't work:
<quote>
./arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h:240:38: error: lvalue required as left operand of assignment
240 | __vcpu_sys_reg(vcpu, DBGVCR32_EL2) = read_sysreg(dbgvcr32_el2);
</quote>
There are plenty more.
> I'm not sure about the ctxt->vncr_array check, so maybe that's still
> important.
In the absence of the flag, it is. And I'm actually tempted to
standardise on checking for vncr_array in vcpu_has_nv() as a
substitute for the flag. It is likely to be a bit cheaper and for the
value to be needed down the line.
I'll rework this shortly.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: Joey Gouly <joey.gouly@arm.com>
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oliver.upton@linux.dev>,
Zenghui Yu <yuzenghui@huawei.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>, Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH 03/25] KVM: arm64: nv: Add sanitising to VNCR-backed sysregs
Date: Tue, 23 Jan 2024 17:33:37 +0000 [thread overview]
Message-ID: <86il3k7y4u.wl-maz@kernel.org> (raw)
In-Reply-To: <20240123134857.GB1283334@e124191.cambridge.arm.com>
On Tue, 23 Jan 2024 13:48:57 +0000,
Joey Gouly <joey.gouly@arm.com> wrote:
>
> Hi,
>
> On Mon, Jan 22, 2024 at 08:18:30PM +0000, Marc Zyngier wrote:
> > VNCR-backed "registers" are actually only memory. Which means that
> > there is zero control over what the guest can write, and that it
> > is the hypervisor's job to actually sanitise the content of the
> > backing store. Yeah, this is fun.
> >
> > In order to preserve some form of sanity, add a repainting mechanism
> > that makes use of a per-VM set of RES0/RES1 masks, one pair per VNCR
> > register. These masks get applied on access to the backing store via
> > __vcpu_sys_reg(), ensuring that the state that is consumed by KVM is
> > correct.
> >
> > So far, nothing populates these masks, but stay tuned.
> >
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> > arch/arm64/include/asm/kvm_host.h | 25 +++++++++++++++++++
> > arch/arm64/kvm/arm.c | 1 +
> > arch/arm64/kvm/nested.c | 41 ++++++++++++++++++++++++++++++-
> > 3 files changed, 66 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index c0cf9c5f5e8d..fe35c59214ad 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -238,6 +238,8 @@ static inline u16 kvm_mpidr_index(struct kvm_mpidr_data *data, u64 mpidr)
> > return index;
> > }
> >
> > +struct kvm_sysreg_masks;
> > +
> > struct kvm_arch {
> > struct kvm_s2_mmu mmu;
> >
> > @@ -312,6 +314,9 @@ struct kvm_arch {
> > #define KVM_ARM_ID_REG_NUM (IDREG_IDX(sys_reg(3, 0, 0, 7, 7)) + 1)
> > u64 id_regs[KVM_ARM_ID_REG_NUM];
> >
> > + /* Masks for VNCR-baked sysregs */
> > + struct kvm_sysreg_masks *sysreg_masks;
> > +
> > /*
> > * For an untrusted host VM, 'pkvm.handle' is used to lookup
> > * the associated pKVM instance in the hypervisor.
> > @@ -474,6 +479,13 @@ enum vcpu_sysreg {
> > NR_SYS_REGS /* Nothing after this line! */
> > };
> >
> > +struct kvm_sysreg_masks {
> > + struct {
> > + u64 res0;
> > + u64 res1;
> > + } mask[NR_SYS_REGS - __VNCR_START__];
> > +};
> > +
> > struct kvm_cpu_context {
> > struct user_pt_regs regs; /* sp = sp_el0 */
> >
> > @@ -868,7 +880,20 @@ static inline u64 *__ctxt_sys_reg(const struct kvm_cpu_context *ctxt, int r)
> >
> > #define ctxt_sys_reg(c,r) (*__ctxt_sys_reg(c,r))
> >
> > +#if defined (__KVM_NVHE_HYPERVISOR__)
> > #define __vcpu_sys_reg(v,r) (ctxt_sys_reg(&(v)->arch.ctxt, (r)))
> > +#else
> > +u64 kvm_vcpu_sanitise_vncr_reg(const struct kvm_vcpu *, enum vcpu_sysreg);
> > +#define __vcpu_sys_reg(v,r) \
> > + (*({ \
> > + const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
> > + u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
> > + if (unlikely(cpus_have_final_cap(ARM64_HAS_NESTED_VIRT) && \
> > + r >= __VNCR_START__ && ctxt->vncr_array)) \
> > + *__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
> > + __r; \
> > + }))
> > +#endif
>
> Can you not use vcpu_has_nv() here? I see that __ctxt_sys_reg() does a similar
> check, but vcpu_has_nv() covers !__KVM_NVHE_HYPERVISOR__, ARM64_HAS_NESTED_VIRT
> and KVM_ARM_VCPU_HAS_EL2 (which I guess is what the ctxt->vncr_array check is
> doing?) I can see it's defined in kvm_nested.h, which includes kvm_host.h, so
> maybe that's an issue.
>
> #define __vcpu_sys_reg(v,r) \
> (*({ \
> const struct kvm_cpu_context *ctxt = &(v)->arch.ctxt; \
> u64 *__r = __ctxt_sys_reg(ctxt, (r)); \
> if (unlikely(vcpu_has_nv(v) && r >= __VNCR_START__)) \
> *__r = kvm_vcpu_sanitise_vncr_reg((v), (r)); \
> __r; \
> }))
>
> And since vcpu_has_nv() already checks __KVM_NVHE_HYPERVISOR__, you don't need
> to define __vcpu_sys_reg() twice.
All good points. Now that we only cater for NV2, vncr_array not being
NULL is a given, although we still need it in __ctxt_sys_reg() as we
don't have the full-fat vcpu at this stage (and thus cannot check for
flags).
>
> Also maybe move that derefence into the macro, like: *__r;, instead of being
> after the first (.
Surprisingly, this doesn't work:
<quote>
./arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h:240:38: error: lvalue required as left operand of assignment
240 | __vcpu_sys_reg(vcpu, DBGVCR32_EL2) = read_sysreg(dbgvcr32_el2);
</quote>
There are plenty more.
> I'm not sure about the ctxt->vncr_array check, so maybe that's still
> important.
In the absence of the flag, it is. And I'm actually tempted to
standardise on checking for vncr_array in vcpu_has_nv() as a
substitute for the flag. It is likely to be a bit cheaper and for the
value to be needed down the line.
I'll rework this shortly.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2024-01-23 17:33 UTC|newest]
Thread overview: 114+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-22 20:18 [PATCH 00/25] KVM/arm64: VM configuration enforcement Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 01/25] arm64: sysreg: Add missing ID_AA64ISAR[13]_EL1 fields and variants Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 21:29 ` Mark Brown
2024-01-22 21:29 ` Mark Brown
2024-01-22 20:18 ` [PATCH 02/25] KVM: arm64: Add feature checking helpers Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-26 19:05 ` Oliver Upton
2024-01-26 19:05 ` Oliver Upton
2024-01-30 12:12 ` Marc Zyngier
2024-01-30 12:12 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 03/25] KVM: arm64: nv: Add sanitising to VNCR-backed sysregs Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-23 13:48 ` Joey Gouly
2024-01-23 13:48 ` Joey Gouly
2024-01-23 17:33 ` Marc Zyngier [this message]
2024-01-23 17:33 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 04/25] KVM: arm64: nv: Add sanitising to EL2 configuration registers Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 05/25] KVM: arm64: nv: Add sanitising to VNCR-backed FGT sysregs Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 06/25] KVM: arm64: nv: Add sanitising to VNCR-backed HCRX_EL2 Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 07/25] KVM: arm64: nv: Drop sanitised_sys_reg() helper Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-23 14:01 ` Joey Gouly
2024-01-23 14:01 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 08/25] KVM: arm64: Unify HDFG[WR]TR_GROUP FGT identifiers Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-23 14:14 ` Joey Gouly
2024-01-23 14:14 ` Joey Gouly
2024-01-23 15:03 ` Marc Zyngier
2024-01-23 15:03 ` Marc Zyngier
2024-01-23 17:42 ` Mark Brown
2024-01-23 17:42 ` Mark Brown
2024-01-22 20:18 ` [PATCH 09/25] KVM: arm64: nv: Correctly handle negative polarity FGTs Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 10/25] KVM: arm64: nv: Turn encoding ranges into discrete XArray stores Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-23 16:37 ` Joey Gouly
2024-01-23 16:37 ` Joey Gouly
2024-01-23 17:45 ` Marc Zyngier
2024-01-23 17:45 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 11/25] KVM: arm64: Drop the requirement for XARRAY_MULTI Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 15:57 ` Joey Gouly
2024-01-24 15:57 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 12/25] KVM: arm64: nv: Move system instructions to their own sys_reg_desc array Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 16:23 ` Joey Gouly
2024-01-24 16:23 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 13/25] KVM: arm64: Always populate the trap configuration xarray Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 16:25 ` Joey Gouly
2024-01-24 16:25 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 14/25] KVM: arm64: Register AArch64 system register entries with the sysreg xarray Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 16:34 ` Joey Gouly
2024-01-24 16:34 ` Joey Gouly
2024-01-24 16:37 ` Marc Zyngier
2024-01-24 16:37 ` Marc Zyngier
2024-01-24 17:02 ` Joey Gouly
2024-01-24 17:02 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 15/25] KVM: arm64: Use the xarray as the primary sysreg/sysinsn walker Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 16:48 ` Joey Gouly
2024-01-24 16:48 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 16/25] KVM: arm64: Rename __check_nv_sr_forward() to triage_sysreg_trap() Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 16:57 ` Joey Gouly
2024-01-24 16:57 ` Joey Gouly
2024-01-30 12:43 ` Marc Zyngier
2024-01-30 12:43 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 17/25] KVM: arm64: Add Fine-Grained UNDEF tracking information Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 18/25] KVM: arm64: Propagate and handle Fine-Grained UNDEF bits Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 15:53 ` Joey Gouly
2024-01-24 15:53 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 19/25] KVM: arm64: Move existing feature disabling over to FGU infrastructure Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-24 17:16 ` Joey Gouly
2024-01-24 17:16 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 20/25] KVM: arm64: Streamline save/restore of HFG[RW]TR_EL2 Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-25 11:30 ` Joey Gouly
2024-01-25 11:30 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 21/25] KVM: arm64: Make TLBI OS/Range UNDEF if not advertised to the guest Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-25 13:30 ` Joey Gouly
2024-01-25 13:30 ` Joey Gouly
2024-01-30 12:46 ` Marc Zyngier
2024-01-30 12:46 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 22/25] KVM: arm64: Make PIR{,E0}_EL1 UNDEF if S1PIE is " Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-23 11:48 ` Joey Gouly
2024-01-23 11:48 ` Joey Gouly
2024-01-23 17:51 ` Marc Zyngier
2024-01-23 17:51 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 23/25] KVM: arm64: Make AMU sysreg UNDEF if FEAT_AMU " Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-25 13:42 ` Joey Gouly
2024-01-25 13:42 ` Joey Gouly
2024-01-22 20:18 ` [PATCH 24/25] KVM: arm64: Make FEAT_MOPS UNDEF if " Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
2024-01-25 16:25 ` Joey Gouly
2024-01-25 16:25 ` Joey Gouly
2024-01-25 17:35 ` Joey Gouly
2024-01-25 17:35 ` Joey Gouly
2024-01-26 9:17 ` Marc Zyngier
2024-01-26 9:17 ` Marc Zyngier
2024-01-22 20:18 ` [PATCH 25/25] KVM: arm64: Add debugfs file for guest's ID registers Marc Zyngier
2024-01-22 20:18 ` Marc Zyngier
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=86il3k7y4u.wl-maz@kernel.org \
--to=maz@kernel.org \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=james.morse@arm.com \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=oliver.upton@linux.dev \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.