> -----Original Message-----
> From: Alexander Graf [mailto:ag...@suse.de]
> Sent: Friday, January 25, 2013 5:37 PM
> To: Bhushan Bharat-R65777
> Cc: kvm-...@vger.kernel.org; kvm@vger.kernel.org; Bhushan Bharat-R65777
> Subject: Re: [PATCH 7/8] KVM: PPC: booke/bookehv: Add debug stub support
> 
> 
> On 16.01.2013, at 09:24, Bharat Bhushan wrote:
> 
> > This patch adds the debug stub support on booke/bookehv.
> > Now QEMU debug stub can use hw breakpoint, watchpoint and software
> > breakpoint to debug guest.
> >
> > Signed-off-by: Bharat Bhushan <bharat.bhus...@freescale.com>
> > ---
> > arch/powerpc/include/asm/kvm_host.h   |    5 +
> > arch/powerpc/include/asm/kvm_ppc.h    |    2 +
> > arch/powerpc/include/uapi/asm/kvm.h   |   22 ++++-
> > arch/powerpc/kernel/asm-offsets.c     |   26 ++++++
> > arch/powerpc/kvm/booke.c              |  124 +++++++++++++++++++++++++----
> > arch/powerpc/kvm/booke_interrupts.S   |  114 ++++++++++++++++++++++++++
> > arch/powerpc/kvm/bookehv_interrupts.S |  145 
> > ++++++++++++++++++++++++++++++++-
> > arch/powerpc/kvm/e500_emulate.c       |    6 ++
> > arch/powerpc/kvm/e500mc.c             |    3 +-
> > 9 files changed, 422 insertions(+), 25 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/kvm_host.h
> > b/arch/powerpc/include/asm/kvm_host.h
> > index f4ba881..a9feeb0 100644
> > --- a/arch/powerpc/include/asm/kvm_host.h
> > +++ b/arch/powerpc/include/asm/kvm_host.h
> > @@ -504,7 +504,12 @@ struct kvm_vcpu_arch {
> >     u32 mmucfg;
> >     u32 epr;
> >     u32 crit_save;
> > +   /* guest debug registers*/
> >     struct kvmppc_booke_debug_reg dbg_reg;
> > +   /* shadow debug registers */
> > +   struct kvmppc_booke_debug_reg shadow_dbg_reg;
> > +   /* host debug registers*/
> > +   struct kvmppc_booke_debug_reg host_dbg_reg;
> > #endif
> >     gpa_t paddr_accessed;
> >     gva_t vaddr_accessed;
> > diff --git a/arch/powerpc/include/asm/kvm_ppc.h
> > b/arch/powerpc/include/asm/kvm_ppc.h
> > index b3c481e..e4b3398 100644
> > --- a/arch/powerpc/include/asm/kvm_ppc.h
> > +++ b/arch/powerpc/include/asm/kvm_ppc.h
> > @@ -45,6 +45,8 @@ enum emulation_result {
> >     EMULATE_FAIL,         /* can't emulate this instruction */
> >     EMULATE_AGAIN,        /* something went wrong. go again */
> >     EMULATE_DO_PAPR,      /* kvm_run filled with PAPR request */
> > +   EMULATE_DEBUG_INST,   /* debug instruction for software
> > +                            breakpoint, exit to userspace */
> 
> Does this do something different from DO_PAPR? Maybe it makes sense to have an
> exit code EMULATE_EXIT_USER?

I think EMULATE_DO_PAPR does something similar but the name is confusing. May 
be we can rename EMULATE_DO_PAPR to 
EMULATE_EXIT_USER.

Thanks
-Bharat
> 
> > };
> >
> > extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu
> > *vcpu); diff --git a/arch/powerpc/include/uapi/asm/kvm.h
> > b/arch/powerpc/include/uapi/asm/kvm.h
> > index e8842ed..a81ab29 100644
> > --- a/arch/powerpc/include/uapi/asm/kvm.h
> > +++ b/arch/powerpc/include/uapi/asm/kvm.h
> > @@ -25,6 +25,7 @@
> > /* Select powerpc specific features in <linux/kvm.h> */ #define
> > __KVM_HAVE_SPAPR_TCE #define __KVM_HAVE_PPC_SMT
> > +#define __KVM_HAVE_GUEST_DEBUG
> >
> > struct kvm_regs {
> >     __u64 pc;
> > @@ -267,7 +268,24 @@ struct kvm_fpu {
> >     __u64 fpr[32];
> > };
> >
> > +/*
> > + * Defines for h/w breakpoint, watchpoint (read, write or both) and
> > + * software breakpoint.
> > + * These are used as "type" in KVM_SET_GUEST_DEBUG ioctl and "status"
> > + * for KVM_DEBUG_EXIT.
> > + */
> > +#define KVMPPC_DEBUG_NONE          0x0
> > +#define KVMPPC_DEBUG_BREAKPOINT            (1UL << 1)
> > +#define KVMPPC_DEBUG_WATCH_WRITE   (1UL << 2)
> > +#define KVMPPC_DEBUG_WATCH_READ            (1UL << 3)
> > struct kvm_debug_exit_arch {
> > +   __u64 address;
> > +   /*
> > +    * exiting to userspace because of h/w breakpoint, watchpoint
> > +    * (read, write or both) and software breakpoint.
> > +    */
> > +   __u32 status;
> > +   __u32 reserved;
> > };
> >
> > /* for KVM_SET_GUEST_DEBUG */
> > @@ -279,10 +297,6 @@ struct kvm_guest_debug_arch {
> >              * Type denotes h/w breakpoint, read watchpoint, write
> >              * watchpoint or watchpoint (both read and write).
> >              */
> > -#define KVMPPC_DEBUG_NOTYPE                0x0
> > -#define KVMPPC_DEBUG_BREAKPOINT            (1UL << 1)
> > -#define KVMPPC_DEBUG_WATCH_WRITE   (1UL << 2)
> > -#define KVMPPC_DEBUG_WATCH_READ            (1UL << 3)
> >             __u32 type;
> >             __u32 reserved;
> >     } bp[16];
> > diff --git a/arch/powerpc/kernel/asm-offsets.c
> > b/arch/powerpc/kernel/asm-offsets.c
> > index 02048f3..22deda7 100644
> > --- a/arch/powerpc/kernel/asm-offsets.c
> > +++ b/arch/powerpc/kernel/asm-offsets.c
> > @@ -563,6 +563,32 @@ int main(void)
> >     DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear));
> >     DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr));
> >     DEFINE(VCPU_CRIT_SAVE, offsetof(struct kvm_vcpu, arch.crit_save));
> > +   DEFINE(VCPU_DBSR, offsetof(struct kvm_vcpu, arch.dbsr));
> > +   DEFINE(VCPU_SHADOW_DBG, offsetof(struct kvm_vcpu, arch.shadow_dbg_reg));
> > +   DEFINE(VCPU_HOST_DBG, offsetof(struct kvm_vcpu, arch.host_dbg_reg));
> > +   DEFINE(KVMPPC_DBG_DBCR0, offsetof(struct kvmppc_booke_debug_reg,
> > +                                     dbcr0));
> > +   DEFINE(KVMPPC_DBG_DBCR1, offsetof(struct kvmppc_booke_debug_reg,
> > +                                     dbcr1));
> > +   DEFINE(KVMPPC_DBG_DBCR2, offsetof(struct kvmppc_booke_debug_reg,
> > +                                     dbcr2));
> > +#ifdef CONFIG_KVM_E500MC
> > +   DEFINE(KVMPPC_DBG_DBCR4, offsetof(struct kvmppc_booke_debug_reg,
> > +                                     dbcr4));
> > +#endif
> > +   DEFINE(KVMPPC_DBG_IAC1, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    iac[0]));
> > +   DEFINE(KVMPPC_DBG_IAC2, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    iac[1]));
> > +   DEFINE(KVMPPC_DBG_IAC3, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    iac[2]));
> > +   DEFINE(KVMPPC_DBG_IAC4, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    iac[3]));
> > +   DEFINE(KVMPPC_DBG_DAC1, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    dac[0]));
> > +   DEFINE(KVMPPC_DBG_DAC2, offsetof(struct kvmppc_booke_debug_reg,
> > +                                    dac[1]));
> > +   DEFINE(VCPU_GUEST_DEBUG, offsetof(struct kvm_vcpu, guest_debug));
> > #endif /* CONFIG_PPC_BOOK3S */
> > #endif /* CONFIG_KVM */
> >
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index
> > 7d5a51c..faa0a0b 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -143,6 +143,9 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32
> > new_msr)
> >
> > #ifdef CONFIG_KVM_BOOKE_HV
> >     new_msr |= MSR_GS;
> > +
> > +   if (vcpu->guest_debug)
> > +           new_msr |= MSR_DE;
> > #endif
> >
> >     vcpu->arch.shared->msr = new_msr;
> > @@ -711,7 +714,8 @@ out:
> >     return ret;
> > }
> >
> > -static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
> > +static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
> > +                     int exit_nr)
> 
> Why pass in exit_nr?
> 
> > {
> >     enum emulation_result er;
> >
> > @@ -728,6 +732,13 @@ static int emulation_exit(struct kvm_run *run, struct
> kvm_vcpu *vcpu)
> >             run->exit_reason = KVM_EXIT_DCR;
> >             return RESUME_HOST;
> >
> > +   case EMULATE_DEBUG_INST:
> > +           run->exit_reason = KVM_EXIT_DEBUG;
> > +           run->debug.arch.address = vcpu->arch.pc;
> > +           run->debug.arch.status = 0;
> > +           kvmppc_account_exit(vcpu, DEBUG_EXITS);
> > +           return RESUME_HOST;
> > +
> >     case EMULATE_FAIL:
> >             printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
> >                    __func__, vcpu->arch.pc, vcpu->arch.last_inst); @@ -743,6
> > +754,28 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu
> *vcpu)
> >     }
> > }
> >
> > +static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu
> > +*vcpu) {
> > +   u32 dbsr = vcpu->arch.dbsr;
> > +   run->debug.arch.status = 0;
> > +   run->debug.arch.address = vcpu->arch.pc;
> > +
> > +   if (dbsr & (DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4)) {
> > +           run->debug.arch.status |= KVMPPC_DEBUG_BREAKPOINT;
> > +   } else {
> > +           if (dbsr & (DBSR_DAC1W | DBSR_DAC2W))
> > +                   run->debug.arch.status |= KVMPPC_DEBUG_WATCH_WRITE;
> > +           else if (dbsr & (DBSR_DAC1R | DBSR_DAC2R))
> > +                   run->debug.arch.status |= KVMPPC_DEBUG_WATCH_READ;
> > +           if (dbsr & (DBSR_DAC1R | DBSR_DAC1W))
> > +                   run->debug.arch.address = 
> > vcpu->arch.shadow_dbg_reg.dac[0];
> > +           else if (dbsr & (DBSR_DAC2R | DBSR_DAC2W))
> > +                   run->debug.arch.address = 
> > vcpu->arch.shadow_dbg_reg.dac[1];
> > +   }
> > +
> > +   return RESUME_HOST;
> > +}
> > +
> > static void kvmppc_fill_pt_regs(struct pt_regs *regs) {
> >     ulong r1, ip, msr, lr;
> > @@ -887,7 +920,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct
> kvm_vcpu *vcpu,
> >             break;
> >
> >     case BOOKE_INTERRUPT_HV_PRIV:
> > -           r = emulation_exit(run, vcpu);
> > +           r = emulation_exit(run, vcpu, exit_nr);
> >             break;
> >
> >     case BOOKE_INTERRUPT_PROGRAM:
> > @@ -906,7 +939,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct
> kvm_vcpu *vcpu,
> >                     break;
> >             }
> >
> > -           r = emulation_exit(run, vcpu);
> > +           r = emulation_exit(run, vcpu, exit_nr);
> >             break;
> >
> >     case BOOKE_INTERRUPT_FP_UNAVAIL:
> > @@ -1096,18 +1129,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct
> kvm_vcpu *vcpu,
> >     }
> >
> >     case BOOKE_INTERRUPT_DEBUG: {
> > -           u32 dbsr;
> > -
> > -           vcpu->arch.pc = mfspr(SPRN_CSRR0);
> > -
> > -           /* clear IAC events in DBSR register */
> > -           dbsr = mfspr(SPRN_DBSR);
> > -           dbsr &= DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4;
> > -           mtspr(SPRN_DBSR, dbsr);
> > -
> > -           run->exit_reason = KVM_EXIT_DEBUG;
> > +           r = kvmppc_handle_debug(run, vcpu);
> > +           if (r == RESUME_HOST) {
> > +                   run->exit_reason = KVM_EXIT_DEBUG;
> > +           }
> >             kvmppc_account_exit(vcpu, DEBUG_EXITS);
> > -           r = RESUME_HOST;
> >             break;
> >     }
> >
> > @@ -1483,10 +1509,78 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu 
> > *vcpu,
> struct kvm_one_reg *reg)
> >     return r;
> > }
> >
> > +#define BP_NUM     KVMPPC_BOOKE_IAC_NUM
> > +#define WP_NUM     KVMPPC_BOOKE_DAC_NUM
> > +
> > int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
> >                                      struct kvm_guest_debug *dbg)
> > {
> > -   return -EINVAL;
> > +
> > +   if (!(dbg->control & KVM_GUESTDBG_ENABLE)) {
> > +           /* Clear All debug events */
> > +           vcpu->arch.shadow_dbg_reg.dbcr0 = 0;
> > +           vcpu->guest_debug = 0;
> > +           return 0;
> > +   }
> > +
> > +   vcpu->guest_debug = dbg->control;
> > +   vcpu->arch.shadow_dbg_reg.dbcr0 = 0;
> > +
> > +   if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
> > +           vcpu->arch.shadow_dbg_reg.dbcr0 |= DBCR0_IDM | DBCR0_IC;
> > +
> > +   if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) {
> > +           struct kvmppc_booke_debug_reg *gdbgr =
> > +                           &(vcpu->arch.shadow_dbg_reg);
> > +           int n, b = 0, w = 0;
> > +           const u32 bp_code[] = {
> > +                   DBCR0_IAC1 | DBCR0_IDM,
> > +                   DBCR0_IAC2 | DBCR0_IDM,
> > +                   DBCR0_IAC3 | DBCR0_IDM,
> > +                   DBCR0_IAC4 | DBCR0_IDM
> > +           };
> > +           const u32 wp_code[] = {
> > +                   DBCR0_DAC1W | DBCR0_IDM,
> > +                   DBCR0_DAC2W | DBCR0_IDM,
> > +                   DBCR0_DAC1R | DBCR0_IDM,
> > +                   DBCR0_DAC2R | DBCR0_IDM
> > +           };
> > +
> > +#ifndef CONFIG_KVM_BOOKE_HV
> 
> Please reverse the logic here. #ifndef ... #else is always a bad idea.
> 
> > +           gdbgr->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US |
> > +                           DBCR1_IAC3US | DBCR1_IAC4US;
> > +           gdbgr->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; #else
> > +           gdbgr->dbcr1 = 0;
> > +           gdbgr->dbcr2 = 0;
> > +#endif
> > +
> > +           for (n = 0; n < (BP_NUM + WP_NUM); n++) {
> > +                   u32 type = dbg->arch.bp[n].type;
> > +
> > +                   if (!type)
> > +                           break;
> > +
> > +                   if (type & (KVMPPC_DEBUG_WATCH_READ |
> > +                               KVMPPC_DEBUG_WATCH_WRITE)) {
> > +                           if (w < WP_NUM) {
> > +                                   if (type & KVMPPC_DEBUG_WATCH_READ)
> > +                                           gdbgr->dbcr0 |= wp_code[w + 2];
> > +                                   if (type & KVMPPC_DEBUG_WATCH_WRITE)
> > +                                           gdbgr->dbcr0 |= wp_code[w];
> > +                                   gdbgr->dac[w] = dbg->arch.bp[n].addr;
> > +                                   w++;
> > +                           }
> > +                   } else if (type & KVMPPC_DEBUG_BREAKPOINT) {
> > +                           if (b < BP_NUM) {
> > +                                   gdbgr->dbcr0 |= bp_code[b];
> > +                                   gdbgr->iac[b] = dbg->arch.bp[n].addr;
> > +                                   b++;
> > +                           }
> > +                   }
> > +           }
> > +   }
> > +   return 0;
> > }
> 
> I'll stop reviewing here. This patch is way too big. Please split it up in
> smaller, understandable bits.
> 
> 
> Alex
> 
> >
> > int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu
> > *fpu) diff --git a/arch/powerpc/kvm/booke_interrupts.S
> > b/arch/powerpc/kvm/booke_interrupts.S
> > index dd9c5d4..734c549 100644
> > --- a/arch/powerpc/kvm/booke_interrupts.S
> > +++ b/arch/powerpc/kvm/booke_interrupts.S
> > @@ -39,6 +39,8 @@
> > #define HOST_MIN_STACK_SIZE (HOST_NV_GPR(R31) + 4) #define
> > HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
> > #define HOST_STACK_LR   (HOST_STACK_SIZE + 4) /* In caller stack frame. */
> > +#define DBCR0_AC_BITS      (DBCR0_IAC1 | DBCR0_IAC2 | DBCR0_IAC3 | 
> > DBCR0_IAC4 | \
> > +                    DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)
> >
> > #define NEED_INST_MASK ((1<<BOOKE_INTERRUPT_PROGRAM) | \
> >                         (1<<BOOKE_INTERRUPT_DTLB_MISS) | \ @@ -52,6
> > +54,8 @@
> >                        (1<<BOOKE_INTERRUPT_PROGRAM) | \
> >                        (1<<BOOKE_INTERRUPT_DTLB_MISS))
> >
> > +#define NEED_DEBUG_SAVE (1<<BOOKE_INTERRUPT_DEBUG)
> > +
> > .macro __KVM_HANDLER ivor_nr scratch srr0
> >     stw     r3, VCPU_GPR(R3)(r4)
> >     stw     r5, VCPU_GPR(R5)(r4)
> > @@ -212,6 +216,59 @@ _GLOBAL(kvmppc_resume_host)
> >     stw     r9, VCPU_FAULT_ESR(r4)
> > ..skip_esr:
> >
> > +   lwz     r9, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR0(r4)
> > +   rlwinm. r8, r9, 0, ~DBCR0_IDM
> > +   beq     skip_load_host_debug
> > +   lwz     r8, 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     r9, VCPU_HOST_DBG+KVMPPC_DBG_DBCR2(r4)
> > +   mtspr   SPRN_DBCR1, r7
> > +   mtspr   SPRN_DBCR2, r9
> > +   PPC_LD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC1, r4)
> > +   PPC_LD(r9, VCPU_HOST_DBG+KVMPPC_DBG_IAC2, r4)
> > +   mtspr   SPRN_IAC1, r7
> > +   mtspr   SPRN_IAC2, r9
> > +#if CONFIG_PPC_ADV_DEBUG_IACS > 2
> > +   PPC_LD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC3, r4)
> > +   PPC_LD(r9, VCPU_HOST_DBG+KVMPPC_DBG_IAC4, r4)
> > +   mtspr   SPRN_IAC3, r3
> > +   mtspr   SPRN_IAC4, r4
> > +#endif
> > +   PPC_LD(r7, VCPU_HOST_DBG+KVMPPC_DBG_DAC1, r4)
> > +   PPC_LD(r9, VCPU_HOST_DBG+KVMPPC_DBG_DAC2, r4)
> > +   mtspr   SPRN_DAC1, r7
> > +   mtspr   SPRN_DAC2, r9
> > +skip_load_hw_bkpts:
> > +   /* Clear h/w DBSR and save current(guest) DBSR */
> > +   mfspr   r9, SPRN_DBSR
> > +   mtspr   SPRN_DBSR, r9
> > +   isync
> > +   andi.   r7, r6, NEED_DEBUG_SAVE
> > +   beq     skip_dbsr_save
> > +   /*
> > +    * If vcpu->guest_debug flag is set then do not check for
> > +    * shared->msr.DE as this debugging (say by QEMU) does not
> > +    * depends on shared->msr.de. In these scanerios MSR.DE is
> > +    * always set using shared_msr and should be handled always.
> > +    */
> > +   lwz     r7, VCPU_GUEST_DEBUG(r4)
> > +   cmpwi   r7, 0
> > +   bne     skip_save_trap_event
> > +   PPC_LL  r3, VCPU_SHARED(r4)
> > +   PPC_LD(r3, VCPU_SHARED_MSR, r3)
> > +   andi.   r3, r3, MSR_DE
> > +   bne     skip_save_trap_event
> > +   andis.  r9, r9, DBSR_TIE@h
> > +skip_save_trap_event:
> > +   stw     r9, VCPU_DBSR(r4)
> > +skip_dbsr_save:
> > +   mtspr   SPRN_DBCR0, r8
> > +skip_load_host_debug:
> > +
> >     /* Save remaining volatile guest register state to vcpu. */
> >     stw     r0, VCPU_GPR(R0)(r4)
> >     stw     r1, VCPU_GPR(R1)(r4)
> > @@ -465,6 +522,63 @@ lightweight_exit:
> >     PPC_LD(r3, VCPU_SHARED_SPRG7, r5)
> >     mtspr   SPRN_SPRG7W, r3
> >
> > +   mfmsr   r7
> > +   rlwinm  r7, r7, 0, ~MSR_DE
> > +   mtmsr   r7
> > +   lwz     r6, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR0(r4)
> > +   rlwinm. r7, r6, 0, ~DBCR0_IDM
> > +   beq     skip_load_guest_debug
> > +   mfspr   r8, SPRN_DBCR0
> > +   stw     r8, VCPU_HOST_DBG+KVMPPC_DBG_DBCR0(r4)
> > +   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_IAC1
> > +   PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC1, r4)
> > +   mfspr   r8, SPRN_IAC2
> > +   PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_IAC2, r4) #if
> > +CONFIG_PPC_ADV_DEBUG_IACS > 2
> > +   mfspr   r7, SPRN_IAC3
> > +   PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_IAC3, r4)
> > +   mfspr   r8, SPRN_IAC4
> > +   PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_IAC4, r4) #endif
> > +   mfspr   r7, SPRN_DAC1
> > +   PPC_STD(r7, VCPU_HOST_DBG+KVMPPC_DBG_DAC1, r4)
> > +   mfspr   r8, SPRN_DAC2
> > +   PPC_STD(r8, VCPU_HOST_DBG+KVMPPC_DBG_DAC2, r4)
> > +   li      r8, 0
> > +   mtspr   SPRN_DBCR0, r8          /* disable all debug event */
> > +   PPC_LD(r7, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR1, r4)
> > +   PPC_LD(r8, VCPU_SHADOW_DBG+KVMPPC_DBG_DBCR2, r4)
> > +   mtspr   SPRN_DBCR1, r7
> > +   mtspr   SPRN_DBCR2, r8
> > +   PPC_LD(r7, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC1, r4)
> > +   PPC_LD(r8, VCPU_SHADOW_DBG+KVMPPC_DBG_IAC2, r4)
> > +   mtspr   SPRN_IAC1, r7
> > +   mtspr   SPRN_IAC2, r8
> > +#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:
> > +   /* Clear if any deferred debug event */
> > +   mfspr   r8, SPRN_DBSR
> > +   mtspr   SPRN_DBSR, r8
> > +   isync
> > +   /* Restore guest DBCR */
> > +   mtspr   SPRN_DBCR0, r6
> > +skip_load_guest_debug:
> > +
> > #ifdef CONFIG_KVM_EXIT_TIMING
> >     /* save enter time */
> > 1:
> > 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)
> > diff --git a/arch/powerpc/kvm/e500_emulate.c
> > b/arch/powerpc/kvm/e500_emulate.c index e78f353..ddb903e 100644
> > --- a/arch/powerpc/kvm/e500_emulate.c
> > +++ b/arch/powerpc/kvm/e500_emulate.c
> > @@ -26,6 +26,7 @@
> > #define XOP_TLBRE   946
> > #define XOP_TLBWE   978
> > #define XOP_TLBILX  18
> > +#define XOP_EHPRIV  270
> >
> > #ifdef CONFIG_KVM_E500MC
> > static int dbell2prio(ulong param)
> > @@ -130,6 +131,11 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct
> kvm_vcpu *vcpu,
> >                     emulated = kvmppc_e500_emul_tlbivax(vcpu, ea);
> >                     break;
> >
> > +           case XOP_EHPRIV:
> > +                   emulated = EMULATE_DEBUG_INST;
> > +                   *advance = 0;
> > +                   break;
> > +
> >             default:
> >                     emulated = EMULATE_FAIL;
> >             }
> > diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
> > index dead142..81abe92 100644
> > --- a/arch/powerpc/kvm/e500mc.c
> > +++ b/arch/powerpc/kvm/e500mc.c
> > @@ -182,8 +182,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
> > {
> >     struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
> >
> > -   vcpu->arch.shadow_epcr = SPRN_EPCR_DSIGS | SPRN_EPCR_DGTMI | \
> > -                            SPRN_EPCR_DUVD;
> > +   vcpu->arch.shadow_epcr = SPRN_EPCR_DSIGS | SPRN_EPCR_DGTMI;
> > #ifdef CONFIG_64BIT
> >     vcpu->arch.shadow_epcr |= SPRN_EPCR_ICM; #endif
> > --
> > 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
> 


--
To unsubscribe from this list: send the line "unsubscribe kvm" 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