int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) { gfn_t gfn, end_gfn; kvm_pfn_t pfn; int r = 0; struct iommu_domain *domain = kvm->arch.iommu_domain; int flags; /* check if iommu exists and in use */ if (!domain) return 0; gfn = slot->base_gfn; end_gfn = gfn + slot->npages; flags = IOMMU_READ; if (!(slot->flags & KVM_MEM_READONLY)) flags |= IOMMU_WRITE; if (!kvm->arch.iommu_noncoherent) flags |= IOMMU_CACHE; while (gfn < end_gfn) { unsigned long page_size; /* Check if already mapped */ if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) { gfn += 1; continue; } /* Get the page size we could use to map */ page_size = kvm_host_page_size(kvm, gfn); /* Make sure the page_size does not exceed the memslot */ while ((gfn + (page_size >> PAGE_SHIFT)) > end_gfn) page_size >>= 1; /* Make sure gfn is aligned to the page size we want to map */ while ((gfn << PAGE_SHIFT) & (page_size - 1)) page_size >>= 1; /* Make sure hva is aligned to the page size we want to map */ while (__gfn_to_hva_memslot(slot, gfn) & (page_size - 1)) page_size >>= 1; /* * Pin all pages we are about to map in memory. This is * important because we unmap and unpin in 4kb steps later. */ pfn = kvm_pin_pages(slot, gfn, page_size >> PAGE_SHIFT); if (is_error_noslot_pfn(pfn)) { gfn += 1; continue; } /* Map into IO address space */ r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn), page_size, flags); if (r) { printk(KERN_ERR "kvm_iommu_map_address:" "iommu failed to map pfn=%llx\n", pfn); kvm_unpin_pages(kvm, pfn, page_size >> PAGE_SHIFT); goto unmap_pages; } gfn += page_size >> PAGE_SHIFT; cond_resched(); } return 0; unmap_pages: kvm_iommu_put_pages(kvm, slot->base_gfn, gfn - slot->base_gfn); return r; }
static int kvmppc_xive_native_set_queue_config(struct kvmppc_xive *xive, long eq_idx, u64 addr) { struct kvm *kvm = xive->kvm; struct kvm_vcpu *vcpu; struct kvmppc_xive_vcpu *xc; void __user *ubufp = (void __user *) addr; u32 server; u8 priority; struct kvm_ppc_xive_eq kvm_eq; int rc; __be32 *qaddr = 0; struct page *page; struct xive_q *q; gfn_t gfn; unsigned long page_size; /* * Demangle priority/server tuple from the EQ identifier */ priority = (eq_idx & KVM_XIVE_EQ_PRIORITY_MASK) >> KVM_XIVE_EQ_PRIORITY_SHIFT; server = (eq_idx & KVM_XIVE_EQ_SERVER_MASK) >> KVM_XIVE_EQ_SERVER_SHIFT; if (copy_from_user(&kvm_eq, ubufp, sizeof(kvm_eq))) return -EFAULT; vcpu = kvmppc_xive_find_server(kvm, server); if (!vcpu) { pr_err("Can't find server %d\n", server); return -ENOENT; } xc = vcpu->arch.xive_vcpu; if (priority != xive_prio_from_guest(priority)) { pr_err("Trying to restore invalid queue %d for VCPU %d\n", priority, server); return -EINVAL; } q = &xc->queues[priority]; pr_devel("%s VCPU %d priority %d fl:%x shift:%d addr:%llx g:%d idx:%d\n", __func__, server, priority, kvm_eq.flags, kvm_eq.qshift, kvm_eq.qaddr, kvm_eq.qtoggle, kvm_eq.qindex); /* * sPAPR specifies a "Unconditional Notify (n) flag" for the * H_INT_SET_QUEUE_CONFIG hcall which forces notification * without using the coalescing mechanisms provided by the * XIVE END ESBs. This is required on KVM as notification * using the END ESBs is not supported. */ if (kvm_eq.flags != KVM_XIVE_EQ_ALWAYS_NOTIFY) { pr_err("invalid flags %d\n", kvm_eq.flags); return -EINVAL; } rc = xive_native_validate_queue_size(kvm_eq.qshift); if (rc) { pr_err("invalid queue size %d\n", kvm_eq.qshift); return rc; } /* reset queue and disable queueing */ if (!kvm_eq.qshift) { q->guest_qaddr = 0; q->guest_qshift = 0; rc = xive_native_configure_queue(xc->vp_id, q, priority, NULL, 0, true); if (rc) { pr_err("Failed to reset queue %d for VCPU %d: %d\n", priority, xc->server_num, rc); return rc; } if (q->qpage) { put_page(virt_to_page(q->qpage)); q->qpage = NULL; } return 0; } if (kvm_eq.qaddr & ((1ull << kvm_eq.qshift) - 1)) { pr_err("queue page is not aligned %llx/%llx\n", kvm_eq.qaddr, 1ull << kvm_eq.qshift); return -EINVAL; } gfn = gpa_to_gfn(kvm_eq.qaddr); page = gfn_to_page(kvm, gfn); if (is_error_page(page)) { pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr); return -EINVAL; } page_size = kvm_host_page_size(kvm, gfn); if (1ull << kvm_eq.qshift > page_size) { pr_warn("Incompatible host page size %lx!\n", page_size); return -EINVAL; } qaddr = page_to_virt(page) + (kvm_eq.qaddr & ~PAGE_MASK); /* * Backup the queue page guest address to the mark EQ page * dirty for migration. */ q->guest_qaddr = kvm_eq.qaddr; q->guest_qshift = kvm_eq.qshift; /* * Unconditional Notification is forced by default at the * OPAL level because the use of END ESBs is not supported by * Linux. */ rc = xive_native_configure_queue(xc->vp_id, q, priority, (__be32 *) qaddr, kvm_eq.qshift, true); if (rc) { pr_err("Failed to configure queue %d for VCPU %d: %d\n", priority, xc->server_num, rc); put_page(page); return rc; } /* * Only restore the queue state when needed. When doing the * H_INT_SET_SOURCE_CONFIG hcall, it should not. */ if (kvm_eq.qtoggle != 1 || kvm_eq.qindex != 0) { rc = xive_native_set_queue_state(xc->vp_id, priority, kvm_eq.qtoggle, kvm_eq.qindex); if (rc) goto error; } rc = kvmppc_xive_attach_escalation(vcpu, priority, xive->single_escalation); error: if (rc) kvmppc_xive_native_cleanup_queue(vcpu, priority); return rc; }