KVM: PPC: Book3S: Introduce hypervisor call H_GET_TCE
authorLaurent Dufour <ldufour@linux.vnet.ibm.com>
Fri, 21 Feb 2014 15:31:10 +0000 (16:31 +0100)
committerPaul Mackerras <paulus@samba.org>
Wed, 26 Mar 2014 12:34:27 +0000 (23:34 +1100)
This introduces the H_GET_TCE hypervisor call, which is basically the
reverse of H_PUT_TCE, as defined in the Power Architecture Platform
Requirements (PAPR).

The hcall H_GET_TCE is required by the kdump kernel, which uses it to
retrieve TCEs set up by the previous (panicked) kernel.

Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S

index fcd53f0d34bad9a26b3b74bc46ecc55b0c673f79..4096f16502a9becab431cb8e3f7c9f51b6989b4f 100644 (file)
@@ -129,6 +129,8 @@ extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
                                struct kvm_create_spapr_tce *args);
 extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                             unsigned long ioba, unsigned long tce);
+extern long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+                            unsigned long ioba);
 extern struct kvm_rma_info *kvm_alloc_rma(void);
 extern void kvm_release_rma(struct kvm_rma_info *ri);
 extern struct page *kvm_alloc_hpt(unsigned long nr_pages);
index 2c25f5412bdb7a080abb87f5baa22c45b00d691d..89e96b3e00398d0fb45bd841924a7f6b541f6718 100644 (file)
@@ -75,3 +75,31 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
        return H_TOO_HARD;
 }
 EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
+
+long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+                     unsigned long ioba)
+{
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_spapr_tce_table *stt;
+
+       list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) {
+               if (stt->liobn == liobn) {
+                       unsigned long idx = ioba >> SPAPR_TCE_SHIFT;
+                       struct page *page;
+                       u64 *tbl;
+
+                       if (ioba >= stt->window_size)
+                               return H_PARAMETER;
+
+                       page = stt->pages[idx / TCES_PER_PAGE];
+                       tbl = (u64 *)page_address(page);
+
+                       vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE];
+                       return H_SUCCESS;
+               }
+       }
+
+       /* Didn't find the liobn, punt it to userspace */
+       return H_TOO_HARD;
+}
+EXPORT_SYMBOL_GPL(kvmppc_h_get_tce);
index 818dce344e82a0fa0a94fe7f21eefdb2483fbc68..7c5788c735c9b560a6f5f7410773d5b12b1009bd 100644 (file)
@@ -1691,7 +1691,7 @@ hcall_real_table:
        .long   0               /* 0x10 - H_CLEAR_MOD */
        .long   0               /* 0x14 - H_CLEAR_REF */
        .long   .kvmppc_h_protect - hcall_real_table
-       .long   0               /* 0x1c - H_GET_TCE */
+       .long   .kvmppc_h_get_tce - hcall_real_table
        .long   .kvmppc_h_put_tce - hcall_real_table
        .long   0               /* 0x24 - H_SET_SPRG0 */
        .long   .kvmppc_h_set_dabr - hcall_real_table