Commit 1c753d00 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Bjorn Andersson

firmware: qcom: tzmem: fix virtual-to-physical address conversion

We currently only correctly convert the virtual address passed by the
caller to qcom_tzmem_to_phys() if it corresponds to the base address of
the chunk. If the user wants to convert some pointer at an offset
relative to that base address, we'll return 0. Let's change the
implementation of qcom_tzmem_to_phys(): iterate over the chunks and try
to call gen_pool_virt_to_phys() just-in-time instead of trying to call
it only once when creating the chunk.

Fixes: 84f5a7b6 ("firmware: qcom: add a dedicated TrustZone buffer allocator")
Reported-by: default avatarJohan Hovold <johan+linaro@kernel.org>
Closes: https://lore.kernel.org/lkml/20240729095542.21097-1-johan+linaro@kernel.org/Acked-by: default avatarAndrew Halaney <ahalaney@redhat.com>
Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/r/20240731-tzmem-efivars-fix-v2-1-f0e84071ec07@linaro.orgSigned-off-by: default avatarBjorn Andersson <andersson@kernel.org>
parent 9960085a
......@@ -40,7 +40,6 @@ struct qcom_tzmem_pool {
};
struct qcom_tzmem_chunk {
phys_addr_t paddr;
size_t size;
struct qcom_tzmem_pool *owner;
};
......@@ -385,7 +384,6 @@ void *qcom_tzmem_alloc(struct qcom_tzmem_pool *pool, size_t size, gfp_t gfp)
return NULL;
}
chunk->paddr = gen_pool_virt_to_phys(pool->genpool, vaddr);
chunk->size = size;
chunk->owner = pool;
......@@ -431,25 +429,37 @@ void qcom_tzmem_free(void *vaddr)
EXPORT_SYMBOL_GPL(qcom_tzmem_free);
/**
* qcom_tzmem_to_phys() - Map the virtual address of a TZ buffer to physical.
* @vaddr: Virtual address of the buffer allocated from a TZ memory pool.
* qcom_tzmem_to_phys() - Map the virtual address of TZ memory to physical.
* @vaddr: Virtual address of memory allocated from a TZ memory pool.
*
* Can be used in any context. The address must have been returned by a call
* to qcom_tzmem_alloc().
* Can be used in any context. The address must point to memory allocated
* using qcom_tzmem_alloc().
*
* Returns: Physical address of the buffer.
* Returns:
* Physical address mapped from the virtual or 0 if the mapping failed.
*/
phys_addr_t qcom_tzmem_to_phys(void *vaddr)
{
struct qcom_tzmem_chunk *chunk;
struct radix_tree_iter iter;
void __rcu **slot;
phys_addr_t ret;
guard(spinlock_irqsave)(&qcom_tzmem_chunks_lock);
chunk = radix_tree_lookup(&qcom_tzmem_chunks, (unsigned long)vaddr);
if (!chunk)
return 0;
radix_tree_for_each_slot(slot, &qcom_tzmem_chunks, &iter, 0) {
chunk = radix_tree_deref_slot_protected(slot,
&qcom_tzmem_chunks_lock);
return chunk->paddr;
ret = gen_pool_virt_to_phys(chunk->owner->genpool,
(unsigned long)vaddr);
if (ret == -1)
continue;
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(qcom_tzmem_to_phys);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment