/* Building of entry/exception code */
 int kvm_mips_entry_setup(void);
 void *kvm_mips_build_vcpu_run(void *addr);
-void *kvm_mips_build_exception(void *addr);
+void *kvm_mips_build_exception(void *addr, void *handler);
 void *kvm_mips_build_exit(void *addr);
 
 /* FPU/MSA context management */
 
        label_msa_1,
        label_return_to_host,
        label_kernel_asid,
+       label_exit_common,
 };
 
 UASM_L_LA(_fpu_1)
 UASM_L_LA(_msa_1)
 UASM_L_LA(_return_to_host)
 UASM_L_LA(_kernel_asid)
+UASM_L_LA(_exit_common)
 
 static void *kvm_mips_build_enter_guest(void *addr);
 static void *kvm_mips_build_ret_from_exit(void *addr);
 /**
  * kvm_mips_build_exception() - Assemble first level guest exception handler.
  * @addr:      Address to start writing code.
+ * @handler:   Address of common handler (within range of @addr).
  *
  * Assemble exception vector code for guest execution. The generated vector will
- * jump to the common exception handler generated by kvm_mips_build_exit().
+ * branch to the common exception handler generated by kvm_mips_build_exit().
  *
  * Returns:    Next address after end of written function.
  */
-void *kvm_mips_build_exception(void *addr)
+void *kvm_mips_build_exception(void *addr, void *handler)
 {
        u32 *p = addr;
+       struct uasm_label labels[2];
+       struct uasm_reloc relocs[2];
+       struct uasm_label *l = labels;
+       struct uasm_reloc *r = relocs;
+
+       memset(labels, 0, sizeof(labels));
+       memset(relocs, 0, sizeof(relocs));
 
        /* Save guest k0 */
        uasm_i_mtc0(&p, K0, scratch_tmp[0], scratch_tmp[1]);
        /* Save k1 @ offset 0x3000 */
        UASM_i_SW(&p, K1, 0x3000, K0);
 
-       /* Exception handler is installed @ offset 0x2000 */
-       uasm_i_addiu(&p, K0, K0, 0x2000);
-       /* Jump to the function */
-       uasm_i_jr(&p, K0);
+       /* Branch to the common handler */
+       uasm_il_b(&p, &r, label_exit_common);
         uasm_i_nop(&p);
 
+       uasm_l_exit_common(&l, handler);
+       uasm_resolve_relocs(relocs, labels);
+
        return p;
 }
 
 
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 {
        int err, size;
-       void *gebase, *p;
+       void *gebase, *p, *handler;
        int i;
 
        struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
        vcpu->arch.guest_ebase = gebase;
 
        /* Build guest exception vectors dynamically in unmapped memory */
+       handler = gebase + 0x2000;
 
        /* TLB Refill, EXL = 0 */
-       kvm_mips_build_exception(gebase);
+       kvm_mips_build_exception(gebase, handler);
 
        /* General Exception Entry point */
-       kvm_mips_build_exception(gebase + 0x180);
+       kvm_mips_build_exception(gebase + 0x180, handler);
 
        /* For vectored interrupts poke the exception code @ all offsets 0-7 */
        for (i = 0; i < 8; i++) {
                kvm_debug("L1 Vectored handler @ %p\n",
                          gebase + 0x200 + (i * VECTORSPACING));
-               kvm_mips_build_exception(gebase + 0x200 + i * VECTORSPACING);
+               kvm_mips_build_exception(gebase + 0x200 + i * VECTORSPACING,
+                                        handler);
        }
 
        /* General exit handler */
-       p = gebase + 0x2000;
+       p = handler;
        p = kvm_mips_build_exit(p);
 
        /* Guest entry routine */