On 04.10.2012, at 16:22, Bhushan Bharat-R65777 wrote:

> 
> 
>> -----Original Message-----
>> From: Alexander Graf [mailto:ag...@suse.de]
>> Sent: Thursday, October 04, 2012 4:56 PM
>> To: Bhushan Bharat-R65777
>> Cc: kvm-...@vger.kernel.org; kvm@vger.kernel.org
>> Subject: Re: [PATCH 6/6] KVM: booke/bookehv: Add debug stub support
>> 
>> 
>> On 04.10.2012, at 13:06, Bhushan Bharat-R65777 wrote:
>> 
>>> 
>>> 
>>>> -----Original Message-----
>>>> From: Alexander Graf [mailto:ag...@suse.de]
>>>> Sent: Monday, September 24, 2012 9:50 PM
>>>> To: Bhushan Bharat-R65777
>>>> Cc: kvm-...@vger.kernel.org; kvm@vger.kernel.org; Bhushan
>>>> Bharat-R65777
>>>> Subject: Re: [PATCH 6/6] KVM: booke/bookehv: Add debug stub support
>>>> 
>>>> 
>>>> On 21.08.2012, at 15:52, 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.h        |   29 ++++++-
>>>>> arch/powerpc/include/asm/kvm_host.h   |    5 +
>>>>> arch/powerpc/kernel/asm-offsets.c     |   26 ++++++
>>>>> arch/powerpc/kvm/booke.c              |  144 
>>>>> +++++++++++++++++++++++++++++--
>> --
>>>>> arch/powerpc/kvm/booke_interrupts.S   |  110 +++++++++++++++++++++++++
>>>>> arch/powerpc/kvm/bookehv_interrupts.S |  141
>> +++++++++++++++++++++++++++++++-
>>>>> arch/powerpc/kvm/e500mc.c             |    3 +-
>>>>> 7 files changed, 435 insertions(+), 23 deletions(-)
>>>>> 
>>>>> diff --git a/arch/powerpc/include/asm/kvm.h
>>>>> b/arch/powerpc/include/asm/kvm.h index 61b197e..53479ea 100644
>>>>> --- a/arch/powerpc/include/asm/kvm.h
>>>>> +++ b/arch/powerpc/include/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;
>>>>> @@ -264,7 +265,31 @@ 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 pc;
>>>>> + /*
>>>>> +  * exception -> returns the exception number. If the KVM_DEBUG_EXIT
>>>>> +  * exit is not handled (say not h/w breakpoint or software breakpoint
>>>>> +  * set for this address) by qemu then it is supposed to inject this
>>>>> +  * exception to guest.
>>>>> +  */
>>>>> + __u32 exception;
>>>>> + /*
>>>>> +  * exiting to userspace because of h/w breakpoint, watchpoint
>>>>> +  * (read, write or both) and software breakpoint.
>>>>> +  */
>>>>> + __u32 status;
>>>>> };
>>>>> 
>>>>> /* for KVM_SET_GUEST_DEBUG */
>>>>> @@ -276,10 +301,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 pad1;
>>>>>           __u64 pad2;
>>>>> diff --git a/arch/powerpc/include/asm/kvm_host.h
>>>> b/arch/powerpc/include/asm/kvm_host.h
>>>>> index c7219c1..3ba465a 100644
>>>>> --- a/arch/powerpc/include/asm/kvm_host.h
>>>>> +++ b/arch/powerpc/include/asm/kvm_host.h
>>>>> @@ -496,7 +496,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/kernel/asm-offsets.c
>>>>> b/arch/powerpc/kernel/asm-
>>>> offsets.c
>>>>> index 555448e..6987821 100644
>>>>> --- a/arch/powerpc/kernel/asm-offsets.c
>>>>> +++ b/arch/powerpc/kernel/asm-offsets.c
>>>>> @@ -564,6 +564,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 dd0e5b8..4d82e34 100644
>>>>> --- a/arch/powerpc/kvm/booke.c
>>>>> +++ b/arch/powerpc/kvm/booke.c
>>>>> @@ -132,6 +132,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;
>>>>> @@ -667,10 +670,21 @@ 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;
>>>>> 
>>>>> + if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) &&
>>>>> +              vcpu->arch.last_inst == KVMPPC_INST_GUEST_GDB) {
>>>> 
>>>> This belongs into the normal emulation code path, behind the same
>>>> switch() that everything else goes through.
>>> 
>>> I am not sure I understood correctly. Below is the reason why I placed this
>> code here.
>>> Instruction where software breakpoint is to be set is replaced by "ehpriv"
>> instruction. On e500v2, this is not a valid instruction can causes program
>> interrupt. On e500mc, "ehpriv" is a valid instruction. Both the exit path 
>> calls
>> emulation_exit(), so we have placed the code in this function.
>>> Do you want this code to be moved in program interrupt exit path for e500v2
>> and BOOKE_INTERRUPT_HV_PRIV for e500mc?
>> 
>> Ok, in this patch you do (basically):
>> 
>> int emulation_exit()
>> {
>>    if (inst == DEBUG_INST) {
>>        debug_stuff();
>>        return;
>>    }
>> 
>>    switch (inst) {
>>        case INST_A:
>>            foo();
>>        ....
>>    }
>> }
> 
> Are not we doing something like this:
> int emulation_exit()
> {
>     if (inst == DEBUG_INST) {
>         debug_stuff();
>         return;
>     }
> 
>     status = kvmppc_emulate_instruction()
>     switch (status) {
>         case FAIL:
>             foo();
>         case DONE:
>               foo1();
>         ....
>     }
> }
> 
> Do you want something like this:
> 
> int emulation_exit()
> {
> 
>     status = kvmppc_emulate_instruction()
>     switch (status) {
>         case FAIL:
>               if (inst == DEBUG_INST) {
>                       debug_stuff();
>                     return;
>               }
>             foo();
> 
>         case DONE:
>               foo1();
>         ....
>     }
> }

No, I want the DEBUG_INST be handled the same as any other instruction we 
emulate.

>> 
>> what I want is:
>> 
>> int emulation_exit()
>> {
>>    switch (inst) {
>>        case INST_A:
>>            foo(); break;
>>        case DEBUG_INST:
>>            debug_stuff(); break;
>>        ....
>>    }
>> }
>> 
>>> 
>>> 
>>>> 
>>>>> +         run->exit_reason = KVM_EXIT_DEBUG;
>>>>> +         run->debug.arch.pc = vcpu->arch.pc;
>>>>> +         run->debug.arch.exception = exit_nr;
>>>>> +         run->debug.arch.status = 0;
>>>>> +         kvmppc_account_exit(vcpu, DEBUG_EXITS);
>>>>> +         return RESUME_HOST;
>>>>> + }
>>>>> +
>>>>>   er = kvmppc_emulate_instruction(run, vcpu);
>>>>>   switch (er) {
>>>>>   case EMULATE_DONE:
>>>>> @@ -697,6 +711,44 @@ static int emulation_exit(struct kvm_run *run,
>>>>> struct
>>>> kvm_vcpu *vcpu)
>>>>>   default:
>>>>>           BUG();
>>>>>   }
>>>>> +
>>>>> + if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_ENABLE) &&
>>>>> +     (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)) {
>>>> 
>>>> I don't understand how this is supposed to work. When we enable
>>>> singlestep, why would we end up in emulation_exit()?
>>> 
>>> When singlestep is enabled then we set DBCR0[ICMP] and the debug handler
>> should be able to handle this. I think you are right.
>>> 
>>>> 
>>>>> +         run->exit_reason = KVM_EXIT_DEBUG;
>>>>> +         return RESUME_HOST;
>>>>> + }
>>>>> +}
>>>>> +
>>>>> +static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu
>>>>> +*vcpu) {
>>>>> + u32 dbsr;
>>>>> +
>>>>> +#ifndef CONFIG_KVM_BOOKE_HV
>>>>> + if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
>>>>> +         vcpu->arch.pc = mfspr(SPRN_DSRR0);
>>>>> + else
>>>>> +         vcpu->arch.pc = mfspr(SPRN_CSRR0); #endif
>>>> 
>>>> Why doesn't this get handled in the asm code that recovers from the
>>>> respective exceptions?
>>> 
>>> Yes. I will remove this.
>>> 
>>>> 
>>>>> + dbsr = vcpu->arch.dbsr;
>>>>> +
>>>>> + run->debug.arch.pc = vcpu->arch.pc;
>>>>> + run->debug.arch.status = 0;
>>>>> + vcpu->arch.dbsr = 0;
>>>>> +
>>>>> + 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.pc = vcpu->arch.shadow_dbg_reg.dac[0];
>>>>> +         else if (dbsr & (DBSR_DAC2R | DBSR_DAC2W))
>>>>> +                 run->debug.arch.pc = vcpu->arch.shadow_dbg_reg.dac[1];
>>>>> + }
>>>> 
>>>> Mind to explain the guest register sharing mechanism you are
>>>> envisioning? Which registers are used by the guest? Which are used by
>>>> the host? Who decides what gets used by whom?
>>> 
>>> struct kvm_vcpu_arch {
>>>     .
>>>     .
>>> 
>>>      /* 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;
>>> 
>>>     .
>>>     .
>>> }
>>> 
>>> dbg_reg: contains the values written by guest.
>>> shadow_dbg_reg: This contains the actual values to be written on behalf of
>> guest/qemu.
>>> host_dbg_reg: the debug register value of host (needed for store/retore
>> purpose).
>>> 
>>> According to current design both, the qemu debug stub and guest, cannot 
>>> share
>> the debug resources. QEMU debug stub is given priority.
>>> But host and guest can share all debug registers and host cannot debug guest
>> if it is using the debug resource (which probably does not look like a good
>> case).
>> 
>> Ok. Assume that in guest context, we only ever want guest debugging enabled. 
>> If
>> QEMU wants to inject a QEMU breakpoint, it will fiddle with the guest debug
>> registers itself to inject its breakpoint into them.
> 
> I would like to understand the context you are describing.
> QEMU would like to inject debug interrupt to guest only if a debug interrupt 
> happened in guest context and QEMU is not able to handle interrupt (because 
> qemu debug have not set). Right?

Yes

> In that case the only thing that needed to be updated is guest->DBSR?

I think you lost me here :)

> 
>> 
>> With that scheme, would we still need shadow debug registers? Or could we 
>> remove
>> that one level of indirection?
>> 
>>> 
>>>> 
>>>>> +
>>>>> + return RESUME_HOST;
>>>>> }
>>>>> 
>>>>> static void kvmppc_fill_pt_regs(struct pt_regs *regs) @@ -843,7
>>>>> +895,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:
>>>>> @@ -862,7 +914,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:
>>>>> @@ -1052,18 +1104,12 @@ 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->debug.arch.exception = exit_nr;
>>>>> +                 run->exit_reason = KVM_EXIT_DEBUG;
>>>>> +         }
>>>>>           kvmppc_account_exit(vcpu, DEBUG_EXITS);
>>>>> -         r = RESUME_HOST;
>>>>>           break;
>>>>>   }
>>>>> 
>>>>> @@ -1403,10 +1449,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..2202936 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,61 @@ _GLOBAL(kvmppc_resume_host)
>>>>>   stw     r9, VCPU_FAULT_ESR(r4)
>>>>> ..skip_esr:
>>>>> 
>>>>> + addi    r7, r4, VCPU_HOST_DBG
>>>>> + mfspr   r9, SPRN_DBCR0
>>>>> + lwz     r8, KVMPPC_DBG_DBCR0(r7)
>>>>> + andis.  r9, r9, DBCR0_AC_BITS@h
>>>>> + beq     skip_load_host_debug
>>>>> + li      r9, 0
>>>>> + mtspr   SPRN_DBCR0, r9          /* disable all debug event */
>>>>> + lwz     r9, KVMPPC_DBG_DBCR1(r7)
>>>>> + mtspr   SPRN_DBCR1, r9
>>>>> + lwz     r9, KVMPPC_DBG_DBCR2(r7)
>>>>> + mtspr   SPRN_DBCR2, r9
>>>>> + lwz     r9, KVMPPC_DBG_IAC1+4(r7)
>>>>> + mtspr   SPRN_IAC1, r9
>>>>> + lwz     r9, KVMPPC_DBG_IAC2+4(r7)
>>>>> + mtspr   SPRN_IAC2, r9
>>>>> +#if CONFIG_PPC_ADV_DEBUG_IACS > 2
>>>>> + lwz     r9, KVMPPC_DBG_IAC3+4(r7)
>>>>> + mtspr   SPRN_IAC3, r9
>>>>> + lwz     r9, KVMPPC_DBG_IAC4+4(r7)
>>>>> + mtspr   SPRN_IAC4, r9
>>>>> +#endif
>>>>> + lwz     r9, KVMPPC_DBG_DAC1+4(r7)
>>>>> + mtspr   SPRN_DAC1, r9
>>>>> + lwz     r9, KVMPPC_DBG_DAC2+4(r7)
>>>> 
>>>> Yikes. Please move this into a struct, similar to how the MSR
>>>> save/restore happens on x86.
>>>> 
>>>> Also, these are 64-bit loads and stores, no?
>>> 
>>> Ok, you mean PPC_LD/STD?
>> 
>> Yeah :).
>> 
>>> 
>>>> 
>>>>> + mtspr   SPRN_DAC2, r9
>>>>> +skip_load_host_debug:
>>>>> + /* 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)
>>>>> +#ifndef CONFIG_64BIT
>>>>> + lwz     r3, (VCPU_SHARED_MSR + 4)(r3)
>>>>> +#else
>>>>> + ld      r3, (VCPU_SHARED_MSR)(r3)
>>>>> +#endif
>>>> 
>>>> Didn't we have 64-bit access helpers for these?
>>> 
>>> I will use PPC_LD.
>>> 
>>>> 
>>>> Also this shouldn't happen in the entry/exit code. We have shadow_msr
>>>> for these purposes.
>>> 
>>> Based on shared_msr.MSR_DE, we set make DBSR (set DBSR_TIE).
>> 
>> Hrm. Yeah, must've misread something here.
>> 
>> It would be awesome if we could make the debug register save/restore a bit 
>> more
>> relaxed though. For example during preemption.
> 
> If we delay this save/restore then host cannot do debugging of KVM code. 
> Right?

You mean using kdb? Does anyone actually do that?

But let's leave this for later as an optimization.


Alex

--
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