summaryrefslogtreecommitdiff
path: root/arch/arm64/kvm/hyp
diff options
context:
space:
mode:
authorLaurentiu Tudor <laurentiu.tudor@nxp.com>2016-07-26 15:43:43 +0300
committerDong Aisheng <aisheng.dong@nxp.com>2021-11-02 16:57:49 +0800
commit3f399019810155070acd34b073432f1c03515100 (patch)
tree933d29a12756d29423976725c677f53c3b79b87d /arch/arm64/kvm/hyp
parentfcc052a740b800c8d799f62e78a94bfb18208d57 (diff)
arm64: KVM: support flushing device memory
In the current implementation, trying to flush memory not covered by the linear map (e.g. device memory) causes a crash. The QMAN region, even though it is a device region, it's cacheable. However, as we map the qman region with the same attributes as the guest, there is no need for cache flush. Use some reserved bits (reserved for software use) from the descriptor to mark this type of memory. This allows dropping the special checks for qman cacheable region when doing cache flushes. Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com> [rebased on upstream changes in KVM memory management - using generic page table API + hyp memory isolation] Signed-off-by: Diana Craciun <diana.craciun@oss.nxp.com>
Diffstat (limited to 'arch/arm64/kvm/hyp')
-rw-r--r--arch/arm64/kvm/hyp/pgtable.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index f8ceebe4982e..43793c746ab8 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -46,6 +46,8 @@
KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W | \
KVM_PTE_LEAF_ATTR_HI_S2_XN)
+#define KVM_PTE_LEAF_ATTR_S2_DEVICE BIT(55)
+
#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2)
#define KVM_MAX_OWNER_ID 1
@@ -686,7 +688,8 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
}
/* Perform CMOs before installation of the guest stage-2 PTE */
- if (mm_ops->dcache_clean_inval_poc && stage2_pte_cacheable(pgt, new))
+ if (mm_ops->dcache_clean_inval_poc && stage2_pte_cacheable(pgt, new) &&
+ !(new & KVM_PTE_LEAF_ATTR_S2_DEVICE))
mm_ops->dcache_clean_inval_poc(kvm_pte_follow(new, mm_ops),
granule);
@@ -1091,7 +1094,8 @@ static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
kvm_pte_t pte = *ptep;
kvm_pte_t *pte_follow;
- if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte))
+ if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte) ||
+ (pte & KVM_PTE_LEAF_ATTR_S2_DEVICE))
return 0;
pte_follow = kvm_pte_follow(pte, mm_ops);