aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/44x.c
diff options
context:
space:
mode:
authorHollis Blanchard <hollisb@us.ibm.com>2008-12-02 16:51:55 -0500
committerAvi Kivity <avi@redhat.com>2008-12-31 09:55:09 -0500
commit7924bd41097ae8991c6d38cef8b1e4058e30d198 (patch)
treeb39629f81598739eb886126c5f3f8705656ce9cd /arch/powerpc/kvm/44x.c
parentc0ca609c5f874f7d6ae8e180afe79317e1943d22 (diff)
KVM: ppc: directly insert shadow mappings into the hardware TLB
Formerly, we used to maintain a per-vcpu shadow TLB and on every entry to the guest would load this array into the hardware TLB. This consumed 1280 bytes of memory (64 entries of 16 bytes plus a struct page pointer each), and also required some assembly to loop over the array on every entry. Instead of saving a copy in memory, we can just store shadow mappings directly into the hardware TLB, accepting that the host kernel will clobber these as part of the normal 440 TLB round robin. When we do that we need less than half the memory, and we have decreased the exit handling time for all guest exits, at the cost of increased number of TLB misses because the host overwrites some guest entries. These savings will be increased on processors with larger TLBs or which implement intelligent flush instructions like tlbivax (which will avoid the need to walk arrays in software). In addition to that and to the code simplification, we have a greater chance of leaving other host userspace mappings in the TLB, instead of forcing all subsequent tasks to re-fault all their mappings. Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/44x.c')
-rw-r--r--arch/powerpc/kvm/44x.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c
index 22054b164b5a..05d72fc8b478 100644
--- a/arch/powerpc/kvm/44x.c
+++ b/arch/powerpc/kvm/44x.c
@@ -96,21 +96,14 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu)
96 96
97void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 97void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
98{ 98{
99 int i;
100
101 /* Mark every guest entry in the shadow TLB entry modified, so that they
102 * will all be reloaded on the next vcpu run (instead of being
103 * demand-faulted). */
104 for (i = 0; i <= tlb_44x_hwater; i++)
105 kvmppc_tlbe_set_modified(vcpu, i);
106} 99}
107 100
108void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) 101void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu)
109{ 102{
110 /* Don't leave guest TLB entries resident when being de-scheduled. */ 103 /* XXX Since every guest uses TS=1 TID=0/1 mappings, we can't leave any TLB
111 /* XXX It would be nice to differentiate between heavyweight exit and 104 * entries around when we're descheduled, so we must completely flush the
112 * sched_out here, since we could avoid the TLB flush for heavyweight 105 * TLB of all guest mappings. On the other hand, if there is only one
113 * exits. */ 106 * guest, this flush is completely unnecessary. */
114 _tlbia(); 107 _tlbia();
115} 108}
116 109
@@ -130,6 +123,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
130{ 123{
131 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); 124 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
132 struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0]; 125 struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0];
126 int i;
133 127
134 tlbe->tid = 0; 128 tlbe->tid = 0;
135 tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; 129 tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID;
@@ -148,6 +142,9 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
148 * CCR1[TCS]. */ 142 * CCR1[TCS]. */
149 vcpu->arch.ccr1 = mfspr(SPRN_CCR1); 143 vcpu->arch.ccr1 = mfspr(SPRN_CCR1);
150 144
145 for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++)
146 vcpu_44x->shadow_refs[i].gtlb_index = -1;
147
151 return 0; 148 return 0;
152} 149}
153 150