kernel: Add hooks for user-accessible timers in the kernel.
Hooks for user-accessible timers allow implementation of a
more efficient gettimeofday in user-space.
Change-Id: If2f63d010c1cf142eb84f3745617e756913e46f7
Signed-off-by: Brent DeGraaf <bdegraaf@codeaurora.org>
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ddfb7c5..48268f0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1561,6 +1561,32 @@
#define in_gate_area(mm, addr) ({(void)mm; in_gate_area_no_mm(addr);})
#endif /* __HAVE_ARCH_GATE_AREA */
+#ifdef CONFIG_USE_USER_ACCESSIBLE_TIMERS
+static inline int use_user_accessible_timers(void) { return 1; }
+extern int in_user_timers_area(struct mm_struct *mm, unsigned long addr);
+extern struct vm_area_struct *get_user_timers_vma(struct mm_struct *mm);
+extern int get_user_timer_page(struct vm_area_struct *vma,
+ struct mm_struct *mm, unsigned long start, unsigned int gup_flags,
+ struct page **pages, int idx, int *goto_next_page);
+#else
+static inline int use_user_accessible_timers(void) { return 0; }
+static inline int in_user_timers_area(struct mm_struct *mm, unsigned long addr)
+{
+ return 0;
+}
+static inline struct vm_area_struct *get_user_timers_vma(struct mm_struct *mm)
+{
+ return NULL;
+}
+static inline int get_user_timer_page(struct vm_area_struct *vma,
+ struct mm_struct *mm, unsigned long start, unsigned int gup_flags,
+ struct page **pages, int idx, int *goto_next_page)
+{
+ *goto_next_page = 0;
+ return 0;
+}
+#endif
+
int drop_caches_sysctl_handler(struct ctl_table *, int,
void __user *, size_t *, loff_t *);
unsigned long shrink_slab(struct shrink_control *shrink,
diff --git a/mm/Kconfig b/mm/Kconfig
index 4cde97f..bbab5a6 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -390,3 +390,14 @@
the memory corresponding to the hole to be removed using memblock-
remove.
+config USE_USER_ACCESSIBLE_TIMERS
+ bool "Enables timers accessible from userspace"
+ depends on MMU
+ help
+ User-accessible timers allow the kernel to map kernel timer
+ registers to a userspace accessible page, to allow faster
+ access to time information. This flag will enable the
+ interface code in the main kernel. However, there are
+ architecture-specific code that will need to be enabled
+ separately.
+
diff --git a/mm/memory.c b/mm/memory.c
index 6105f47..174fcaa 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1726,6 +1726,19 @@
goto next_page;
}
+ if (use_user_accessible_timers()) {
+ if (!vma && in_user_timers_area(mm, start)) {
+ int goto_next_page = 0;
+ int user_timer_ret = get_user_timer_page(vma,
+ mm, start, gup_flags, pages, i,
+ &goto_next_page);
+ if (goto_next_page)
+ goto next_page;
+ else
+ return user_timer_ret;
+ }
+ }
+
if (!vma ||
(vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
!(vm_flags & vma->vm_flags))
diff --git a/mm/mlock.c b/mm/mlock.c
index ef726e8..38c77ab 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -229,7 +229,9 @@
if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) ||
is_vm_hugetlb_page(vma) ||
- vma == get_gate_vma(current->mm))) {
+ vma == get_gate_vma(current->mm) ||
+ ((use_user_accessible_timers() &&
+ (vma == get_user_timers_vma(current->mm)))))) {
__mlock_vma_pages_range(vma, start, end, NULL);
@@ -324,7 +326,9 @@
int lock = !!(newflags & VM_LOCKED);
if (newflags == vma->vm_flags || (vma->vm_flags & VM_SPECIAL) ||
- is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm))
+ is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm) ||
+ ((use_user_accessible_timers()) &&
+ (vma == get_user_timers_vma(current->mm))))
goto out; /* don't set VM_LOCKED, don't count */
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);