On Guest entry: if guest is wants to use the debug register then
save h/w debug register in host_dbg_reg and load the debug registers
with shadow_dbg_reg. Otherwise leave h/w debug registers as is.

On guest exit: If guest/user-space is using the debug resource then
restore the h/w debug register with host_dbg_reg. No need to save guest
debug register as shadow_dbg_reg is having required values. If guest is not
using the debug resources then no need to restore h/w registers.

Signed-off-by: Bharat Bhushan <bharat.bhus...@freescale.com>
---
 arch/powerpc/kvm/bookehv_interrupts.S |  145 ++++++++++++++++++++++++++++++++-
 1 files changed, 141 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kvm/bookehv_interrupts.S 
b/arch/powerpc/kvm/bookehv_interrupts.S
index e8ed7d6..0d830cc 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -62,6 +62,10 @@
 #define NEED_EMU               0x00000001 /* emulation -- save nv regs */
 #define NEED_DEAR              0x00000002 /* save faulting DEAR */
 #define NEED_ESR               0x00000004 /* save faulting ESR */
+#define NEED_DBSR              0x00000008 /* save DBSR */
+
+#define DBCR0_AC_BITS  (DBCR0_IAC1 | DBCR0_IAC2 | DBCR0_IAC3 | DBCR0_IAC4 | \
+                        DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)
 
 /*
  * On entry:
@@ -201,6 +205,11 @@
        PPC_STL r9, VCPU_FAULT_DEAR(r4)
        .endif
 
+       .if     \flags & NEED_DBSR
+       mfspr   r9, SPRN_DBSR
+       stw     r9, VCPU_DBSR(r4)
+       .endif
+
        b       kvmppc_resume_host
 .endm
 
@@ -316,9 +325,9 @@ kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, EX_PARAMS(GDBELL), 
\
 kvm_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, EX_PARAMS(CRIT), \
        SPRN_CSRR0, SPRN_CSRR1, 0
 kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(DBG), \
-       SPRN_DSRR0, SPRN_DSRR1, 0
+       SPRN_DSRR0, SPRN_DSRR1, NEED_DBSR
 kvm_handler BOOKE_INTERRUPT_DEBUG, EX_PARAMS(CRIT), \
-       SPRN_CSRR0, SPRN_CSRR1, 0
+       SPRN_CSRR0, SPRN_CSRR1, NEED_DBSR
 #else
 /*
  * For input register values, see arch/powerpc/include/asm/kvm_booke_hv_asm.h
@@ -411,9 +420,9 @@ kvm_handler BOOKE_INTERRUPT_GUEST_DBELL, SPRN_GSRR0, 
SPRN_GSRR1, 0
 kvm_lvl_handler BOOKE_INTERRUPT_GUEST_DBELL_CRIT, \
        SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
 kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
-       SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, 0
+       SPRN_SPRG_RSCRATCH_CRIT, SPRN_CSRR0, SPRN_CSRR1, NEED_DBSR
 kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
-       SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, 0
+       SPRN_SPRG_RSCRATCH_DBG, SPRN_DSRR0, SPRN_DSRR1, NEED_DBSR
 #endif
 
 /* Registers:
@@ -423,6 +432,56 @@ kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
  *  r14: KVM exit number
  */
 _GLOBAL(kvmppc_resume_host)
+       /*
+        * If guest not used debug facility then hw debug registers
+        * already have proper host values. If guest used debug
+        * facility then restore host debug registers.
+        * No Need to save guest debug registers as they are already intact
+        * in guest/shadow registers.
+        */
+       lwz     r9, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR0(r4)
+       rlwinm. r8, r9, 0, ~DBCR0_IDM
+       beq     skip_load_host_debug
+       lwz     r3, VCPU_HOST_DBG+KVMPPC_DBG_DBCR0(r4)
+       andis.  r9, r9, DBCR0_AC_BITS@h
+       li      r9, 0
+       mtspr   SPRN_DBCR0, r9          /* disable all debug event */
+       beq     skip_load_hw_bkpts
+       lwz     r7, VCPU_HOST_DBG+KVMPPC_DBG_DBCR1(r4)
+       lwz     r8, VCPU_HOST_DBG+KVMPPC_DBG_DBCR2(r4)
+       lwz     r9, VCPU_HOST_DBG+KVMPPC_DBG_DBCR4(r4)
+       mtspr   SPRN_DBCR1, r7
+       PPC_LD(r6, VCPU_HOST_DBG+KVMPPC_DBG_IAC1, r4)
+       PPC_LD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC2, r4)
+       mtspr   SPRN_DBCR2, r8
+       mtspr   SPRN_DBCR4, r9
+       mtspr   SPRN_IAC1, r6
+       mtspr   SPRN_IAC2, r7
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       PPC_LD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC3, r4)
+       PPC_LD(r8, VCPU_HOST_DBG+KVMPPC_DBG_IAC4, r4)
+       mtspr   SPRN_IAC3, r7
+       mtspr   SPRN_IAC4, r8
+#endif
+       PPC_LD(r8, VCPU_HOST_DBG+KVMPPC_DBG_DAC1, r4)
+       PPC_LD(r9, VCPU_HOST_DBG+KVMPPC_DBG_DAC2, r4)
+       mtspr   SPRN_DAC1, r8
+       mtspr   SPRN_DAC2, r9
+skip_load_hw_bkpts:
+       isync
+       /* Clear h/w DBSR */
+       mfspr   r8, SPRN_DBSR
+       mtspr   SPRN_DBSR, r8
+       isync
+       /* Clear EPCR.DUVD and set host DBCR0 */
+       mfspr   r8, SPRN_EPCR
+       rlwinm  r8, r8, 0, ~SPRN_EPCR_DUVD
+       mtspr   SPRN_EPCR, r8
+       isync
+       mtspr   SPRN_DBCR0, r3
+       isync
+skip_load_host_debug:
+
        /* Save remaining volatile guest register state to vcpu. */
        mfspr   r3, SPRN_VRSAVE
        PPC_STL r0, VCPU_GPR(R0)(r4)
@@ -662,6 +721,84 @@ lightweight_exit:
        mtspr   SPRN_SPRG6W, r7
        mtspr   SPRN_SPRG7W, r8
 
+       mfmsr   r7
+       rlwinm  r7, r7, 0, ~MSR_DE
+       mtmsr   r7
+       /*
+        * Load hw debug registers with guest(shadow) debug registers
+        * if guest is using the debug facility and also set EPCR.DUVD
+        * to not allow debug events in HV mode. Do not change the
+        * debug registers if guest is not using the debug facility.
+        */
+       lwz     r6, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR0(r4)
+       rlwinm. r7, r6, 0, ~DBCR0_IDM
+       beq     skip_load_guest_debug
+       /* Save host DBCR0 */
+       mfspr   r8, SPRN_DBCR0
+       stw     r8, VCPU_HOST_DBG+KVMPPC_DBG_DBCR0(r4)
+       /*
+        * Save host DBCR1/2, IACx and DACx and load guest DBCR1/2,
+        * IACx and DACx if guest using hw breakpoint/watchpoints.
+        */
+       andis.  r3, r6, DBCR0_AC_BITS@h
+       beq     skip_hw_bkpts
+       mfspr   r7, SPRN_DBCR1
+       stw     r7, VCPU_HOST_DBG+KVMPPC_DBG_DBCR1(r4)
+       mfspr   r8, SPRN_DBCR2
+       stw     r8, VCPU_HOST_DBG+KVMPPC_DBG_DBCR2(r4)
+       mfspr   r7, SPRN_DBCR4
+       stw     r7, VCPU_HOST_DBG+KVMPPC_DBG_DBCR4(r4)
+       mfspr   r8, SPRN_IAC1
+       PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_IAC1, r4)
+       mfspr   r7, SPRN_IAC2
+       PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC2, r4)
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       mfspr   r8, SPRN_IAC3
+       PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_IAC3, r4)
+       mfspr   r7, SPRN_IAC4
+       PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC4, r4)
+#endif
+       mfspr   r8, SPRN_DAC1
+       PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_DAC1, r4)
+       mfspr   r7, SPRN_DAC2
+       PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_DAC2, r4)
+       li      r8, 0
+       mtspr   SPRN_DBCR0, r8          /* disable all debug event */
+       lwz     r7, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR1(r4)
+       lwz     r8, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR2(r4)
+       lwz     r9, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR4(r4)
+       mtspr   SPRN_DBCR1, r7
+       PPC_LD(r7, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC1, r4)
+       PPC_LD(r3, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC2, r4)
+       mtspr   SPRN_DBCR2, r8
+       mtspr   SPRN_DBCR4, r9
+       mtspr   SPRN_IAC1, r7
+       mtspr   SPRN_IAC2, r3
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       PPC_LD(r7, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC3, r4)
+       PPC_LD(r8, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC4, r4)
+       mtspr   SPRN_IAC3, r7
+       mtspr   SPRN_IAC4, r8
+#endif
+       PPC_LD(r7, VCPU_SHADOW_DBG+KVMPPC_DBG_DAC1, r4)
+       PPC_LD(r8, VCPU_SHADOW_DBG+KVMPPC_DBG_DAC2, r4)
+       mtspr   SPRN_DAC1, r7
+       mtspr   SPRN_DAC2, r8
+skip_hw_bkpts:
+       /* Set EPCR.DUVD and guest DBCR0 */
+       mfspr   r7, SPRN_EPCR
+       oris    r7, r7, SPRN_EPCR_DUVD@h
+       mtspr   SPRN_EPCR, r7
+       isync
+       /* Clear if any deferred debug event */
+       mfspr   r8, SPRN_DBSR
+       mtspr   SPRN_DBSR, r8
+       isync
+       /* Restore guest DBCR */
+       mtspr   SPRN_DBCR0, r6
+       isync
+skip_load_guest_debug:
+
        /* Load some guest volatiles. */
        PPC_LL  r3, VCPU_LR(r4)
        PPC_LL  r5, VCPU_XER(r4)
-- 
1.7.0.4


--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to