]> git.karo-electronics.de Git - linux-beck.git/commitdiff
KVM: PPC: Graciously fail broken LE hypercalls
authorAlexander Graf <agraf@suse.de>
Tue, 13 May 2014 15:05:51 +0000 (17:05 +0200)
committerAlexander Graf <agraf@suse.de>
Fri, 30 May 2014 12:26:26 +0000 (14:26 +0200)
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

index c9924475368f7687a23a76cf0ec89caab118559b..3f295269af37e7625869d677241c3f12cf6e0d22 100644 (file)
@@ -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: