From patchwork Tue Apr 20 00:49:48 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 93585 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 o3K0o5FE011494 for ; Tue, 20 Apr 2010 00:50:05 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752790Ab0DTAt7 (ORCPT ); Mon, 19 Apr 2010 20:49:59 -0400 Received: from cantor2.suse.de ([195.135.220.15]:42257 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752070Ab0DTAtz (ORCPT ); Mon, 19 Apr 2010 20:49:55 -0400 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id B36A086A2E; Tue, 20 Apr 2010 02:49:54 +0200 (CEST) From: Alexander Graf To: kvm-ppc@vger.kernel.org Cc: kvm@vger.kernel.org Subject: [PATCH 3/9] KVM: PPC: Improve split mode Date: Tue, 20 Apr 2010 02:49:48 +0200 Message-Id: <1271724594-6223-4-git-send-email-agraf@suse.de> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1271724594-6223-1-git-send-email-agraf@suse.de> References: <1271724594-6223-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]); Tue, 20 Apr 2010 00:50:05 +0000 (UTC) diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index 5d3bd0c..6f74d93 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h @@ -100,11 +100,10 @@ struct kvmppc_vcpu_book3s { #define CONTEXT_GUEST 1 #define CONTEXT_GUEST_END 2 -#define VSID_REAL_DR 0x7ffffffffff00000ULL -#define VSID_REAL_IR 0x7fffffffffe00000ULL -#define VSID_SPLIT_MASK 0x7fffffffffe00000ULL -#define VSID_REAL 0x7fffffffffc00000ULL -#define VSID_BAT 0x7fffffffffb00000ULL +#define VSID_REAL 0x1fffffffffc00000ULL +#define VSID_BAT 0x1fffffffffb00000ULL +#define VSID_REAL_DR 0x2000000000000000ULL +#define VSID_REAL_IR 0x4000000000000000ULL #define VSID_PR 0x8000000000000000ULL extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask); diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index a03163b..91dc42d 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -147,16 +147,8 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) } } - if (((vcpu->arch.msr & (MSR_IR|MSR_DR)) != (old_msr & (MSR_IR|MSR_DR))) || - (vcpu->arch.msr & MSR_PR) != (old_msr & MSR_PR)) { - bool dr = (vcpu->arch.msr & MSR_DR) ? true : false; - bool ir = (vcpu->arch.msr & MSR_IR) ? true : false; - - /* Flush split mode PTEs */ - if (dr != ir) - kvmppc_mmu_pte_vflush(vcpu, VSID_SPLIT_MASK, - VSID_SPLIT_MASK); - + if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) != + (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { kvmppc_mmu_flush_segments(vcpu); kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); } @@ -534,6 +526,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, bool is_mmio = false; bool dr = (vcpu->arch.msr & MSR_DR) ? true : false; bool ir = (vcpu->arch.msr & MSR_IR) ? true : false; + u64 vsid; relocated = data ? dr : ir; @@ -551,13 +544,20 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { case 0: - pte.vpage |= VSID_REAL; + pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); break; case MSR_DR: - pte.vpage |= VSID_REAL_DR; - break; case MSR_IR: - pte.vpage |= VSID_REAL_IR; + vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); + + if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) == MSR_DR) + pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12)); + else + pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12)); + pte.vpage |= vsid; + + if (vsid == -1) + page_found = -EINVAL; break; } diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c index 33186b7..0b10503 100644 --- a/arch/powerpc/kvm/book3s_32_mmu.c +++ b/arch/powerpc/kvm/book3s_32_mmu.c @@ -330,30 +330,35 @@ static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool lar static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid) { + ulong ea = esid << SID_SHIFT; + struct kvmppc_sr *sr; + u64 gvsid = esid; + + if (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + sr = find_sr(to_book3s(vcpu), ea); + if (sr->valid) + gvsid = sr->vsid; + } + /* In case we only have one of MSR_IR or MSR_DR set, let's put that in the real-mode context (and hope RM doesn't access high memory) */ switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { case 0: - *vsid = (VSID_REAL >> 16) | esid; + *vsid = VSID_REAL | esid; break; case MSR_IR: - *vsid = (VSID_REAL_IR >> 16) | esid; + *vsid = VSID_REAL_IR | gvsid; break; case MSR_DR: - *vsid = (VSID_REAL_DR >> 16) | esid; + *vsid = VSID_REAL_DR | gvsid; break; case MSR_DR|MSR_IR: - { - ulong ea = esid << SID_SHIFT; - struct kvmppc_sr *sr = find_sr(to_book3s(vcpu), ea); - if (!sr->valid) return -1; *vsid = sr->vsid; break; - } default: BUG(); } diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index a9241e9..612de6e 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c @@ -442,29 +442,32 @@ static void kvmppc_mmu_book3s_64_tlbie(struct kvm_vcpu *vcpu, ulong va, static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid) { + ulong ea = esid << SID_SHIFT; + struct kvmppc_slb *slb; + u64 gvsid = esid; + + if (vcpu->arch.msr & (MSR_DR|MSR_IR)) { + slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); + if (slb) + gvsid = slb->vsid; + } + switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { case 0: - *vsid = (VSID_REAL >> 16) | esid; + *vsid = VSID_REAL | esid; break; case MSR_IR: - *vsid = (VSID_REAL_IR >> 16) | esid; + *vsid = VSID_REAL_IR | gvsid; break; case MSR_DR: - *vsid = (VSID_REAL_DR >> 16) | esid; + *vsid = VSID_REAL_DR | gvsid; break; case MSR_DR|MSR_IR: - { - ulong ea; - struct kvmppc_slb *slb; - ea = esid << SID_SHIFT; - slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); - if (slb) - *vsid = slb->vsid; - else + if (!slb) return -ENOENT; + *vsid = gvsid; break; - } default: BUG(); break;