On Tue, Dec 13, 2022 at 09:27:04PM +0530, Sibi Sankar wrote: > Hey Robin, > > Thanks for taking time to review the series. > > On 12/13/22 20:37, Robin Murphy wrote: > > On 2022-12-13 14:07, Sibi Sankar wrote: > > > The memory region allocated using dma_alloc_attr with no kernel mapping > > > attribute set would still be a part of the linear kernel map. Any access > > > to this region by the application processor after assigning it to the > > > remote Q6 will result in a XPU violation. Fix this by replacing the > > > dynamically allocated memory region with a no-map carveout and unmap the > > > modem metadata memory region before passing control to the remote Q6. > > > > > > Reported-by: Amit Pundir <amit.pundir@xxxxxxxxxx> > > > Fixes: 6c5a9dc2481b ("remoteproc: qcom: Make secure world call for > > > mem ownership switch") > > > Signed-off-by: Sibi Sankar <quic_sibis@xxxxxxxxxxx> > > > --- > > > > > > The addition of the carveout and memunmap is required only on SoCs that > > > mandate memory protection before transferring control to Q6, hence the > > > driver falls back to dynamic memory allocation in the absence of the > > > modem metadata carveout. > > > > The DMA_ATTR_NO_KERNEL_MAPPING stuff is still broken and pointless, so > > I'd expect to see this solution replacing it, not being added alongside. > > It's just silly to say pass the "I don't need a CPU mapping" flag, then > > manually open-code the same CPU mapping you would have got if you > > hadn't, in a way that only works at all when a cacheable alias exists > > anyway. > > only a subset of SoCs supported by the driver are affected by > the bug i.e. on the others dma_alloc_attr would still work > without problems. I can perhaps drop the NO_KERNEL_MAPPING along > with the vmap/vunmap and simplify things for those SoCs. > Or perhaps revert fc156629b23a? Thanks, Mani > - Sibi > > > > > Thanks, > > Robin. > > > > > drivers/remoteproc/qcom_q6v5_mss.c | 85 +++++++++++++++++++++--------- > > > 1 file changed, 61 insertions(+), 24 deletions(-) > > > > > > diff --git a/drivers/remoteproc/qcom_q6v5_mss.c > > > b/drivers/remoteproc/qcom_q6v5_mss.c > > > index fddb63cffee0..8264275ecbd0 100644 > > > --- a/drivers/remoteproc/qcom_q6v5_mss.c > > > +++ b/drivers/remoteproc/qcom_q6v5_mss.c > > > @@ -211,6 +211,7 @@ struct q6v5 { > > > size_t mba_size; > > > size_t dp_size; > > > + phys_addr_t mdata_phys; > > > phys_addr_t mpss_phys; > > > phys_addr_t mpss_reloc; > > > size_t mpss_size; > > > @@ -935,6 +936,7 @@ static int q6v5_mpss_init_image(struct q6v5 > > > *qproc, const struct firmware *fw, > > > { > > > unsigned long dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS | > > > DMA_ATTR_NO_KERNEL_MAPPING; > > > unsigned long flags = VM_DMA_COHERENT | VM_FLUSH_RESET_PERMS; > > > + void *mdata_region; > > > struct page **pages; > > > struct page *page; > > > dma_addr_t phys; > > > @@ -951,34 +953,48 @@ static int q6v5_mpss_init_image(struct q6v5 > > > *qproc, const struct firmware *fw, > > > if (IS_ERR(metadata)) > > > return PTR_ERR(metadata); > > > - page = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, > > > dma_attrs); > > > - if (!page) { > > > - kfree(metadata); > > > - dev_err(qproc->dev, "failed to allocate mdt buffer\n"); > > > - return -ENOMEM; > > > - } > > > + if (qproc->mdata_phys) { > > > + mdata_region = memremap(qproc->mdata_phys, size, MEMREMAP_WC); > > > + if (!mdata_region) { > > > + dev_err(qproc->dev, "unable to map memory region: > > > %pa+%zx\n", > > > + &qproc->mdata_phys, size); > > > + ret = -EBUSY; > > > + goto free_dma_attrs; > > > + } > > > - count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > > - pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL); > > > - if (!pages) { > > > - ret = -ENOMEM; > > > - goto free_dma_attrs; > > > - } > > > + memcpy(mdata_region, metadata, size); > > > + memunmap(mdata_region); > > > + phys = qproc->mdata_phys; > > > + } else { > > > + page = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, > > > dma_attrs); > > > + if (!page) { > > > + kfree(metadata); > > > + dev_err(qproc->dev, "failed to allocate mdt buffer\n"); > > > + return -ENOMEM; > > > + } > > > - for (i = 0; i < count; i++) > > > - pages[i] = nth_page(page, i); > > > + count = PAGE_ALIGN(size) >> PAGE_SHIFT; > > > + pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL); > > > + if (!pages) { > > > + ret = -ENOMEM; > > > + goto free_dma_attrs; > > > + } > > > - vaddr = vmap(pages, count, flags, pgprot_dmacoherent(PAGE_KERNEL)); > > > - kfree(pages); > > > - if (!vaddr) { > > > - dev_err(qproc->dev, "unable to map memory region: > > > %pa+%zx\n", &phys, size); > > > - ret = -EBUSY; > > > - goto free_dma_attrs; > > > - } > > > + for (i = 0; i < count; i++) > > > + pages[i] = nth_page(page, i); > > > - memcpy(vaddr, metadata, size); > > > + vaddr = vmap(pages, count, flags, > > > pgprot_dmacoherent(PAGE_KERNEL)); > > > + kfree(pages); > > > + if (!vaddr) { > > > + dev_err(qproc->dev, "unable to map memory region: > > > %pa+%zx\n", &phys, size); > > > + ret = -EBUSY; > > > + goto free_dma_attrs; > > > + } > > > - vunmap(vaddr); > > > + memcpy(vaddr, metadata, size); > > > + > > > + vunmap(vaddr); > > > + } > > > /* Hypervisor mapping to access metadata by modem */ > > > mdata_perm = BIT(QCOM_SCM_VMID_HLOS); > > > @@ -1008,7 +1024,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, page, phys, dma_attrs); > > > + if (!qproc->mdata_phys) > > > + dma_free_attrs(qproc->dev, size, page, phys, dma_attrs); > > > kfree(metadata); > > > return ret < 0 ? ret : 0; > > > @@ -1882,6 +1899,26 @@ static int q6v5_alloc_memory_region(struct > > > q6v5 *qproc) > > > qproc->mpss_phys = qproc->mpss_reloc = r.start; > > > qproc->mpss_size = resource_size(&r); > > > + if (!child) { > > > + node = of_parse_phandle(qproc->dev->of_node, > > > "memory-region", 2); > > > + } else { > > > + child = of_get_child_by_name(qproc->dev->of_node, "metadata"); > > > + node = of_parse_phandle(child, "memory-region", 0); > > > + of_node_put(child); > > > + } > > > + > > > + if (!node) > > > + return 0; > > > + > > > + ret = of_address_to_resource(node, 0, &r); > > > + of_node_put(node); > > > + if (ret) { > > > + dev_err(qproc->dev, "unable to resolve metadata region\n"); > > > + return ret; > > > + } > > > + > > > + qproc->mdata_phys = r.start; > > > + > > > return 0; > > > } -- மணிவண்ணன் சதாசிவம்