aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-03-12 14:16:52 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2015-03-12 17:34:49 -0400
commitaeda9130c38e2e0e77c1aaa65292c2f5a81107a8 (patch)
tree1c217726f4716686217af22f9f1997c7cc9860a1
parent35307b9a5f7ebcc8d8db41c73b69c131b48ace2b (diff)
arm/arm64: KVM: Optimize handling of Access Flag faults
Now that we have page aging in Stage-2, it becomes obvious that we're doing way too much work handling the fault. The page is not going anywhere (it is still mapped), the page tables are already allocated, and all we want is to flip a bit in the PMD or PTE. Also, we can avoid any form of TLB invalidation, since a page with the AF bit off is not allowed to be cached. An obvious solution is to have a separate handler for FSC_ACCESS, where we pride ourselves to only do the very minimum amount of work. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Acked-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r--arch/arm/kvm/mmu.c46
-rw-r--r--arch/arm/kvm/trace.h15
2 files changed, 61 insertions, 0 deletions
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 1831aa26eef8..56c8b03c0ca1 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1304,6 +1304,46 @@ out_unlock:
1304 return ret; 1304 return ret;
1305} 1305}
1306 1306
1307/*
1308 * Resolve the access fault by making the page young again.
1309 * Note that because the faulting entry is guaranteed not to be
1310 * cached in the TLB, we don't need to invalidate anything.
1311 */
1312static void handle_access_fault(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
1313{
1314 pmd_t *pmd;
1315 pte_t *pte;
1316 pfn_t pfn;
1317 bool pfn_valid = false;
1318
1319 trace_kvm_access_fault(fault_ipa);
1320
1321 spin_lock(&vcpu->kvm->mmu_lock);
1322
1323 pmd = stage2_get_pmd(vcpu->kvm, NULL, fault_ipa);
1324 if (!pmd || pmd_none(*pmd)) /* Nothing there */
1325 goto out;
1326
1327 if (kvm_pmd_huge(*pmd)) { /* THP, HugeTLB */
1328 *pmd = pmd_mkyoung(*pmd);
1329 pfn = pmd_pfn(*pmd);
1330 pfn_valid = true;
1331 goto out;
1332 }
1333
1334 pte = pte_offset_kernel(pmd, fault_ipa);
1335 if (pte_none(*pte)) /* Nothing there either */
1336 goto out;
1337
1338 *pte = pte_mkyoung(*pte); /* Just a page... */
1339 pfn = pte_pfn(*pte);
1340 pfn_valid = true;
1341out:
1342 spin_unlock(&vcpu->kvm->mmu_lock);
1343 if (pfn_valid)
1344 kvm_set_pfn_accessed(pfn);
1345}
1346
1307/** 1347/**
1308 * kvm_handle_guest_abort - handles all 2nd stage aborts 1348 * kvm_handle_guest_abort - handles all 2nd stage aborts
1309 * @vcpu: the VCPU pointer 1349 * @vcpu: the VCPU pointer
@@ -1371,6 +1411,12 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
1371 /* Userspace should not be able to register out-of-bounds IPAs */ 1411 /* Userspace should not be able to register out-of-bounds IPAs */
1372 VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE); 1412 VM_BUG_ON(fault_ipa >= KVM_PHYS_SIZE);
1373 1413
1414 if (fault_status == FSC_ACCESS) {
1415 handle_access_fault(vcpu, fault_ipa);
1416 ret = 1;
1417 goto out_unlock;
1418 }
1419
1374 ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status); 1420 ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status);
1375 if (ret == 0) 1421 if (ret == 0)
1376 ret = 1; 1422 ret = 1;
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
index c09f37faff01..0ec35392d208 100644
--- a/arch/arm/kvm/trace.h
+++ b/arch/arm/kvm/trace.h
@@ -68,6 +68,21 @@ TRACE_EVENT(kvm_guest_fault,
68 __entry->hxfar, __entry->vcpu_pc) 68 __entry->hxfar, __entry->vcpu_pc)
69); 69);
70 70
71TRACE_EVENT(kvm_access_fault,
72 TP_PROTO(unsigned long ipa),
73 TP_ARGS(ipa),
74
75 TP_STRUCT__entry(
76 __field( unsigned long, ipa )
77 ),
78
79 TP_fast_assign(
80 __entry->ipa = ipa;
81 ),
82
83 TP_printk("IPA: %lx", __entry->ipa)
84);
85
71TRACE_EVENT(kvm_irq_line, 86TRACE_EVENT(kvm_irq_line,
72 TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level), 87 TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
73 TP_ARGS(type, vcpu_idx, irq_num, level), 88 TP_ARGS(type, vcpu_idx, irq_num, level),