From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965493AbcALMDw (ORCPT ); Tue, 12 Jan 2016 07:03:52 -0500 Received: from terminus.zytor.com ([198.137.202.10]:58037 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965478AbcALMDs (ORCPT ); Tue, 12 Jan 2016 07:03:48 -0500 Date: Tue, 12 Jan 2016 04:02:37 -0800 From: tip-bot for Andy Lutomirski Message-ID: Cc: luto@kernel.org, tglx@linutronix.de, mingo@kernel.org, luto@amacapital.net, keescook@chromium.org, hpa@zytor.com, oleg@redhat.com, fenghua.yu@intel.com, torvalds@linux-foundation.org, quentin.casasnovas@oracle.com, linux-kernel@vger.kernel.org, peterz@infradead.org, bp@alien8.de, dave.hansen@linux.intel.com Reply-To: oleg@redhat.com, hpa@zytor.com, keescook@chromium.org, mingo@kernel.org, luto@amacapital.net, luto@kernel.org, tglx@linutronix.de, bp@alien8.de, dave.hansen@linux.intel.com, peterz@infradead.org, linux-kernel@vger.kernel.org, quentin.casasnovas@oracle.com, torvalds@linux-foundation.org, fenghua.yu@intel.com In-Reply-To: References: To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/asm] mm: Add a vm_special_mapping.fault() method Git-Commit-ID: f872f5400cc01373d8e29d9c7a5296ccfaf4ccf3 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: f872f5400cc01373d8e29d9c7a5296ccfaf4ccf3 Gitweb: http://git.kernel.org/tip/f872f5400cc01373d8e29d9c7a5296ccfaf4ccf3 Author: Andy Lutomirski AuthorDate: Tue, 29 Dec 2015 20:12:19 -0800 Committer: Ingo Molnar CommitDate: Tue, 12 Jan 2016 11:59:34 +0100 mm: Add a vm_special_mapping.fault() method Requiring special mappings to give a list of struct pages is inflexible: it prevents sane use of IO memory in a special mapping, it's inefficient (it requires arch code to initialize a list of struct pages, and it requires the mm core to walk the entire list just to figure out how long it is), and it prevents arch code from doing anything fancy when a special mapping fault occurs. Add a .fault method as an alternative to filling in a .pages array. Looks-OK-to: Andrew Morton Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Dave Hansen Cc: Fenghua Yu Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Peter Zijlstra Cc: Quentin Casasnovas Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/a26d1677c0bc7e774c33f469451a78ca31e9e6af.1451446564.git.luto@kernel.org Signed-off-by: Ingo Molnar --- include/linux/mm_types.h | 22 +++++++++++++++++++--- mm/mmap.c | 13 +++++++++---- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index f8d1492..c88e48a 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -568,10 +568,26 @@ static inline void clear_tlb_flush_pending(struct mm_struct *mm) } #endif -struct vm_special_mapping -{ - const char *name; +struct vm_fault; + +struct vm_special_mapping { + const char *name; /* The name, e.g. "[vdso]". */ + + /* + * If .fault is not provided, this points to a + * NULL-terminated array of pages that back the special mapping. + * + * This must not be NULL unless .fault is provided. + */ struct page **pages; + + /* + * If non-NULL, then this is called to resolve page faults + * on the special mapping. If used, .pages is not checked. + */ + int (*fault)(const struct vm_special_mapping *sm, + struct vm_area_struct *vma, + struct vm_fault *vmf); }; enum tlb_flush_reason { diff --git a/mm/mmap.c b/mm/mmap.c index 2ce04a6..f717453 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -3030,11 +3030,16 @@ static int special_mapping_fault(struct vm_area_struct *vma, pgoff_t pgoff; struct page **pages; - if (vma->vm_ops == &legacy_special_mapping_vmops) + if (vma->vm_ops == &legacy_special_mapping_vmops) { pages = vma->vm_private_data; - else - pages = ((struct vm_special_mapping *)vma->vm_private_data)-> - pages; + } else { + struct vm_special_mapping *sm = vma->vm_private_data; + + if (sm->fault) + return sm->fault(sm, vma, vmf); + + pages = sm->pages; + } for (pgoff = vmf->pgoff; pgoff && *pages; ++pages) pgoff--;