Skip to content

Commit 4a157d6

Browse files
paulusmackagraf
authored andcommitted
KVM: PPC: Book3S HV: Fix endianness of instruction obtained from HEIR register
There are two ways in which a guest instruction can be obtained from the guest in the guest exit code in book3s_hv_rmhandlers.S. If the exit was caused by a Hypervisor Emulation interrupt (i.e. an illegal instruction), the offending instruction is in the HEIR register (Hypervisor Emulation Instruction Register). If the exit was caused by a load or store to an emulated MMIO device, we load the instruction from the guest by turning data relocation on and loading the instruction with an lwz instruction. Unfortunately, in the case where the guest has opposite endianness to the host, these two methods give results of different endianness, but both get put into vcpu->arch.last_inst. The HEIR value has been loaded using guest endianness, whereas the lwz will load the instruction using host endianness. The rest of the code that uses vcpu->arch.last_inst assumes it was loaded using host endianness. To fix this, we define a new vcpu field to store the HEIR value. Then, in kvmppc_handle_exit_hv(), we transfer the value from this new field to vcpu->arch.last_inst, doing a byte-swap if the guest and host endianness differ. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
1 parent c17b98c commit 4a157d6

File tree

4 files changed

+9
-2
lines changed

4 files changed

+9
-2
lines changed

arch/powerpc/include/asm/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ struct kvm_vcpu_arch {
651651
spinlock_t tbacct_lock;
652652
u64 busy_stolen;
653653
u64 busy_preempt;
654+
655+
u32 emul_inst;
654656
#endif
655657
};
656658

arch/powerpc/kernel/asm-offsets.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ int main(void)
498498
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
499499
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
500500
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
501+
DEFINE(VCPU_HEIR, offsetof(struct kvm_vcpu, arch.emul_inst));
501502
#endif
502503
#ifdef CONFIG_PPC_BOOK3S
503504
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));

arch/powerpc/kvm/book3s_hv.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
831831
* Accordingly return to Guest or Host.
832832
*/
833833
case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
834+
if (vcpu->arch.emul_inst != KVM_INST_FETCH_FAILED)
835+
vcpu->arch.last_inst = kvmppc_need_byteswap(vcpu) ?
836+
swab32(vcpu->arch.emul_inst) :
837+
vcpu->arch.emul_inst;
834838
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) {
835839
r = kvmppc_emulate_debug_inst(run, vcpu);
836840
} else {

arch/powerpc/kvm/book3s_hv_rmhandlers.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,13 +983,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
983983

984984
stw r12,VCPU_TRAP(r9)
985985

986-
/* Save HEIR (HV emulation assist reg) in last_inst
986+
/* Save HEIR (HV emulation assist reg) in emul_inst
987987
if this is an HEI (HV emulation interrupt, e40) */
988988
li r3,KVM_INST_FETCH_FAILED
989989
cmpwi r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
990990
bne 11f
991991
mfspr r3,SPRN_HEIR
992-
11: stw r3,VCPU_LAST_INST(r9)
992+
11: stw r3,VCPU_HEIR(r9)
993993

994994
/* these are volatile across C function calls */
995995
mfctr r3

0 commit comments

Comments
 (0)