From: Marc Zyngier <maz@kernel.org>
To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org
Cc: James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oliver.upton@linux.dev>,
Zenghui Yu <yuzenghui@huawei.com>,
Joey Gouly <joey.gouly@arm.com>
Subject: [PATCH 3/4] KVM: arm64: nv: Add additional trap setup for CPTR_EL2
Date: Tue, 4 Jun 2024 14:05:52 +0100 [thread overview]
Message-ID: <20240604130553.199981-4-maz@kernel.org> (raw)
In-Reply-To: <20240604130553.199981-1-maz@kernel.org>
We need to teach KVM a couple of new tricks. CPTR_EL2 and its
VHE accessor CPACR_EL1 need to be handled specially:
- CPACR_EL1 is trapped on VHE so that we can track the TCPAC
and TTA bits
- CPTR_EL2.{TCPAC,E0POE} are propagated from L1 to L2
As a consequence of CPTR_EL2 being always trapped, we update
vcpu_sanitised_cptr_el2() so that it doesn't try to read from
the CPU registers, but from the shadow copy (ensuring that we
always have up-to-date TCPAC and TTA bits).
This helper will also be used when handling the CPTR_EL1 trap.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/kvm_emulate.h | 2 +-
arch/arm64/kvm/hyp/vhe/switch.c | 23 ++++++++++++++++++++++-
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index e86de04ba1c4..cc5c93b46e6f 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -607,7 +607,7 @@ static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu)
*/
static inline u64 vcpu_sanitised_cptr_el2(const struct kvm_vcpu *vcpu)
{
- u64 cptr = vcpu_read_sys_reg(vcpu, CPTR_EL2);
+ u64 cptr = __vcpu_sys_reg(vcpu, CPTR_EL2);
if (!vcpu_el2_e2h_is_set(vcpu))
cptr = translate_cptr_el2_to_cpacr_el1(cptr);
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index d07b4f4be5e5..b4ba236526d6 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -67,6 +67,8 @@ static u64 __compute_hcr(struct kvm_vcpu *vcpu)
static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
{
+ u64 cptr;
+
/*
* With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to
* CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2,
@@ -85,11 +87,23 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
__activate_traps_fpsimd32(vcpu);
}
+ if (!vcpu_has_nv(vcpu))
+ goto write;
+
+ /*
+ * The architecture is a bit crap (what a surprise): an EL2 guest
+ * writing to CPTR_EL2 via CPACR_EL1 can't set any of TCPAC or TTA,
+ * as they are RES0 in the guest's view. To work around it, trap the
+ * sucker using the very same bit it can't set...
+ */
+ if (vcpu_el2_e2h_is_set(vcpu) && is_hyp_ctxt(vcpu))
+ val |= CPTR_EL2_TCPAC;
+
/*
* Layer the guest hypervisor's trap configuration on top of our own if
* we're in a nested context.
*/
- if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
+ if (is_hyp_ctxt(vcpu))
goto write;
if (guest_hyp_fpsimd_traps_enabled(vcpu))
@@ -97,6 +111,13 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
if (guest_hyp_sve_traps_enabled(vcpu))
val &= ~CPACR_ELx_ZEN;
+ cptr = vcpu_sanitised_cptr_el2(vcpu);
+
+ if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S2POE, IMP))
+ val |= cptr & CPACR_ELx_E0POE;
+
+ val |= cptr & CPTR_EL2_TCPAC;
+
write:
write_sysreg(val, cpacr_el1);
}
--
2.39.2
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org
Cc: James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Oliver Upton <oliver.upton@linux.dev>,
Zenghui Yu <yuzenghui@huawei.com>,
Joey Gouly <joey.gouly@arm.com>
Subject: [PATCH 3/4] KVM: arm64: nv: Add additional trap setup for CPTR_EL2
Date: Tue, 4 Jun 2024 14:05:52 +0100 [thread overview]
Message-ID: <20240604130553.199981-4-maz@kernel.org> (raw)
In-Reply-To: <20240604130553.199981-1-maz@kernel.org>
We need to teach KVM a couple of new tricks. CPTR_EL2 and its
VHE accessor CPACR_EL1 need to be handled specially:
- CPACR_EL1 is trapped on VHE so that we can track the TCPAC
and TTA bits
- CPTR_EL2.{TCPAC,E0POE} are propagated from L1 to L2
As a consequence of CPTR_EL2 being always trapped, we update
vcpu_sanitised_cptr_el2() so that it doesn't try to read from
the CPU registers, but from the shadow copy (ensuring that we
always have up-to-date TCPAC and TTA bits).
This helper will also be used when handling the CPTR_EL1 trap.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
arch/arm64/include/asm/kvm_emulate.h | 2 +-
arch/arm64/kvm/hyp/vhe/switch.c | 23 ++++++++++++++++++++++-
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index e86de04ba1c4..cc5c93b46e6f 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -607,7 +607,7 @@ static __always_inline void kvm_reset_cptr_el2(struct kvm_vcpu *vcpu)
*/
static inline u64 vcpu_sanitised_cptr_el2(const struct kvm_vcpu *vcpu)
{
- u64 cptr = vcpu_read_sys_reg(vcpu, CPTR_EL2);
+ u64 cptr = __vcpu_sys_reg(vcpu, CPTR_EL2);
if (!vcpu_el2_e2h_is_set(vcpu))
cptr = translate_cptr_el2_to_cpacr_el1(cptr);
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index d07b4f4be5e5..b4ba236526d6 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -67,6 +67,8 @@ static u64 __compute_hcr(struct kvm_vcpu *vcpu)
static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
{
+ u64 cptr;
+
/*
* With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to
* CPTR_EL2. In general, CPACR_EL1 has the same layout as CPTR_EL2,
@@ -85,11 +87,23 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
__activate_traps_fpsimd32(vcpu);
}
+ if (!vcpu_has_nv(vcpu))
+ goto write;
+
+ /*
+ * The architecture is a bit crap (what a surprise): an EL2 guest
+ * writing to CPTR_EL2 via CPACR_EL1 can't set any of TCPAC or TTA,
+ * as they are RES0 in the guest's view. To work around it, trap the
+ * sucker using the very same bit it can't set...
+ */
+ if (vcpu_el2_e2h_is_set(vcpu) && is_hyp_ctxt(vcpu))
+ val |= CPTR_EL2_TCPAC;
+
/*
* Layer the guest hypervisor's trap configuration on top of our own if
* we're in a nested context.
*/
- if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
+ if (is_hyp_ctxt(vcpu))
goto write;
if (guest_hyp_fpsimd_traps_enabled(vcpu))
@@ -97,6 +111,13 @@ static void __activate_cptr_traps(struct kvm_vcpu *vcpu)
if (guest_hyp_sve_traps_enabled(vcpu))
val &= ~CPACR_ELx_ZEN;
+ cptr = vcpu_sanitised_cptr_el2(vcpu);
+
+ if (kvm_has_feat(vcpu->kvm, ID_AA64MMFR3_EL1, S2POE, IMP))
+ val |= cptr & CPACR_ELx_E0POE;
+
+ val |= cptr & CPTR_EL2_TCPAC;
+
write:
write_sysreg(val, cpacr_el1);
}
--
2.39.2
_______________________________________________
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-06-04 13:06 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-04 13:05 [PATCH 0/4] KVM: arm64: nv: Add CPTR_EL2 handling Marc Zyngier
2024-06-04 13:05 ` Marc Zyngier
2024-06-04 13:05 ` [PATCH 1/4] KVM: arm64: nv: Add TCPAC/TTA to CPTR->CPACR conversion helper Marc Zyngier
2024-06-04 13:05 ` Marc Zyngier
2024-06-04 13:05 ` [PATCH 2/4] KVM: arm64: nv: Add trap description for CPTR_EL2 Marc Zyngier
2024-06-04 13:05 ` Marc Zyngier
2024-06-04 13:05 ` Marc Zyngier [this message]
2024-06-04 13:05 ` [PATCH 3/4] KVM: arm64: nv: Add additional trap setup " Marc Zyngier
2024-06-04 13:05 ` [PATCH 4/4] KVM: arm64: nv: Handle CPACR_EL1 traps Marc Zyngier
2024-06-04 13:05 ` Marc Zyngier
2024-06-04 18:49 ` [PATCH 0/4] KVM: arm64: nv: Add CPTR_EL2 handling Oliver Upton
2024-06-04 18:49 ` Oliver Upton
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=20240604130553.199981-4-maz@kernel.org \
--to=maz@kernel.org \
--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=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.