ANDROID: KVM: arm64: iommu: Fix tracking of MMIO
As MMIO can be donated, it's not safe to ignore tracking it anymore. Taint any MMIO mapped in the IOMMU, so it can never be donated later. Bug: 357781595 Bug: 384432312 Change-Id: I9dced4529cb7525ae06e475e599e29e060f89483 Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
committed by
Treehugger Robot
parent
bdb9c5d1b2
commit
2bf285b26c
@@ -14,13 +14,13 @@
|
||||
* 01: The page is owned by the page-table owner, but is shared
|
||||
* with another entity.
|
||||
* 10: The page is shared with, but not owned by the page-table owner.
|
||||
* 11: Reserved for future use (lending).
|
||||
* 11: The page is tainted by host, and can't transition.
|
||||
*/
|
||||
enum pkvm_page_state {
|
||||
PKVM_PAGE_OWNED = 0ULL,
|
||||
PKVM_PAGE_SHARED_OWNED = BIT(0),
|
||||
PKVM_PAGE_SHARED_BORROWED = BIT(1),
|
||||
__PKVM_PAGE_RESERVED = BIT(0) | BIT(1),
|
||||
PKVM_PAGE_TAINTED = BIT(0) | BIT(1),
|
||||
|
||||
/* Special non-meta state that only applies to host pages. Will not go in PTE SW bits. */
|
||||
PKVM_MODULE_OWNED_PAGE = BIT(2),
|
||||
|
||||
@@ -1747,12 +1747,37 @@ int __pkvm_host_use_dma(phys_addr_t phys_addr, size_t size)
|
||||
return -EINVAL;
|
||||
|
||||
host_lock_component();
|
||||
ret = ___host_check_page_state_range(phys_addr, size, PKVM_PAGE_OWNED, reg, false);
|
||||
if (ret || !reg)
|
||||
goto out_ret;
|
||||
/*
|
||||
* Some differences between handling of RAM and device memory:
|
||||
* - The hyp vmemmap area for device memory is not backed by physical
|
||||
* pages in the hyp page tables.
|
||||
* - However, in some cases modules can donate MMIO, as they can't be
|
||||
* refcounted, taint them by marking them as shared PKVM_PAGE_TAINTED, and that
|
||||
* will prevent any future transition.
|
||||
*/
|
||||
if (!reg) {
|
||||
enum kvm_pgtable_prot prot;
|
||||
|
||||
for (i = 0; i < nr_pages; i++)
|
||||
__pkvm_host_use_dma_page(phys_addr + i * PAGE_SIZE);
|
||||
ret = ___host_check_page_state_range(phys_addr, size,
|
||||
PKVM_PAGE_TAINTED,
|
||||
reg, false);
|
||||
if (!ret)
|
||||
goto out_ret;
|
||||
ret = ___host_check_page_state_range(phys_addr, size,
|
||||
PKVM_PAGE_OWNED,
|
||||
reg, false);
|
||||
if (ret)
|
||||
goto out_ret;
|
||||
prot = pkvm_mkstate(PKVM_HOST_MMIO_PROT, PKVM_PAGE_TAINTED);
|
||||
ret = host_stage2_idmap_locked(phys_addr, size, prot, false);
|
||||
} else {
|
||||
ret = ___host_check_page_state_range(phys_addr, size, PKVM_PAGE_OWNED, reg, false);
|
||||
if (ret)
|
||||
goto out_ret;
|
||||
|
||||
for (i = 0; i < nr_pages; i++)
|
||||
__pkvm_host_use_dma_page(phys_addr + i * PAGE_SIZE);
|
||||
}
|
||||
|
||||
out_ret:
|
||||
host_unlock_component();
|
||||
|
||||
Reference in New Issue
Block a user