提交 c47df7b6 编写于 作者: E Eric Auger 提交者: Zheng Zengkai

iommu/smmuv3: Implement attach/detach_pasid_table

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I401IF
CVE: NA

------------------------------

On attach_pasid_table() we program STE S1 related info set
by the guest into the actual physical STEs. At minimum
we need to program the context descriptor GPA and compute
whether the stage1 is translated/bypassed or aborted.

On detach, the stage 1 config is unset and the abort flag is
unset.
Signed-off-by: NEric Auger <eric.auger@redhat.com>
Signed-off-by: Kunkun Jiang<jiangkunkun@huawei.com>
Reviewed-by: NKeqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 54cb4594
......@@ -1005,6 +1005,10 @@ static void arm_smmu_write_cd_l1_desc(__le64 *dst,
WRITE_ONCE(*dst, cpu_to_le64(val));
}
/*
* Must not be used in case of nested mode where the CD table is owned
* by the guest
*/
static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
u32 ssid)
{
......@@ -3285,6 +3289,93 @@ static void arm_smmu_get_resv_regions(struct device *dev,
iommu_dma_get_resv_regions(dev, head);
}
static int arm_smmu_attach_pasid_table(struct iommu_domain *domain,
struct iommu_pasid_table_config *cfg)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_master *master;
struct arm_smmu_device *smmu;
unsigned long flags;
int ret = -EINVAL;
if (cfg->format != IOMMU_PASID_FORMAT_SMMUV3)
return -EINVAL;
if (cfg->version != PASID_TABLE_CFG_VERSION_1 ||
cfg->vendor_data.smmuv3.version != PASID_TABLE_SMMUV3_CFG_VERSION_1)
return -EINVAL;
mutex_lock(&smmu_domain->init_mutex);
smmu = smmu_domain->smmu;
if (!smmu)
goto out;
if (smmu_domain->stage != ARM_SMMU_DOMAIN_NESTED)
goto out;
switch (cfg->config) {
case IOMMU_PASID_CONFIG_ABORT:
smmu_domain->s1_cfg.set = false;
smmu_domain->abort = true;
break;
case IOMMU_PASID_CONFIG_BYPASS:
smmu_domain->s1_cfg.set = false;
smmu_domain->abort = false;
break;
case IOMMU_PASID_CONFIG_TRANSLATE:
/* we do not support S1 <-> S1 transitions */
if (smmu_domain->s1_cfg.set)
goto out;
/*
* we currently support a single CD so s1fmt and s1dss
* fields are also ignored
*/
if (cfg->pasid_bits)
goto out;
smmu_domain->s1_cfg.cdcfg.cdtab_dma = cfg->base_ptr;
smmu_domain->s1_cfg.set = true;
smmu_domain->abort = false;
break;
default:
goto out;
}
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_for_each_entry(master, &smmu_domain->devices, domain_head)
arm_smmu_install_ste_for_dev(master);
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
ret = 0;
out:
mutex_unlock(&smmu_domain->init_mutex);
return ret;
}
static void arm_smmu_detach_pasid_table(struct iommu_domain *domain)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_master *master;
unsigned long flags;
mutex_lock(&smmu_domain->init_mutex);
if (smmu_domain->stage != ARM_SMMU_DOMAIN_NESTED)
goto unlock;
smmu_domain->s1_cfg.set = false;
smmu_domain->abort = false;
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
list_for_each_entry(master, &smmu_domain->devices, domain_head)
arm_smmu_install_ste_for_dev(master);
spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
unlock:
mutex_unlock(&smmu_domain->init_mutex);
}
static bool arm_smmu_dev_has_feature(struct device *dev,
enum iommu_dev_features feat)
{
......@@ -3508,6 +3599,8 @@ static struct iommu_ops arm_smmu_ops = {
.of_xlate = arm_smmu_of_xlate,
.get_resv_regions = arm_smmu_get_resv_regions,
.put_resv_regions = generic_iommu_put_resv_regions,
.attach_pasid_table = arm_smmu_attach_pasid_table,
.detach_pasid_table = arm_smmu_detach_pasid_table,
.dev_has_feat = arm_smmu_dev_has_feature,
.dev_feat_enabled = arm_smmu_dev_feature_enabled,
.dev_enable_feat = arm_smmu_dev_enable_feature,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册