Message ID | 20240526144443.14345-9-jason-jh.lin@mediatek.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add CMDQ secure driver for SVP | expand |
Hi, Jason: On Sun, 2024-05-26 at 22:44 +0800, Jason-JH.Lin wrote: > Open secure cmdq_pkt APIs to support executing commands in secure world. > > 1. Add cmdq_sec_pkt_alloc_sec_data(), cmdq_sec_pkt_free_sec_data() and > cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt that will > be referenced in the secure world. > > 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() to > generate commands that need to be executed in the secure world. > In cmdq_sec_pkt_write(), we need to prepare the metadata to store > buffer offset of the secure buffer handle because secure world can > only translate the start address of secure buffer by secure handle. > > Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com> > Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com> > --- [snip] > + > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum cmdq_sec_scenario scenario) > +{ > + struct cmdq_sec_data *sec_data; > + int ret; > + > + if (!pkt) { > + pr_err("invalid pkt:%p", pkt); > + return -EINVAL; > + } > + > + ret = cmdq_sec_pkt_alloc_sec_data(pkt); > + if (ret < 0) > + return ret; > + > + pr_debug("[%s %d] pkt:%p sec_data:%p scen:%u", > + __func__, __LINE__, pkt, pkt->sec_data, scenario); > + > + sec_data = (struct cmdq_sec_data *)pkt->sec_data; > + sec_data->scenario = scenario; > + > + return 0; > +} What does cmdq_sec_pkt_set_data() exactly do? It seems to enable/disable protection on hardware of certain pipeline. In future, you would use secure GCE for normal video and secure video. Would you also use secure display pipeline for both normal video and secure video? If so, I think we could drop this function because the hardware is always protected. Regards, CK > +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_set_data); > +
Hi CK, On Tue, 2024-05-28 at 03:01 +0000, CK Hu (胡俊光) wrote: > Hi, Jason: > > On Sun, 2024-05-26 at 22:44 +0800, Jason-JH.Lin wrote: > > Open secure cmdq_pkt APIs to support executing commands in secure > > world. > > > > 1. Add cmdq_sec_pkt_alloc_sec_data(), cmdq_sec_pkt_free_sec_data() > > and > > cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt that > > will > > be referenced in the secure world. > > > > 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() to > > generate commands that need to be executed in the secure world. > > In cmdq_sec_pkt_write(), we need to prepare the metadata to > > store > > buffer offset of the secure buffer handle because secure world > > can > > only translate the start address of secure buffer by secure > > handle. > > > > Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com> > > Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com> > > --- > > [snip] > > > + > > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum > > cmdq_sec_scenario scenario) > > +{ > > + struct cmdq_sec_data *sec_data; > > + int ret; > > + > > + if (!pkt) { > > + pr_err("invalid pkt:%p", pkt); > > + return -EINVAL; > > + } > > + > > + ret = cmdq_sec_pkt_alloc_sec_data(pkt); > > + if (ret < 0) > > + return ret; > > + > > + pr_debug("[%s %d] pkt:%p sec_data:%p scen:%u", > > + __func__, __LINE__, pkt, pkt->sec_data, scenario); > > + > > + sec_data = (struct cmdq_sec_data *)pkt->sec_data; > > + sec_data->scenario = scenario; > > + > > + return 0; > > +} > > What does cmdq_sec_pkt_set_data() exactly do? It seems to > enable/disable protection on hardware of certain pipeline. > In future, you would use secure GCE for normal video and secure > video. > Would you also use secure display pipeline for both normal video and > secure video? I think I won't do that. > If so, I think we could drop this function because the hardware is > always protected. > But we will use ENABLE and DISABLE scenario to notify secure world to enable/disable the protection of secure buffer and register by setting larb port and DAPC. If there is secure memory output scenario (WiFi Display scenario) in the same display pipeline as main display scenario, we will need to use this scenario to differentiate them. Regards, Jason-JH.Lin > Regards, > CK > > > +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_set_data); > > +
Hi, Jason: On Tue, 2024-05-28 at 15:33 +0000, Jason-JH Lin (林睿祥) wrote: > Hi CK, > > On Tue, 2024-05-28 at 03:01 +0000, CK Hu (胡俊光) wrote: > > Hi, Jason: > > > > On Sun, 2024-05-26 at 22:44 +0800, Jason-JH.Lin wrote: > > > Open secure cmdq_pkt APIs to support executing commands in secure > > > world. > > > > > > 1. Add cmdq_sec_pkt_alloc_sec_data(), cmdq_sec_pkt_free_sec_data() > > > and > > > cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt that > > > will > > > be referenced in the secure world. > > > > > > 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() to > > > generate commands that need to be executed in the secure world. > > > In cmdq_sec_pkt_write(), we need to prepare the metadata to > > > store > > > buffer offset of the secure buffer handle because secure world > > > can > > > only translate the start address of secure buffer by secure > > > handle. > > > > > > Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com> > > > Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com> > > > --- > > > > [snip] > > > > > + > > > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum > > > cmdq_sec_scenario scenario) > > > +{ > > > + struct cmdq_sec_data *sec_data; > > > + int ret; > > > + > > > + if (!pkt) { > > > + pr_err("invalid pkt:%p", pkt); > > > + return -EINVAL; > > > + } > > > + > > > + ret = cmdq_sec_pkt_alloc_sec_data(pkt); > > > + if (ret < 0) > > > + return ret; > > > + > > > + pr_debug("[%s %d] pkt:%p sec_data:%p scen:%u", > > > + __func__, __LINE__, pkt, pkt->sec_data, scenario); > > > + > > > + sec_data = (struct cmdq_sec_data *)pkt->sec_data; > > > + sec_data->scenario = scenario; > > > + > > > + return 0; > > > +} > > > > What does cmdq_sec_pkt_set_data() exactly do? It seems to > > enable/disable protection on hardware of certain pipeline. > > In future, you would use secure GCE for normal video and secure > > video. > > Would you also use secure display pipeline for both normal video and > > secure video? > > I think I won't do that. > > > If so, I think we could drop this function because the hardware is > > always protected. > > > > But we will use ENABLE and DISABLE scenario to notify secure world to > enable/disable the protection of secure buffer and register by setting > larb port and DAPC. > > If there is secure memory output scenario (WiFi Display scenario) in > the same display pipeline as main display scenario, we will need to use > this scenario to differentiate them. This API looks no relation with CMDQ. All the job is that display control larb, dapc to turn on/off protection. All the process is done by CPU not GCE, right? If so, this API should be provided by display TA not CMDQ TA. Regards, CK > > Regards, > Jason-JH.Lin > > > Regards, > > CK > > > > > +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_set_data); > > > +
Hi CK, On Wed, 2024-05-29 at 01:58 +0000, CK Hu (胡俊光) wrote: > Hi, Jason: > > On Tue, 2024-05-28 at 15:33 +0000, Jason-JH Lin (林睿祥) wrote: > > Hi CK, > > > > On Tue, 2024-05-28 at 03:01 +0000, CK Hu (胡俊光) wrote: > > > Hi, Jason: > > > > > > On Sun, 2024-05-26 at 22:44 +0800, Jason-JH.Lin wrote: > > > > Open secure cmdq_pkt APIs to support executing commands in > > > > secure > > > > world. > > > > > > > > 1. Add cmdq_sec_pkt_alloc_sec_data(), > > > > cmdq_sec_pkt_free_sec_data() > > > > and > > > > cmdq_sec_pkt_set_data() to prepare the sec_data in cmdq_pkt > > > > that > > > > will > > > > be referenced in the secure world. > > > > > > > > 2. Add cmdq_sec_insert_backup_cookie() and cmdq_sec_pkt_write() > > > > to > > > > generate commands that need to be executed in the secure > > > > world. > > > > In cmdq_sec_pkt_write(), we need to prepare the metadata to > > > > store > > > > buffer offset of the secure buffer handle because secure > > > > world > > > > can > > > > only translate the start address of secure buffer by secure > > > > handle. > > > > > > > > Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com> > > > > Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com> > > > > --- > > > > > > [snip] > > > > > > > + > > > > +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum > > > > cmdq_sec_scenario scenario) > > > > +{ > > > > + struct cmdq_sec_data *sec_data; > > > > + int ret; > > > > + > > > > + if (!pkt) { > > > > + pr_err("invalid pkt:%p", pkt); > > > > + return -EINVAL; > > > > + } > > > > + > > > > + ret = cmdq_sec_pkt_alloc_sec_data(pkt); > > > > + if (ret < 0) > > > > + return ret; > > > > + > > > > + pr_debug("[%s %d] pkt:%p sec_data:%p scen:%u", > > > > + __func__, __LINE__, pkt, pkt->sec_data, > > > > scenario); > > > > + > > > > + sec_data = (struct cmdq_sec_data *)pkt->sec_data; > > > > + sec_data->scenario = scenario; > > > > + > > > > + return 0; > > > > +} > > > > > > What does cmdq_sec_pkt_set_data() exactly do? It seems to > > > enable/disable protection on hardware of certain pipeline. > > > In future, you would use secure GCE for normal video and secure > > > video. > > > Would you also use secure display pipeline for both normal video > > > and > > > secure video? > > > > I think I won't do that. > > > > > If so, I think we could drop this function because the hardware > > > is > > > always protected. > > > > > > > But we will use ENABLE and DISABLE scenario to notify secure world > > to > > enable/disable the protection of secure buffer and register by > > setting > > larb port and DAPC. > > > > If there is secure memory output scenario (WiFi Display scenario) > > in > > the same display pipeline as main display scenario, we will need to > > use > > this scenario to differentiate them. > > This API looks no relation with CMDQ. All the job is that display > control larb, dapc to turn on/off protection. > All the process is done by CPU not GCE, right? We nee to make sure all the settings are finished during vblanking, so all processes are done by GCE, we will insert the settings of larb and dapc by referencing to the other instruction for display HW and also the scenario here. > If so, this API should be provided by display TA not CMDQ TA. > Maybe we could parsing OVL layer control and WDMA instructions to decide to on/off the larb and dapc settings and also the scenario in secure world. I would try to remove this as well, then we only need to pass the command buffer and metadata list for buffer handle and its offset to the secure world. Regards, Jason-JH.Lin > Regards, > CK > > > > > Regards, > > Jason-JH.Lin > > > > > Regards, > > > CK > > > > > > > +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_set_data); > > > > +
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c index 42fae05f61a8..de6557f3ca2f 100644 --- a/drivers/soc/mediatek/mtk-cmdq-helper.c +++ b/drivers/soc/mediatek/mtk-cmdq-helper.c @@ -562,4 +562,159 @@ int cmdq_pkt_finalize(struct cmdq_pkt *pkt) } EXPORT_SYMBOL(cmdq_pkt_finalize); +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt) +{ + struct cmdq_client *cl = (struct cmdq_client *)pkt->cl; + struct cmdq_operand left, right; + dma_addr_t addr; + + addr = cmdq_sec_get_exec_cnt_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_read_s(pkt, CMDQ_THR_SPR_IDX1, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + + left.reg = true; + left.idx = CMDQ_THR_SPR_IDX1; + right.reg = false; + right.value = 1; + cmdq_pkt_logic_command(pkt, CMDQ_THR_SPR_IDX1, &left, CMDQ_LOGIC_ADD, &right); + + addr = cmdq_sec_get_cookie_addr(cl->chan); + cmdq_pkt_assign(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_HIGH(addr)); + cmdq_pkt_write_s(pkt, CMDQ_THR_SPR_IDX2, CMDQ_ADDR_LOW(addr), CMDQ_THR_SPR_IDX1); + cmdq_pkt_set_event(pkt, cmdq_sec_get_eof_event_id(cl->chan)); + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_insert_backup_cookie); + +static int cmdq_sec_realloc_addr_list(struct cmdq_pkt *pkt, const u32 count) +{ + struct cmdq_sec_data *sec_data = (struct cmdq_sec_data *)pkt->sec_data; + void *prev = (void *)(unsigned long)sec_data->addr_metadatas, *curr; + + if (count <= sec_data->addr_metadata_max_cnt) + return 0; + + curr = kcalloc(count, sizeof(*sec_data), GFP_KERNEL); + if (!curr) + return -ENOMEM; + + if (count && sec_data->addr_metadatas) + memcpy(curr, prev, sizeof(*sec_data) * sec_data->addr_metadata_max_cnt); + + kfree(prev); + + sec_data->addr_metadatas = (uintptr_t)curr; + sec_data->addr_metadata_max_cnt = count; + return 0; +} + +void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt) +{ + kfree(pkt->sec_data); +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_free_sec_data); + +int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt) +{ + struct cmdq_sec_data *sec_data; + + if (pkt->sec_data) + return 0; + + sec_data = kzalloc(sizeof(*sec_data), GFP_KERNEL); + if (!sec_data) + return -ENOMEM; + + pkt->sec_data = (void *)sec_data; + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_alloc_sec_data); + +static int cmdq_sec_append_metadata(struct cmdq_pkt *pkt, + const enum cmdq_iwc_addr_metadata_type type, + const u32 base, const u32 offset) +{ + struct cmdq_sec_data *sec_data; + struct iwc_cmdq_addr_metadata_t *meta; + int idx, max, ret; + + pr_debug("[%s %d] pkt:%p type:%u base:%#x offset:%#x", + __func__, __LINE__, pkt, type, base, offset); + + ret = cmdq_sec_pkt_alloc_sec_data(pkt); + if (ret < 0) + return ret; + + sec_data = (struct cmdq_sec_data *)pkt->sec_data; + idx = sec_data->addr_metadata_cnt; + if (idx >= CMDQ_IWC_MAX_ADDR_LIST_LENGTH) { + pr_err("idx:%u reach over:%u", idx, CMDQ_IWC_MAX_ADDR_LIST_LENGTH); + return -EFAULT; + } + + if (!sec_data->addr_metadata_max_cnt) + max = ADDR_METADATA_MAX_COUNT_ORIGIN; + else if (idx >= sec_data->addr_metadata_max_cnt) + max = sec_data->addr_metadata_max_cnt * 2; + else + max = sec_data->addr_metadata_max_cnt; + + ret = cmdq_sec_realloc_addr_list(pkt, max); + if (ret) + return ret; + + if (!sec_data->addr_metadatas) { + pr_info("addr_metadatas is missing"); + + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + return -ENOMEM; + + sec_data->addr_metadatas = (uintptr_t)(void *)meta; + } + meta = (struct iwc_cmdq_addr_metadata_t *)(uintptr_t)sec_data->addr_metadatas; + + meta[idx].type = type; + meta[idx].base_handle = base; + meta[idx].offset = offset; + sec_data->addr_metadata_cnt += 1; + return 0; +} + +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum cmdq_sec_scenario scenario) +{ + struct cmdq_sec_data *sec_data; + int ret; + + if (!pkt) { + pr_err("invalid pkt:%p", pkt); + return -EINVAL; + } + + ret = cmdq_sec_pkt_alloc_sec_data(pkt); + if (ret < 0) + return ret; + + pr_debug("[%s %d] pkt:%p sec_data:%p scen:%u", + __func__, __LINE__, pkt, pkt->sec_data, scenario); + + sec_data = (struct cmdq_sec_data *)pkt->sec_data; + sec_data->scenario = scenario; + + return 0; +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_set_data); + +int cmdq_sec_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, + enum cmdq_iwc_addr_metadata_type type, + u32 base, u32 base_offset) +{ + cmdq_pkt_write(pkt, subsys, offset, base); + + return cmdq_sec_append_metadata(pkt, type, base, base_offset); +} +EXPORT_SYMBOL_GPL(cmdq_sec_pkt_write); + MODULE_LICENSE("GPL v2"); diff --git a/include/linux/soc/mediatek/mtk-cmdq.h b/include/linux/soc/mediatek/mtk-cmdq.h index 5bee6f7fc400..6baf60313409 100644 --- a/include/linux/soc/mediatek/mtk-cmdq.h +++ b/include/linux/soc/mediatek/mtk-cmdq.h @@ -9,6 +9,7 @@ #include <linux/mailbox_client.h> #include <linux/mailbox/mtk-cmdq-mailbox.h> +#include <linux/mailbox/mtk-cmdq-sec-mailbox.h> #include <linux/timer.h> #define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0))) @@ -399,6 +400,52 @@ int cmdq_pkt_eoc(struct cmdq_pkt *pkt); */ int cmdq_pkt_finalize(struct cmdq_pkt *pkt); +/** + * cmdq_sec_pkt_free_sec_data() - free sec_data for CMDQ packet. + * @pkt: the CMDQ packet. + */ +void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt); + +/** + * cmdq_sec_pkt_alloc_sec_data() - allocate sec_data for CMDQ packet. + * @pkt: the CMDQ packet. + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt); + +/** + * cmdq_sec_insert_backup_cookie() - append backup cookie related instructions. + * @pkt: the CMDQ packet. + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt); + +/** + * cmdq_sec_pkt_set_data() - set secure configuration to sec_data in CDMQ packet. + * @pkt: the CMDQ packet. + * @scenario: the scenario to CMDQ TA. + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum cmdq_sec_scenario scenario); + +/** + * cmdq_sec_pkt_write() - append write secure buffer related instructions. + * @pkt: the CMDQ packet. + * @subsys: the CMDQ sub system code. + * @offset: register offset from CMDQ sub system. + * @type: the address metadata conversion type. + * @base: the secure handle of secure buffer. + * @base_offset:the address offset of secure buffer. + * + * Return: 0 for success; else the error code is returned + */ +int cmdq_sec_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, + enum cmdq_iwc_addr_metadata_type type, + u32 base, u32 base_offset); + #else /* IS_ENABLED(CONFIG_MTK_CMDQ) */ static inline int cmdq_dev_get_client_reg(struct device *dev, @@ -524,6 +571,30 @@ static inline int cmdq_pkt_finalize(struct cmdq_pkt *pkt) return -EINVAL; } +static inline void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt) {} + +static inline int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt) +{ + return -EINVAL; +} + +static inline int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt) +{ + return -EINVAL; +} + +static inline int cmdq_sec_pkt_set_data(struct cmdq_pkt *pkt, enum cmdq_sec_scenario scenario) +{ + return -EINVAL; +} + +static inline int cmdq_sec_pkt_write(struct cmdq_pkt *pkt, u8 subsys, u16 offset, + enum cmdq_iwc_addr_metadata_type type, + u32 base, u32 base_offset) +{ + return -EINVAL; +} + #endif /* IS_ENABLED(CONFIG_MTK_CMDQ) */ #endif /* __MTK_CMDQ_H__ */