Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 84f5a7b67b61 ("firmware: qcom: add a dedicated TrustZone buffer allocator")
Reported-by: Johan Hovold <johan+linaro@kernel.org>
Closes: https://lore.kernel.org/lkml/20240729095542.21097-1-johan+linaro@kernel.org/
Acked-by: Andrew Halaney <ahalaney@redhat.com>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/r/20240731-tzmem-efivars-fix-v2-1-f0e84071ec07@linaro.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Bartosz Golaszewski and committed by
Bjorn Andersson
1c753d00 9960085a

+21 -11
+21 -11
drivers/firmware/qcom/qcom_tzmem.c
··· 40 40 }; 41 41 42 42 struct qcom_tzmem_chunk { 43 - phys_addr_t paddr; 44 43 size_t size; 45 44 struct qcom_tzmem_pool *owner; 46 45 }; ··· 384 385 return NULL; 385 386 } 386 387 387 - chunk->paddr = gen_pool_virt_to_phys(pool->genpool, vaddr); 388 388 chunk->size = size; 389 389 chunk->owner = pool; 390 390 ··· 429 431 EXPORT_SYMBOL_GPL(qcom_tzmem_free); 430 432 431 433 /** 432 - * qcom_tzmem_to_phys() - Map the virtual address of a TZ buffer to physical. 433 - * @vaddr: Virtual address of the buffer allocated from a TZ memory pool. 434 + * qcom_tzmem_to_phys() - Map the virtual address of TZ memory to physical. 435 + * @vaddr: Virtual address of memory allocated from a TZ memory pool. 434 436 * 435 - * Can be used in any context. The address must have been returned by a call 436 - * to qcom_tzmem_alloc(). 437 + * Can be used in any context. The address must point to memory allocated 438 + * using qcom_tzmem_alloc(). 437 439 * 438 - * Returns: Physical address of the buffer. 440 + * Returns: 441 + * Physical address mapped from the virtual or 0 if the mapping failed. 439 442 */ 440 443 phys_addr_t qcom_tzmem_to_phys(void *vaddr) 441 444 { 442 445 struct qcom_tzmem_chunk *chunk; 446 + struct radix_tree_iter iter; 447 + void __rcu **slot; 448 + phys_addr_t ret; 443 449 444 450 guard(spinlock_irqsave)(&qcom_tzmem_chunks_lock); 445 451 446 - chunk = radix_tree_lookup(&qcom_tzmem_chunks, (unsigned long)vaddr); 447 - if (!chunk) 448 - return 0; 452 + radix_tree_for_each_slot(slot, &qcom_tzmem_chunks, &iter, 0) { 453 + chunk = radix_tree_deref_slot_protected(slot, 454 + &qcom_tzmem_chunks_lock); 449 455 450 - return chunk->paddr; 456 + ret = gen_pool_virt_to_phys(chunk->owner->genpool, 457 + (unsigned long)vaddr); 458 + if (ret == -1) 459 + continue; 460 + 461 + return ret; 462 + } 463 + 464 + return 0; 451 465 } 452 466 EXPORT_SYMBOL_GPL(qcom_tzmem_to_phys); 453 467