|
@@ -209,6 +209,32 @@ fail:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
|
|
|
+ unsigned long ioba, unsigned long tce)
|
|
|
+{
|
|
|
+ struct kvmppc_spapr_tce_table *stt = kvmppc_find_table(vcpu, liobn);
|
|
|
+ long ret;
|
|
|
+
|
|
|
+ /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
|
|
|
+ /* liobn, ioba, tce); */
|
|
|
+
|
|
|
+ if (!stt)
|
|
|
+ return H_TOO_HARD;
|
|
|
+
|
|
|
+ ret = kvmppc_ioba_validate(stt, ioba, 1);
|
|
|
+ if (ret != H_SUCCESS)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = kvmppc_tce_validate(stt, tce);
|
|
|
+ if (ret != H_SUCCESS)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ kvmppc_tce_put(stt, ioba >> stt->page_shift, tce);
|
|
|
+
|
|
|
+ return H_SUCCESS;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
|
|
|
+
|
|
|
long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
|
|
|
unsigned long liobn, unsigned long ioba,
|
|
|
unsigned long tce_list, unsigned long npages)
|
|
@@ -264,3 +290,29 @@ unlock_exit:
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(kvmppc_h_put_tce_indirect);
|
|
|
+
|
|
|
+long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
|
|
|
+ unsigned long liobn, unsigned long ioba,
|
|
|
+ unsigned long tce_value, unsigned long npages)
|
|
|
+{
|
|
|
+ struct kvmppc_spapr_tce_table *stt;
|
|
|
+ long i, ret;
|
|
|
+
|
|
|
+ stt = kvmppc_find_table(vcpu, liobn);
|
|
|
+ if (!stt)
|
|
|
+ return H_TOO_HARD;
|
|
|
+
|
|
|
+ ret = kvmppc_ioba_validate(stt, ioba, npages);
|
|
|
+ if (ret != H_SUCCESS)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* Check permission bits only to allow userspace poison TCE for debug */
|
|
|
+ if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ))
|
|
|
+ return H_PARAMETER;
|
|
|
+
|
|
|
+ for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
|
|
|
+ kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value);
|
|
|
+
|
|
|
+ return H_SUCCESS;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce);
|