Commit 4782e0cd authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

KVM: PPC: Book3S HV P9: Fixes for TM softpatch interrupt NIP

The softpatch interrupt sets HSRR0 to the faulting instruction +4, so
it should subtract 4 for the faulting instruction address in the case
it is a TM softpatch interrupt (the instruction was not executed) and
it was not emulated.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210811160134.904987-4-npiggin@gmail.com
parent daac40e8
...@@ -46,6 +46,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -46,6 +46,15 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
u64 newmsr, bescr; u64 newmsr, bescr;
int ra, rs; int ra, rs;
/*
* The TM softpatch interrupt sets NIP to the instruction following
* the faulting instruction, which is not executed. Rewind nip to the
* faulting instruction so it looks like a normal synchronous
* interrupt, then update nip in the places where the instruction is
* emulated.
*/
vcpu->arch.regs.nip -= 4;
/* /*
* rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit * rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit
* in these instructions, so masking bit 31 out doesn't change these * in these instructions, so masking bit 31 out doesn't change these
...@@ -67,7 +76,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -67,7 +76,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
(newmsr & MSR_TM))); (newmsr & MSR_TM)));
newmsr = sanitize_msr(newmsr); newmsr = sanitize_msr(newmsr);
vcpu->arch.shregs.msr = newmsr; vcpu->arch.shregs.msr = newmsr;
vcpu->arch.cfar = vcpu->arch.regs.nip - 4; vcpu->arch.cfar = vcpu->arch.regs.nip;
vcpu->arch.regs.nip = vcpu->arch.shregs.srr0; vcpu->arch.regs.nip = vcpu->arch.shregs.srr0;
return RESUME_GUEST; return RESUME_GUEST;
...@@ -100,7 +109,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -100,7 +109,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.bescr = bescr; vcpu->arch.bescr = bescr;
msr = (msr & ~MSR_TS_MASK) | MSR_TS_T; msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
vcpu->arch.shregs.msr = msr; vcpu->arch.shregs.msr = msr;
vcpu->arch.cfar = vcpu->arch.regs.nip - 4; vcpu->arch.cfar = vcpu->arch.regs.nip;
vcpu->arch.regs.nip = vcpu->arch.ebbrr; vcpu->arch.regs.nip = vcpu->arch.ebbrr;
return RESUME_GUEST; return RESUME_GUEST;
...@@ -116,6 +125,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -116,6 +125,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE); newmsr = (newmsr & ~MSR_LE) | (msr & MSR_LE);
newmsr = sanitize_msr(newmsr); newmsr = sanitize_msr(newmsr);
vcpu->arch.shregs.msr = newmsr; vcpu->arch.shregs.msr = newmsr;
vcpu->arch.regs.nip += 4;
return RESUME_GUEST; return RESUME_GUEST;
/* ignore bit 31, see comment above */ /* ignore bit 31, see comment above */
...@@ -152,6 +162,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -152,6 +162,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
msr = (msr & ~MSR_TS_MASK) | MSR_TS_S; msr = (msr & ~MSR_TS_MASK) | MSR_TS_S;
} }
vcpu->arch.shregs.msr = msr; vcpu->arch.shregs.msr = msr;
vcpu->arch.regs.nip += 4;
return RESUME_GUEST; return RESUME_GUEST;
/* ignore bit 31, see comment above */ /* ignore bit 31, see comment above */
...@@ -189,6 +200,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -189,6 +200,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) |
(((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29); (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29);
vcpu->arch.shregs.msr &= ~MSR_TS_MASK; vcpu->arch.shregs.msr &= ~MSR_TS_MASK;
vcpu->arch.regs.nip += 4;
return RESUME_GUEST; return RESUME_GUEST;
/* ignore bit 31, see comment above */ /* ignore bit 31, see comment above */
...@@ -220,6 +232,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu) ...@@ -220,6 +232,7 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) | vcpu->arch.regs.ccr = (vcpu->arch.regs.ccr & 0x0fffffff) |
(((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29); (((msr & MSR_TS_MASK) >> MSR_TS_S_LG) << 29);
vcpu->arch.shregs.msr = msr | MSR_TS_S; vcpu->arch.shregs.msr = msr | MSR_TS_S;
vcpu->arch.regs.nip += 4;
return RESUME_GUEST; return RESUME_GUEST;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment