Commit 20019790 authored by Claudio Imbrenda's avatar Claudio Imbrenda
Browse files

KVM: s390: Refactor and split some gmap helpers



Refactor some gmap functions; move the implementation into a separate
file with only helper functions. The new helper functions work on vm
addresses, leaving all gmap logic in the gmap functions, which mostly
become just wrappers.

The whole gmap handling is going to be moved inside KVM soon, but the
helper functions need to touch core mm functions, and thus need to
stay in the core of kernel.

Reviewed-by: default avatarSteffen Eiden <seiden@linux.ibm.com>
Reviewed-by: default avatarChristoph Schlameuss <schlameuss@linux.ibm.com>
Acked-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Link: https://lore.kernel.org/r/20250528095502.226213-4-imbrenda@linux.ibm.com


Signed-off-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20250528095502.226213-4-imbrenda@linux.ibm.com>
parent 7e42ad66
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -13075,12 +13075,14 @@ S: Supported
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
F:	Documentation/virt/kvm/s390*
F:	arch/s390/include/asm/gmap.h
F:	arch/s390/include/asm/gmap_helpers.h
F:	arch/s390/include/asm/kvm*
F:	arch/s390/include/uapi/asm/kvm*
F:	arch/s390/include/uapi/asm/uvdevice.h
F:	arch/s390/kernel/uv.c
F:	arch/s390/kvm/
F:	arch/s390/mm/gmap.c
F:	arch/s390/mm/gmap_helpers.c
F:	drivers/s390/char/uvdevice.c
F:	tools/testing/selftests/drivers/s390x/uvdevice/
F:	tools/testing/selftests/kvm/*/s390/
+0 −2
Original line number Diff line number Diff line
@@ -110,7 +110,6 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,
int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
unsigned long __gmap_translate(struct gmap *, unsigned long gaddr);
int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr);
void gmap_discard(struct gmap *, unsigned long from, unsigned long to);
void __gmap_zap(struct gmap *, unsigned long gaddr);
void gmap_unlink(struct mm_struct *, unsigned long *table, unsigned long vmaddr);

@@ -134,7 +133,6 @@ int gmap_protect_one(struct gmap *gmap, unsigned long gaddr, int prot, unsigned

void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4],
			     unsigned long gaddr, unsigned long vmaddr);
int s390_disable_cow_sharing(void);
int s390_replace_asce(struct gmap *gmap);
void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns);
int __s390_uv_destroy_range(struct mm_struct *mm, unsigned long start,
+15 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 *  Helper functions for KVM guest address space mapping code
 *
 *    Copyright IBM Corp. 2025
 */

#ifndef _ASM_S390_GMAP_HELPERS_H
#define _ASM_S390_GMAP_HELPERS_H

void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr);
void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned long end);
int gmap_helper_disable_cow_sharing(void);

#endif /* _ASM_S390_GMAP_HELPERS_H */
+25 −5
Original line number Diff line number Diff line
@@ -11,12 +11,30 @@
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <asm/gmap.h>
#include <asm/gmap_helpers.h>
#include <asm/virtio-ccw.h>
#include "kvm-s390.h"
#include "trace.h"
#include "trace-s390.h"
#include "gaccess.h"

static void do_discard_gfn_range(struct kvm_vcpu *vcpu, gfn_t gfn_start, gfn_t gfn_end)
{
	struct kvm_memslot_iter iter;
	struct kvm_memory_slot *slot;
	struct kvm_memslots *slots;
	unsigned long start, end;

	slots = kvm_vcpu_memslots(vcpu);

	kvm_for_each_memslot_in_gfn_range(&iter, slots, gfn_start, gfn_end) {
		slot = iter.slot;
		start = __gfn_to_hva_memslot(slot, max(gfn_start, slot->base_gfn));
		end = __gfn_to_hva_memslot(slot, min(gfn_end, slot->base_gfn + slot->npages));
		gmap_helper_discard(vcpu->kvm->mm, start, end);
	}
}

static int diag_release_pages(struct kvm_vcpu *vcpu)
{
	unsigned long start, end;
@@ -32,12 +50,13 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)

	VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);

	mmap_read_lock(vcpu->kvm->mm);
	/*
	 * We checked for start >= end above, so lets check for the
	 * fast path (no prefix swap page involved)
	 */
	if (end <= prefix || start >= prefix + 2 * PAGE_SIZE) {
		gmap_discard(vcpu->arch.gmap, start, end);
		do_discard_gfn_range(vcpu, gpa_to_gfn(start), gpa_to_gfn(end));
	} else {
		/*
		 * This is slow path.  gmap_discard will check for start
@@ -45,13 +64,14 @@ static int diag_release_pages(struct kvm_vcpu *vcpu)
		 * prefix and let gmap_discard make some of these calls
		 * NOPs.
		 */
		gmap_discard(vcpu->arch.gmap, start, prefix);
		do_discard_gfn_range(vcpu, gpa_to_gfn(start), gpa_to_gfn(prefix));
		if (start <= prefix)
			gmap_discard(vcpu->arch.gmap, 0, PAGE_SIZE);
			do_discard_gfn_range(vcpu, 0, 1);
		if (end > prefix + PAGE_SIZE)
			gmap_discard(vcpu->arch.gmap, PAGE_SIZE, 2 * PAGE_SIZE);
		gmap_discard(vcpu->arch.gmap, prefix + 2 * PAGE_SIZE, end);
			do_discard_gfn_range(vcpu, 1, 2);
		do_discard_gfn_range(vcpu, gpa_to_gfn(prefix) + 2, gpa_to_gfn(end));
	}
	mmap_read_unlock(vcpu->kvm->mm);
	return 0;
}

+4 −1
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include <asm/machine.h>
#include <asm/stp.h>
#include <asm/gmap.h>
#include <asm/gmap_helpers.h>
#include <asm/nmi.h>
#include <asm/isc.h>
#include <asm/sclp.h>
@@ -2674,7 +2675,9 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
		if (r)
			break;

		r = s390_disable_cow_sharing();
		mmap_write_lock(kvm->mm);
		r = gmap_helper_disable_cow_sharing();
		mmap_write_unlock(kvm->mm);
		if (r)
			break;

Loading