Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

RISC-V: KVM: Implement MMU notifiers

This patch implements MMU notifiers for KVM RISC-V so that Guest
physical address space is in-sync with Host physical address space.

This will allow swapping, page migration, etc to work transparently
with KVM RISC-V.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Alexander Graf <graf@amazon.com>
Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>

authored by

Anup Patel and committed by
Anup Patel
9955371c 9d05c1fe

+89 -5
+2
arch/riscv/include/asm/kvm_host.h
··· 196 196 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {} 197 197 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {} 198 198 199 + #define KVM_ARCH_WANT_MMU_NOTIFIER 200 + 199 201 void __kvm_riscv_hfence_gvma_vmid_gpa(unsigned long gpa, unsigned long vmid); 200 202 void __kvm_riscv_hfence_gvma_vmid(unsigned long vmid); 201 203 void __kvm_riscv_hfence_gvma_gpa(unsigned long gpa);
+1
arch/riscv/kvm/Kconfig
··· 20 20 config KVM 21 21 tristate "Kernel-based Virtual Machine (KVM) support (EXPERIMENTAL)" 22 22 depends on RISCV_SBI && MMU 23 + select MMU_NOTIFIER 23 24 select PREEMPT_NOTIFIERS 24 25 select ANON_INODES 25 26 select KVM_MMIO
+85 -5
arch/riscv/kvm/mmu.c
··· 300 300 } 301 301 } 302 302 303 - static void stage2_unmap_range(struct kvm *kvm, gpa_t start, gpa_t size) 303 + static void stage2_unmap_range(struct kvm *kvm, gpa_t start, 304 + gpa_t size, bool may_block) 304 305 { 305 306 int ret; 306 307 pte_t *ptep; ··· 326 325 327 326 next: 328 327 addr += page_size; 328 + 329 + /* 330 + * If the range is too large, release the kvm->mmu_lock 331 + * to prevent starvation and lockup detector warnings. 332 + */ 333 + if (may_block && addr < end) 334 + cond_resched_lock(&kvm->mmu_lock); 329 335 } 330 336 } 331 337 ··· 413 405 out: 414 406 stage2_cache_flush(&pcache); 415 407 return ret; 416 - 417 408 } 418 409 419 410 void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm, ··· 554 547 spin_lock(&kvm->mmu_lock); 555 548 if (ret) 556 549 stage2_unmap_range(kvm, mem->guest_phys_addr, 557 - mem->memory_size); 550 + mem->memory_size, false); 558 551 spin_unlock(&kvm->mmu_lock); 559 552 560 553 out: 561 554 mmap_read_unlock(current->mm); 562 555 return ret; 556 + } 557 + 558 + bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) 559 + { 560 + if (!kvm->arch.pgd) 561 + return 0; 562 + 563 + stage2_unmap_range(kvm, range->start << PAGE_SHIFT, 564 + (range->end - range->start) << PAGE_SHIFT, 565 + range->may_block); 566 + return 0; 567 + } 568 + 569 + bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) 570 + { 571 + int ret; 572 + kvm_pfn_t pfn = pte_pfn(range->pte); 573 + 574 + if (!kvm->arch.pgd) 575 + return 0; 576 + 577 + WARN_ON(range->end - range->start != 1); 578 + 579 + ret = stage2_map_page(kvm, NULL, range->start << PAGE_SHIFT, 580 + __pfn_to_phys(pfn), PAGE_SIZE, true, true); 581 + if (ret) { 582 + kvm_debug("Failed to map stage2 page (error %d)\n", ret); 583 + return 1; 584 + } 585 + 586 + return 0; 587 + } 588 + 589 + bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) 590 + { 591 + pte_t *ptep; 592 + u32 ptep_level = 0; 593 + u64 size = (range->end - range->start) << PAGE_SHIFT; 594 + 595 + if (!kvm->arch.pgd) 596 + return 0; 597 + 598 + WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PGDIR_SIZE); 599 + 600 + if (!stage2_get_leaf_entry(kvm, range->start << PAGE_SHIFT, 601 + &ptep, &ptep_level)) 602 + return 0; 603 + 604 + return ptep_test_and_clear_young(NULL, 0, ptep); 605 + } 606 + 607 + bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range) 608 + { 609 + pte_t *ptep; 610 + u32 ptep_level = 0; 611 + u64 size = (range->end - range->start) << PAGE_SHIFT; 612 + 613 + if (!kvm->arch.pgd) 614 + return 0; 615 + 616 + WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PGDIR_SIZE); 617 + 618 + if (!stage2_get_leaf_entry(kvm, range->start << PAGE_SHIFT, 619 + &ptep, &ptep_level)) 620 + return 0; 621 + 622 + return pte_young(*ptep); 563 623 } 564 624 565 625 int kvm_riscv_stage2_map(struct kvm_vcpu *vcpu, ··· 643 569 struct kvm_mmu_page_cache *pcache = &vcpu->arch.mmu_page_cache; 644 570 bool logging = (memslot->dirty_bitmap && 645 571 !(memslot->flags & KVM_MEM_READONLY)) ? true : false; 646 - unsigned long vma_pagesize; 572 + unsigned long vma_pagesize, mmu_seq; 647 573 648 574 mmap_read_lock(current->mm); 649 575 ··· 682 608 return ret; 683 609 } 684 610 611 + mmu_seq = kvm->mmu_notifier_seq; 612 + 685 613 hfn = gfn_to_pfn_prot(kvm, gfn, is_write, &writeable); 686 614 if (hfn == KVM_PFN_ERR_HWPOISON) { 687 615 send_sig_mceerr(BUS_MCEERR_AR, (void __user *)hva, ··· 702 626 703 627 spin_lock(&kvm->mmu_lock); 704 628 629 + if (mmu_notifier_retry(kvm, mmu_seq)) 630 + goto out_unlock; 631 + 705 632 if (writeable) { 706 633 kvm_set_pfn_dirty(hfn); 707 634 mark_page_dirty(kvm, gfn); ··· 718 639 if (ret) 719 640 kvm_err("Failed to map in stage2\n"); 720 641 642 + out_unlock: 721 643 spin_unlock(&kvm->mmu_lock); 722 644 kvm_set_pfn_accessed(hfn); 723 645 kvm_release_pfn_clean(hfn); ··· 755 675 756 676 spin_lock(&kvm->mmu_lock); 757 677 if (kvm->arch.pgd) { 758 - stage2_unmap_range(kvm, 0UL, stage2_gpa_size); 678 + stage2_unmap_range(kvm, 0UL, stage2_gpa_size, false); 759 679 pgd = READ_ONCE(kvm->arch.pgd); 760 680 kvm->arch.pgd = NULL; 761 681 kvm->arch.pgd_phys = 0;
+1
arch/riscv/kvm/vm.c
··· 65 65 case KVM_CAP_IOEVENTFD: 66 66 case KVM_CAP_DEVICE_CTRL: 67 67 case KVM_CAP_USER_MEMORY: 68 + case KVM_CAP_SYNC_MMU: 68 69 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: 69 70 case KVM_CAP_ONE_REG: 70 71 case KVM_CAP_READONLY_MEM: