aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/include/asm/kvm_arm.h1
-rw-r--r--arch/arm/include/asm/kvm_host.h13
-rw-r--r--arch/arm/kvm/mmu.c65
-rw-r--r--arch/arm/kvm/trace.h33
-rw-r--r--arch/arm64/include/asm/esr.h1
-rw-r--r--arch/arm64/include/asm/kvm_arm.h1
-rw-r--r--arch/arm64/include/asm/kvm_host.h13
7 files changed, 104 insertions, 23 deletions
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 816db0bf2dd8..d995821f1698 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -185,6 +185,7 @@
185#define HSR_COND (0xfU << HSR_COND_SHIFT) 185#define HSR_COND (0xfU << HSR_COND_SHIFT)
186 186
187#define FSC_FAULT (0x04) 187#define FSC_FAULT (0x04)
188#define FSC_ACCESS (0x08)
188#define FSC_PERM (0x0c) 189#define FSC_PERM (0x0c)
189 190
190/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ 191/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 902a7d1441ae..d71607c16601 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -167,19 +167,10 @@ void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
167 167
168unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); 168unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
169int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); 169int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
170int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
171int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
170 172
171/* We do not have shadow page tables, hence the empty hooks */ 173/* We do not have shadow page tables, hence the empty hooks */
172static inline int kvm_age_hva(struct kvm *kvm, unsigned long start,
173 unsigned long end)
174{
175 return 0;
176}
177
178static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
179{
180 return 0;
181}
182
183static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm, 174static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
184 unsigned long address) 175 unsigned long address)
185{ 176{
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index ffa06e07eed2..1831aa26eef8 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1299,6 +1299,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
1299 1299
1300out_unlock: 1300out_unlock:
1301 spin_unlock(&kvm->mmu_lock); 1301 spin_unlock(&kvm->mmu_lock);
1302 kvm_set_pfn_accessed(pfn);
1302 kvm_release_pfn_clean(pfn); 1303 kvm_release_pfn_clean(pfn);
1303 return ret; 1304 return ret;
1304} 1305}
@@ -1333,7 +1334,8 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
1333 1334
1334 /* Check the stage-2 fault is trans. fault or write fault */ 1335 /* Check the stage-2 fault is trans. fault or write fault */
1335 fault_status = kvm_vcpu_trap_get_fault_type(vcpu); 1336 fault_status = kvm_vcpu_trap_get_fault_type(vcpu);
1336 if (fault_status != FSC_FAULT && fault_status != FSC_PERM) { 1337 if (fault_status != FSC_FAULT && fault_status != FSC_PERM &&
1338 fault_status != FSC_ACCESS) {
1337 kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n", 1339 kvm_err("Unsupported FSC: EC=%#x xFSC=%#lx ESR_EL2=%#lx\n",
1338 kvm_vcpu_trap_get_class(vcpu), 1340 kvm_vcpu_trap_get_class(vcpu),
1339 (unsigned long)kvm_vcpu_trap_get_fault(vcpu), 1341 (unsigned long)kvm_vcpu_trap_get_fault(vcpu),
@@ -1475,6 +1477,67 @@ void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte)
1475 handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte); 1477 handle_hva_to_gpa(kvm, hva, end, &kvm_set_spte_handler, &stage2_pte);
1476} 1478}
1477 1479
1480static int kvm_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
1481{
1482 pmd_t *pmd;
1483 pte_t *pte;
1484
1485 pmd = stage2_get_pmd(kvm, NULL, gpa);
1486 if (!pmd || pmd_none(*pmd)) /* Nothing there */
1487 return 0;
1488
1489 if (kvm_pmd_huge(*pmd)) { /* THP, HugeTLB */
1490 if (pmd_young(*pmd)) {
1491 *pmd = pmd_mkold(*pmd);
1492 return 1;
1493 }
1494
1495 return 0;
1496 }
1497
1498 pte = pte_offset_kernel(pmd, gpa);
1499 if (pte_none(*pte))
1500 return 0;
1501
1502 if (pte_young(*pte)) {
1503 *pte = pte_mkold(*pte); /* Just a page... */
1504 return 1;
1505 }
1506
1507 return 0;
1508}
1509
1510static int kvm_test_age_hva_handler(struct kvm *kvm, gpa_t gpa, void *data)
1511{
1512 pmd_t *pmd;
1513 pte_t *pte;
1514
1515 pmd = stage2_get_pmd(kvm, NULL, gpa);
1516 if (!pmd || pmd_none(*pmd)) /* Nothing there */
1517 return 0;
1518
1519 if (kvm_pmd_huge(*pmd)) /* THP, HugeTLB */
1520 return pmd_young(*pmd);
1521
1522 pte = pte_offset_kernel(pmd, gpa);
1523 if (!pte_none(*pte)) /* Just a page... */
1524 return pte_young(*pte);
1525
1526 return 0;
1527}
1528
1529int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end)
1530{
1531 trace_kvm_age_hva(start, end);
1532 return handle_hva_to_gpa(kvm, start, end, kvm_age_hva_handler, NULL);
1533}
1534
1535int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
1536{
1537 trace_kvm_test_age_hva(hva);
1538 return handle_hva_to_gpa(kvm, hva, hva, kvm_test_age_hva_handler, NULL);
1539}
1540
1478void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu) 1541void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu)
1479{ 1542{
1480 mmu_free_memory_cache(&vcpu->arch.mmu_page_cache); 1543 mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
index 6817664b46b8..c09f37faff01 100644
--- a/arch/arm/kvm/trace.h
+++ b/arch/arm/kvm/trace.h
@@ -210,6 +210,39 @@ TRACE_EVENT(kvm_set_spte_hva,
210 TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva) 210 TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
211); 211);
212 212
213TRACE_EVENT(kvm_age_hva,
214 TP_PROTO(unsigned long start, unsigned long end),
215 TP_ARGS(start, end),
216
217 TP_STRUCT__entry(
218 __field( unsigned long, start )
219 __field( unsigned long, end )
220 ),
221
222 TP_fast_assign(
223 __entry->start = start;
224 __entry->end = end;
225 ),
226
227 TP_printk("mmu notifier age hva: %#08lx -- %#08lx",
228 __entry->start, __entry->end)
229);
230
231TRACE_EVENT(kvm_test_age_hva,
232 TP_PROTO(unsigned long hva),
233 TP_ARGS(hva),
234
235 TP_STRUCT__entry(
236 __field( unsigned long, hva )
237 ),
238
239 TP_fast_assign(
240 __entry->hva = hva;
241 ),
242
243 TP_printk("mmu notifier test age hva: %#08lx", __entry->hva)
244);
245
213TRACE_EVENT(kvm_hvc, 246TRACE_EVENT(kvm_hvc,
214 TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm), 247 TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
215 TP_ARGS(vcpu_pc, r0, imm), 248 TP_ARGS(vcpu_pc, r0, imm),
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 92bbae381598..70522450ca23 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -90,6 +90,7 @@
90#define ESR_ELx_FSC (0x3F) 90#define ESR_ELx_FSC (0x3F)
91#define ESR_ELx_FSC_TYPE (0x3C) 91#define ESR_ELx_FSC_TYPE (0x3C)
92#define ESR_ELx_FSC_EXTABT (0x10) 92#define ESR_ELx_FSC_EXTABT (0x10)
93#define ESR_ELx_FSC_ACCESS (0x08)
93#define ESR_ELx_FSC_FAULT (0x04) 94#define ESR_ELx_FSC_FAULT (0x04)
94#define ESR_ELx_FSC_PERM (0x0C) 95#define ESR_ELx_FSC_PERM (0x0C)
95#define ESR_ELx_CV (UL(1) << 24) 96#define ESR_ELx_CV (UL(1) << 24)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 94674eb7e7bb..9e5543e08955 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -187,6 +187,7 @@
187 187
188/* For compatibility with fault code shared with 32-bit */ 188/* For compatibility with fault code shared with 32-bit */
189#define FSC_FAULT ESR_ELx_FSC_FAULT 189#define FSC_FAULT ESR_ELx_FSC_FAULT
190#define FSC_ACCESS ESR_ELx_FSC_ACCESS
190#define FSC_PERM ESR_ELx_FSC_PERM 191#define FSC_PERM ESR_ELx_FSC_PERM
191 192
192/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ 193/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 967fb1cee300..f0f58c9beec0 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -179,19 +179,10 @@ int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
179int kvm_unmap_hva_range(struct kvm *kvm, 179int kvm_unmap_hva_range(struct kvm *kvm,
180 unsigned long start, unsigned long end); 180 unsigned long start, unsigned long end);
181void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); 181void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
182int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
183int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
182 184
183/* We do not have shadow page tables, hence the empty hooks */ 185/* We do not have shadow page tables, hence the empty hooks */
184static inline int kvm_age_hva(struct kvm *kvm, unsigned long start,
185 unsigned long end)
186{
187 return 0;
188}
189
190static inline int kvm_test_age_hva(struct kvm *kvm, unsigned long hva)
191{
192 return 0;
193}
194
195static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm, 186static inline void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
196 unsigned long address) 187 unsigned long address)
197{ 188{