#define PPC_DBELL_MSG_BRDCAST  (0x04000000)
 #define PPC_DBELL_TYPE(x)      (((x) & 0xf) << (63-36))
+#define PPC_DBELL_TYPE_MASK    PPC_DBELL_TYPE(0xf)
 #define PPC_DBELL_LPID(x)      ((x) << (63 - 49))
+#define PPC_DBELL_PIR_MASK     0x3fff
 enum ppc_dbell {
        PPC_DBELL = 0,          /* doorbell */
        PPC_DBELL_CRIT = 1,     /* critical doorbell */
 
                int_class = INT_CLASS_NONCRIT;
                break;
        case BOOKE_IRQPRIO_CRITICAL:
+       case BOOKE_IRQPRIO_DBELL_CRIT:
                allowed = vcpu->arch.shared->msr & MSR_CE;
                allowed = allowed && !crit;
                msr_mask = MSR_GS | MSR_ME;
                keep_irq = true;
                /* fall through */
        case BOOKE_IRQPRIO_EXTERNAL:
+       case BOOKE_IRQPRIO_DBELL:
                allowed = vcpu->arch.shared->msr & MSR_EE;
                allowed = allowed && !crit;
                msr_mask = MSR_GS | MSR_CE | MSR_ME | MSR_DE;
 
 
 #include <asm/kvm_ppc.h>
 #include <asm/disassemble.h>
+#include <asm/dbell.h>
 
 #include "booke.h"
 #include "e500.h"
 
+#define XOP_MSGSND  206
+#define XOP_MSGCLR  238
 #define XOP_TLBIVAX 786
 #define XOP_TLBSX   914
 #define XOP_TLBRE   946
 #define XOP_TLBWE   978
 #define XOP_TLBILX  18
 
+#ifdef CONFIG_KVM_E500MC
+static int dbell2prio(ulong param)
+{
+       int msg = param & PPC_DBELL_TYPE_MASK;
+       int prio = -1;
+
+       switch (msg) {
+       case PPC_DBELL_TYPE(PPC_DBELL):
+               prio = BOOKE_IRQPRIO_DBELL;
+               break;
+       case PPC_DBELL_TYPE(PPC_DBELL_CRIT):
+               prio = BOOKE_IRQPRIO_DBELL_CRIT;
+               break;
+       default:
+               break;
+       }
+
+       return prio;
+}
+
+static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb)
+{
+       ulong param = vcpu->arch.gpr[rb];
+       int prio = dbell2prio(param);
+
+       if (prio < 0)
+               return EMULATE_FAIL;
+
+       clear_bit(prio, &vcpu->arch.pending_exceptions);
+       return EMULATE_DONE;
+}
+
+static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
+{
+       ulong param = vcpu->arch.gpr[rb];
+       int prio = dbell2prio(rb);
+       int pir = param & PPC_DBELL_PIR_MASK;
+       int i;
+       struct kvm_vcpu *cvcpu;
+
+       if (prio < 0)
+               return EMULATE_FAIL;
+
+       kvm_for_each_vcpu(i, cvcpu, vcpu->kvm) {
+               int cpir = cvcpu->arch.shared->pir;
+               if ((param & PPC_DBELL_MSG_BRDCAST) || (cpir == pir)) {
+                       set_bit(prio, &cvcpu->arch.pending_exceptions);
+                       kvm_vcpu_kick(cvcpu);
+               }
+       }
+
+       return EMULATE_DONE;
+}
+#endif
+
 int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
                            unsigned int inst, int *advance)
 {
        case 31:
                switch (get_xop(inst)) {
 
+#ifdef CONFIG_KVM_E500MC
+               case XOP_MSGSND:
+                       emulated = kvmppc_e500_emul_msgsnd(vcpu, get_rb(inst));
+                       break;
+
+               case XOP_MSGCLR:
+                       emulated = kvmppc_e500_emul_msgclr(vcpu, get_rb(inst));
+                       break;
+#endif
+
                case XOP_TLBRE:
                        emulated = kvmppc_e500_emul_tlbre(vcpu);
                        break;