All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robin Murphy <robin.murphy@arm.com>
To: Marc Zyngier <marc.zyngier@arm.com>,
	Christoffer Dall <christoffer.dall@linaro.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will.deacon@arm.com>
Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	kvmarm@lists.cs.columbia.edu
Subject: Re: [PATCH 1/2] arm64: KVM: Fix AArch32 to AArch64 register mapping
Date: Tue, 17 Nov 2015 11:27:51 +0000	[thread overview]
Message-ID: <564B0F37.6040708@arm.com> (raw)
In-Reply-To: <1447669698-15939-2-git-send-email-marc.zyngier@arm.com>

Hi Marc,

On 16/11/15 10:28, Marc Zyngier wrote:
> When running a 32bit guest under a 64bit hypervisor, the ARMv8
> architecture defines a mapping of the 32bit registers in the 64bit
> space. This includes banked registers that are being demultiplexed
> over the 64bit ones.
>
> On exception caused by an operation involving a 32bit register, the
> HW exposes the register number in the ESR_EL2 register. It was so
> far understood that SW had to compute which register was AArch64
> register was used (based on the current AArch32 mode and register
> number).
>
> It turns out that I misinterpreted the ARM ARM, and the clue is in
> D1.20.1: "For some exceptions, the exception syndrome given in the
> ESR_ELx identifies one or more register numbers from the issued
> instruction that generated the exception. Where the exception is
> taken from an Exception level using AArch32 these register numbers
> give the AArch64 view of the register."
>
> Which means that the HW is already giving us the translated version,
> and that we shouldn't try to interpret it at all (for example, doing
> an MMIO operation from the IRQ mode using the LR register leads to
> very unexpected behaviours).
>
> The fix is thus not to perform a call to vcpu_reg32() at all from
> vcpu_reg(), and use whatever register number is supplied directly.
> The only case we need to find out about the mapping is when we
> actively generate a register access, which only occurs when injecting
> a fault in a guest.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm64/include/asm/kvm_emulate.h | 8 +++++---
>   arch/arm64/kvm/inject_fault.c        | 2 +-
>   2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 17e92f0..3ca894e 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -99,11 +99,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
>   	*vcpu_cpsr(vcpu) |= COMPAT_PSR_T_BIT;
>   }
>
> +/*
> + * vcpu_reg should always be passed a register number coming from a
> + * read of ESR_EL2. Otherwise, it may give the wrong result on AArch32
> + * with banked registers.
> + */
>   static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
>   {
> -	if (vcpu_mode_is_32bit(vcpu))
> -		return vcpu_reg32(vcpu, reg_num);
> -
>   	return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
>   }
>
> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index 85c5715..648112e 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -48,7 +48,7 @@ static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
>
>   	/* Note: These now point to the banked copies */
>   	*vcpu_spsr(vcpu) = new_spsr_value;
> -	*vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
> +	*vcpu_reg32(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;

To the best of my knowledge after picking through all the uses of 
vcpu_reg, particularly in the shared 32-bit code, this does seem to be 
the only one which involves a potentially-banked register number that 
didn't originally come from an ESR read, and thus needs translation.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

(unfortunately I don't have an actual test-case as it was already a 
third-hand report when I started trying to look into it).

Thanks for picking this up,
Robin.

>
>   	/* Branch to exception vector */
>   	if (sctlr & (1 << 13))
>

WARNING: multiple messages have this Message-ID (diff)
From: robin.murphy@arm.com (Robin Murphy)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/2] arm64: KVM: Fix AArch32 to AArch64 register mapping
Date: Tue, 17 Nov 2015 11:27:51 +0000	[thread overview]
Message-ID: <564B0F37.6040708@arm.com> (raw)
In-Reply-To: <1447669698-15939-2-git-send-email-marc.zyngier@arm.com>

Hi Marc,

On 16/11/15 10:28, Marc Zyngier wrote:
> When running a 32bit guest under a 64bit hypervisor, the ARMv8
> architecture defines a mapping of the 32bit registers in the 64bit
> space. This includes banked registers that are being demultiplexed
> over the 64bit ones.
>
> On exception caused by an operation involving a 32bit register, the
> HW exposes the register number in the ESR_EL2 register. It was so
> far understood that SW had to compute which register was AArch64
> register was used (based on the current AArch32 mode and register
> number).
>
> It turns out that I misinterpreted the ARM ARM, and the clue is in
> D1.20.1: "For some exceptions, the exception syndrome given in the
> ESR_ELx identifies one or more register numbers from the issued
> instruction that generated the exception. Where the exception is
> taken from an Exception level using AArch32 these register numbers
> give the AArch64 view of the register."
>
> Which means that the HW is already giving us the translated version,
> and that we shouldn't try to interpret it at all (for example, doing
> an MMIO operation from the IRQ mode using the LR register leads to
> very unexpected behaviours).
>
> The fix is thus not to perform a call to vcpu_reg32() at all from
> vcpu_reg(), and use whatever register number is supplied directly.
> The only case we need to find out about the mapping is when we
> actively generate a register access, which only occurs when injecting
> a fault in a guest.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>   arch/arm64/include/asm/kvm_emulate.h | 8 +++++---
>   arch/arm64/kvm/inject_fault.c        | 2 +-
>   2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index 17e92f0..3ca894e 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -99,11 +99,13 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
>   	*vcpu_cpsr(vcpu) |= COMPAT_PSR_T_BIT;
>   }
>
> +/*
> + * vcpu_reg should always be passed a register number coming from a
> + * read of ESR_EL2. Otherwise, it may give the wrong result on AArch32
> + * with banked registers.
> + */
>   static inline unsigned long *vcpu_reg(const struct kvm_vcpu *vcpu, u8 reg_num)
>   {
> -	if (vcpu_mode_is_32bit(vcpu))
> -		return vcpu_reg32(vcpu, reg_num);
> -
>   	return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.regs[reg_num];
>   }
>
> diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
> index 85c5715..648112e 100644
> --- a/arch/arm64/kvm/inject_fault.c
> +++ b/arch/arm64/kvm/inject_fault.c
> @@ -48,7 +48,7 @@ static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
>
>   	/* Note: These now point to the banked copies */
>   	*vcpu_spsr(vcpu) = new_spsr_value;
> -	*vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;
> +	*vcpu_reg32(vcpu, 14) = *vcpu_pc(vcpu) + return_offset;

To the best of my knowledge after picking through all the uses of 
vcpu_reg, particularly in the shared 32-bit code, this does seem to be 
the only one which involves a potentially-banked register number that 
didn't originally come from an ESR read, and thus needs translation.

Reviewed-by: Robin Murphy <robin.murphy@arm.com>

(unfortunately I don't have an actual test-case as it was already a 
third-hand report when I started trying to look into it).

Thanks for picking this up,
Robin.

>
>   	/* Branch to exception vector */
>   	if (sctlr & (1 << 13))
>

  reply	other threads:[~2015-11-17 11:27 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-16 10:28 [PATCH 0/2] arm64: KVM: Fixes for 4.4-rc2 Marc Zyngier
2015-11-16 10:28 ` Marc Zyngier
2015-11-16 10:28 ` [PATCH 1/2] arm64: KVM: Fix AArch32 to AArch64 register mapping Marc Zyngier
2015-11-16 10:28   ` Marc Zyngier
2015-11-17 11:27   ` Robin Murphy [this message]
2015-11-17 11:27     ` Robin Murphy
2015-11-16 10:28 ` [PATCH 2/2] arm64: KVM: Add workaround for Cortex-A57 erratum 834220 Marc Zyngier
2015-11-16 10:28   ` Marc Zyngier
2015-11-17 17:35   ` Will Deacon
2015-11-17 17:35     ` Will Deacon
2015-11-24 16:59 ` [PATCH 0/2] arm64: KVM: Fixes for 4.4-rc2 Christoffer Dall
2015-11-24 16:59   ` Christoffer Dall

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=564B0F37.6040708@arm.com \
    --to=robin.murphy@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=christoffer.dall@linaro.org \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=marc.zyngier@arm.com \
    --cc=will.deacon@arm.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.