Commit f872f540 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar

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 <akpm@linux-foundation.org>
Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/a26d1677c0bc7e774c33f469451a78ca31e9e6af.1451446564.git.luto@kernel.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent aa042141
...@@ -568,10 +568,26 @@ static inline void clear_tlb_flush_pending(struct mm_struct *mm) ...@@ -568,10 +568,26 @@ static inline void clear_tlb_flush_pending(struct mm_struct *mm)
} }
#endif #endif
struct vm_special_mapping struct vm_fault;
{
const char *name; 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; 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 { enum tlb_flush_reason {
......
...@@ -3030,11 +3030,16 @@ static int special_mapping_fault(struct vm_area_struct *vma, ...@@ -3030,11 +3030,16 @@ static int special_mapping_fault(struct vm_area_struct *vma,
pgoff_t pgoff; pgoff_t pgoff;
struct page **pages; struct page **pages;
if (vma->vm_ops == &legacy_special_mapping_vmops) if (vma->vm_ops == &legacy_special_mapping_vmops) {
pages = vma->vm_private_data; pages = vma->vm_private_data;
else } else {
pages = ((struct vm_special_mapping *)vma->vm_private_data)-> struct vm_special_mapping *sm = vma->vm_private_data;
pages;
if (sm->fault)
return sm->fault(sm, vma, vmf);
pages = sm->pages;
}
for (pgoff = vmf->pgoff; pgoff && *pages; ++pages) for (pgoff = vmf->pgoff; pgoff && *pages; ++pages)
pgoff--; pgoff--;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment