aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2011-12-12 07:36:37 -0500
committerAvi Kivity <avi@redhat.com>2012-03-05 07:52:37 -0500
commit697d3899dcb4bcd918d060a92db57b794e56b077 (patch)
tree173cdd849eca204fec8b64ea520b619372c3d970 /arch/powerpc/kvm/book3s_hv.c
parent06ce2c63d933e347f8a199f123a8a293619ab3d2 (diff)
KVM: PPC: Implement MMIO emulation support for Book3S HV guests
This provides the low-level support for MMIO emulation in Book3S HV guests. When the guest tries to map a page which is not covered by any memslot, that page is taken to be an MMIO emulation page. Instead of inserting a valid HPTE, we insert an HPTE that has the valid bit clear but another hypervisor software-use bit set, which we call HPTE_V_ABSENT, to indicate that this is an absent page. An absent page is treated much like a valid page as far as guest hcalls (H_ENTER, H_REMOVE, H_READ etc.) are concerned, except of course that an absent HPTE doesn't need to be invalidated with tlbie since it was never valid as far as the hardware is concerned. When the guest accesses a page for which there is an absent HPTE, it will take a hypervisor data storage interrupt (HDSI) since we now set the VPM1 bit in the LPCR. Our HDSI handler for HPTE-not-present faults looks up the hash table and if it finds an absent HPTE mapping the requested virtual address, will switch to kernel mode and handle the fault in kvmppc_book3s_hv_page_fault(), which at present just calls kvmppc_hv_emulate_mmio() to set up the MMIO emulation. This is based on an earlier patch by Benjamin Herrenschmidt, but since heavily reworked. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv.c')
-rw-r--r--arch/powerpc/kvm/book3s_hv.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 6ed0a84ef91c..45aabb9a527f 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -326,19 +326,18 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
326 break; 326 break;
327 } 327 }
328 /* 328 /*
329 * We get these next two if the guest does a bad real-mode access, 329 * We get this if the guest accesses a page which it thinks
330 * as we have enabled VRMA (virtualized real mode area) mode in the 330 * it has mapped but which is not actually present, because
331 * LPCR. We just generate an appropriate DSI/ISI to the guest. 331 * it is for an emulated I/O device.
332 * Any other HDSI interrupt has been handled already.
332 */ 333 */
333 case BOOK3S_INTERRUPT_H_DATA_STORAGE: 334 case BOOK3S_INTERRUPT_H_DATA_STORAGE:
334 vcpu->arch.shregs.dsisr = vcpu->arch.fault_dsisr; 335 r = kvmppc_book3s_hv_page_fault(run, vcpu,
335 vcpu->arch.shregs.dar = vcpu->arch.fault_dar; 336 vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
336 kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
337 r = RESUME_GUEST;
338 break; 337 break;
339 case BOOK3S_INTERRUPT_H_INST_STORAGE: 338 case BOOK3S_INTERRUPT_H_INST_STORAGE:
340 kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE, 339 kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE,
341 0x08000000); 340 vcpu->arch.shregs.msr & 0x58000000);
342 r = RESUME_GUEST; 341 r = RESUME_GUEST;
343 break; 342 break;
344 /* 343 /*
@@ -1195,6 +1194,8 @@ static int kvmppc_hv_setup_rma(struct kvm_vcpu *vcpu)
1195 1194
1196 /* Update VRMASD field in the LPCR */ 1195 /* Update VRMASD field in the LPCR */
1197 senc = slb_pgsize_encoding(psize); 1196 senc = slb_pgsize_encoding(psize);
1197 kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
1198 (VRMA_VSID << SLB_VSID_SHIFT_1T);
1198 lpcr = kvm->arch.lpcr & ~LPCR_VRMASD; 1199 lpcr = kvm->arch.lpcr & ~LPCR_VRMASD;
1199 lpcr |= senc << (LPCR_VRMASD_SH - 4); 1200 lpcr |= senc << (LPCR_VRMASD_SH - 4);
1200 kvm->arch.lpcr = lpcr; 1201 kvm->arch.lpcr = lpcr;
@@ -1291,7 +1292,9 @@ int kvmppc_core_init_vm(struct kvm *kvm)
1291 kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR); 1292 kvm->arch.host_lpcr = lpcr = mfspr(SPRN_LPCR);
1292 lpcr &= LPCR_PECE | LPCR_LPES; 1293 lpcr &= LPCR_PECE | LPCR_LPES;
1293 lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE | 1294 lpcr |= (4UL << LPCR_DPFD_SH) | LPCR_HDICE |
1294 LPCR_VPM0 | LPCR_VRMA_L; 1295 LPCR_VPM0 | LPCR_VPM1;
1296 kvm->arch.vrma_slb_v = SLB_VSID_B_1T |
1297 (VRMA_VSID << SLB_VSID_SHIFT_1T);
1295 } 1298 }
1296 kvm->arch.lpcr = lpcr; 1299 kvm->arch.lpcr = lpcr;
1297 1300