From patchwork Wed Feb 3 07:53:53 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Liu Yu-B13201 X-Patchwork-Id: 76623 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1384AAZ027412 for ; Wed, 3 Feb 2010 08:04:11 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755336Ab0BCIEI (ORCPT ); Wed, 3 Feb 2010 03:04:08 -0500 Received: from az33egw02.freescale.net ([192.88.158.103]:40217 "EHLO az33egw02.freescale.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754923Ab0BCIED (ORCPT ); Wed, 3 Feb 2010 03:04:03 -0500 Received: from de01smr01.freescale.net (de01smr01.freescale.net [10.208.0.31]) by az33egw02.freescale.net (8.14.3/az33egw02) with ESMTP id o1383qld027726; Wed, 3 Feb 2010 01:03:52 -0700 (MST) Received: from zch01exm26.fsl.freescale.net (zch01exm26.ap.freescale.net [10.192.129.221]) by de01smr01.freescale.net (8.13.1/8.13.0) with ESMTP id o138AUem006115; Wed, 3 Feb 2010 02:10:31 -0600 (CST) Received: from localhost ([10.193.20.106]) by zch01exm26.fsl.freescale.net with Microsoft SMTPSVC(6.0.3790.3959); Wed, 3 Feb 2010 16:03:50 +0800 From: Liu Yu To: agraf@suse.de, hollis@penguinppc.org, kvm-ppc@vger.kernel.org Cc: kvm@vger.kernel.org, Liu Yu Subject: [PATCH 4/4] kvmppc/booke: exit_nr fixup for guest debug single step Date: Wed, 3 Feb 2010 15:53:53 +0800 Message-Id: <1265183633-2230-5-git-send-email-yu.liu@freescale.com> X-Mailer: git-send-email 1.6.4 In-Reply-To: <1265183633-2230-4-git-send-email-yu.liu@freescale.com> References: <1265183633-2230-1-git-send-email-yu.liu@freescale.com> <1265183633-2230-2-git-send-email-yu.liu@freescale.com> <1265183633-2230-3-git-send-email-yu.liu@freescale.com> <1265183633-2230-4-git-send-email-yu.liu@freescale.com> X-OriginalArrivalTime: 03 Feb 2010 08:03:50.0341 (UTC) FILETIME=[6B7E3F50:01CAA4A7] Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 03 Feb 2010 08:04:11 +0000 (UTC) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index ec2722d..9056708 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,8 @@ #include "booke.h" unsigned long kvmppc_booke_handlers; +unsigned long kvmppc_booke_handler_addr[16]; +#define handler_vector_num (sizeof(kvmppc_booke_handler_addr)/sizeof(kvmppc_booke_handler_addr[0])) #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU @@ -214,6 +217,80 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) } } +int kvmppc_read_guest(struct kvm_vcpu *vcpu, unsigned long geaddr, + void *data, int len) +{ + int gtlb_index; + gpa_t gpa; + gfn_t gfn; + struct page *page; + void *headdr, *from; + + /* Check the guest TLB. */ + gtlb_index = kvmppc_mmu_itlb_index(vcpu, geaddr); + if (gtlb_index < 0) + return -EFAULT; + + gpa = kvmppc_mmu_xlate(vcpu, gtlb_index, geaddr); + gfn = gpa >> PAGE_SHIFT; + + page = gfn_to_page(vcpu->kvm, gfn); + if (page == bad_page) + return -EFAULT; + + headdr = kmap_atomic(page, KM_USER0); + if (!headdr) + return -EFAULT; + from = headdr + (geaddr & (PAGE_SIZE - 1)); + memcpy(data, from, len); + kunmap_atomic(headdr, KM_USER0); + + return 0; +} + +static unsigned int kvmppc_guest_debug_exitnr_fixup(struct kvm_vcpu *vcpu, + unsigned int exit_nr) +{ + unsigned int ret = exit_nr; + + u32 csrr0 = mfspr(SPRN_CSRR0); + u32 dbsr = mfspr(SPRN_DBSR); + + if ((dbsr | DBSR_IC) && + csrr0 >= kvmppc_booke_handlers && + csrr0 < kvmppc_booke_handlers + (PAGE_SIZE << VCPU_SIZE_ORDER)) { + int i = 0; + + for (i = 0; i < handler_vector_num; i++) { + if (kvmppc_booke_handler_addr[i] && + csrr0 == kvmppc_booke_handler_addr[i] + 4) { + mtspr(SPRN_DBSR, ~0); + ret = i; + break; + } + } + + } + + switch (ret) { + case BOOKE_INTERRUPT_DEBUG: + case BOOKE_INTERRUPT_ITLB_MISS: + case BOOKE_INTERRUPT_EXTERNAL: + case BOOKE_INTERRUPT_DECREMENTER: + break; + + case BOOKE_INTERRUPT_PROGRAM: + case BOOKE_INTERRUPT_DTLB_MISS: + /* Need to save the last instruction */ + kvmppc_read_guest(vcpu, vcpu->arch.pc, &vcpu->arch.last_inst, 4); + break; + default: + printk("Unhandled debug after interrupt:%d\n", ret); + } + + return ret; +} + /** * kvmppc_handle_exit * @@ -233,6 +310,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, run->exit_reason = KVM_EXIT_UNKNOWN; run->ready_for_interrupt_injection = 1; + if (unlikely(exit_nr == BOOKE_INTERRUPT_DEBUG)) + exit_nr = kvmppc_guest_debug_exitnr_fixup(vcpu, exit_nr); + switch (exit_nr) { case BOOKE_INTERRUPT_MACHINE_CHECK: printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR)); @@ -686,6 +766,8 @@ int __init kvmppc_booke_init(void) memcpy((void *)kvmppc_booke_handlers + ivor[i], kvmppc_handlers_start + i * kvmppc_handler_len, kvmppc_handler_len); + kvmppc_booke_handler_addr[i] = + (unsigned long)kvmppc_booke_handlers + ivor[i]; } flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 644ff1d..fdc48c1 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -42,16 +42,17 @@ #define HOST_STACK_LR (HOST_STACK_SIZE + 4) /* In caller stack frame. */ #define NEED_INST_MASK ((1<