mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 08:44:21 +08:00
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>
This commit is contained in:
parent
c17b98cf60
commit
4a157d61b4
@ -651,6 +651,8 @@ struct kvm_vcpu_arch {
|
|||||||
spinlock_t tbacct_lock;
|
spinlock_t tbacct_lock;
|
||||||
u64 busy_stolen;
|
u64 busy_stolen;
|
||||||
u64 busy_preempt;
|
u64 busy_preempt;
|
||||||
|
|
||||||
|
u32 emul_inst;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -498,6 +498,7 @@ int main(void)
|
|||||||
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
|
DEFINE(VCPU_DAR, offsetof(struct kvm_vcpu, arch.shregs.dar));
|
||||||
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
|
DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
|
||||||
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
|
DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
|
||||||
|
DEFINE(VCPU_HEIR, offsetof(struct kvm_vcpu, arch.emul_inst));
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PPC_BOOK3S
|
#ifdef CONFIG_PPC_BOOK3S
|
||||||
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
|
DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
|
||||||
|
@ -831,6 +831,10 @@ static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu,
|
|||||||
* Accordingly return to Guest or Host.
|
* Accordingly return to Guest or Host.
|
||||||
*/
|
*/
|
||||||
case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
|
case BOOK3S_INTERRUPT_H_EMUL_ASSIST:
|
||||||
|
if (vcpu->arch.emul_inst != KVM_INST_FETCH_FAILED)
|
||||||
|
vcpu->arch.last_inst = kvmppc_need_byteswap(vcpu) ?
|
||||||
|
swab32(vcpu->arch.emul_inst) :
|
||||||
|
vcpu->arch.emul_inst;
|
||||||
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) {
|
if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) {
|
||||||
r = kvmppc_emulate_debug_inst(run, vcpu);
|
r = kvmppc_emulate_debug_inst(run, vcpu);
|
||||||
} else {
|
} else {
|
||||||
|
@ -983,13 +983,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
|
|||||||
|
|
||||||
stw r12,VCPU_TRAP(r9)
|
stw r12,VCPU_TRAP(r9)
|
||||||
|
|
||||||
/* Save HEIR (HV emulation assist reg) in last_inst
|
/* Save HEIR (HV emulation assist reg) in emul_inst
|
||||||
if this is an HEI (HV emulation interrupt, e40) */
|
if this is an HEI (HV emulation interrupt, e40) */
|
||||||
li r3,KVM_INST_FETCH_FAILED
|
li r3,KVM_INST_FETCH_FAILED
|
||||||
cmpwi r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
|
cmpwi r12,BOOK3S_INTERRUPT_H_EMUL_ASSIST
|
||||||
bne 11f
|
bne 11f
|
||||||
mfspr r3,SPRN_HEIR
|
mfspr r3,SPRN_HEIR
|
||||||
11: stw r3,VCPU_LAST_INST(r9)
|
11: stw r3,VCPU_HEIR(r9)
|
||||||
|
|
||||||
/* these are volatile across C function calls */
|
/* these are volatile across C function calls */
|
||||||
mfctr r3
|
mfctr r3
|
||||||
|
Loading…
Reference in New Issue
Block a user