From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755087AbdL1RvF (ORCPT ); Thu, 28 Dec 2017 12:51:05 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:58889 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754343AbdL1RN7 (ORCPT ); Thu, 28 Dec 2017 12:13:59 -0500 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Haibin Zhang" , "Christoffer Dall" , "Dongjiu Geng" , "Marc Zyngier" Date: Thu, 28 Dec 2017 17:05:44 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 132/204] arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort In-Reply-To: X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.52-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dongjiu Geng 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 ] Signed-off-by: Dongjiu Geng Tested-by: Haibin Zhang Reviewed-by: Marc Zyngier Signed-off-by: Christoffer Dall [bwh: Backported to 3.16: - Don't delete cpsr variable in inject_abt() as it's still needed - Adjust context] Signed-off-by: Ben Hutchings --- --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -295,7 +295,7 @@ void kvm_inject_undefined(struct kvm_vcp u32 return_offset = (is_thumb) ? 2 : 4; new_spsr_value = cpsr; - new_lr_value = *vcpu_pc(vcpu) - return_offset; + new_lr_value = *vcpu_pc(vcpu) + return_offset; *vcpu_cpsr(vcpu) = (cpsr & ~MODE_MASK) | UND_MODE; *vcpu_cpsr(vcpu) |= PSR_I_BIT; @@ -324,9 +324,8 @@ static void inject_abt(struct kvm_vcpu * unsigned long new_spsr_value; unsigned long cpsr = *vcpu_cpsr(vcpu); u32 sctlr = vcpu->arch.cp15[c1_SCTLR]; - 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; new_spsr_value = cpsr; --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -29,12 +29,26 @@ PSR_I_BIT | PSR_D_BIT) #define EL1_EXCEPT_SYNC_OFFSET 0x200 +/* + * 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;