/** * kvm_free_stage2_pgd - free all stage-2 tables * @kvm: The KVM struct pointer for the VM. * * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all * underlying level-2 and level-3 tables before freeing the actual level-1 table * and setting the struct pointer to NULL. * * Note we don't need locking here as this is only called when the VM is * destroyed, which can only be done once. */ void kvm_free_stage2_pgd(struct kvm *kvm) { if (kvm->arch.pgd == NULL) return; unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); free_pages((unsigned long)kvm->arch.pgd, S2_PGD_ORDER); kvm->arch.pgd = NULL; }
/** * kvm_free_stage2_pgd - free all stage-2 tables * @kvm: The KVM struct pointer for the VM. * * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all * underlying level-2 and level-3 tables before freeing the actual level-1 table * and setting the struct pointer to NULL. * * Note we don't need locking here as this is only called when the VM is * destroyed, which can only be done once. */ void kvm_free_stage2_pgd(struct kvm *kvm) { if (kvm->arch.pgd == NULL) return; unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); kvm_tlb_flush_vmid_ipa(kvm, 0); /* Invalidate TLB ALL */ free_pages((unsigned long)kvm->arch.pgd, S2_PGD_ORDER); kvm->arch.pgd = NULL; }
/** * kvm_free_stage2_pgd - free all stage-2 tables * @kvm: The KVM struct pointer for the VM. * * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all * underlying level-2 and level-3 tables before freeing the actual level-1 table * and setting the struct pointer to NULL. * * Note we don't need locking here as this is only called when the VM is * destroyed, which can only be done once. */ void kvm_free_stage2_pgd(struct kvm *kvm) { if (kvm->arch.pgd == NULL) return; unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE); kvm_free_hwpgd(kvm_get_hwpgd(kvm)); if (KVM_PREALLOC_LEVEL > 0) kfree(kvm->arch.pgd); kvm->arch.pgd = NULL; }
static void stage2_unmap_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) { hva_t hva = memslot->userspace_addr; phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT; phys_addr_t size = PAGE_SIZE * memslot->npages; hva_t reg_end = hva + size; /* * A memory region could potentially cover multiple VMAs, and any holes * between them, so iterate over all of them to find out if we should * unmap any of them. * * +--------------------------------------------+ * +---------------+----------------+ +----------------+ * | : VMA 1 | VMA 2 | | VMA 3 : | * +---------------+----------------+ +----------------+ * | memory region | * +--------------------------------------------+ */ do { struct vm_area_struct *vma = find_vma(current->mm, hva); hva_t vm_start, vm_end; if (!vma || vma->vm_start >= reg_end) break; /* * Take the intersection of this VMA with the memory region */ vm_start = max(hva, vma->vm_start); vm_end = min(reg_end, vma->vm_end); if (!(vma->vm_flags & VM_PFNMAP)) { gpa_t gpa = addr + (vm_start - memslot->userspace_addr); unmap_stage2_range(kvm, gpa, vm_end - vm_start); } hva = vm_end; } while (hva < reg_end); }