Messages in this thread | | | Subject | Re: [PATCH] remoteproc: qcom_q6v5_mss: map/unmap metadata region before/after use | From | Sibi Sankar <> | Date | Wed, 11 May 2022 11:21:43 +0530 |
| |
Hey Matthias, Thanks for taking time to review the patch.
On 5/6/22 11:37 PM, Matthias Kaehlcke wrote: > On Fri, May 06, 2022 at 07:21:26PM +0530, Sibi Sankar wrote: >> The application processor accessing the dynamically assigned metadata >> region after assigning it to the remote Q6 would lead to an XPU violation. >> Fix this by un-mapping the metadata region post firmware header copy. The >> metadata region is freed only after the modem Q6 is done with fw header >> authentication. >> >> Signed-off-by: Sibi Sankar <quic_sibis@quicinc.com> > > Should this have a 'Fixes:' tag It ideally should have but similar to what we did for mba and mpss region map/unmap, it would be a ugly backport since it would point to the very first commit. We can agree to do a backport if it's ever reported upstream on any of the older SoCs.
-Sibi
> >> --- >> drivers/remoteproc/qcom_q6v5_mss.c | 43 +++++++++++++++++++++++++++++++------- >> 1 file changed, 35 insertions(+), 8 deletions(-) >> >> diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c >> index af217de75e4d..eb34a258b67b 100644 >> --- a/drivers/remoteproc/qcom_q6v5_mss.c >> +++ b/drivers/remoteproc/qcom_q6v5_mss.c >> @@ -10,6 +10,7 @@ >> #include <linux/clk.h> >> #include <linux/delay.h> >> #include <linux/devcoredump.h> >> +#include <linux/dma-map-ops.h> >> #include <linux/dma-mapping.h> >> #include <linux/interrupt.h> >> #include <linux/kernel.h> >> @@ -932,27 +933,52 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc, >> static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw, >> const char *fw_name) >> { >> - unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS; >> + unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_KERNEL_MAPPING; >> + unsigned long flags = VM_DMA_COHERENT | VM_FLUSH_RESET_PERMS; >> + struct page **pages; >> + struct page *page; >> dma_addr_t phys; >> void *metadata; >> int mdata_perm; >> int xferop_ret; >> size_t size; >> - void *ptr; >> + void *vaddr; >> + int count; >> int ret; >> + int i; >> >> metadata = qcom_mdt_read_metadata(fw, &size, fw_name, qproc->dev); >> if (IS_ERR(metadata)) >> return PTR_ERR(metadata); >> >> - ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs); >> - if (!ptr) { >> - kfree(metadata); >> + page = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs); >> + if (!page) { >> dev_err(qproc->dev, "failed to allocate mdt buffer\n"); >> - return -ENOMEM; >> + ret = -ENOMEM; >> + goto free_metadata; >> + } >> + >> + count = PAGE_ALIGN(size) >> PAGE_SHIFT; >> + pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL); >> + if (!pages) { >> + ret = -ENOMEM; >> + goto free_metadata; >> } >> >> - memcpy(ptr, metadata, size); >> + for (i = 0; i < count; i++) >> + pages[i] = nth_page(page, i); >> + >> + vaddr = vmap(pages, count, flags, dma_pgprot(qproc->dev, PAGE_KERNEL, dma_attrs)); >> + kfree(pages); >> + if (!vaddr) { >> + dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n", &phys, size); >> + ret = -EBUSY; >> + goto free_metadata; >> + } >> + >> + memcpy(vaddr, metadata, size); >> + >> + vunmap(vaddr); >> >> /* Hypervisor mapping to access metadata by modem */ >> mdata_perm = BIT(QCOM_SCM_VMID_HLOS); >> @@ -982,7 +1008,8 @@ static int q6v5_mpss_init_image(struct q6v5 *qproc, const struct firmware *fw, >> "mdt buffer not reclaimed system may become unstable\n"); >> >> free_dma_attrs: >> - dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs); >> + dma_free_attrs(qproc->dev, size, page, phys, dma_attrs); >> +free_metadata: >> kfree(metadata); >> >> return ret < 0 ? ret : 0; >> -- >> 2.7.4 >>
| |