Commit 36567f1d authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-riscv-fixes-6.18-2' of https://github.com/kvm-riscv/linux into HEAD

KVM/riscv fixes for 6.18, take #2

- Fix check for local interrupts on riscv32
- Read HGEIP CSR on the correct cpu when checking for IMSIC interrupts
- Remove automatic I/O mapping from kvm_arch_prepare_memory_region()
parents 6146a0f1 8c5fa376
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -689,8 +689,20 @@ bool kvm_riscv_vcpu_aia_imsic_has_interrupt(struct kvm_vcpu *vcpu)
	 */

	read_lock_irqsave(&imsic->vsfile_lock, flags);
	if (imsic->vsfile_cpu > -1)
	if (imsic->vsfile_cpu > -1) {
		/*
		 * This function is typically called from kvm_vcpu_block() via
		 * kvm_arch_vcpu_runnable() upon WFI trap. The kvm_vcpu_block()
		 * can be preempted and the blocking VCPU might resume on a
		 * different CPU. This means it is possible that current CPU
		 * does not match the imsic->vsfile_cpu hence this function
		 * must check imsic->vsfile_cpu before accessing HGEIP CSR.
		 */
		if (imsic->vsfile_cpu != vcpu->cpu)
			ret = true;
		else
			ret = !!(csr_read(CSR_HGEIP) & BIT(imsic->vsfile_hgei));
	}
	read_unlock_irqrestore(&imsic->vsfile_lock, flags);

	return ret;
+2 −23
Original line number Diff line number Diff line
@@ -171,7 +171,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
				enum kvm_mr_change change)
{
	hva_t hva, reg_end, size;
	gpa_t base_gpa;
	bool writable;
	int ret = 0;

@@ -190,15 +189,13 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
	hva = new->userspace_addr;
	size = new->npages << PAGE_SHIFT;
	reg_end = hva + size;
	base_gpa = new->base_gfn << PAGE_SHIFT;
	writable = !(new->flags & KVM_MEM_READONLY);

	mmap_read_lock(current->mm);

	/*
	 * A memory region could potentially cover multiple VMAs, and
	 * any holes between them, so iterate over all of them to find
	 * out if we can map any of them right now.
	 * any holes between them, so iterate over all of them.
	 *
	 *     +--------------------------------------------+
	 * +---------------+----------------+   +----------------+
@@ -209,7 +206,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
	 */
	do {
		struct vm_area_struct *vma;
		hva_t vm_start, vm_end;
		hva_t vm_end;

		vma = find_vma_intersection(current->mm, hva, reg_end);
		if (!vma)
@@ -225,36 +222,18 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
		}

		/* 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 = base_gpa + (vm_start - hva);
			phys_addr_t pa;

			pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
			pa += vm_start - vma->vm_start;

			/* IO region dirty page logging not allowed */
			if (new->flags & KVM_MEM_LOG_DIRTY_PAGES) {
				ret = -EINVAL;
				goto out;
			}

			ret = kvm_riscv_mmu_ioremap(kvm, gpa, pa, vm_end - vm_start,
						    writable, false);
			if (ret)
				break;
		}
		hva = vm_end;
	} while (hva < reg_end);

	if (change == KVM_MR_FLAGS_ONLY)
		goto out;

	if (ret)
		kvm_riscv_mmu_iounmap(kvm, base_gpa, size);

out:
	mmap_read_unlock(current->mm);
	return ret;
+1 −1
Original line number Diff line number Diff line
@@ -212,7 +212,7 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)

int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
	return (kvm_riscv_vcpu_has_interrupts(vcpu, -1UL) &&
	return (kvm_riscv_vcpu_has_interrupts(vcpu, -1ULL) &&
		!kvm_riscv_vcpu_stopped(vcpu) && !vcpu->arch.pause);
}