diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c index a6e0f3634756..fbab335d3490 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/iommu.c @@ -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); } diff --git a/include/kvm/iommu.h b/include/kvm/iommu.h index 6ff78d766466..c524ba84a9cf 100644 --- a/include/kvm/iommu.h +++ b/include/kvm/iommu.h @@ -3,6 +3,7 @@ #define __KVM_IOMMU_H #include +#include #include #ifdef __KVM_NVHE_HYPERVISOR__ #include @@ -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 */