MIPS: KVM: Relative branch to common exit handler
authorJames Hogan <james.hogan@imgtec.com>
Thu, 23 Jun 2016 16:34:46 +0000 (17:34 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 5 Jul 2016 14:08:55 +0000 (16:08 +0200)
Use a relative branch to get from the individual exception vectors to
the common guest exit handler, rather than loading the address of the
exit handler and jumping to it.

This is made easier due to the fact we are now generating the entry code
dynamically. This will also allow the exception code to be further
reduced in future patches.

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim KrÄmář <rkrcmar@redhat.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/mips/include/asm/kvm_host.h
arch/mips/kvm/entry.c
arch/mips/kvm/mips.c

index a80c3208b23493d78144fd7d223e54cc4d768abc..b32785543787bc1faac7537889dea61f8d478646 100644 (file)
@@ -538,7 +538,7 @@ extern int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu);
 /* 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 */
index b6e7fd9f12f0eca34fc07b84c4ec30184525ed93..fb2cbf653474eb22733621b8d059c42adbaede40 100644 (file)
@@ -69,12 +69,14 @@ enum label_id {
        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);
@@ -327,15 +329,23 @@ static void *kvm_mips_build_enter_guest(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]);
@@ -349,12 +359,13 @@ void *kvm_mips_build_exception(void *addr)
        /* 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;
 }
 
index 26cc0b93c565423a337a456b259140dcb6faab3f..7c76768ff364ed5bfedaf1191a367fbef95c7e32 100644 (file)
@@ -265,7 +265,7 @@ static inline void dump_handler(const char *symbol, void *start, void *end)
 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);
@@ -304,22 +304,24 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
        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 */