diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 392 |
1 files changed, 224 insertions, 168 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 9328ee6..7e62965 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -40,7 +40,9 @@ #include "timing.h" #include "booke.h" -#include "trace.h" + +#define CREATE_TRACE_POINTS +#include "trace_booke.h" unsigned long kvmppc_booke_handlers; @@ -676,53 +678,13 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu) return r; } -static void kvmppc_load_usespace_gebug(void) -{ - switch_booke_debug_regs(¤t->thread); -} - -static void kvmppc_booke_vcpu_load_debug_regs(struct kvm_vcpu *vcpu) -{ - if (!vcpu->arch.debug_active) - return; - - /* Disable all debug events and clead pending debug events */ - mtspr(SPRN_DBCR0, 0x0); - kvmppc_clear_dbsr(); - - /* - * Check whether guest still need debug resource, if not then there - * is no need to restore guest context. - */ - if (!vcpu->arch.shadow_dbg_reg.dbcr0) - return; - - /* Load Guest Context */ - mtspr(SPRN_DBCR1, vcpu->arch.shadow_dbg_reg.dbcr1); - mtspr(SPRN_DBCR2, vcpu->arch.shadow_dbg_reg.dbcr2); -#ifdef CONFIG_KVM_E500MC - mtspr(SPRN_DBCR4, vcpu->arch.shadow_dbg_reg.dbcr4); -#endif - mtspr(SPRN_IAC1, vcpu->arch.shadow_dbg_reg.iac[0]); - mtspr(SPRN_IAC2, vcpu->arch.shadow_dbg_reg.iac[1]); -#if CONFIG_PPC_ADV_DEBUG_IACS > 2 - mtspr(SPRN_IAC3, vcpu->arch.shadow_dbg_reg.iac[2]); - mtspr(SPRN_IAC4, vcpu->arch.shadow_dbg_reg.iac[3]); -#endif - mtspr(SPRN_DAC1, vcpu->arch.shadow_dbg_reg.dac[0]); - mtspr(SPRN_DAC2, vcpu->arch.shadow_dbg_reg.dac[1]); - - /* Enable debug events after other debug registers restored */ - mtspr(SPRN_DBCR0, vcpu->arch.shadow_dbg_reg.dbcr0); -} - int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) { int ret, s; + struct thread_struct thread; #ifdef CONFIG_PPC_FPU - unsigned int fpscr; + struct thread_fp_state fp; int fpexc_mode; - u64 fpr[32]; #endif #ifdef CONFIG_ALTIVEC @@ -742,18 +704,16 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) goto out; } - kvm_guest_enter(); - #ifdef CONFIG_PPC_FPU /* Save userspace FPU state in stack */ enable_kernel_fp(); - memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr)); - fpscr = current->thread.fpscr.val; + fp = current->thread.fp_state; fpexc_mode = current->thread.fpexc_mode; /* Restore guest FPU state to thread */ - memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr)); - current->thread.fpscr.val = vcpu->arch.fpscr; + memcpy(current->thread.fp_state.fpr, vcpu->arch.fpr, + sizeof(vcpu->arch.fpr)); + current->thread.fp_state.fpscr = vcpu->arch.fpscr; /* * Since we can't trap on MSR_FP in GS-mode, we consider the guest @@ -770,13 +730,15 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) if (cpu_has_feature(CPU_FTR_ALTIVEC)) { /* Save userspace VEC state in stack */ enable_kernel_altivec(); - memcpy(vr, current->thread.vr, sizeof(current->thread.vr)); - vscr = current->thread.vscr; + memcpy(vr, current->thread.vr_state.vr, + sizeof(current->thread.vr_state.vr)); + vscr = current->thread.vr_state.vscr; used_vr = current->thread.used_vr; /* Restore guest VEC state to thread */ - memcpy(current->thread.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); - current->thread.vscr = vcpu->arch.vscr; + memcpy(current->thread.vr_state.vr, vcpu->arch.vr, + sizeof(vcpu->arch.vr)); + current->thread.vr_state.vscr = vcpu->arch.vscr; vcpu->arch.vec_active = 1; @@ -784,14 +746,11 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) } #endif - /* - * Clear current->thread.dbcr0 so that kernel does not - * restore h/w registers on context switch in vcpu running state. - */ - vcpu->arch.debug_active = 1; - vcpu->arch.saved_dbcr0 = current->thread.dbcr0; - current->thread.dbcr0 = 0; - kvmppc_booke_vcpu_load_debug_regs(vcpu); + /* Switch to guest debug context */ + thread.debug = vcpu->arch.shadow_dbg_reg; + switch_booke_debug_regs(&thread); + thread.debug = current->thread.debug; + current->thread.debug = vcpu->arch.shadow_dbg_reg; kvmppc_fix_ee_before_entry(); @@ -800,10 +759,9 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) /* No need for kvm_guest_exit. It's done in handle_exit. We also get here with interrupts enabled. */ - /* Restore thread->dbcr0 */ - vcpu->arch.debug_active = 0; - current->thread.dbcr0 = vcpu->arch.saved_dbcr0; - kvmppc_load_usespace_gebug(); + /* Switch back to user space debug context */ + switch_booke_debug_regs(&thread); + current->thread.debug = thread.debug; #ifdef CONFIG_PPC_FPU kvmppc_save_guest_fp(vcpu); @@ -811,12 +769,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) vcpu->fpu_active = 0; /* Save guest FPU state from thread */ - memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr)); - vcpu->arch.fpscr = current->thread.fpscr.val; + memcpy(vcpu->arch.fpr, current->thread.fp_state.fpr, + sizeof(vcpu->arch.fpr)); + vcpu->arch.fpscr = current->thread.fp_state.fpscr; /* Restore userspace FPU state from stack */ - memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); - current->thread.fpscr.val = fpscr; + current->thread.fp_state = fp; current->thread.fpexc_mode = fpexc_mode; #endif @@ -827,12 +785,14 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) vcpu->arch.vec_active = 0; /* Save guest VEC state from thread */ - memcpy(vcpu->arch.vr, current->thread.vr, sizeof(vcpu->arch.vr)); - vcpu->arch.vscr = current->thread.vscr; + memcpy(vcpu->arch.vr, current->thread.vr_state.vr, + sizeof(vcpu->arch.vr)); + vcpu->arch.vscr = current->thread.vr_state.vscr; /* Restore userspace VEC state from stack */ - memcpy(current->thread.vr, vr, sizeof(current->thread.vr)); - current->thread.vscr = vscr; + memcpy(current->thread.vr_state.vr, vr, + sizeof(current->thread.vr_state.vr)); + current->thread.vr_state.vscr = vscr; current->thread.used_vr = used_vr; } #endif @@ -877,17 +837,11 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) } } -/* - * Currently we do not support debug resource emulation to guest, - * so always exit to user space irrespective of user space is - * expecting the debug exception or not. This is unexpected event - * and let us leave the action on user space. - */ static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu *vcpu) { - u32 dbsr = mfspr(SPRN_DBSR); + struct debug_reg *dbg_reg = &(vcpu->arch.shadow_dbg_reg); + u32 dbsr = vcpu->arch.dbsr; - kvmppc_clear_dbsr(); run->debug.arch.status = 0; run->debug.arch.address = vcpu->arch.pc; @@ -899,9 +853,9 @@ static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu *vcpu) 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]; + run->debug.arch.address = dbg_reg->dac1; else if (dbsr & (DBSR_DAC2R | DBSR_DAC2W)) - run->debug.arch.address = vcpu->arch.shadow_dbg_reg.dac[1]; + run->debug.arch.address = dbg_reg->dac2; } return RESUME_HOST; @@ -943,7 +897,7 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, kvmppc_fill_pt_regs(®s); timer_interrupt(®s); break; -#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_BOOK3E_64) +#if defined(CONFIG_PPC_DOORBELL) case BOOKE_INTERRUPT_DOORBELL: kvmppc_fill_pt_regs(®s); doorbell_exception(®s); @@ -967,6 +921,11 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, case BOOKE_INTERRUPT_CRITICAL: unknown_exception(®s); break; + case BOOKE_INTERRUPT_DEBUG: + /* Save DBSR before preemption is enabled */ + vcpu->arch.dbsr = mfspr(SPRN_DBSR); + kvmppc_clear_dbsr(); + break; } } @@ -1506,7 +1465,7 @@ static int set_sregs_arch206(struct kvm_vcpu *vcpu, return 0; } -void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) +int kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) { sregs->u.e.features |= KVM_SREGS_E_IVOR; @@ -1526,6 +1485,7 @@ void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) sregs->u.e.ivor_low[13] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; sregs->u.e.ivor_low[14] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; sregs->u.e.ivor_low[15] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; + return 0; } int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) @@ -1560,8 +1520,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, get_sregs_base(vcpu, sregs); get_sregs_arch206(vcpu, sregs); - kvmppc_core_get_sregs(vcpu, sregs); - return 0; + return vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs); } int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, @@ -1580,7 +1539,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, if (ret < 0) return ret; - return kvmppc_core_set_sregs(vcpu, sregs); + return vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs); } int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) @@ -1588,7 +1547,6 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) int r = 0; union kvmppc_one_reg val; int size; - long int i; size = one_reg_size(reg->id); if (size > sizeof(val)) @@ -1596,16 +1554,24 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) switch (reg->id) { case KVM_REG_PPC_IAC1: + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac1); + break; case KVM_REG_PPC_IAC2: + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac2); + break; +#if CONFIG_PPC_ADV_DEBUG_IACS > 2 case KVM_REG_PPC_IAC3: + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac3); + break; case KVM_REG_PPC_IAC4: - i = reg->id - KVM_REG_PPC_IAC1; - val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac[i]); + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac4); break; +#endif case KVM_REG_PPC_DAC1: + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac1); + break; case KVM_REG_PPC_DAC2: - i = reg->id - KVM_REG_PPC_DAC1; - val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac[i]); + val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2); break; case KVM_REG_PPC_EPR: { u32 epr = get_guest_epr(vcpu); @@ -1624,10 +1590,13 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) val = get_reg_val(reg->id, vcpu->arch.tsr); break; case KVM_REG_PPC_DEBUG_INST: - val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV); + val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV_DEBUG); + break; + case KVM_REG_PPC_VRSAVE: + val = get_reg_val(reg->id, vcpu->arch.vrsave); break; default: - r = kvmppc_get_one_reg(vcpu, reg->id, &val); + r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, reg->id, &val); break; } @@ -1645,7 +1614,6 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) int r = 0; union kvmppc_one_reg val; int size; - long int i; size = one_reg_size(reg->id); if (size > sizeof(val)) @@ -1656,16 +1624,24 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) switch (reg->id) { case KVM_REG_PPC_IAC1: + vcpu->arch.dbg_reg.iac1 = set_reg_val(reg->id, val); + break; case KVM_REG_PPC_IAC2: + vcpu->arch.dbg_reg.iac2 = set_reg_val(reg->id, val); + break; +#if CONFIG_PPC_ADV_DEBUG_IACS > 2 case KVM_REG_PPC_IAC3: + vcpu->arch.dbg_reg.iac3 = set_reg_val(reg->id, val); + break; case KVM_REG_PPC_IAC4: - i = reg->id - KVM_REG_PPC_IAC1; - vcpu->arch.dbg_reg.iac[i] = set_reg_val(reg->id, val); + vcpu->arch.dbg_reg.iac4 = set_reg_val(reg->id, val); break; +#endif case KVM_REG_PPC_DAC1: + vcpu->arch.dbg_reg.dac1 = set_reg_val(reg->id, val); + break; case KVM_REG_PPC_DAC2: - i = reg->id - KVM_REG_PPC_DAC1; - vcpu->arch.dbg_reg.dac[i] = set_reg_val(reg->id, val); + vcpu->arch.dbg_reg.dac2 = set_reg_val(reg->id, val); break; case KVM_REG_PPC_EPR: { u32 new_epr = set_reg_val(reg->id, val); @@ -1699,8 +1675,11 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) kvmppc_set_tcr(vcpu, tcr); break; } + case KVM_REG_PPC_VRSAVE: + vcpu->arch.vrsave = set_reg_val(reg->id, val); + break; default: - r = kvmppc_set_one_reg(vcpu, reg->id, &val); + r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, reg->id, &val); break; } @@ -1731,12 +1710,12 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) return -ENOTSUPP; } -void kvmppc_core_free_memslot(struct kvm_memory_slot *free, +void kvmppc_core_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, struct kvm_memory_slot *dont) { } -int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, +int kvmppc_core_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, unsigned long npages) { return 0; @@ -1812,53 +1791,98 @@ void kvmppc_decrementer_func(unsigned long data) kvmppc_set_tsr_bits(vcpu, TSR_DIS); } -static void kvmppc_booke_vcpu_put_debug_regs(struct kvm_vcpu *vcpu) +static int kvmppc_booke_add_breakpoint(struct debug_reg *dbg_reg, + uint64_t addr, int index) { - /* Disable all debug events First */ - mtspr(SPRN_DBCR0, 0x0); - /* Disable pending debug event by clearing DBSR */ - kvmppc_clear_dbsr(); + switch (index) { + case 0: + dbg_reg->dbcr0 |= DBCR0_IAC1; + dbg_reg->iac1 = addr; + break; + case 1: + dbg_reg->dbcr0 |= DBCR0_IAC2; + dbg_reg->iac2 = addr; + break; +#if CONFIG_PPC_ADV_DEBUG_IACS > 2 + case 2: + dbg_reg->dbcr0 |= DBCR0_IAC3; + dbg_reg->iac3 = addr; + break; + case 3: + dbg_reg->dbcr0 |= DBCR0_IAC4; + dbg_reg->iac4 = addr; + break; +#endif + default: + return -EINVAL; + } + + dbg_reg->dbcr0 |= DBCR0_IDM; + return 0; +} + +static int kvmppc_booke_add_watchpoint(struct debug_reg *dbg_reg, uint64_t addr, + int type, int index) +{ + switch (index) { + case 0: + if (type & KVMPPC_DEBUG_WATCH_READ) + dbg_reg->dbcr0 |= DBCR0_DAC1R; + if (type & KVMPPC_DEBUG_WATCH_WRITE) + dbg_reg->dbcr0 |= DBCR0_DAC1W; + dbg_reg->dac1 = addr; + break; + case 1: + if (type & KVMPPC_DEBUG_WATCH_READ) + dbg_reg->dbcr0 |= DBCR0_DAC2R; + if (type & KVMPPC_DEBUG_WATCH_WRITE) + dbg_reg->dbcr0 |= DBCR0_DAC2W; + dbg_reg->dac2 = addr; + break; + default: + return -EINVAL; + } + + dbg_reg->dbcr0 |= DBCR0_IDM; + return 0; +} +void kvm_guest_protect_msr(struct kvm_vcpu *vcpu, ulong prot_bitmap, bool set) +{ + /* XXX: Add similar MSR protection for BookE-PR */ +#ifdef CONFIG_KVM_BOOKE_HV + BUG_ON(prot_bitmap & ~(MSRP_UCLEP | MSRP_DEP | MSRP_PMMP)); + if (set) { + if (prot_bitmap & MSR_UCLE) + vcpu->arch.shadow_msrp |= MSRP_UCLEP; + if (prot_bitmap & MSR_DE) + vcpu->arch.shadow_msrp |= MSRP_DEP; + if (prot_bitmap & MSR_PMM) + vcpu->arch.shadow_msrp |= MSRP_PMMP; + } else { + if (prot_bitmap & MSR_UCLE) + vcpu->arch.shadow_msrp &= ~MSRP_UCLEP; + if (prot_bitmap & MSR_DE) + vcpu->arch.shadow_msrp &= ~MSRP_DEP; + if (prot_bitmap & MSR_PMM) + vcpu->arch.shadow_msrp &= ~MSRP_PMMP; + } +#endif } int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg) { - struct kvmppc_booke_debug_reg *dbg_reg; + struct debug_reg *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 - }; if (!(dbg->control & KVM_GUESTDBG_ENABLE)) { - /* Clear All debug events */ vcpu->arch.shadow_dbg_reg.dbcr0 = 0; vcpu->guest_debug = 0; -#ifdef CONFIG_KVM_BOOKE_HV - /* - * When user space is not using the debug resources - * then allow guest to change the MSR.DE. - */ - vcpu->arch.shadow_msrp &= ~MSRP_DEP; -#endif + kvm_guest_protect_msr(vcpu, MSR_DE, false); return 0; } -#ifdef CONFIG_KVM_BOOKE_HV - /* - * When user space is using the debug resource then - * do not allow guest to change the MSR.DE. - */ - vcpu->arch.shadow_msrp &= ~MSRP_DEP; -#endif + kvm_guest_protect_msr(vcpu, MSR_DE, true); vcpu->guest_debug = dbg->control; vcpu->arch.shadow_dbg_reg.dbcr0 = 0; /* Set DBCR0_EDM in guest visible DBCR0 register. */ @@ -1867,53 +1891,51 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, 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)) - /* Code below handles only HW breakpoints */ - return 0; - + /* Code below handles only HW breakpoints */ dbg_reg = &(vcpu->arch.shadow_dbg_reg); +#ifdef CONFIG_KVM_BOOKE_HV /* - * On BOOKE (e500v2); Set DBCR1 and DBCR2 to allow debug events - * to occur when MSR.PR is set. - * On BOOKE-HV (e500mc+); MSR.PR = 0 when guest is running. So we - * should clear DBCR1 and DBCR2. And EPCR.DUVD is used to control - * that debug events will not come in hypervisor (GS = 0). + * On BookE-HV (e500mc) the guest is always executed with MSR.GS=1 + * DBCR1 and DBCR2 are set to trigger debug events when MSR.PR is 0 */ -#ifdef CONFIG_KVM_BOOKE_HV dbg_reg->dbcr1 = 0; dbg_reg->dbcr2 = 0; #else + /* + * On BookE-PR (e500v2) the guest is always executed with MSR.PR=1 + * We set DBCR1 and DBCR2 to only trigger debug events when MSR.PR + * is set. + */ dbg_reg->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | DBCR1_IAC3US | DBCR1_IAC4US; dbg_reg->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; #endif + if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) + return 0; + for (n = 0; n < (KVMPPC_BOOKE_IAC_NUM + KVMPPC_BOOKE_DAC_NUM); n++) { - u32 type = dbg->arch.bp[n].type; + uint64_t addr = dbg->arch.bp[n].addr; + uint32_t type = dbg->arch.bp[n].type; - if (!type) + if (type == KVMPPC_DEBUG_NONE) continue; - if (type & (KVMPPC_DEBUG_WATCH_READ | - KVMPPC_DEBUG_WATCH_WRITE)) { - if (w >= KVMPPC_BOOKE_DAC_NUM) - return -EINVAL; - - if (type & KVMPPC_DEBUG_WATCH_READ) - dbg_reg->dbcr0 |= wp_code[w + 2]; - if (type & KVMPPC_DEBUG_WATCH_WRITE) - dbg_reg->dbcr0 |= wp_code[w]; + if (type & !(KVMPPC_DEBUG_WATCH_READ | + KVMPPC_DEBUG_WATCH_WRITE | + KVMPPC_DEBUG_BREAKPOINT)) + return -EINVAL; - dbg_reg->dac[w] = dbg->arch.bp[n].addr; - w++; - } else if (type & KVMPPC_DEBUG_BREAKPOINT) { - if (b >= KVMPPC_BOOKE_IAC_NUM) + if (type & KVMPPC_DEBUG_BREAKPOINT) { + /* Setting H/W breakpoint */ + if (kvmppc_booke_add_breakpoint(dbg_reg, addr, b++)) + return -EINVAL; + } else { + /* Setting H/W watchpoint */ + if (kvmppc_booke_add_watchpoint(dbg_reg, addr, + type, w++)) return -EINVAL; - - dbg_reg->dbcr0 |= bp_code[b]; - dbg_reg->iac[b] = dbg->arch.bp[n].addr; - b++; } } @@ -1924,8 +1946,6 @@ void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { vcpu->cpu = smp_processor_id(); current->thread.kvm_vcpu = vcpu; - - kvmppc_booke_vcpu_load_debug_regs(vcpu); } void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu) @@ -1933,7 +1953,43 @@ void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu) current->thread.kvm_vcpu = NULL; vcpu->cpu = -1; - kvmppc_booke_vcpu_put_debug_regs(vcpu); + /* Clear pending debug event in DBSR */ + kvmppc_clear_dbsr(); +} + +void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) +{ + vcpu->kvm->arch.kvm_ops->mmu_destroy(vcpu); +} + +int kvmppc_core_init_vm(struct kvm *kvm) +{ + return kvm->arch.kvm_ops->init_vm(kvm); +} + +struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) +{ + return kvm->arch.kvm_ops->vcpu_create(kvm, id); +} + +void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) +{ + vcpu->kvm->arch.kvm_ops->vcpu_free(vcpu); +} + +void kvmppc_core_destroy_vm(struct kvm *kvm) +{ + kvm->arch.kvm_ops->destroy_vm(kvm); +} + +void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ + vcpu->kvm->arch.kvm_ops->vcpu_load(vcpu, cpu); +} + +void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) +{ + vcpu->kvm->arch.kvm_ops->vcpu_put(vcpu); } int __init kvmppc_booke_init(void) |