Re: [PATCH v5 06/33] KVM: PPC: Book3S HV: Simplify real-mode interrupt handling

2018-10-08 Thread David Gibson
On Mon, Oct 08, 2018 at 04:30:52PM +1100, Paul Mackerras wrote:
> This streamlines the first part of the code that handles a hypervisor
> interrupt that occurred in the guest.  With this, all of the real-mode
> handling that occurs is done before the "guest_exit_cont" label; once
> we get to that label we are committed to exiting to host virtual mode.
> Thus the machine check and HMI real-mode handling is moved before that
> label.
> 
> Also, the code to handle external interrupts is moved out of line, as
> is the code that calls kvmppc_realmode_hmi_handler().
> 
> Signed-off-by: Paul Mackerras 

Reviewed-by: David Gibson 

> ---
>  arch/powerpc/kvm/book3s_hv_ras.c|   8 ++
>  arch/powerpc/kvm/book3s_hv_rmhandlers.S | 220 
> 
>  2 files changed, 119 insertions(+), 109 deletions(-)
> 
> diff --git a/arch/powerpc/kvm/book3s_hv_ras.c 
> b/arch/powerpc/kvm/book3s_hv_ras.c
> index b11043b..ee564b6 100644
> --- a/arch/powerpc/kvm/book3s_hv_ras.c
> +++ b/arch/powerpc/kvm/book3s_hv_ras.c
> @@ -331,5 +331,13 @@ long kvmppc_realmode_hmi_handler(void)
>   } else {
>   wait_for_tb_resync();
>   }
> +
> + /*
> +  * Reset tb_offset_applied so the guest exit code won't try
> +  * to subtract the previous timebase offset from the timebase.
> +  */
> + if (local_paca->kvm_hstate.kvm_vcore)
> + local_paca->kvm_hstate.kvm_vcore->tb_offset_applied = 0;
> +
>   return 0;
>  }
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S 
> b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index 5b2ae34..fc360b5 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -1018,8 +1018,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
>  no_xive:
>  #endif /* CONFIG_KVM_XICS */
>  
> -deliver_guest_interrupt:
> -kvmppc_cede_reentry: /* r4 = vcpu, r13 = paca */
> +deliver_guest_interrupt: /* r4 = vcpu, r13 = paca */
>   /* Check if we can deliver an external or decrementer interrupt now */
>   ld  r0, VCPU_PENDING_EXC(r4)
>  BEGIN_FTR_SECTION
> @@ -1269,18 +1268,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>   std r3, VCPU_CTR(r9)
>   std r4, VCPU_XER(r9)
>  
> -#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> - /* For softpatch interrupt, go off and do TM instruction emulation */
> - cmpwi   r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
> - beq kvmppc_tm_emul
> -#endif
> + /* Save more register state  */
> + mfdar   r3
> + mfdsisr r4
> + std r3, VCPU_DAR(r9)
> + stw r4, VCPU_DSISR(r9)
>  
>   /* If this is a page table miss then see if it's theirs or ours */
>   cmpwi   r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
>   beq kvmppc_hdsi
> + std r3, VCPU_FAULT_DAR(r9)
> + stw r4, VCPU_FAULT_DSISR(r9)
>   cmpwi   r12, BOOK3S_INTERRUPT_H_INST_STORAGE
>   beq kvmppc_hisi
>  
> +#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
> + /* For softpatch interrupt, go off and do TM instruction emulation */
> + cmpwi   r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
> + beq kvmppc_tm_emul
> +#endif
> +
>   /* See if this is a leftover HDEC interrupt */
>   cmpwi   r12,BOOK3S_INTERRUPT_HV_DECREMENTER
>   bne 2f
> @@ -1303,7 +1310,7 @@ BEGIN_FTR_SECTION
>  END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
>   lbz r0, HSTATE_HOST_IPI(r13)
>   cmpwi   r0, 0
> - beq 4f
> + beq maybe_reenter_guest
>   b   guest_exit_cont
>  3:
>   /* If it's a hypervisor facility unavailable interrupt, save HFSCR */
> @@ -1315,82 +1322,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
>  14:
>   /* External interrupt ? */
>   cmpwi   r12, BOOK3S_INTERRUPT_EXTERNAL
> - bne+guest_exit_cont
> -
> - /* External interrupt, first check for host_ipi. If this is
> -  * set, we know the host wants us out so let's do it now
> -  */
> - bl  kvmppc_read_intr
> -
> - /*
> -  * Restore the active volatile registers after returning from
> -  * a C function.
> -  */
> - ld  r9, HSTATE_KVM_VCPU(r13)
> - li  r12, BOOK3S_INTERRUPT_EXTERNAL
> -
> - /*
> -  * kvmppc_read_intr return codes:
> -  *
> -  * Exit to host (r3 > 0)
> -  *   1 An interrupt is pending that needs to be handled by the host
> -  * Exit guest and return to host by branching to guest_exit_cont
> -  *
> -  *   2 Passthrough that needs completion in the host
> -  * Exit guest and return to host by branching to guest_exit_cont
> -  * However, we also set r12 to BOOK3S_INTERRUPT_HV_RM_HARD
> -  * to indicate to the host to complete handling the interrupt
> -  *
> -  * Before returning to guest, we check if any CPU is heading out
> -  * to the host and if so, we head out also. If no CPUs are heading
> -  * check return values <= 0.
> -  *
> -  * Return to guest (r3 <= 0)
> -  *  0 No external interrupt is pending
> 

[PATCH v5 06/33] KVM: PPC: Book3S HV: Simplify real-mode interrupt handling

2018-10-07 Thread Paul Mackerras
This streamlines the first part of the code that handles a hypervisor
interrupt that occurred in the guest.  With this, all of the real-mode
handling that occurs is done before the "guest_exit_cont" label; once
we get to that label we are committed to exiting to host virtual mode.
Thus the machine check and HMI real-mode handling is moved before that
label.

Also, the code to handle external interrupts is moved out of line, as
is the code that calls kvmppc_realmode_hmi_handler().

Signed-off-by: Paul Mackerras 
---
 arch/powerpc/kvm/book3s_hv_ras.c|   8 ++
 arch/powerpc/kvm/book3s_hv_rmhandlers.S | 220 
 2 files changed, 119 insertions(+), 109 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index b11043b..ee564b6 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -331,5 +331,13 @@ long kvmppc_realmode_hmi_handler(void)
} else {
wait_for_tb_resync();
}
+
+   /*
+* Reset tb_offset_applied so the guest exit code won't try
+* to subtract the previous timebase offset from the timebase.
+*/
+   if (local_paca->kvm_hstate.kvm_vcore)
+   local_paca->kvm_hstate.kvm_vcore->tb_offset_applied = 0;
+
return 0;
 }
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S 
b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 5b2ae34..fc360b5 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -1018,8 +1018,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 no_xive:
 #endif /* CONFIG_KVM_XICS */
 
-deliver_guest_interrupt:
-kvmppc_cede_reentry:   /* r4 = vcpu, r13 = paca */
+deliver_guest_interrupt:   /* r4 = vcpu, r13 = paca */
/* Check if we can deliver an external or decrementer interrupt now */
ld  r0, VCPU_PENDING_EXC(r4)
 BEGIN_FTR_SECTION
@@ -1269,18 +1268,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
std r3, VCPU_CTR(r9)
std r4, VCPU_XER(r9)
 
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-   /* For softpatch interrupt, go off and do TM instruction emulation */
-   cmpwi   r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
-   beq kvmppc_tm_emul
-#endif
+   /* Save more register state  */
+   mfdar   r3
+   mfdsisr r4
+   std r3, VCPU_DAR(r9)
+   stw r4, VCPU_DSISR(r9)
 
/* If this is a page table miss then see if it's theirs or ours */
cmpwi   r12, BOOK3S_INTERRUPT_H_DATA_STORAGE
beq kvmppc_hdsi
+   std r3, VCPU_FAULT_DAR(r9)
+   stw r4, VCPU_FAULT_DSISR(r9)
cmpwi   r12, BOOK3S_INTERRUPT_H_INST_STORAGE
beq kvmppc_hisi
 
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+   /* For softpatch interrupt, go off and do TM instruction emulation */
+   cmpwi   r12, BOOK3S_INTERRUPT_HV_SOFTPATCH
+   beq kvmppc_tm_emul
+#endif
+
/* See if this is a leftover HDEC interrupt */
cmpwi   r12,BOOK3S_INTERRUPT_HV_DECREMENTER
bne 2f
@@ -1303,7 +1310,7 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
lbz r0, HSTATE_HOST_IPI(r13)
cmpwi   r0, 0
-   beq 4f
+   beq maybe_reenter_guest
b   guest_exit_cont
 3:
/* If it's a hypervisor facility unavailable interrupt, save HFSCR */
@@ -1315,82 +1322,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 14:
/* External interrupt ? */
cmpwi   r12, BOOK3S_INTERRUPT_EXTERNAL
-   bne+guest_exit_cont
-
-   /* External interrupt, first check for host_ipi. If this is
-* set, we know the host wants us out so let's do it now
-*/
-   bl  kvmppc_read_intr
-
-   /*
-* Restore the active volatile registers after returning from
-* a C function.
-*/
-   ld  r9, HSTATE_KVM_VCPU(r13)
-   li  r12, BOOK3S_INTERRUPT_EXTERNAL
-
-   /*
-* kvmppc_read_intr return codes:
-*
-* Exit to host (r3 > 0)
-*   1 An interrupt is pending that needs to be handled by the host
-* Exit guest and return to host by branching to guest_exit_cont
-*
-*   2 Passthrough that needs completion in the host
-* Exit guest and return to host by branching to guest_exit_cont
-* However, we also set r12 to BOOK3S_INTERRUPT_HV_RM_HARD
-* to indicate to the host to complete handling the interrupt
-*
-* Before returning to guest, we check if any CPU is heading out
-* to the host and if so, we head out also. If no CPUs are heading
-* check return values <= 0.
-*
-* Return to guest (r3 <= 0)
-*  0 No external interrupt is pending
-* -1 A guest wakeup IPI (which has now been cleared)
-*In either case, we return to guest to deliver any pending
-*guest interrupts.
-*
-* -2 A PCI