diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 35485dd6927e..642e4204cf25 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -30,10 +30,8 @@ | |||
30 | #include <asm/kvm_ppc.h> | 30 | #include <asm/kvm_ppc.h> |
31 | #include "timing.h" | 31 | #include "timing.h" |
32 | #include <asm/cacheflush.h> | 32 | #include <asm/cacheflush.h> |
33 | #include <asm/kvm_44x.h> | ||
34 | 33 | ||
35 | #include "booke.h" | 34 | #include "booke.h" |
36 | #include "44x_tlb.h" | ||
37 | 35 | ||
38 | unsigned long kvmppc_booke_handlers; | 36 | unsigned long kvmppc_booke_handlers; |
39 | 37 | ||
@@ -120,6 +118,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
120 | case BOOKE_IRQPRIO_DATA_STORAGE: | 118 | case BOOKE_IRQPRIO_DATA_STORAGE: |
121 | case BOOKE_IRQPRIO_INST_STORAGE: | 119 | case BOOKE_IRQPRIO_INST_STORAGE: |
122 | case BOOKE_IRQPRIO_FP_UNAVAIL: | 120 | case BOOKE_IRQPRIO_FP_UNAVAIL: |
121 | case BOOKE_IRQPRIO_SPE_UNAVAIL: | ||
122 | case BOOKE_IRQPRIO_SPE_FP_DATA: | ||
123 | case BOOKE_IRQPRIO_SPE_FP_ROUND: | ||
123 | case BOOKE_IRQPRIO_AP_UNAVAIL: | 124 | case BOOKE_IRQPRIO_AP_UNAVAIL: |
124 | case BOOKE_IRQPRIO_ALIGNMENT: | 125 | case BOOKE_IRQPRIO_ALIGNMENT: |
125 | allowed = 1; | 126 | allowed = 1; |
@@ -165,7 +166,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
165 | unsigned int priority; | 166 | unsigned int priority; |
166 | 167 | ||
167 | priority = __ffs(*pending); | 168 | priority = __ffs(*pending); |
168 | while (priority <= BOOKE_MAX_INTERRUPT) { | 169 | while (priority <= BOOKE_IRQPRIO_MAX) { |
169 | if (kvmppc_booke_irqprio_deliver(vcpu, priority)) | 170 | if (kvmppc_booke_irqprio_deliver(vcpu, priority)) |
170 | break; | 171 | break; |
171 | 172 | ||
@@ -263,6 +264,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
263 | r = RESUME_GUEST; | 264 | r = RESUME_GUEST; |
264 | break; | 265 | break; |
265 | 266 | ||
267 | case BOOKE_INTERRUPT_SPE_UNAVAIL: | ||
268 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL); | ||
269 | r = RESUME_GUEST; | ||
270 | break; | ||
271 | |||
272 | case BOOKE_INTERRUPT_SPE_FP_DATA: | ||
273 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA); | ||
274 | r = RESUME_GUEST; | ||
275 | break; | ||
276 | |||
277 | case BOOKE_INTERRUPT_SPE_FP_ROUND: | ||
278 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND); | ||
279 | r = RESUME_GUEST; | ||
280 | break; | ||
281 | |||
266 | case BOOKE_INTERRUPT_DATA_STORAGE: | 282 | case BOOKE_INTERRUPT_DATA_STORAGE: |
267 | vcpu->arch.dear = vcpu->arch.fault_dear; | 283 | vcpu->arch.dear = vcpu->arch.fault_dear; |
268 | vcpu->arch.esr = vcpu->arch.fault_esr; | 284 | vcpu->arch.esr = vcpu->arch.fault_esr; |
@@ -284,29 +300,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
284 | r = RESUME_GUEST; | 300 | r = RESUME_GUEST; |
285 | break; | 301 | break; |
286 | 302 | ||
287 | /* XXX move to a 440-specific file. */ | ||
288 | case BOOKE_INTERRUPT_DTLB_MISS: { | 303 | case BOOKE_INTERRUPT_DTLB_MISS: { |
289 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
290 | struct kvmppc_44x_tlbe *gtlbe; | ||
291 | unsigned long eaddr = vcpu->arch.fault_dear; | 304 | unsigned long eaddr = vcpu->arch.fault_dear; |
292 | int gtlb_index; | 305 | int gtlb_index; |
306 | gpa_t gpaddr; | ||
293 | gfn_t gfn; | 307 | gfn_t gfn; |
294 | 308 | ||
295 | /* Check the guest TLB. */ | 309 | /* Check the guest TLB. */ |
296 | gtlb_index = kvmppc_44x_dtlb_index(vcpu, eaddr); | 310 | gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr); |
297 | if (gtlb_index < 0) { | 311 | if (gtlb_index < 0) { |
298 | /* The guest didn't have a mapping for it. */ | 312 | /* The guest didn't have a mapping for it. */ |
299 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); | 313 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); |
300 | vcpu->arch.dear = vcpu->arch.fault_dear; | 314 | vcpu->arch.dear = vcpu->arch.fault_dear; |
301 | vcpu->arch.esr = vcpu->arch.fault_esr; | 315 | vcpu->arch.esr = vcpu->arch.fault_esr; |
316 | kvmppc_mmu_dtlb_miss(vcpu); | ||
302 | kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); | 317 | kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); |
303 | r = RESUME_GUEST; | 318 | r = RESUME_GUEST; |
304 | break; | 319 | break; |
305 | } | 320 | } |
306 | 321 | ||
307 | gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; | 322 | gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr); |
308 | vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr); | 323 | gfn = gpaddr >> PAGE_SHIFT; |
309 | gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT; | ||
310 | 324 | ||
311 | if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { | 325 | if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { |
312 | /* The guest TLB had a mapping, but the shadow TLB | 326 | /* The guest TLB had a mapping, but the shadow TLB |
@@ -315,13 +329,13 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
315 | * b) the guest used a large mapping which we're faking | 329 | * b) the guest used a large mapping which we're faking |
316 | * Either way, we need to satisfy the fault without | 330 | * Either way, we need to satisfy the fault without |
317 | * invoking the guest. */ | 331 | * invoking the guest. */ |
318 | kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, | 332 | kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); |
319 | gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index); | ||
320 | kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); | 333 | kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); |
321 | r = RESUME_GUEST; | 334 | r = RESUME_GUEST; |
322 | } else { | 335 | } else { |
323 | /* Guest has mapped and accessed a page which is not | 336 | /* Guest has mapped and accessed a page which is not |
324 | * actually RAM. */ | 337 | * actually RAM. */ |
338 | vcpu->arch.paddr_accessed = gpaddr; | ||
325 | r = kvmppc_emulate_mmio(run, vcpu); | 339 | r = kvmppc_emulate_mmio(run, vcpu); |
326 | kvmppc_account_exit(vcpu, MMIO_EXITS); | 340 | kvmppc_account_exit(vcpu, MMIO_EXITS); |
327 | } | 341 | } |
@@ -329,10 +343,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
329 | break; | 343 | break; |
330 | } | 344 | } |
331 | 345 | ||
332 | /* XXX move to a 440-specific file. */ | ||
333 | case BOOKE_INTERRUPT_ITLB_MISS: { | 346 | case BOOKE_INTERRUPT_ITLB_MISS: { |
334 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
335 | struct kvmppc_44x_tlbe *gtlbe; | ||
336 | unsigned long eaddr = vcpu->arch.pc; | 347 | unsigned long eaddr = vcpu->arch.pc; |
337 | gpa_t gpaddr; | 348 | gpa_t gpaddr; |
338 | gfn_t gfn; | 349 | gfn_t gfn; |
@@ -341,18 +352,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
341 | r = RESUME_GUEST; | 352 | r = RESUME_GUEST; |
342 | 353 | ||
343 | /* Check the guest TLB. */ | 354 | /* Check the guest TLB. */ |
344 | gtlb_index = kvmppc_44x_itlb_index(vcpu, eaddr); | 355 | gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr); |
345 | if (gtlb_index < 0) { | 356 | if (gtlb_index < 0) { |
346 | /* The guest didn't have a mapping for it. */ | 357 | /* The guest didn't have a mapping for it. */ |
347 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); | 358 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); |
359 | kvmppc_mmu_itlb_miss(vcpu); | ||
348 | kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); | 360 | kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); |
349 | break; | 361 | break; |
350 | } | 362 | } |
351 | 363 | ||
352 | kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS); | 364 | kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS); |
353 | 365 | ||
354 | gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; | 366 | gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr); |
355 | gpaddr = tlb_xlate(gtlbe, eaddr); | ||
356 | gfn = gpaddr >> PAGE_SHIFT; | 367 | gfn = gpaddr >> PAGE_SHIFT; |
357 | 368 | ||
358 | if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { | 369 | if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { |
@@ -362,8 +373,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
362 | * b) the guest used a large mapping which we're faking | 373 | * b) the guest used a large mapping which we're faking |
363 | * Either way, we need to satisfy the fault without | 374 | * Either way, we need to satisfy the fault without |
364 | * invoking the guest. */ | 375 | * invoking the guest. */ |
365 | kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, | 376 | kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); |
366 | gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index); | ||
367 | } else { | 377 | } else { |
368 | /* Guest mapped and leaped at non-RAM! */ | 378 | /* Guest mapped and leaped at non-RAM! */ |
369 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); | 379 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); |