diff --git a/Documentation/ABI/testing/sysfs-class-iommu-ummu-iommu b/Documentation/ABI/testing/sysfs-class-iommu-ummu-iommu index 48ba4d6d4c60db8b81660ac6ec90f7880feb8783..e5b576672af8cd1810011d392cd1522ff7278ce9 100644 --- a/Documentation/ABI/testing/sysfs-class-iommu-ummu-iommu +++ b/Documentation/ABI/testing/sysfs-class-iommu-ummu-iommu @@ -104,7 +104,7 @@ Contact: Jingbin Wu Description: Maximum TokenID bit width supported in non-secure state. -What: /sys/class/iommu/ummu./ummu-iommu/tid_type +What: /sys/class/iommu/logic_ummu/tid_type Date: Oct 2025 KernelVersion: 6.6 Contact: Jingbin Wu diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index d4237341e76d7afa8104baa4d618334841d313b0..b9a451bd7d6502226fadf5847d103362925f42d0 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -8345,7 +8345,6 @@ CONFIG_UB_UBUS=y # UB Bus Core Driver CONFIG_UB_UBUS_BUS=m CONFIG_UB_UBFI=m -CONFIG_UB_UBRT_PLAT_DEV=y CONFIG_UB_UBUS_USI=y CONFIG_ARM_GIC_V3_ITS_UBUS=y CONFIG_VFIO_UB=m diff --git a/drivers/iommu/hisilicon/Kconfig b/drivers/iommu/hisilicon/Kconfig index e41f492a7ca65bf76c19cf3553077980e3ebf754..60e612b57ca66e033a391766fb31ab9d69da3933 100644 --- a/drivers/iommu/hisilicon/Kconfig +++ b/drivers/iommu/hisilicon/Kconfig @@ -18,7 +18,7 @@ config UB_UMMU_BASE config UB_UMMU tristate "Hisilicon UB MMU Support" depends on ARM64 && ARCH_HISI - depends on UB_UBUS && UB_UBFI && UB_UBRT_PLAT_DEV + depends on UB_UBUS && UB_UBFI default n select IOMMU_API select IOMMU_IO_PGTABLE_LPAE diff --git a/drivers/iommu/hisilicon/attribute.c b/drivers/iommu/hisilicon/attribute.c index adb360ea541c068829aa70c5d2170f227074dbd0..3ee3c523bb41ec128feb1071dca5ea6e07e635ce 100644 --- a/drivers/iommu/hisilicon/attribute.c +++ b/drivers/iommu/hisilicon/attribute.c @@ -187,44 +187,6 @@ static ssize_t eid_list_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(eid_list); -static const char *get_domain_type_str(u32 domain_type) -{ - switch (domain_type) { - case IOMMU_DOMAIN_DMA: - return "IOMMU_DOMAIN_DMA"; - case IOMMU_DOMAIN_SVA: - return "IOMMU_DOMAIN_SVA"; - default: - return "UNKNOWN DOMAIN TYPE"; - } -} - -static ssize_t tid_type_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ummu_core_device *ummu_core; - u32 tid = 0, tid_type; - int ret; - - ret = kstrtouint(buf, 0, &tid); - if (ret < 0 || tid >= UMMU_INVALID_TID) - return -EINVAL; - - ummu_core = to_ummu_core(dev_to_iommu_device(dev)); - ret = ummu_core_get_tid_type(ummu_core, tid, &tid_type); - if (ret) { - pr_err("Invalid tid = 0x%x, ret = %d.\n", tid, ret); - return ret; - } - - pr_info("tid = 0x%x, domain_type = %s.\n", tid, - get_domain_type_str(tid_type)); - - return (ssize_t)count; -} -static DEVICE_ATTR_WO(tid_type); - static struct attribute *ummu_iommu_attrs[] = { &dev_attr_features.attr, &dev_attr_tid_bits.attr, @@ -240,7 +202,6 @@ static struct attribute *ummu_iommu_attrs[] = { &dev_attr_permq_num.attr, &dev_attr_permq_ent_num.attr, &dev_attr_eid_list.attr, - &dev_attr_tid_type.attr, NULL, }; diff --git a/drivers/iommu/hisilicon/cfg_table.c b/drivers/iommu/hisilicon/cfg_table.c index 7c7a486a7bdde4a3f05ff9ea10921e91ab1e8b23..fe208646a8f3f3ec79551fa80328e1877535915b 100644 --- a/drivers/iommu/hisilicon/cfg_table.c +++ b/drivers/iommu/hisilicon/cfg_table.c @@ -1125,7 +1125,7 @@ static void ummu_device_make_default_tecte(struct ummu_device *ummu, TECT_ENT0_TCR_EL2 : TECT_ENT0_TCR_NSEL1; target->data[0] = cpu_to_le64( TECT_ENT0_V | FIELD_PREP(TECT_ENT0_TCRC_SEL, tcr_sel) | - (ummu->cap.support_mapt ? TECT_ENT0_MAPT_EN : 0) | + ((ummu->cap.features & UMMU_FEAT_MAPT) ? TECT_ENT0_MAPT_EN : 0) | FIELD_PREP(TECT_ENT0_ST_MODE, TECT_ENT0_ST_MODE_S1) | FIELD_PREP(TECT_ENT0_PRIV_SEL, TECT_ENT0_PRIV_SEL_PRIV)); @@ -1174,7 +1174,12 @@ void ummu_build_s2_domain_tecte(struct ummu_domain *u_domain, static bool check_tecte_can_set(const struct ummu_tecte_data *tecte, const struct ummu_tecte_data *src) { - u32 st_mode = FIELD_GET(TECT_ENT0_ST_MODE, le64_to_cpu(tecte->data[0])); + u32 st_mode; + + if (!src->data[0]) + return true; + + st_mode = FIELD_GET(TECT_ENT0_ST_MODE, le64_to_cpu(tecte->data[0])); switch (st_mode) { case TECT_ENT0_ST_MODE_ABORT: @@ -1298,8 +1303,11 @@ void ummu_del_eid(struct ummu_core_device *core_dev, guid_t *guid, eid_t eid, en } ummu_device_delete_kvtbl(ummu, meta->tecte_tag, eid, kv_index); - if (kref_read(&meta->ref) == 1) + /* 2 indicates that only the last EID remains. */ + if (kref_read(&meta->ref) == 2) { ummu_device_write_tecte(ummu, meta->tecte_tag, &ummu_clear_tecte); + meta->valid = false; + } os_meta_del_eid(meta, eid); } diff --git a/drivers/iommu/hisilicon/flush.c b/drivers/iommu/hisilicon/flush.c index ea2aa23100d36ba7b7d662600453460478d69702..064f964b51be76205bd374bea9207b5faab69359 100644 --- a/drivers/iommu/hisilicon/flush.c +++ b/drivers/iommu/hisilicon/flush.c @@ -328,17 +328,19 @@ void ummu_sync_tct(struct ummu_device *ummu, u32 tecte_tag, u32 tid, .deid_0 = tecte_tag, }, }; - struct ummu_mcmdq_ent cmd_plbi_all = { - .opcode = CMD_PLBI_OS_EIDTID, - .plbi = { - .tid = tid, - .tecte_tag = tecte_tag, - }, - }; - trace_ummu_sync_tct(dev_name(ummu->dev), tecte_tag, tid, leaf); - if (!ummu->cap.prod_ver) + if (ummu->cap.options & UMMU_OPT_SYNC_WITH_PLBI) { + struct ummu_mcmdq_ent cmd_plbi_all = { + .opcode = CMD_PLBI_OS_EIDTID, + .plbi = { + .tid = tid, + .tecte_tag = tecte_tag, + }, + }; ummu_mcmdq_issue_cmd(ummu, &cmd_plbi_all); + } + + trace_ummu_sync_tct(dev_name(ummu->dev), tecte_tag, tid, leaf); ummu_mcmdq_issue_cmd_with_sync(ummu, &cmd_cfgi_tct); } diff --git a/drivers/iommu/hisilicon/iommu.c b/drivers/iommu/hisilicon/iommu.c index 49c377534b3b05995f567d68dae0883a5c54f0e7..3cb202c4edc3ee616614b810d0144e06b6c1f19f 100644 --- a/drivers/iommu/hisilicon/iommu.c +++ b/drivers/iommu/hisilicon/iommu.c @@ -675,7 +675,7 @@ static void ummu_cfg_sync(struct ummu_base_domain *base_domain) else u_domain = to_ummu_domain(&base_domain->domain); - ummu = core_to_ummu_device(u_domain->base_domain.core_dev); + ummu = core_to_ummu_device(base_domain->core_dev); tag = u_domain->cfgs.tecte_tag; tid = u_domain->base_domain.tid; @@ -712,18 +712,13 @@ static int ummu_sync_dom_cfg(struct ummu_base_domain *src, dst_domain->cfgs.tecte_tag = src_domain->cfgs.tecte_tag; dst_domain->cfgs.stage = src_domain->cfgs.stage; break; - case SYNC_NESTED_DOM_MUTI_CFG: - src_domain = to_nested_domain(&src->domain)->s2_parent; - dst_domain = to_nested_domain(&dst->domain)->s2_parent; - dst_domain->base_domain.tid = src_domain->base_domain.tid; - dst_domain->cfgs.tecte_tag = src_domain->cfgs.tecte_tag; - dst_domain->cfgs.stage = src_domain->cfgs.stage; - break; case SYNC_CLEAR_DOM_ALL_CFG: dst_domain = to_ummu_domain(&dst->domain); memset(&dst_domain->cfgs, 0, sizeof(dst_domain->cfgs)); dst_domain->base_domain.tid = UMMU_INVALID_TID; break; + case SYNC_TYPE_NONE: + break; default: return -EINVAL; } diff --git a/drivers/iommu/hisilicon/logic_ummu/logic_ummu.c b/drivers/iommu/hisilicon/logic_ummu/logic_ummu.c index eede1c16bddf1907cbf166f6bce58bf4c36de68c..bc3a62290ff443bf4093f5940c134cb8d060e182 100644 --- a/drivers/iommu/hisilicon/logic_ummu/logic_ummu.c +++ b/drivers/iommu/hisilicon/logic_ummu/logic_ummu.c @@ -21,11 +21,6 @@ #include "../ummu_cfg_v1.h" #include "logic_ummu.h" -struct logic_ummu_domain { - struct ummu_base_domain base_domain; - struct ummu_base_domain *agent_domain; -}; - struct logic_ummu_device { struct ummu_core_device core_dev; struct ummu_device *agent_device; @@ -41,6 +36,12 @@ struct logic_ummu_viommu { struct iommu_domain *nested; }; +struct logic_ummu_domain { + struct ummu_base_domain base_domain; + struct ummu_base_domain *agent_domain; + struct logic_ummu_viommu *logic_viommu; +}; + struct eid_info { enum eid_type type; eid_t eid; @@ -192,11 +193,11 @@ static int logic_ummu_attach_dev(struct iommu_domain *domain, struct device *dev) { struct logic_ummu_domain *logic_domain = iommu_to_logic_domain(domain); + const struct ummu_device_helper *helper = get_agent_helper(); const struct ummu_core_ops *core_ops = get_agent_core_ops(); struct ummu_base_domain *ummu_base_domain, *agent_domain; - const struct ummu_device_helper *helper = get_agent_helper(); + enum ummu_dom_cfg_sync_type sync_type = SYNC_TYPE_NONE; const struct iommu_domain_ops *ops; - enum ummu_dom_cfg_sync_type sync_type; int ret; agent_domain = logic_domain->agent_domain; @@ -217,9 +218,7 @@ static int logic_ummu_attach_dev(struct iommu_domain *domain, } /* the domain attributes might be changed, sync to logic domain */ logic_domain_update_attr(logic_domain); - if (domain->type == IOMMU_DOMAIN_NESTED) - sync_type = SYNC_NESTED_DOM_MUTI_CFG; - else + if (domain->type != IOMMU_DOMAIN_NESTED) sync_type = SYNC_DOM_MUTI_CFG; list_for_each_entry(ummu_base_domain, &logic_domain->base_domain.list, @@ -516,10 +515,12 @@ static void logic_ummu_free(struct iommu_domain *domain) return; } - if (domain->type != IOMMU_DOMAIN_NESTED) + if (domain->type != IOMMU_DOMAIN_NESTED) { logic_domain_free(logic_domain, ops); - else + } else { logic_nested_domain_free(logic_domain, ops); + logic_domain->logic_viommu->nested = NULL; + } kfree(logic_domain); } @@ -1020,6 +1021,7 @@ logic_ummu_viommu_alloc_domain_nested(struct iommufd_viommu *viommu, } } logic_vummu->nested = &logic_domain->base_domain.domain; + logic_domain->logic_viommu = logic_vummu; return &logic_domain->base_domain.domain; error_handle: list_for_each_entry_safe(nested_base_domain, iter, &logic_domain->base_domain.list, list) { @@ -1042,8 +1044,10 @@ logic_ummu_viommu_cache_invalidate(struct iommufd_viommu *viommu, u32 cmd_num, succ_cnt; int err, ret = 0; - if (!logic_vummu->nested || !array) + if (!logic_vummu->nested || !array) { + pr_debug("invalid viommu.\n"); return -EINVAL; + } if (!helper || !helper->cache_invalidate_user) return -EOPNOTSUPP; @@ -2057,6 +2061,61 @@ static inline struct fwnode_handle *logic_ummu_alloc_fwnode_static(void) return handle; } +static const char *get_domain_type_str(u32 domain_type) +{ + switch (domain_type) { + case IOMMU_DOMAIN_DMA: + return "IOMMU_DOMAIN_DMA"; + case IOMMU_DOMAIN_IDENTITY: + return "IOMMU_DOMAIN_IDENTITY"; + case IOMMU_DOMAIN_SVA: + return "IOMMU_DOMAIN_SVA"; + default: + return "UNKNOWN DOMAIN TYPE"; + } +} + +static ssize_t tid_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ummu_core_device *ummu_core; + u32 tid = 0, tid_type; + int ret; + + ret = kstrtouint(buf, 0, &tid); + if (ret < 0 || tid >= UMMU_INVALID_TID) + return -EINVAL; + + ummu_core = to_ummu_core(dev_to_iommu_device(dev)); + ret = ummu_core_get_tid_type(ummu_core, tid, &tid_type); + if (ret) { + pr_err("Invalid tid = 0x%x, ret = %d.\n", tid, ret); + return ret; + } + + pr_info("tid = 0x%x, domain_type = %s.\n", tid, + get_domain_type_str(tid_type)); + + return (ssize_t)count; +} +static DEVICE_ATTR_WO(tid_type); + +static struct attribute *logic_ummu_attrs[] = { + &dev_attr_tid_type.attr, + NULL, +}; + +static struct attribute_group logic_ummu_group = { + .name = NULL, + .attrs = logic_ummu_attrs, +}; + +const struct attribute_group *logic_ummu_groups[] = { + &logic_ummu_group, + NULL, +}; + int logic_ummu_device_init(void) { int ret; @@ -2081,7 +2140,7 @@ int logic_ummu_device_init(void) pr_err("add logic ummu device failed\n"); goto out_free_fwnode; } - ret = iommu_device_sysfs_add(&logic_ummu.core_dev.iommu, NULL, NULL, + ret = iommu_device_sysfs_add(&logic_ummu.core_dev.iommu, NULL, logic_ummu_groups, "%s", "logic_ummu"); if (ret) { pr_err("register logic ummu to sysfs failed.\n"); diff --git a/drivers/iommu/hisilicon/nested.c b/drivers/iommu/hisilicon/nested.c index 0eed1d9f8d25c275ea9c3e04614cc6bd198fe00e..f7804811a5ed4e772ef4f1d7be2ca7b4369e66e7 100644 --- a/drivers/iommu/hisilicon/nested.c +++ b/drivers/iommu/hisilicon/nested.c @@ -31,8 +31,8 @@ static void ummu_build_nested_domain_tct(struct ummu_domain *u_domain, tcr_sel = (ummu->cap.features & UMMU_FEAT_E2H) ? TECT_ENT0_TCR_EL2 : TECT_ENT0_TCR_NSEL1; target->data[0] |= cpu_to_le64( - FIELD_PREP(TECT_ENT0_TCRC_SEL, tcr_sel) | - (ummu->cap.support_mapt ? TECT_ENT0_MAPT_EN : 0)); + FIELD_PREP(TECT_ENT0_TCRC_SEL, tcr_sel) | + ((ummu->cap.features & UMMU_FEAT_MAPT) ? TECT_ENT0_MAPT_EN : 0)); } static void ummu_build_nested_domain_tecte( @@ -184,7 +184,6 @@ static int ummu_fix_user_cmd(struct ummu_device *ummu, case CMD_CFGI_TECT_RANGE: case CMD_CFGI_TCT: case CMD_CFGI_TCT_ALL: - case CMD_CFGI_TECTS_PIDM: cmd[2] &= ~CMD_CFGI_2_TECTE_TAG; cmd[2] |= FIELD_PREP(CMD_CFGI_2_TECTE_TAG, tecte_tag); break; diff --git a/drivers/iommu/hisilicon/perm_queue.c b/drivers/iommu/hisilicon/perm_queue.c index ae85563bce78d918c2aca9939737ee5dade48d68..2e80dec5eaf969d1dc0a5c722b303bbc76e2f2a3 100644 --- a/drivers/iommu/hisilicon/perm_queue.c +++ b/drivers/iommu/hisilicon/perm_queue.c @@ -12,10 +12,7 @@ #include "regs.h" #include "perm_queue.h" -#define PCMDQ_ENT_BYTES 16U -#define PCPLQ_ENT_BYTES 4U #define PERMQ_CTXTBL_BYTES 64U - #define PERMQ_CTXTBL_STATUS GENMASK(1, 0) #define PERMQ_CTXTBL_RESET 0x0 #define PERMQ_CTXTBL_READY 0x1 @@ -44,8 +41,10 @@ void ummu_device_uninit_permqs(struct ummu_device *ummu) { - if (ummu->cap.support_mapt) - xa_destroy(&ummu->permq_ctx_cfg.permq_xa); + if (!(ummu->cap.features & UMMU_FEAT_MAPT)) + return; + + xa_destroy(&ummu->permq_ctx_cfg.permq_xa); mutex_destroy(&ummu->permq_ctx_cfg.permq_rel_mutex); } @@ -335,6 +334,7 @@ int ummu_domain_config_permq(struct ummu_domain *domain) domain->qid = qid; ummu_init_permq_ctxtbl_ent(domain, permq); + dma_wmb(); ummu_init_permq_ctrltbl_ent(ummu->ucmdq_ctrl_page, qid); return 0; diff --git a/drivers/iommu/hisilicon/perm_queue.h b/drivers/iommu/hisilicon/perm_queue.h index d3e8c580e5b69cf40879af201b47a169d974ef2c..6f9ac919af294cbecbe92449b7fa0b0b30b59929 100644 --- a/drivers/iommu/hisilicon/perm_queue.h +++ b/drivers/iommu/hisilicon/perm_queue.h @@ -10,6 +10,9 @@ #define UMMU_INVALID_QID ((u32)-1) +#define PCMDQ_ENT_BYTES 16U +#define PCPLQ_ENT_BYTES 4U + #define PQ_WRAP(idx, size) ((idx) & (size)) #define PQ_IDX(idx, size) ((idx) & ((size) - 1)) diff --git a/drivers/iommu/hisilicon/perm_table.c b/drivers/iommu/hisilicon/perm_table.c index 3827fa7b017b4a05addac64d771372df63889c07..ec14575b3cba0f3db8a5a16ed98ca8eb2a81793b 100644 --- a/drivers/iommu/hisilicon/perm_table.c +++ b/drivers/iommu/hisilicon/perm_table.c @@ -75,20 +75,6 @@ static const u32 g_mapt_range_bits[MAPT_MAX_LVL_INDEX + 1][2] = { { 47, 39 }, (GET_BITS_MASK(g_mapt_range_bits[level][0] - \ g_mapt_range_bits[level][1] + 1))) -#define GET_LEVEL_INDEX_RANGE(base, limit, lvl, base_index, limit_index, \ - cross_level) \ - do { \ - (base_index) = GET_LEVEL_BLOCK_INDEX(base, lvl); \ - if ((limit) >> (g_mapt_range_bits[lvl][0] + 1) == \ - (base) >> (g_mapt_range_bits[lvl][0] + 1)) { \ - (limit_index) = GET_LEVEL_BLOCK_INDEX(limit, lvl); \ - cross_level = false; \ - } else { \ - (limit_index) = MAPT_MAX_ENTRY_INDEX - 1; \ - cross_level = true; \ - } \ - } while (0) - #define ENTRY_ADDR_LOW(addr) FIELD_GET(GENMASK(31, 0), (addr)) #define ENTRY_ADDR_HIGH(addr) FIELD_GET(GENMASK(47, 32), (addr)) @@ -217,7 +203,7 @@ static int ummu_alloc_mapt_mem_for_table(struct ummu_domain *ummu_domain, goto err_out; } - if (ummu->cap.prod_ver == NO_PROD_ID) { + if (ummu->cap.options & UMMU_OPT_CHK_MAPT_CONTINUITY) { ret = ummu_device_check_pa_continuity(ummu, virt_to_phys(alloc_ptr), PAGE_ORDER_TO_MAPT_ORDER(blk_para->block_size_order), @@ -945,7 +931,7 @@ static int ummu_table_clear_node_by_level(struct ummu_data_info *data_info, static int ummu_table_clear_head_node(struct ummu_data_info *data_info, u32 level, struct ummu_mapt_table_node *pre_node, struct ummu_mapt_table_node *cur_node, u64 node_base, - u64 node_limit) + u64 node_limit) { u16 loop_cnt, max_loop = MAPT_MAX_ENTRY_INDEX << MAPT_MAX_LVL_INDEX; u64 rest_node_base, cur_base, cur_limit; @@ -1253,6 +1239,11 @@ int ummu_perm_grant(struct iommu_domain *domain, void *va, size_t size, ret = ummu_update_info(data_info.op, mapt_info, &data_info); plb_gather->va = (void *)data_info.data_base; + if (data_info.op == UMMU_GRANT) + plb_gather->size = 0; + else + plb_gather->size = data_info.data_size; + plb_gather->size = data_info.data_size; data_info.tokenval = 0; return ret; diff --git a/drivers/iommu/hisilicon/queue.c b/drivers/iommu/hisilicon/queue.c index a3eb96996df010bb0f6d3cae0e960a6bc2f2ee45..35cb355a456eafc9a96059311e5759acdabab035 100644 --- a/drivers/iommu/hisilicon/queue.c +++ b/drivers/iommu/hisilicon/queue.c @@ -251,7 +251,8 @@ static int ummu_mcmdq_init(struct ummu_device *ummu) int cpu, ret; ummu->nr_mcmdq = 1UL << ummu->cap.mcmdq_log2num; - ummu->nr_mcmdq -= 1; + if (ummu->cap.options & UMMU_OPT_MCMDQ_DECREASE) + ummu->nr_mcmdq -= 1; shift = order_base_2(num_possible_cpus() / ummu->nr_mcmdq); ummu->mcmdq = devm_alloc_percpu(ummu->dev, struct ummu_mcmdq *); diff --git a/drivers/iommu/hisilicon/queue.h b/drivers/iommu/hisilicon/queue.h index 2f60fd52ce8342d9af5dd24dd24109e303f46268..0b112bd90e6ac0be8cf26d020ed7034c97050345 100644 --- a/drivers/iommu/hisilicon/queue.h +++ b/drivers/iommu/hisilicon/queue.h @@ -204,7 +204,6 @@ struct ummu_mcmdq_ent { #define CMD_CFGI_TECT_RANGE 0x09 #define CMD_CFGI_TCT 0x0A #define CMD_CFGI_TCT_ALL 0x0B -#define CMD_CFGI_TECTS_PIDM 0x0C struct { bool leaf; u32 tid; diff --git a/drivers/iommu/hisilicon/sva.c b/drivers/iommu/hisilicon/sva.c index f9a63544ace08c7e4879dc1f164dd7421d5aec74..192771e2304d31addb403730f78f7726b274cb49 100644 --- a/drivers/iommu/hisilicon/sva.c +++ b/drivers/iommu/hisilicon/sva.c @@ -313,7 +313,7 @@ static int ummu_sva_collect_domain_cfg(struct ummu_domain *domain, ioasid_t id) domain->cfgs.sva_mode = UMMU_MODE_SVA; } - if (ummu->cap.support_mapt && + if ((ummu->cap.features & UMMU_FEAT_MAPT) && domain->cfgs.sva_mode != UMMU_MODE_SVA_DISABLE_PTB) { domain->cfgs.s1_cfg.io_pt_cfg.mode = mode; if (!ksva) { diff --git a/drivers/iommu/hisilicon/sva.h b/drivers/iommu/hisilicon/sva.h index e91fa1e119205c3f69f89062a15214f2ddcb1100..4b3189fcbcffd0bc9838e6c72f9827e51449bb35 100644 --- a/drivers/iommu/hisilicon/sva.h +++ b/drivers/iommu/hisilicon/sva.h @@ -55,7 +55,7 @@ static inline int ummu_master_disable_sva(struct ummu_master *master, return -ENODEV; } -static void ummu_iopf_queue_free(struct ummu_device *ummu) +static inline void ummu_iopf_queue_free(struct ummu_device *ummu) { } diff --git a/drivers/iommu/hisilicon/ummu-core/core_eid.c b/drivers/iommu/hisilicon/ummu-core/core_eid.c index fd3360d400d0a3dbbf566e7a86599844cb8271be..9877bb892904330f33f34440461390f4f1ad2849 100644 --- a/drivers/iommu/hisilicon/ummu-core/core_eid.c +++ b/drivers/iommu/hisilicon/ummu-core/core_eid.c @@ -55,7 +55,7 @@ int ummu_core_add_eid(guid_t *guid, eid_t eid, enum eid_type type) /* cached the eid */ spin_lock(&eid_func_lock); list_for_each_entry(info, &eid_pre_insmode, list) - if (guid_equal(guid, &info->guid) && info->eid == eid) { + if (info->eid == eid) { ret = -EEXIST; goto out_unlock_spin; } @@ -95,7 +95,7 @@ void ummu_core_del_eid(guid_t *guid, eid_t eid, enum eid_type type) /* uncache the eid */ spin_lock(&eid_func_lock); list_for_each_entry_safe(info, next, &eid_pre_insmode, list) - if (guid_equal(guid, &info->guid) && info->eid == eid) { + if (info->eid == eid) { list_del(&info->list); kfree(info); } diff --git a/drivers/iommu/hisilicon/ummu.h b/drivers/iommu/hisilicon/ummu.h index 95ff2c927742c2f70df57e0f9cb49cc2396ec20f..ea391498c97b9e423f848c330c92cc8ad6cfb230 100644 --- a/drivers/iommu/hisilicon/ummu.h +++ b/drivers/iommu/hisilicon/ummu.h @@ -31,11 +31,6 @@ struct ummu_l1_tct_desc { phys_addr_t l2ptr_phys; }; -enum ummu_ver { - NO_PROD_ID = 0, - MAX_VER, -}; - enum ummu_device_msi_index { EVTQ_MSI_INDEX, GERROR_MSI_INDEX, @@ -172,7 +167,6 @@ struct ummu_capability { #define UMMU_FEAT_TOKEN_CHK BIT(26) #define UMMU_FEAT_PERMQ BIT(27) #define UMMU_FEAT_NESTING BIT(28) - u32 features; u32 deid_bits; u32 tid_bits; @@ -183,6 +177,9 @@ struct ummu_capability { #define UMMU_OPT_MSIPOLL (1UL << 0) #define UMMU_OPT_DOUBLE_PLBI (1UL << 1) #define UMMU_OPT_KCMD_PLBI (1UL << 2) +#define UMMU_OPT_CHK_MAPT_CONTINUITY (1UL << 3) +#define UMMU_OPT_MCMDQ_DECREASE (1UL << 4) +#define UMMU_OPT_SYNC_WITH_PLBI (1UL << 5) u32 options; #define UMMU_MAX_ASIDS (1UL << 16) @@ -190,7 +187,6 @@ struct ummu_capability { #define UMMU_MAX_VMIDS (1UL << 16) unsigned int vmid_bits; - bool support_mapt; u32 mcmdq_log2num; u32 mcmdq_log2size; u32 evtq_log2num; @@ -202,7 +198,6 @@ struct ummu_capability { } permq_ent_num; u32 mtm_gp_max; u32 mtm_id_max; - u16 prod_ver; }; struct ummu_permq_addr { @@ -240,9 +235,9 @@ struct ummu_hash_table_cfg { /* ummu device inner helper functions */ enum ummu_dom_cfg_sync_type { + SYNC_TYPE_NONE, SYNC_DOM_ALL_CFG, SYNC_DOM_MUTI_CFG, - SYNC_NESTED_DOM_MUTI_CFG, SYNC_CLEAR_DOM_ALL_CFG, }; diff --git a/drivers/iommu/hisilicon/ummu_main.c b/drivers/iommu/hisilicon/ummu_main.c index 53adf3d2fdcfd91b3072d02ff45742c042365204..14d6e08b2c2cd4828f22ab46ba38b3032383e2d7 100644 --- a/drivers/iommu/hisilicon/ummu_main.c +++ b/drivers/iommu/hisilicon/ummu_main.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "logic_ummu/logic_ummu.h" #include "ummu_impl.h" @@ -28,7 +30,7 @@ #define UMMU_DRV_NAME "ummu" #define HISI_VENDOR_ID 0xCC08 -static bool ummu_special_identify; +static u16 ummu_chip_identifier; int ummu_write_reg_sync(struct ummu_device *ummu, u32 val, u32 reg_off, u32 ack_off) @@ -123,7 +125,7 @@ static int ummu_init_structures(struct ummu_device *ummu) if (ret) goto resource_release; - if (ummu->cap.support_mapt) { + if (ummu->cap.features & UMMU_FEAT_MAPT) { /* ctrl page is private for every ummu hardware */ ummu_device_init_permq_ctrl_page(ummu); /* ctx table is common for every ummu hardware */ @@ -139,21 +141,26 @@ static int ummu_init_structures(struct ummu_device *ummu) return ret; } -static void ummu_device_hw_probe_ver(struct ummu_device *ummu) +static void ummu_device_hw_probe_iidr(struct ummu_device *ummu) { u32 reg = readl_relaxed(ummu->base + UMMU_IIDR); - ummu->cap.prod_ver = (u16)FIELD_GET(IIDR_PROD_ID, reg); /* - * On the hisi chip with IIDR_PROD_ID set to 0, - * ummu enables special_identify to perform some - * specialized operations. + * In the 1st generation On the hisi chip, IIDR_PROD_ID is set to 0, + * ummu enables chip_identifier to perform some specialized operations. */ - if (ummu_special_identify && !ummu->cap.prod_ver) { + if ((ummu_chip_identifier == HISI_VENDOR_ID) && + !FIELD_GET(IIDR_PROD_ID, reg)) { ummu->cap.options |= UMMU_OPT_DOUBLE_PLBI; ummu->cap.options |= UMMU_OPT_KCMD_PLBI; + ummu->cap.options |= UMMU_OPT_CHK_MAPT_CONTINUITY; + ummu->cap.options |= UMMU_OPT_MCMDQ_DECREASE; + ummu->cap.options |= UMMU_OPT_SYNC_WITH_PLBI; ummu->cap.features &= ~UMMU_FEAT_STALLS; } + + dev_notice(ummu->dev, "features 0x%08x, options 0x%08x.\n", + ummu->cap.features, ummu->cap.options); } static void ummu_device_hw_probe_cap0(struct ummu_device *ummu) @@ -176,7 +183,8 @@ static void ummu_device_hw_probe_cap0(struct ummu_device *ummu) ubrt_pasids = ummu->core_dev.iommu.max_pasids; cap_pasids = 1 << ummu->cap.tid_bits; if (ubrt_pasids > cap_pasids) - pr_warn("ubrt max_pasids[%u] beyond capacity.\n", ubrt_pasids); + dev_warn(ummu->dev, "ubrt max_pasids[%u] beyond capacity.\n", + ubrt_pasids); pasids = min(cap_pasids, (1UL << UB_MAX_TID_BITS)); ummu->core_dev.iommu.max_pasids = min(ubrt_pasids, pasids); /* TECTE_TAG size */ @@ -432,10 +440,14 @@ static int ummu_device_hw_probe_cap4(struct ummu_device *ummu) int hw_permq_ent; hw_permq_ent = 1 << FIELD_GET(CAP4_UCMDQ_LOG2SIZE, reg); - ummu->cap.permq_ent_num.cmdq_num = hw_permq_ent; + ummu->cap.permq_ent_num.cmdq_num = + min_t(int, round_up(PAGE_SIZE / PCMDQ_ENT_BYTES, PCMDQ_ENT_BYTES), + hw_permq_ent); hw_permq_ent = 1 << FIELD_GET(CAP4_UCPLQ_LOG2SIZE, reg); - ummu->cap.permq_ent_num.cplq_num = hw_permq_ent; + ummu->cap.permq_ent_num.cplq_num = + min_t(int, round_up(PAGE_SIZE / PCPLQ_ENT_BYTES, PCPLQ_ENT_BYTES), + hw_permq_ent); if (ummu->impl_ops && ummu->impl_ops->hw_probe) return ummu->impl_ops->hw_probe(ummu); @@ -450,7 +462,7 @@ static void ummu_device_hw_probe_cap5(struct ummu_device *ummu) ummu->cap.features |= UMMU_FEAT_RANGE_PLBI; if (reg & CAP5_MAPT_SUPPORT) - ummu->cap.support_mapt = true; + ummu->cap.features |= UMMU_FEAT_MAPT; if (reg & CAP5_PT_GRAN4K_BIT) ummu->cap.ptsize_bitmap |= SZ_4K; @@ -470,8 +482,8 @@ static void ummu_device_hw_probe_cap5(struct ummu_device *ummu) if (ummu_sva_supported(ummu)) ummu->cap.features |= UMMU_FEAT_SVA; - dev_info(ummu->dev, "ias = %u-bit, oas = %u-bit, features = 0x%08x.\n", - ummu->cap.ias, ummu->cap.oas, ummu->cap.features); + dev_info(ummu->dev, "ias %u-bit, oas %u-bit.\n", + ummu->cap.ias, ummu->cap.oas); } static void ummu_device_hw_probe_cap6(struct ummu_device *ummu) @@ -508,7 +520,7 @@ static int ummu_device_hw_init(struct ummu_device *ummu) ummu_device_hw_probe_cap5(ummu); ummu_device_hw_probe_cap6(ummu); - ummu_device_hw_probe_ver(ummu); + ummu_device_hw_probe_iidr(ummu); return 0; } @@ -601,7 +613,7 @@ static int ummu_device_reset(struct ummu_device *ummu) if (ret) return ret; - if (ummu->cap.support_mapt) { + if (ummu->cap.features & UMMU_FEAT_MAPT) { ummu_device_set_permq_ctxtbl(ummu); ret = ummu_device_mapt_enable(ummu); if (ret) @@ -644,8 +656,7 @@ static int ummu_device_ubrt_probe(struct ummu_device *ummu) } node = (struct ummu_node *)fw->ubrt_node; - if (node->vendor_id == HISI_VENDOR_ID) - ummu_special_identify = true; + ummu_chip_identifier = node->vendor_id; ummu->core_dev.iommu.min_pasids = node->min_tid; ummu->core_dev.iommu.max_pasids = node->max_tid; @@ -766,24 +777,28 @@ static void ummu_device_shutdown(struct platform_device *pdev) ummu_device_disable(ummu); } +#ifdef CONFIG_OF static const struct of_device_id hisi_ummu_of_match[] = { { .compatible = "ub,ummu", }, { } }; MODULE_DEVICE_TABLE(of, hisi_ummu_of_match); +#endif +#ifdef CONFIG_ACPI static const struct acpi_device_id hisi_ummu_acpi_match[] = { { "HISI0551", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, hisi_ummu_acpi_match); +#endif struct platform_driver ummu_driver = { .driver = { .name = UMMU_DRV_NAME, .suppress_bind_attrs = true, - .of_match_table = hisi_ummu_of_match, - .acpi_match_table = hisi_ummu_acpi_match, + .of_match_table = of_match_ptr(hisi_ummu_of_match), + .acpi_match_table = ACPI_PTR(hisi_ummu_acpi_match), }, .probe = ummu_device_probe, .remove = ummu_device_remove, diff --git a/drivers/irqchip/irq-gic-v3-its-platform-msi.c b/drivers/irqchip/irq-gic-v3-its-platform-msi.c index 1ca7ef6186a20846df7b13cd6a502dbc5a094c46..884b088f4873c0961a6ff0f4a064a9b60380b183 100644 --- a/drivers/irqchip/irq-gic-v3-its-platform-msi.c +++ b/drivers/irqchip/irq-gic-v3-its-platform-msi.c @@ -80,13 +80,10 @@ static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, } #endif - if (dev->of_node) { + if (dev->of_node) ret = of_pmsi_get_dev_id(domain, dev, &dev_id); - } else { + else ret = iort_pmsi_get_dev_id(dev, &dev_id); - if (ret) - ret = ubrt_pmsi_get_interrupt_id(dev, &dev_id); - } if (ret) return ret; diff --git a/drivers/perf/hisilicon/ummu_pmu.c b/drivers/perf/hisilicon/ummu_pmu.c index d145bcee10faa9d89d4f88e23bc7d729ac5eae9a..69b79bf1efcebdf12482a433e66f4f5e248eb802 100644 --- a/drivers/perf/hisilicon/ummu_pmu.c +++ b/drivers/perf/hisilicon/ummu_pmu.c @@ -5,6 +5,8 @@ * Monitor Counter Groups (PMCG) associated with an UMMU node to monitor that node. */ +#include +#include #include #include #include @@ -1029,17 +1031,21 @@ static void ummu_pmu_shutdown(struct platform_device *pdev) ummu_pmu_disable(&ummu_pmu->pmu); } +#ifdef CONFIG_OF static const struct of_device_id hisi_ummu_pmu_of_match[] = { { .compatible = "ub,ummu_pmu", }, { } }; MODULE_DEVICE_TABLE(of, hisi_ummu_pmu_of_match); +#endif +#ifdef CONFIG_ACPI static const struct acpi_device_id hisi_ummu_pmu_acpi_match[] = { {"HISI0571", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, hisi_ummu_pmu_acpi_match); +#endif static ssize_t partid_store(struct device *kobj, struct device_attribute *attr, const char *buf, size_t count) @@ -1143,8 +1149,8 @@ static struct platform_driver ummu_pmu_driver = { .driver = { .name = UMMU_PMU_DRV_NAME, .suppress_bind_attrs = true, - .of_match_table = hisi_ummu_pmu_of_match, - .acpi_match_table = hisi_ummu_pmu_acpi_match, + .of_match_table = of_match_ptr(hisi_ummu_pmu_of_match), + .acpi_match_table = ACPI_PTR(hisi_ummu_pmu_acpi_match), .dev_groups = ummu_pmu_groups }, .probe = ummu_pmu_probe, diff --git a/drivers/ub/ubfi/Kconfig b/drivers/ub/ubfi/Kconfig index d3889afb24521a62dc20c178c4799592f9e3af4e..4cb8a264fe9af1a7adb5b0433b103c62c0f08ea6 100644 --- a/drivers/ub/ubfi/Kconfig +++ b/drivers/ub/ubfi/Kconfig @@ -15,16 +15,4 @@ config UB_UBFI within Linux. To compile this driver as a module, choose M here. Say 'M' here unless you know what you are doing -config UB_UBRT_PLAT_DEV - bool "Enable UBRT platform device support" - depends on UB_UBUS - default n - help - This option enables the configuration of platform devices related to - the ub ubrt table. - If enabled, the UBRT-related platform device will obtain the - interrupt ID from the ubrt table instead of the IORT table. - The obtained interrupt ID will be used for the MSI interrupt of the - UBRT-related platform device. - endif diff --git a/drivers/ub/ubfi/irq.c b/drivers/ub/ubfi/irq.c index 5835bc8421b367cb34c6ed58f6e636277267e581..3f449ff5aa0bf58192b1bc7b5714eaf0cd212545 100644 --- a/drivers/ub/ubfi/irq.c +++ b/drivers/ub/ubfi/irq.c @@ -77,32 +77,3 @@ void ubrt_unregister_gsi(u32 hwirq) } EXPORT_SYMBOL_GPL(ubrt_unregister_gsi); -#if IS_ENABLED(CONFIG_UB_UBRT_PLAT_DEV) -int ubrt_pmsi_get_interrupt_id(struct device *dev, u32 *interrupt_id) -{ - struct ubrt_fwnode *fw; - struct ummu_node *node; - - if (!dev->fwnode) - return -EINVAL; - - fw = ubrt_fwnode_get(dev->fwnode); - if (!fw) - return -ENODEV; - - switch (fw->type) { - case UBRT_UMMU: - node = (struct ummu_node *)fw->ubrt_node; - *interrupt_id = node->intr_id; - break; - case UBRT_UMMU_PMU: - node = (struct ummu_node *)fw->ubrt_node; - *interrupt_id = node->pmu_intr_id; - break; - default: - return -ENODEV; - } - dev_info(dev, "ubct pmsi successfully obtained interrupt id[0x%x].\n", *interrupt_id); - return 0; -} -#endif diff --git a/drivers/ub/ubfi/ummu.c b/drivers/ub/ubfi/ummu.c index 93f6dcbf8aa605d837489589cd32d32c5875f28d..b1e3618b83184a729777566b3cf975930b100f8b 100644 --- a/drivers/ub/ubfi/ummu.c +++ b/drivers/ub/ubfi/ummu.c @@ -109,14 +109,15 @@ static int __init ummu_add_resources(struct platform_device *pdev, static int ummu_rename_device(struct platform_device *pdev, enum ubrt_node_type type) { - static int device_count; + static int device_ummu_count; + static int device_pmu_count; char new_name[32]; int ret; if (type == UBRT_UMMU) - ret = snprintf(new_name, sizeof(new_name), "ummu.%d", device_count); + ret = snprintf(new_name, sizeof(new_name), "ummu.%d", device_ummu_count++); else - ret = snprintf(new_name, sizeof(new_name), "ummu_pmu.%d", device_count); + ret = snprintf(new_name, sizeof(new_name), "ummu_pmu.%d", device_pmu_count++); if (ret < 0 || ret >= sizeof(new_name)) { dev_err(&pdev->dev, "failed to generate new device name\n"); @@ -130,8 +131,6 @@ static int ummu_rename_device(struct platform_device *pdev, enum ubrt_node_type } pdev->name = pdev->dev.kobj.name; - device_count++; - return 0; } @@ -173,6 +172,7 @@ static int ummu_config_update(struct platform_device *pdev, return 0; } +#ifdef CONFIG_ACPI static acpi_status acpi_processor_ummu(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -239,7 +239,6 @@ static acpi_status acpi_processor_ummu(acpi_handle handle, u32 lvl, return status; } -#ifdef CONFIG_ACPI static int acpi_update_ummu_config(struct ummu_node *ummu_node, u32 index) { acpi_status status; diff --git a/include/ub/ubfi/ubfi.h b/include/ub/ubfi/ubfi.h index 5867311b10a63edded76a3ae34a2c201ff69f5aa..158bbc7f1aa36d4c3fa6d7f1e434a1fbf0c6300b 100644 --- a/include/ub/ubfi/ubfi.h +++ b/include/ub/ubfi/ubfi.h @@ -219,11 +219,4 @@ extern u8 ubc_feature; void ubrt_iommu_get_resv_regions(struct device *dev, struct list_head *list); #endif /* CONFIG_UB_UBFI */ -#if IS_ENABLED(CONFIG_UB_UBRT_PLAT_DEV) -int ubrt_pmsi_get_interrupt_id(struct device *dev, u32 *interrupt_id); -#else -static inline int ubrt_pmsi_get_interrupt_id(struct device *dev, u32 *interrupt_id) -{ return -ENODEV; } -#endif /* CONFIG_UB_UBRT_PLAT_DEV */ - #endif /* _UB_UBFI_UBFI_H_ */