All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: Oliver Upton <oliver.upton@linux.dev>
Cc: kvmarm@lists.linux.dev, Joey Gouly <joey.gouly@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Mingwei Zhang <mizhang@google.com>,
	Colton Lewis <coltonlewis@google.com>,
	Alexandru Elisei <alexandru.elisei@arm.com>
Subject: Re: [PATCH 14/15] KVM: arm64: Don't hijack guest context MDSCR_EL1
Date: Sat, 09 Nov 2024 12:59:06 +0000	[thread overview]
Message-ID: <86v7wwzhph.wl-maz@kernel.org> (raw)
In-Reply-To: <20241108222418.1677420-15-oliver.upton@linux.dev>

On Fri, 08 Nov 2024 22:24:18 +0000,
Oliver Upton <oliver.upton@linux.dev> wrote:
> 
> Stealing MDSCR_EL1 in the guest's kvm_cpu_context for external debugging
> is rather gross. Just add a field for this instead and let the context
> switch code pick the correct one based on the debug owner.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  arch/arm64/include/asm/kvm_host.h          |  2 +-
>  arch/arm64/kvm/debug.c                     | 45 ++++------------------
>  arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 38 ++++++++++++------
>  3 files changed, 35 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index f8c7e37180ab..036c6de5819e 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -751,6 +751,7 @@ struct kvm_vcpu_arch {
>  	 */
>  	struct kvm_guest_debug_arch vcpu_debug_state;
>  	struct kvm_guest_debug_arch external_debug_state;
> +	u64 external_mdscr_el1;
>  
>  	enum {
>  		VCPU_DEBUG_FREE,
> @@ -771,7 +772,6 @@ struct kvm_vcpu_arch {
>  	 * are using guest debug.
>  	 */
>  	struct {
> -		u32	mdscr_el1;
>  		bool	pstate_ss;
>  	} guest_debug_preserved;
>  
> diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
> index 9ac237c3ae0c..a23d214a0fb0 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -32,19 +32,12 @@
>   */
>  static void save_guest_debug_regs(struct kvm_vcpu *vcpu)
>  {
> -	u64 val = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> -
> -	vcpu->arch.guest_debug_preserved.mdscr_el1 = val;
>  	vcpu->arch.guest_debug_preserved.pstate_ss =
>  					(*vcpu_cpsr(vcpu) & DBG_SPSR_SS);
>  }
>  
>  static void restore_guest_debug_regs(struct kvm_vcpu *vcpu)
>  {
> -	u64 val = vcpu->arch.guest_debug_preserved.mdscr_el1;
> -
> -	vcpu_write_sys_reg(vcpu, val, MDSCR_EL1);
> -
>  	if (vcpu->arch.guest_debug_preserved.pstate_ss)
>  		*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
>  	else
> @@ -149,36 +142,6 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
>  				*vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
>  			else
>  				*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
> -
> -			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> -			mdscr |= DBG_MDSCR_SS;
> -			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
> -		} else {
> -			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> -			mdscr &= ~DBG_MDSCR_SS;
> -			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
> -		}
> -
> -		/*
> -		 * Enable breakpoints and watchpoints if userspace wants them.
> -		 */
> -		if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW) {
> -			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> -			mdscr |= DBG_MDSCR_MDE;
> -			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
> -
> -		/*
> -		 * The OS Lock blocks debug exceptions in all ELs when it is
> -		 * enabled. If the guest has enabled the OS Lock, constrain its
> -		 * effects to the guest. Emulate the behavior by clearing
> -		 * MDSCR_EL1.MDE. In so doing, we ensure that host debug
> -		 * exceptions are unaffected by guest configuration of the OS
> -		 * Lock.
> -		 */
> -		} else if (kvm_vcpu_os_lock_enabled(vcpu)) {
> -			mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> -			mdscr &= ~DBG_MDSCR_MDE;
> -			vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
>  		}
>  	}
>  }
> @@ -232,6 +195,14 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
>  	KVM_BUG_ON(vcpu_get_flag(vcpu, SYSREGS_ON_CPU), vcpu->kvm);
>  
>  	if (vcpu->guest_debug || kvm_vcpu_os_lock_enabled(vcpu)) {
> +		mdscr = MDSCR_EL1_TDCC;

Eh... this is new. Why?

> +
> +		if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
> +			mdscr |= MDSCR_EL1_SS;
> +		if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW)
> +			mdscr |= MDSCR_EL1_MDE;

I think this would at least deserve a comment that guest_debug
indicates that *the host* is debugging the guest. It is one of the
thing that throws me every time I read this code.

The other thing is that I can't completely convince myself that this
rewrite is strictly equivalent, because we now operate on different
states. For example, I don't see that we effectively block debug
exceptions when the OS Lock is enabled. Where is that handled now?

> +
> +		vcpu->arch.external_mdscr_el1 = mdscr;
>  		vcpu->arch.debug_owner = VCPU_DEBUG_HOST_OWNED;
>  	} else {
>  		mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
> diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
> index a998b2f6abcb..49770963cf84 100644
> --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
> +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
> @@ -18,9 +18,33 @@
>  
>  static inline bool ctxt_has_s1poe(struct kvm_cpu_context *ctxt);
>  
> +static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt)
> +{
> +	struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu;
> +
> +	if (!vcpu)
> +		vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt);
> +
> +	return vcpu;
> +}
> +
> +static inline bool ctxt_is_guest(struct kvm_cpu_context *ctxt)
> +{
> +	return host_data_ptr(host_ctxt) != ctxt;
> +}
> +
> +#define ctxt_mdscr_el1(ctxt)						\
> +({									\
> +	u64 *__p = &ctxt_sys_reg(ctxt, MDSCR_EL1);			\
> +	struct kvm_vcpu *__v = ctxt_to_vcpu(ctxt);			\
> +	if (ctxt_is_guest(ctxt) && kvm_host_owns_debug_regs(__v))	\
> +		__p = &(__v)->arch.external_mdscr_el1;			\
> +	__p;								\
> +})
> +

Anything that prevents this helper from being an actual (inline) function?

>  static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
>  {
> -	ctxt_sys_reg(ctxt, MDSCR_EL1)	= read_sysreg(mdscr_el1);
> +	*ctxt_mdscr_el1(ctxt)	= read_sysreg(mdscr_el1);
>  
>  	// POR_EL0 can affect uaccess, so must be saved/restored early.
>  	if (ctxt_has_s1poe(ctxt))
> @@ -33,16 +57,6 @@ static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
>  	ctxt_sys_reg(ctxt, TPIDRRO_EL0)	= read_sysreg(tpidrro_el0);
>  }
>  
> -static inline struct kvm_vcpu *ctxt_to_vcpu(struct kvm_cpu_context *ctxt)
> -{
> -	struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu;
> -
> -	if (!vcpu)
> -		vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt);
> -
> -	return vcpu;
> -}
> -
>  static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt)
>  {
>  	struct kvm_vcpu *vcpu = ctxt_to_vcpu(ctxt);
> @@ -139,7 +153,7 @@ static inline void __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt)
>  
>  static inline void __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
>  {
> -	write_sysreg(ctxt_sys_reg(ctxt, MDSCR_EL1),  mdscr_el1);
> +	write_sysreg(*ctxt_mdscr_el1(ctxt),  mdscr_el1);
>  
>  	// POR_EL0 can affect uaccess, so must be saved/restored early.
>  	if (ctxt_has_s1poe(ctxt))

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

  reply	other threads:[~2024-11-09 12:59 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-08 22:24 [PATCH 00/15] KVM: arm64: Debug cleanups Oliver Upton
2024-11-08 22:24 ` [PATCH 01/15] KVM: arm64: Drop MDSCR_EL1_DEBUG_MASK Oliver Upton
2024-11-08 22:24 ` [PATCH 02/15] KVM: arm64: Get rid of __kvm_get_mdcr_el2() and related warts Oliver Upton
2024-11-11 11:00   ` Suzuki K Poulose
2024-11-12  7:22     ` Oliver Upton
2024-11-08 22:24 ` [PATCH 03/15] KVM: arm64: Track presence of SPE/TRBE in kvm_host_data instead of vCPU Oliver Upton
2024-11-11 13:47   ` Suzuki K Poulose
2024-11-11 15:58     ` Suzuki K Poulose
2024-11-11 16:09       ` James Clark
2024-11-11 18:17         ` Oliver Upton
2024-11-08 22:24 ` [PATCH 04/15] KVM: arm64: Move host SME/SVE tracking flags to host data Oliver Upton
2024-11-09 11:39   ` Marc Zyngier
2024-11-08 22:24 ` [PATCH 05/15] KVM: arm64: Evaluate debug owner at vcpu_load() Oliver Upton
2024-11-08 22:24 ` [PATCH 06/15] KVM: arm64: Advance debug_owner state machine for sysreg traps Oliver Upton
2024-11-09 11:47   ` Marc Zyngier
2024-11-08 22:24 ` [PATCH 07/15] KVM: arm64: Clean up KVM_SET_GUEST_DEBUG handler Oliver Upton
2024-11-08 22:24 ` [PATCH 08/15] KVM: arm64: Select debug state to save/restore based on debug owner Oliver Upton
2024-11-09 11:57   ` Marc Zyngier
2024-11-09 17:13     ` Oliver Upton
2024-11-08 22:24 ` [PATCH 09/15] KVM: arm64: Remove debug tracepoints Oliver Upton
2024-11-09 12:02   ` Marc Zyngier
2024-11-09 13:17     ` Marc Zyngier
2024-11-08 22:24 ` [PATCH 10/15] KVM: arm64: Remove vestiges of debug_ptr Oliver Upton
2024-11-08 22:24 ` [PATCH 11/15] KVM: arm64: Use debug_owner to track if debug regs need save/restore Oliver Upton
2024-11-09 12:11   ` Marc Zyngier
2024-11-09 17:18     ` Oliver Upton
2024-11-09 22:37       ` Marc Zyngier
2024-11-09 23:46         ` Oliver Upton
2024-11-08 22:24 ` [PATCH 12/15] KVM: arm64: Reload vCPU for accesses to OSLAR_EL1 Oliver Upton
2024-11-08 22:24 ` [PATCH 13/15] KVM: arm64: Compute MDCR_EL2 at vcpu_load() Oliver Upton
2024-11-09 12:28   ` Marc Zyngier
2024-11-08 22:24 ` [PATCH 14/15] KVM: arm64: Don't hijack guest context MDSCR_EL1 Oliver Upton
2024-11-09 12:59   ` Marc Zyngier [this message]
2024-11-08 22:24 ` [PATCH 15/15] KVM: arm64: Manage software step state at load/put Oliver Upton
2024-11-09 13:13 ` [PATCH 00/15] KVM: arm64: Debug cleanups Marc Zyngier
2024-11-09 17:08   ` 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=86v7wwzhph.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=alexandru.elisei@arm.com \
    --cc=coltonlewis@google.com \
    --cc=joey.gouly@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=mizhang@google.com \
    --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.