From patchwork Fri Jun 25 23:25:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 108179 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o5PNPhG9001598 for ; Fri, 25 Jun 2010 23:25:43 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756887Ab0FYXZk (ORCPT ); Fri, 25 Jun 2010 19:25:40 -0400 Received: from cantor2.suse.de ([195.135.220.15]:54791 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756710Ab0FYXZU (ORCPT ); Fri, 25 Jun 2010 19:25:20 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 0404D8A908; Sat, 26 Jun 2010 01:25:15 +0200 (CEST) From: Alexander Graf To: kvm-ppc@vger.kernel.org Cc: KVM list , linuxppc-dev Subject: [PATCH 14/26] KVM: PPC: Magic Page BookE support Date: Sat, 26 Jun 2010 01:25:02 +0200 Message-Id: <1277508314-915-15-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1277508314-915-1-git-send-email-agraf@suse.de> References: <1277508314-915-1-git-send-email-agraf@suse.de> 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]); Fri, 25 Jun 2010 23:25:43 +0000 (UTC) diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 2229df9..7957aa4 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -241,6 +241,31 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) vcpu->arch.shared->int_pending = 0; } +/* Check if a DTLB miss was on the magic page. Returns !0 if so. */ +int kvmppc_dtlb_magic_page(struct kvm_vcpu *vcpu, ulong eaddr) +{ + ulong mp_ea = vcpu->arch.magic_page_ea; + ulong gpaddr = vcpu->arch.magic_page_pa; + int gtlb_index = 11 | (1 << 16); /* Random number in TLB1 */ + + /* Check for existence of magic page */ + if(likely(!mp_ea)) + return 0; + + /* Check if we're on the magic page */ + if(likely((eaddr >> 12) != (mp_ea >> 12))) + return 0; + + /* Don't map in user mode */ + if(vcpu->arch.shared->msr & MSR_PR) + return 0; + + kvmppc_mmu_map(vcpu, vcpu->arch.magic_page_ea, gpaddr, gtlb_index); + kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); + + return 1; +} + /** * kvmppc_handle_exit * @@ -308,6 +333,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, r = RESUME_HOST; break; case EMULATE_FAIL: + case EMULATE_DO_MMIO: /* XXX Deliver Program interrupt to guest. */ printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", __func__, vcpu->arch.pc, vcpu->arch.last_inst); @@ -377,6 +403,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, gpa_t gpaddr; gfn_t gfn; + if (kvmppc_dtlb_magic_page(vcpu, eaddr)) + break; + /* Check the guest TLB. */ gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr); if (gtlb_index < 0) { diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index 66845a5..f5582ca 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c @@ -295,9 +295,22 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, struct page *new_page; struct tlbe *stlbe; hpa_t hpaddr; + u32 mas2 = gtlbe->mas2; + u32 mas3 = gtlbe->mas3; stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel]; + if ((vcpu_e500->vcpu.arch.magic_page_ea) && + ((vcpu_e500->vcpu.arch.magic_page_pa >> PAGE_SHIFT) == gfn) && + !(vcpu_e500->vcpu.arch.shared->msr & MSR_PR)) { + mas2 = 0; + mas3 = E500_TLB_SUPER_PERM_MASK; + hpaddr = virt_to_phys(vcpu_e500->vcpu.arch.shared); + new_page = pfn_to_page(hpaddr >> PAGE_SHIFT); + get_page(new_page); + goto mapped; + } + /* Get reference to new page. */ new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn); if (is_error_page(new_page)) { @@ -305,6 +318,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, kvm_release_page_clean(new_page); return; } + +mapped: hpaddr = page_to_phys(new_page); /* Drop reference to old page. */ @@ -316,10 +331,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K) | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID; stlbe->mas2 = (gvaddr & MAS2_EPN) - | e500_shadow_mas2_attrib(gtlbe->mas2, + | e500_shadow_mas2_attrib(mas2, vcpu_e500->vcpu.arch.shared->msr & MSR_PR); stlbe->mas3 = (hpaddr & MAS3_RPN) - | e500_shadow_mas3_attrib(gtlbe->mas3, + | e500_shadow_mas3_attrib(mas3, vcpu_e500->vcpu.arch.shared->msr & MSR_PR); stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN;