Skip to content

Commit 1c753d0

Browse files
Bartosz Golaszewskiandersson
authored andcommitted
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: 84f5a7b ("firmware: qcom: add a dedicated TrustZone buffer allocator") Reported-by: Johan Hovold <[email protected]> Closes: https://lore.kernel.org/lkml/[email protected]/ Acked-by: Andrew Halaney <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 9960085 commit 1c753d0

File tree

1 file changed

+21
-11
lines changed

1 file changed

+21
-11
lines changed

drivers/firmware/qcom/qcom_tzmem.c

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ struct qcom_tzmem_pool {
4040
};
4141

4242
struct qcom_tzmem_chunk {
43-
phys_addr_t paddr;
4443
size_t size;
4544
struct qcom_tzmem_pool *owner;
4645
};
@@ -385,7 +384,6 @@ void *qcom_tzmem_alloc(struct qcom_tzmem_pool *pool, size_t size, gfp_t gfp)
385384
return NULL;
386385
}
387386

388-
chunk->paddr = gen_pool_virt_to_phys(pool->genpool, vaddr);
389387
chunk->size = size;
390388
chunk->owner = pool;
391389

@@ -431,25 +429,37 @@ void qcom_tzmem_free(void *vaddr)
431429
EXPORT_SYMBOL_GPL(qcom_tzmem_free);
432430

433431
/**
434-
* qcom_tzmem_to_phys() - Map the virtual address of a TZ buffer to physical.
435-
* @vaddr: Virtual address of the buffer allocated from a TZ memory pool.
432+
* qcom_tzmem_to_phys() - Map the virtual address of TZ memory to physical.
433+
* @vaddr: Virtual address of memory allocated from a TZ memory pool.
436434
*
437-
* Can be used in any context. The address must have been returned by a call
438-
* to qcom_tzmem_alloc().
435+
* Can be used in any context. The address must point to memory allocated
436+
* using qcom_tzmem_alloc().
439437
*
440-
* Returns: Physical address of the buffer.
438+
* Returns:
439+
* Physical address mapped from the virtual or 0 if the mapping failed.
441440
*/
442441
phys_addr_t qcom_tzmem_to_phys(void *vaddr)
443442
{
444443
struct qcom_tzmem_chunk *chunk;
444+
struct radix_tree_iter iter;
445+
void __rcu **slot;
446+
phys_addr_t ret;
445447

446448
guard(spinlock_irqsave)(&qcom_tzmem_chunks_lock);
447449

448-
chunk = radix_tree_lookup(&qcom_tzmem_chunks, (unsigned long)vaddr);
449-
if (!chunk)
450-
return 0;
450+
radix_tree_for_each_slot(slot, &qcom_tzmem_chunks, &iter, 0) {
451+
chunk = radix_tree_deref_slot_protected(slot,
452+
&qcom_tzmem_chunks_lock);
451453

452-
return chunk->paddr;
454+
ret = gen_pool_virt_to_phys(chunk->owner->genpool,
455+
(unsigned long)vaddr);
456+
if (ret == -1)
457+
continue;
458+
459+
return ret;
460+
}
461+
462+
return 0;
453463
}
454464
EXPORT_SYMBOL_GPL(qcom_tzmem_to_phys);
455465

0 commit comments

Comments
 (0)