From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6B69145FFB3 for ; Fri, 31 Jul 2026 16:43:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785516236; cv=none; b=iPyPysv8j0tSUp9mtR2dQ4DueR7s+Q/lLIYsETTUJVKTK/y4ukgBkIdtiexCUp0LoVliu/72x3Ja/cUXQO2EpjAViHmWZfHi5MMuJ32jJB7Z5v65ebTa9DX/ESiz+3EVN+5E1xDHM099G5hiE2gXTsDURyY/5ZFKMXCr1sQ4mLA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785516236; c=relaxed/simple; bh=04S1gzKFN2BK4RzlrOHQobVEGSqWLyPeu4/lGaAgilE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C2Hbo4NpP+rBo46YAATVU7jJZdvvyU/eAzwWishV6zDfjJjVEsxzJUOGIN+XCGpkjrSF3x4JzyPD4EGjw9Z/p9FQlXwZ7b4Q7QRhoBPC7BZpoWiIujOnY/qg+AXy6ogU5PzalwyUNQk7gjxslnRkrKpgpQ92mEZjuEcVltk4Xq0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Tr5ucZnr; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=Z+FaFEU9; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Tr5ucZnr"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="Z+FaFEU9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1785516233; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VBHFLJxPt4apj6AE6jTX9tz6JkNc6fSnqMXU7ny6bKM=; b=Tr5ucZnrhSBDQ5AMzIL/s45An7zdvRtOJnfNT1YM/M3i4j/ks7TA3SNECy7oHOYGZc6hw2 JqEE9dR3qosB4E64HDG6w0ZJpOrGX8rdc1bm1nHJ4G59aanC6djD3+BptjSiSnxmVMYl4r oOARmoyNlz8wQu4e+9dxQ6Sas2U6HK8= Received: from mail-ed1-f70.google.com (mail-ed1-f70.google.com [209.85.208.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-454-3J-wPV5aPca3pJOsBPbooA-1; Fri, 31 Jul 2026 12:43:48 -0400 X-MC-Unique: 3J-wPV5aPca3pJOsBPbooA-1 X-Mimecast-MFC-AGG-ID: 3J-wPV5aPca3pJOsBPbooA_1785516227 Received: by mail-ed1-f70.google.com with SMTP id 4fb4d7f45d1cf-698aa8bd688so1362465a12.0 for ; Fri, 31 Jul 2026 09:43:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1785516227; x=1786121027; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=VBHFLJxPt4apj6AE6jTX9tz6JkNc6fSnqMXU7ny6bKM=; b=Z+FaFEU93OqDL/AhvReT9Neyl2KZ7ZMDSanAz5yDXvljd+We7QmdxdUu/wei6WmNgT wnopHr9jk6G17VktXHQp6/eYwhEv8ogdV4GCczzYuZRUaryhbgGnGjDVV40IVkwoT7Oj sMS0wKS1QHLCY7mY3XIP2I3zy2QZ2OuvFBZHGwLnwqDa6qPdnt2uMoD2qQy0Q6JocMXJ sfDZmwXX59PbYiMmDWdD6+Tn5EwXKf75YYRNtUkvvftGdumXC5PrAr1v7bVDKYIi3A4R qHA2lhNNtymh3QnrVxhcCHHFpwYl4yY6EbRRWJn3ow6SBGFjntSYtOf/+/LoD6IPczZQ bVnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785516227; x=1786121027; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=VBHFLJxPt4apj6AE6jTX9tz6JkNc6fSnqMXU7ny6bKM=; b=CosJfemNdiZC0Jm+tg75HFdtTEtKWC+OXU0DslFR2a4VwbwvFd8zifa54JF3OPemny iOz/VzDpKVcTydDw1owEC2DlcO3T1zyjhe7GDea+2y8QEFnNswGvn8pVU/3o5COueW4e nedF/WghK3XLtOEBUyQ6QDeTBrB5CUWvyOR2wsX5TCwCZ8RQnWmLNKmJU5wHbHvT41pc l/OtupawbrtuS4Se+9wI/WP0elPsUAgY6dD8tUSxTv20aiRwCHi5C2LiG1+auWyh0UyT EVMyOqvuvLI2ZsP+VJe4z9OrpKmkxMc8/3yNysdF5JFxWjFECA1m3wV0CvUlGAQ/eUVK VqRg== X-Gm-Message-State: AOJu0YzUxOwDD1wgHf70kxzuKHEM68iT0ohOlJImC7b+4YpI4Gp51+Z7 SJRZmUiYZjkAJIWnlrCcpiEYP3hAdDoReeaa5WdQB8x4GMhlElJiyH4bwF/mL6uHz7LlowIXGsm WJNtQROXqPLORuAxX0ieklfqHglb+fQOBfszmZcq2PMB4BtT0Eei4zZJEst4NqTql2Mx4unCA7v Fqf0fUln9YiFdC/cn2fNkDot4Q8lePoldZiPZujs+EjtPaM4IIow== X-Gm-Gg: AR+sD10GJxnCbsYgsYun+0JlPRCUKFmsgEzypIiR7oFj0faIHz6SI8/ZkYmLUbY10cH QVLFREq0al4IamkQV4jZEVMtXN6BSVU+iSjk03N13e35Q7A9ok19V7jNikf/8tsyM4BXNOD+OO6 uv8CRILY2MSBPrl45I8yiHfG56GMETBSh/kLj0b0MHmvAafBclISS449rjR8wW/IqgWpOhYTrst IjzjxRfBokdOgyW0n+kgW5/H5S6oaSShbP22PfdEBKvx9KubU2BV6gJZOH3GUXGjSVtea7oV0I/ hb37/7wFfqgqk7x23KdmEBzAw4ONJZ03sLZVhUxglljrxJG2tffUeZKlOIlOx3sAQ2ecRvSahO6 xZHwZBRG4d0LqKPket9yFESnrm5Hc9P8njyxCBBvHqUNFfnNg9Ge9a9PemoQMFjW/utltO0AsMq A2oyU= X-Received: by 2002:a05:6402:4491:b0:6a0:47:71a3 with SMTP id 4fb4d7f45d1cf-6a0a7d09735mr241970a12.20.1785516226776; Fri, 31 Jul 2026 09:43:46 -0700 (PDT) X-Received: by 2002:a05:6402:4491:b0:6a0:47:71a3 with SMTP id 4fb4d7f45d1cf-6a0a7d09735mr241946a12.20.1785516226373; Fri, 31 Jul 2026 09:43:46 -0700 (PDT) Received: from [192.168.10.48] ([151.95.34.92]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6a09c655626sm2907232a12.22.2026.07.31.09.43.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 31 Jul 2026 09:43:45 -0700 (PDT) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: Boris Brezillon , Thomas Zimmermann , David Hildenbrand , Michal Hocko , Sergio Lopez , Christian Koenig , Huang Rui , bcm-kernel-feedback-list@broadcom.com, dri-devel@lists.freedesktop.org, linux-mm@kvack.org Subject: [PATCH RFT 1/3] mm: export variants of vmf_insert_pfn* for use with pfn_mkwrite() Date: Fri, 31 Jul 2026 18:43:39 +0200 Message-ID: <20260731164341.1109827-2-pbonzini@redhat.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260731164341.1109827-1-pbonzini@redhat.com> References: <20260731164341.1109827-1-pbonzini@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Right now, users of .pfn_mkwrite() have no way to create a PTE that has gone through maybe_mkwrite(). Because vma_set_page_prot() will have cleared the writable PTE bit, users of fixup_user_fault() will see a read-only PTE and have no clue that the page needs a *second* fault to reach its final status. Handling this in fixup_user_fault() is problematic: the information about the presence of *_mkwrite is only recorded in vma->vm_page_prot, which is an opaque pgprot_t, therefore only follow_pfnmap_start() knows how to retrieve it. There are actually some preexisting functions that suggest how this is supposed to be handled, namely vmf_insert_page_mkwrite() and vmf_insert_pfn_pmd(). Adjust mm/memory.c to export two more functions: vmf_insert_pfn_mkwrite() for the common case where vma->vm_page_prot is okay, and __vmf_insert_pfn_prot() when really all parameters are needed. This makes it possible to fix drivers that use .pfn_mkwrite together with vmf_insert_pfn() and vmf_insert_pfn_prot(). Signed-off-by: Paolo Bonzini --- include/linux/mm.h | 4 +++ mm/huge_memory.c | 2 +- mm/memory.c | 75 +++++++++++++++++++++++++++++++++------------- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 34c79b5fcb9b..33c7de36b214 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4551,6 +4551,10 @@ vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t pgprot); +vm_fault_t vmf_insert_pfn_mkwrite(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, bool write); +vm_fault_t __vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t pgprot, bool mkwrite); vm_fault_t vmf_insert_mixed(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); vm_fault_t vmf_insert_mixed_mkwrite(struct vm_area_struct *vma, diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b5d1e9d4463d..2f4dcaa819b7 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1615,7 +1615,7 @@ static vm_fault_t insert_pmd(struct vm_area_struct *vma, unsigned long addr, * @pfn: pfn to insert * @write: whether it's a write fault * - * Insert a pmd size pfn. See vmf_insert_pfn() for additional info. + * Insert a pmd size pfn. See vmf_insert_pfn_mkwrite() for additional info. * * Return: vm_fault_t value. */ diff --git a/mm/memory.c b/mm/memory.c index 40997a26846f..7b950be8f511 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2718,6 +2718,34 @@ static vm_fault_t insert_pfn(struct vm_area_struct *vma, unsigned long addr, return VM_FAULT_NOPAGE; } +vm_fault_t __vmf_insert_pfn_prot(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn, pgprot_t pgprot, + bool mkwrite) +{ + /* + * Technically, architectures with pte_special can avoid all these + * restrictions (same for remap_pfn_range). However we would like + * consistency in testing and feature parity among all, so we should + * try to keep these invariants in place for everybody. + */ + BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))); + BUG_ON((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) == + (VM_PFNMAP|VM_MIXEDMAP)); + BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags)); + BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn)); + + if (addr < vma->vm_start || addr >= vma->vm_end) + return VM_FAULT_SIGBUS; + + if (!pfn_modify_allowed(pfn, pgprot)) + return VM_FAULT_SIGBUS; + + pfnmap_setup_cachemode_pfn(pfn, &pgprot); + + return insert_pfn(vma, addr, pfn, pgprot, mkwrite); +} +EXPORT_SYMBOL(__vmf_insert_pfn_prot); + /** * vmf_insert_pfn_prot - insert single pfn into user vma with specified pgprot * @vma: user vma to map to @@ -2754,27 +2782,7 @@ static vm_fault_t insert_pfn(struct vm_area_struct *vma, unsigned long addr, vm_fault_t vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, pgprot_t pgprot) { - /* - * Technically, architectures with pte_special can avoid all these - * restrictions (same for remap_pfn_range). However we would like - * consistency in testing and feature parity among all, so we should - * try to keep these invariants in place for everybody. - */ - BUG_ON(!(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))); - BUG_ON((vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP)) == - (VM_PFNMAP|VM_MIXEDMAP)); - BUG_ON((vma->vm_flags & VM_PFNMAP) && is_cow_mapping(vma->vm_flags)); - BUG_ON((vma->vm_flags & VM_MIXEDMAP) && pfn_valid(pfn)); - - if (addr < vma->vm_start || addr >= vma->vm_end) - return VM_FAULT_SIGBUS; - - if (!pfn_modify_allowed(pfn, pgprot)) - return VM_FAULT_SIGBUS; - - pfnmap_setup_cachemode_pfn(pfn, &pgprot); - - return insert_pfn(vma, addr, pfn, pgprot, false); + return __vmf_insert_pfn_prot(vma, addr, pfn, pgprot, false); } EXPORT_SYMBOL(vmf_insert_pfn_prot); @@ -2805,6 +2813,31 @@ vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma, unsigned long addr, } EXPORT_SYMBOL(vmf_insert_pfn); +/** + * vmf_insert_pfn_mkwrite - insert single pfn into user vma, possibly writable + * @vma: user vma to map to + * @addr: target user address of this page + * @pfn: source kernel pfn + * @write: whether the PTE should be installed writable + * + * Like vmf_insert_pfn(), except that @write allows installing a writable + * PTE even when @vma is under write notification, i.e. when it has a + * .page_mkwrite() or .pfn_mkwrite() callback and vma_set_page_prot() has + * therefore cleared the write bit from @vma->vm_page_prot. + * + * Note that neither of these callbacks is invoked, so the caller must + * itself do whatever they would have done if @write is true. + * + * Context: Process context. May allocate using %GFP_KERNEL. + * Return: vm_fault_t value. + */ +vm_fault_t vmf_insert_pfn_mkwrite(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, bool write) +{ + return __vmf_insert_pfn_prot(vma, addr, pfn, vma->vm_page_prot, write); +} +EXPORT_SYMBOL(vmf_insert_pfn_mkwrite); + static bool vm_mixed_ok(struct vm_area_struct *vma, unsigned long pfn, bool mkwrite) { -- 2.55.0