diff mbox

[7/8] KVM: PPC: booke/bookehv: Add debug stub support

Message ID 1358324685-30225-6-git-send-email-bharat.bhushan@freescale.com
State New, archived
Headers show

Commit Message

Bharat Bhushan Jan. 16, 2013, 8:24 a.m. UTC
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.bhushan@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(-)

Comments

Alexander Graf Jan. 25, 2013, 12:07 p.m. UTC | #1
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.bhushan@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?

> };
> 
> 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 majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bharat Bhushan Feb. 1, 2013, 6:31 a.m. UTC | #2
> -----Original Message-----
> From: Alexander Graf [mailto:agraf@suse.de]
> Sent: Friday, January 25, 2013 5:37 PM
> To: Bhushan Bharat-R65777
> Cc: kvm-ppc@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.bhushan@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 majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf Feb. 1, 2013, 8:21 a.m. UTC | #3
On 01.02.2013, at 07:31, Bhushan Bharat-R65777 wrote:

> 
> 
>> -----Original Message-----
>> From: Alexander Graf [mailto:agraf@suse.de]
>> Sent: Friday, January 25, 2013 5:37 PM
>> To: Bhushan Bharat-R65777
>> Cc: kvm-ppc@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.bhushan@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.

Yeah, please check that it actually does the right thing still for PAPR exits then :).


Alex

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

Patch

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 */
 };
 
 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)
 {
 	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
+		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;
 }
 
 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