aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/booke.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r--arch/powerpc/kvm/booke.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 924c7b4b1107..eb24383c87d2 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -24,10 +24,12 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/vmalloc.h> 25#include <linux/vmalloc.h>
26#include <linux/fs.h> 26#include <linux/fs.h>
27
27#include <asm/cputable.h> 28#include <asm/cputable.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
29#include <asm/kvm_ppc.h> 30#include <asm/kvm_ppc.h>
30#include <asm/cacheflush.h> 31#include <asm/cacheflush.h>
32#include <asm/kvm_44x.h>
31 33
32#include "booke.h" 34#include "booke.h"
33#include "44x_tlb.h" 35#include "44x_tlb.h"
@@ -207,10 +209,6 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
207 * handled this interrupt the moment we enabled interrupts. 209 * handled this interrupt the moment we enabled interrupts.
208 * Now we just offer it a chance to reschedule the guest. */ 210 * Now we just offer it a chance to reschedule the guest. */
209 211
210 /* XXX At this point the TLB still holds our shadow TLB, so if
211 * we do reschedule the host will fault over it. Perhaps we
212 * should politely restore the host's entries to minimize
213 * misses before ceding control. */
214 vcpu->stat.dec_exits++; 212 vcpu->stat.dec_exits++;
215 if (need_resched()) 213 if (need_resched())
216 cond_resched(); 214 cond_resched();
@@ -281,14 +279,17 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
281 r = RESUME_GUEST; 279 r = RESUME_GUEST;
282 break; 280 break;
283 281
282 /* XXX move to a 440-specific file. */
284 case BOOKE_INTERRUPT_DTLB_MISS: { 283 case BOOKE_INTERRUPT_DTLB_MISS: {
284 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
285 struct kvmppc_44x_tlbe *gtlbe; 285 struct kvmppc_44x_tlbe *gtlbe;
286 unsigned long eaddr = vcpu->arch.fault_dear; 286 unsigned long eaddr = vcpu->arch.fault_dear;
287 int gtlb_index;
287 gfn_t gfn; 288 gfn_t gfn;
288 289
289 /* Check the guest TLB. */ 290 /* Check the guest TLB. */
290 gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); 291 gtlb_index = kvmppc_44x_dtlb_index(vcpu, eaddr);
291 if (!gtlbe) { 292 if (gtlb_index < 0) {
292 /* The guest didn't have a mapping for it. */ 293 /* The guest didn't have a mapping for it. */
293 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); 294 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
294 vcpu->arch.dear = vcpu->arch.fault_dear; 295 vcpu->arch.dear = vcpu->arch.fault_dear;
@@ -298,6 +299,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
298 break; 299 break;
299 } 300 }
300 301
302 gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
301 vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr); 303 vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr);
302 gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT; 304 gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
303 305
@@ -309,7 +311,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
309 * Either way, we need to satisfy the fault without 311 * Either way, we need to satisfy the fault without
310 * invoking the guest. */ 312 * invoking the guest. */
311 kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, 313 kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid,
312 gtlbe->word2, get_tlb_bytes(gtlbe)); 314 gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
313 vcpu->stat.dtlb_virt_miss_exits++; 315 vcpu->stat.dtlb_virt_miss_exits++;
314 r = RESUME_GUEST; 316 r = RESUME_GUEST;
315 } else { 317 } else {
@@ -322,17 +324,20 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
322 break; 324 break;
323 } 325 }
324 326
327 /* XXX move to a 440-specific file. */
325 case BOOKE_INTERRUPT_ITLB_MISS: { 328 case BOOKE_INTERRUPT_ITLB_MISS: {
329 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
326 struct kvmppc_44x_tlbe *gtlbe; 330 struct kvmppc_44x_tlbe *gtlbe;
327 unsigned long eaddr = vcpu->arch.pc; 331 unsigned long eaddr = vcpu->arch.pc;
328 gpa_t gpaddr; 332 gpa_t gpaddr;
329 gfn_t gfn; 333 gfn_t gfn;
334 int gtlb_index;
330 335
331 r = RESUME_GUEST; 336 r = RESUME_GUEST;
332 337
333 /* Check the guest TLB. */ 338 /* Check the guest TLB. */
334 gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); 339 gtlb_index = kvmppc_44x_itlb_index(vcpu, eaddr);
335 if (!gtlbe) { 340 if (gtlb_index < 0) {
336 /* The guest didn't have a mapping for it. */ 341 /* The guest didn't have a mapping for it. */
337 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); 342 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
338 vcpu->stat.itlb_real_miss_exits++; 343 vcpu->stat.itlb_real_miss_exits++;
@@ -341,6 +346,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
341 346
342 vcpu->stat.itlb_virt_miss_exits++; 347 vcpu->stat.itlb_virt_miss_exits++;
343 348
349 gtlbe = &vcpu_44x->guest_tlb[gtlb_index];
344 gpaddr = tlb_xlate(gtlbe, eaddr); 350 gpaddr = tlb_xlate(gtlbe, eaddr);
345 gfn = gpaddr >> PAGE_SHIFT; 351 gfn = gpaddr >> PAGE_SHIFT;
346 352
@@ -352,7 +358,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
352 * Either way, we need to satisfy the fault without 358 * Either way, we need to satisfy the fault without
353 * invoking the guest. */ 359 * invoking the guest. */
354 kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, 360 kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid,
355 gtlbe->word2, get_tlb_bytes(gtlbe)); 361 gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
356 } else { 362 } else {
357 /* Guest mapped and leaped at non-RAM! */ 363 /* Guest mapped and leaped at non-RAM! */
358 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); 364 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);