diff mbox

KVM: PPC: Graciously fail broken LE hypercalls

Message ID 1400157328-52208-1-git-send-email-agraf@suse.de
State New, archived
Headers show

Commit Message

Alexander Graf May 15, 2014, 12:35 p.m. UTC
There are LE Linux guests out there that don't handle hypercalls correctly.
Instead of interpreting the instruction stream from device tree as big endian
they assume it's a little endian instruction stream and fail.

When we see an illegal instruction from such a byte reversed instruction stream,
bail out graciously and just declare every hcall as error.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/kvm/book3s_emulate.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

Comments

Christian Zigotzky May 15, 2014, 1:02 p.m. UTC | #1
Just for info: Lubuntu 14.04 PowerPC on QEMU with "PR" KVM enabled is 
faster on my PA6T system than Lubuntu 14.04 PowerPC on QEMU on my 
2.93GHz quad core PC. That's amazing.

Screenshot: http://www.supertuxkart-amiga.de/amiga/QEMU_PR_KVM_A1-X1000.jpg

Thanks a lot for "PR" KVM! :-)

- Christian
--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index c992447..3f29526 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -94,8 +94,25 @@  int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
 	int rs = get_rs(inst);
 	int ra = get_ra(inst);
 	int rb = get_rb(inst);
+	u32 inst_sc = 0x44000002;
 
 	switch (get_op(inst)) {
+	case 0:
+		emulated = EMULATE_FAIL;
+		if ((kvmppc_get_msr(vcpu) & MSR_LE) &&
+		    (inst == swab32(inst_sc))) {
+			/*
+			 * This is the byte reversed syscall instruction of our
+			 * hypercall handler. Early versions of LE Linux didn't
+			 * swap the instructions correctly and ended up in
+			 * illegal instructions.
+			 * Just always fail hypercalls on these broken systems.
+			 */
+			kvmppc_set_gpr(vcpu, 3, EV_UNIMPLEMENTED);
+			kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4);
+			emulated = EMULATE_DONE;
+		}
+		break;
 	case 19:
 		switch (get_xop(inst)) {
 		case OP_19_XOP_RFID: