@@ -375,10 +375,41 @@ phys_addr_t kvm_iommu_iova_to_phys(pkvm_handle_t domain_id, unsigned long iova)
return phys;
}
+static int iommu_power_on(struct kvm_power_domain *pd)
+{
+ struct kvm_hyp_iommu *iommu = container_of(pd, struct kvm_hyp_iommu,
+ power_domain);
+
+ /*
+ * We currently assume that the device retains its architectural state
+ * across power off, hence no save/restore.
+ */
+ kvm_iommu_lock(iommu);
+ iommu->power_is_off = false;
+ kvm_iommu_unlock(iommu);
+ return 0;
+}
+
+static int iommu_power_off(struct kvm_power_domain *pd)
+{
+ struct kvm_hyp_iommu *iommu = container_of(pd, struct kvm_hyp_iommu,
+ power_domain);
+
+ kvm_iommu_lock(iommu);
+ iommu->power_is_off = true;
+ kvm_iommu_unlock(iommu);
+ return 0;
+}
+
+static const struct kvm_power_domain_ops iommu_power_ops = {
+ .power_on = iommu_power_on,
+ .power_off = iommu_power_off,
+};
+
/* Must be called from the IOMMU driver per IOMMU */
int kvm_iommu_init_device(struct kvm_hyp_iommu *iommu)
{
kvm_iommu_lock_init(iommu);
- return 0;
+ return pkvm_init_power_domain(&iommu->power_domain, &iommu_power_ops);
}
@@ -3,6 +3,7 @@
#define __KVM_IOMMU_H
#include <asm/kvm_host.h>
+#include <kvm/power_domain.h>
#include <linux/io-pgtable.h>
#ifdef __KVM_NVHE_HYPERVISOR__
#include <nvhe/spinlock.h>
@@ -51,6 +52,8 @@ struct kvm_hyp_iommu {
#else
u32 unused;
#endif
+ struct kvm_power_domain power_domain;
+ bool power_is_off;
};
#endif /* __KVM_IOMMU_H */