Patch "arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort" has been added to the 4.9-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
arm-arm64-kvm-set-right-lr-register-value-for-32-bit-guest-when-inject-abort.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
fd6c8c206fc5d0717b0433b191de0715122f33bbMon Sep 17 00:00:00 2001
From: Dongjiu Geng <[email protected]>
Date: Tue, 17 Oct 2017 22:23:49 +0800
Subject: arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort
From: Dongjiu Geng <[email protected]>
commit fd6c8c206fc5d0717b0433b191de0715122f33bb upstream.
When a exception is trapped to EL2, hardware uses ELR_ELx to hold the current fault instruction address. If KVM wants to inject a abort to 32 bit guest, it needs to set the LR register for the guest to emulate this abort happened in the guest. Because ARM32 architecture is pipelined execution, so the LR value has an offset to the fault instruction address.
The offsets applied to Link value for exceptions as shown below, which should be added for the ARM32 link register(LR).
Table taken from ARMv8 ARM DDI0487B-B, table G1-10:
Exception Offset, for PE state of:
A32 T32
Undefined Instruction +4 +2
Prefetch Abort +4 +4
Data Abort +8 +8
IRQ or FIQ +4 +4
[ Removed unused variables in inject_abt to avoid compile warnings.
-- Christoffer ]
--- arch/arm/kvm/emulate.c | 6 ++---- arch/arm64/kvm/inject_fault.c | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-)
arch/arm/kvm/emulate.c +2 -4
@@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu32 return_offset = (is_thumb) ?2 :4 ;kvm_update_psr (vcpu,UND_MODE ); - *vcpu_reg (vcpu,14 ) = *vcpu_pc (vcpu) - return_offset; + *vcpu_reg (vcpu,14 ) = *vcpu_pc (vcpu) + return_offset;/* Branch to exception vector */ *vcpu_pc (vcpu) =exc_vector_base (vcpu) + vect_offset;
@@ -239,10 +239,8 @@ void kvm_inject_undefined(struct kvm_vcp*/ static void inject_abt (struct kvm_vcpu *vcpu,bool is_pabt,unsigned long addr) { -unsigned long cpsr = *vcpu_cpsr (vcpu); -bool is_thumb = (cpsr &PSR_T_BIT );u32 vect_offset; -u32 return_offset = (is_thumb) ?4 :0 ; +u32 return_offset = (is_pabt) ?4 :8 ;bool is_lpae;kvm_update_psr (vcpu,ABT_MODE );
arch/arm64/kvm/inject_fault.c +15 -1
@@ -33,12 +33,26 @@#define LOWER_EL_AArch64_VECTOR 0x400#define LOWER_EL_AArch32_VECTOR 0x600 +/* +* Table taken from ARMv8 ARM DDI0487B-B, table G1-10. +*/ +static const u8 return_offsets[8 ][2 ] = { + [0 ] = {0 ,0 },/* Reset, unused */ + [1 ] = {4 ,2 },/* Undefined */ + [2 ] = {0 ,0 },/* SVC, unused */ + [3 ] = {4 ,4 },/* Prefetch abort */ + [4 ] = {8 ,8 },/* Data abort */ + [5 ] = {0 ,0 },/* HVC, unused */ + [6 ] = {4 ,4 },/* IRQ, unused */ + [7 ] = {4 ,4 },/* FIQ, unused */ +}; +static void prepare_fault32 (struct kvm_vcpu *vcpu,u32 mode,u32 vect_offset) {unsigned long cpsr;unsigned long new_spsr_value = *vcpu_cpsr (vcpu);bool is_thumb = (new_spsr_value &COMPAT_PSR_T_BIT ); -u32 return_offset = (is_thumb) ?4 :0 ; +u32 return_offset = return_offsets[vect_offset >>2 ][is_thumb];u32 sctlr =vcpu_cp15 (vcpu, c1_SCTLR); cpsr = mode |COMPAT_PSR_I_BIT ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/arm-arm64-kvm-set-right-lr-register-value-for-32-bit-guest-when-inject-abort.patch