From 2bf285b26cb41337e5f2e83b3620e59789cd7b18 Mon Sep 17 00:00:00 2001 From: Mostafa Saleh Date: Mon, 3 Feb 2025 11:05:00 +0000 Subject: [PATCH] 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 --- arch/arm64/kvm/hyp/include/nvhe/memory.h | 4 +-- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 35 ++++++++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h index cccef45019d0..d7572a62640a 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h @@ -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), diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 1d3ee3b65e4b..c4c3e24a9f2c 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -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();