Merge branches 'akpm' and 'akpm-hotfixes' (patches from Andrew)
Merge yet more updates and hotfixes from Andrew Morton: "Post-linux-next material, based upon latest upstream to catch the now-merged dependencies: - 10 patches. Subsystems affected by this patch series: mm (vmstat and migration) and compat. And bunch of hotfixes, mostly cc:stable: - 8 patches. Subsystems affected by this patch series: mm (hmm, hugetlb, vmscan, pagealloc, pagemap, kmemleak, mempolicy, and memblock)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: arch: remove compat_alloc_user_space compat: remove some compat entry points mm: simplify compat numa syscalls mm: simplify compat_sys_move_pages kexec: avoid compat_alloc_user_space kexec: move locking into do_kexec_load mm: migrate: change to use bool type for 'page_was_mapped' mm: migrate: fix the incorrect function name in comments mm: migrate: introduce a local variable to get the number of pages mm/vmstat: protect per cpu variables with preempt disable on RT * emailed hotfixes from Andrew Morton <akpm@linux-foundation.org>: nds32/setup: remove unused memblock_region variable in setup_memory() mm/mempolicy: fix a race between offset_il_node and mpol_rebind_task mm/kmemleak: allow __GFP_NOLOCKDEP passed to kmemleak's gfp mmap_lock: change trace and locking order mm/page_alloc.c: avoid accessing uninitialized pcp page migratetype mm,vmscan: fix divide by zero in get_scan_count mm/hugetlb: initialize hugetlb_usage in mm_init mm/hmm: bypass devmap pte when all pfn requested flags are fulfilled
This commit is contained in:
Коммит
a3fa7a101d
|
@ -107,11 +107,6 @@ struct compat_statfs {
|
|||
#define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
|
||||
#define COMPAT_MINSIGSTKSZ 2048
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
return (void __user *)compat_user_stack_pointer() - len;
|
||||
}
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
compat_key_t key;
|
||||
__compat_uid32_t uid;
|
||||
|
|
|
@ -430,17 +430,6 @@ extern unsigned long __must_check __arch_copy_to_user(void __user *to, const voi
|
|||
__actu_ret; \
|
||||
})
|
||||
|
||||
extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n);
|
||||
#define raw_copy_in_user(to, from, n) \
|
||||
({ \
|
||||
unsigned long __aciu_ret; \
|
||||
uaccess_ttbr0_enable(); \
|
||||
__aciu_ret = __arch_copy_in_user(__uaccess_mask_ptr(to), \
|
||||
__uaccess_mask_ptr(from), (n)); \
|
||||
uaccess_ttbr0_disable(); \
|
||||
__aciu_ret; \
|
||||
})
|
||||
|
||||
#define INLINE_COPY_TO_USER
|
||||
#define INLINE_COPY_FROM_USER
|
||||
|
||||
|
|
|
@ -649,11 +649,11 @@ __SYSCALL(__NR_inotify_add_watch, sys_inotify_add_watch)
|
|||
#define __NR_inotify_rm_watch 318
|
||||
__SYSCALL(__NR_inotify_rm_watch, sys_inotify_rm_watch)
|
||||
#define __NR_mbind 319
|
||||
__SYSCALL(__NR_mbind, compat_sys_mbind)
|
||||
__SYSCALL(__NR_mbind, sys_mbind)
|
||||
#define __NR_get_mempolicy 320
|
||||
__SYSCALL(__NR_get_mempolicy, compat_sys_get_mempolicy)
|
||||
__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
|
||||
#define __NR_set_mempolicy 321
|
||||
__SYSCALL(__NR_set_mempolicy, compat_sys_set_mempolicy)
|
||||
__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
|
||||
#define __NR_openat 322
|
||||
__SYSCALL(__NR_openat, compat_sys_openat)
|
||||
#define __NR_mkdirat 323
|
||||
|
@ -699,7 +699,7 @@ __SYSCALL(__NR_tee, sys_tee)
|
|||
#define __NR_vmsplice 343
|
||||
__SYSCALL(__NR_vmsplice, sys_vmsplice)
|
||||
#define __NR_move_pages 344
|
||||
__SYSCALL(__NR_move_pages, compat_sys_move_pages)
|
||||
__SYSCALL(__NR_move_pages, sys_move_pages)
|
||||
#define __NR_getcpu 345
|
||||
__SYSCALL(__NR_getcpu, sys_getcpu)
|
||||
#define __NR_epoll_pwait 346
|
||||
|
@ -811,7 +811,7 @@ __SYSCALL(__NR_rseq, sys_rseq)
|
|||
#define __NR_io_pgetevents 399
|
||||
__SYSCALL(__NR_io_pgetevents, compat_sys_io_pgetevents)
|
||||
#define __NR_migrate_pages 400
|
||||
__SYSCALL(__NR_migrate_pages, compat_sys_migrate_pages)
|
||||
__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
|
||||
#define __NR_kexec_file_load 401
|
||||
__SYSCALL(__NR_kexec_file_load, sys_kexec_file_load)
|
||||
/* 402 is unused */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
lib-y := clear_user.o delay.o copy_from_user.o \
|
||||
copy_to_user.o copy_in_user.o copy_page.o \
|
||||
copy_to_user.o copy_page.o \
|
||||
clear_page.o csum.o insn.o memchr.o memcpy.o \
|
||||
memset.o memcmp.o strcmp.o strncmp.o strlen.o \
|
||||
strnlen.o strchr.o strrchr.o tishift.o
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copy from user space to user space
|
||||
*
|
||||
* Copyright (C) 2012 ARM Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <asm/asm-uaccess.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
/*
|
||||
* Copy from user space to user space (alignment handled by the hardware)
|
||||
*
|
||||
* Parameters:
|
||||
* x0 - to
|
||||
* x1 - from
|
||||
* x2 - n
|
||||
* Returns:
|
||||
* x0 - bytes not copied
|
||||
*/
|
||||
.macro ldrb1 reg, ptr, val
|
||||
user_ldst 9998f, ldtrb, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro strb1 reg, ptr, val
|
||||
user_ldst 9998f, sttrb, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro ldrh1 reg, ptr, val
|
||||
user_ldst 9997f, ldtrh, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro strh1 reg, ptr, val
|
||||
user_ldst 9997f, sttrh, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro ldr1 reg, ptr, val
|
||||
user_ldst 9997f, ldtr, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro str1 reg, ptr, val
|
||||
user_ldst 9997f, sttr, \reg, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro ldp1 reg1, reg2, ptr, val
|
||||
user_ldp 9997f, \reg1, \reg2, \ptr, \val
|
||||
.endm
|
||||
|
||||
.macro stp1 reg1, reg2, ptr, val
|
||||
user_stp 9997f, \reg1, \reg2, \ptr, \val
|
||||
.endm
|
||||
|
||||
end .req x5
|
||||
srcin .req x15
|
||||
SYM_FUNC_START(__arch_copy_in_user)
|
||||
add end, x0, x2
|
||||
mov srcin, x1
|
||||
#include "copy_template.S"
|
||||
mov x0, #0
|
||||
ret
|
||||
SYM_FUNC_END(__arch_copy_in_user)
|
||||
EXPORT_SYMBOL(__arch_copy_in_user)
|
||||
|
||||
.section .fixup,"ax"
|
||||
.align 2
|
||||
9997: cmp dst, dstin
|
||||
b.ne 9998f
|
||||
// Before being absolutely sure we couldn't copy anything, try harder
|
||||
USER(9998f, ldtrb tmp1w, [srcin])
|
||||
USER(9998f, sttrb tmp1w, [dst])
|
||||
add dst, dst, #1
|
||||
9998: sub x0, end, dst // bytes not copied
|
||||
ret
|
||||
.previous
|
|
@ -154,8 +154,6 @@ FEXPORT(__raw_copy_from_user)
|
|||
EXPORT_SYMBOL(__raw_copy_from_user)
|
||||
FEXPORT(__raw_copy_to_user)
|
||||
EXPORT_SYMBOL(__raw_copy_to_user)
|
||||
FEXPORT(__raw_copy_in_user)
|
||||
EXPORT_SYMBOL(__raw_copy_in_user)
|
||||
/*
|
||||
* Note: dst & src may be unaligned, len may be 0
|
||||
* Temps
|
||||
|
|
|
@ -96,14 +96,6 @@ struct compat_statfs {
|
|||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)
|
||||
((unsigned long) current_thread_info() + THREAD_SIZE - 32) - 1;
|
||||
|
||||
return (void __user *) (regs->regs[29] - len);
|
||||
}
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
compat_key_t key;
|
||||
__compat_uid32_t uid;
|
||||
|
|
|
@ -428,7 +428,6 @@ do { \
|
|||
|
||||
extern size_t __raw_copy_from_user(void *__to, const void *__from, size_t __n);
|
||||
extern size_t __raw_copy_to_user(void *__to, const void *__from, size_t __n);
|
||||
extern size_t __raw_copy_in_user(void *__to, const void *__from, size_t __n);
|
||||
|
||||
static inline unsigned long
|
||||
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
|
||||
|
@ -480,31 +479,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
|
|||
#define INLINE_COPY_FROM_USER
|
||||
#define INLINE_COPY_TO_USER
|
||||
|
||||
static inline unsigned long
|
||||
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
register void __user *__cu_to_r __asm__("$4");
|
||||
register const void __user *__cu_from_r __asm__("$5");
|
||||
register long __cu_len_r __asm__("$6");
|
||||
|
||||
__cu_to_r = to;
|
||||
__cu_from_r = from;
|
||||
__cu_len_r = n;
|
||||
|
||||
__asm__ __volatile__(
|
||||
".set\tnoreorder\n\t"
|
||||
__MODULE_JAL(__raw_copy_in_user)
|
||||
".set\tnoat\n\t"
|
||||
__UA_ADDU "\t$1, %1, %2\n\t"
|
||||
".set\tat\n\t"
|
||||
".set\treorder"
|
||||
: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r)
|
||||
:
|
||||
: "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31",
|
||||
DADDI_SCRATCH, "memory");
|
||||
return __cu_len_r;
|
||||
}
|
||||
|
||||
extern __kernel_size_t __bzero(void __user *addr, __kernel_size_t size);
|
||||
|
||||
/*
|
||||
|
|
|
@ -239,9 +239,9 @@
|
|||
228 n32 clock_nanosleep sys_clock_nanosleep_time32
|
||||
229 n32 tgkill sys_tgkill
|
||||
230 n32 utimes sys_utimes_time32
|
||||
231 n32 mbind compat_sys_mbind
|
||||
232 n32 get_mempolicy compat_sys_get_mempolicy
|
||||
233 n32 set_mempolicy compat_sys_set_mempolicy
|
||||
231 n32 mbind sys_mbind
|
||||
232 n32 get_mempolicy sys_get_mempolicy
|
||||
233 n32 set_mempolicy sys_set_mempolicy
|
||||
234 n32 mq_open compat_sys_mq_open
|
||||
235 n32 mq_unlink sys_mq_unlink
|
||||
236 n32 mq_timedsend sys_mq_timedsend_time32
|
||||
|
@ -258,7 +258,7 @@
|
|||
247 n32 inotify_init sys_inotify_init
|
||||
248 n32 inotify_add_watch sys_inotify_add_watch
|
||||
249 n32 inotify_rm_watch sys_inotify_rm_watch
|
||||
250 n32 migrate_pages compat_sys_migrate_pages
|
||||
250 n32 migrate_pages sys_migrate_pages
|
||||
251 n32 openat sys_openat
|
||||
252 n32 mkdirat sys_mkdirat
|
||||
253 n32 mknodat sys_mknodat
|
||||
|
@ -279,7 +279,7 @@
|
|||
268 n32 sync_file_range sys_sync_file_range
|
||||
269 n32 tee sys_tee
|
||||
270 n32 vmsplice sys_vmsplice
|
||||
271 n32 move_pages compat_sys_move_pages
|
||||
271 n32 move_pages sys_move_pages
|
||||
272 n32 set_robust_list compat_sys_set_robust_list
|
||||
273 n32 get_robust_list compat_sys_get_robust_list
|
||||
274 n32 kexec_load compat_sys_kexec_load
|
||||
|
|
|
@ -279,9 +279,9 @@
|
|||
265 o32 clock_nanosleep sys_clock_nanosleep_time32
|
||||
266 o32 tgkill sys_tgkill
|
||||
267 o32 utimes sys_utimes_time32
|
||||
268 o32 mbind sys_mbind compat_sys_mbind
|
||||
269 o32 get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
270 o32 set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
268 o32 mbind sys_mbind
|
||||
269 o32 get_mempolicy sys_get_mempolicy
|
||||
270 o32 set_mempolicy sys_set_mempolicy
|
||||
271 o32 mq_open sys_mq_open compat_sys_mq_open
|
||||
272 o32 mq_unlink sys_mq_unlink
|
||||
273 o32 mq_timedsend sys_mq_timedsend_time32
|
||||
|
@ -298,7 +298,7 @@
|
|||
284 o32 inotify_init sys_inotify_init
|
||||
285 o32 inotify_add_watch sys_inotify_add_watch
|
||||
286 o32 inotify_rm_watch sys_inotify_rm_watch
|
||||
287 o32 migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
287 o32 migrate_pages sys_migrate_pages
|
||||
288 o32 openat sys_openat compat_sys_openat
|
||||
289 o32 mkdirat sys_mkdirat
|
||||
290 o32 mknodat sys_mknodat
|
||||
|
@ -319,7 +319,7 @@
|
|||
305 o32 sync_file_range sys_sync_file_range sys32_sync_file_range
|
||||
306 o32 tee sys_tee
|
||||
307 o32 vmsplice sys_vmsplice
|
||||
308 o32 move_pages sys_move_pages compat_sys_move_pages
|
||||
308 o32 move_pages sys_move_pages
|
||||
309 o32 set_robust_list sys_set_robust_list compat_sys_set_robust_list
|
||||
310 o32 get_robust_list sys_get_robust_list compat_sys_get_robust_list
|
||||
311 o32 kexec_load sys_kexec_load compat_sys_kexec_load
|
||||
|
|
|
@ -666,8 +666,6 @@ FEXPORT(__raw_copy_from_user)
|
|||
EXPORT_SYMBOL(__raw_copy_from_user)
|
||||
FEXPORT(__raw_copy_to_user)
|
||||
EXPORT_SYMBOL(__raw_copy_to_user)
|
||||
FEXPORT(__raw_copy_in_user)
|
||||
EXPORT_SYMBOL(__raw_copy_in_user)
|
||||
#endif
|
||||
/* Legacy Mode, user <-> user */
|
||||
__BUILD_COPY_USER LEGACY_MODE USEROP USEROP
|
||||
|
@ -703,13 +701,4 @@ EXPORT_SYMBOL(__raw_copy_to_user)
|
|||
__BUILD_COPY_USER EVA_MODE KERNELOP USEROP
|
||||
END(__raw_copy_to_user)
|
||||
|
||||
/*
|
||||
* __copy_in_user (EVA)
|
||||
*/
|
||||
|
||||
LEAF(__raw_copy_in_user)
|
||||
EXPORT_SYMBOL(__raw_copy_in_user)
|
||||
__BUILD_COPY_USER EVA_MODE USEROP USEROP
|
||||
END(__raw_copy_in_user)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -244,7 +244,6 @@ static void __init setup_memory(void)
|
|||
unsigned long ram_start_pfn;
|
||||
unsigned long free_ram_start_pfn;
|
||||
phys_addr_t memory_start, memory_end;
|
||||
struct memblock_region *region;
|
||||
|
||||
memory_end = memory_start = 0;
|
||||
|
||||
|
|
|
@ -163,12 +163,6 @@ struct compat_shmid64_ds {
|
|||
#define COMPAT_ELF_NGREG 80
|
||||
typedef compat_ulong_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
|
||||
|
||||
static __inline__ void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = ¤t->thread.regs;
|
||||
return (void __user *)regs->gr[30];
|
||||
}
|
||||
|
||||
static inline int __is_compat_task(struct task_struct *t)
|
||||
{
|
||||
return test_tsk_thread_flag(t, TIF_32BIT);
|
||||
|
|
|
@ -215,8 +215,6 @@ unsigned long __must_check raw_copy_to_user(void __user *dst, const void *src,
|
|||
unsigned long len);
|
||||
unsigned long __must_check raw_copy_from_user(void *dst, const void __user *src,
|
||||
unsigned long len);
|
||||
unsigned long __must_check raw_copy_in_user(void __user *dst, const void __user *src,
|
||||
unsigned long len);
|
||||
#define INLINE_COPY_TO_USER
|
||||
#define INLINE_COPY_FROM_USER
|
||||
|
||||
|
|
|
@ -292,9 +292,9 @@
|
|||
258 32 clock_nanosleep sys_clock_nanosleep_time32
|
||||
258 64 clock_nanosleep sys_clock_nanosleep
|
||||
259 common tgkill sys_tgkill
|
||||
260 common mbind sys_mbind compat_sys_mbind
|
||||
261 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
262 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
260 common mbind sys_mbind
|
||||
261 common get_mempolicy sys_get_mempolicy
|
||||
262 common set_mempolicy sys_set_mempolicy
|
||||
# 263 was vserver
|
||||
264 common add_key sys_add_key
|
||||
265 common request_key sys_request_key
|
||||
|
@ -331,7 +331,7 @@
|
|||
292 64 sync_file_range sys_sync_file_range
|
||||
293 common tee sys_tee
|
||||
294 common vmsplice sys_vmsplice
|
||||
295 common move_pages sys_move_pages compat_sys_move_pages
|
||||
295 common move_pages sys_move_pages
|
||||
296 common getcpu sys_getcpu
|
||||
297 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
298 common statfs64 sys_statfs64 compat_sys_statfs64
|
||||
|
|
|
@ -38,14 +38,6 @@ unsigned long raw_copy_from_user(void *dst, const void __user *src,
|
|||
}
|
||||
EXPORT_SYMBOL(raw_copy_from_user);
|
||||
|
||||
unsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long len)
|
||||
{
|
||||
mtsp(get_user_space(), 1);
|
||||
mtsp(get_user_space(), 2);
|
||||
return pa_memcpy((void __force *)dst, (void __force *)src, len);
|
||||
}
|
||||
|
||||
|
||||
void * memcpy(void * dst,const void *src, size_t count)
|
||||
{
|
||||
mtsp(get_kernel_space(), 1);
|
||||
|
@ -54,7 +46,6 @@ void * memcpy(void * dst,const void *src, size_t count)
|
|||
return dst;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(raw_copy_in_user);
|
||||
EXPORT_SYMBOL(memcpy);
|
||||
|
||||
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
|
|
|
@ -83,22 +83,6 @@ struct compat_statfs {
|
|||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current->thread.regs;
|
||||
unsigned long usp = regs->gpr[1];
|
||||
|
||||
/*
|
||||
* We can't access below the stack pointer in the 32bit ABI and
|
||||
* can access 288 bytes in the 64bit big-endian ABI,
|
||||
* or 512 bytes with the new ELFv2 little-endian ABI.
|
||||
*/
|
||||
if (!is_32bit_task())
|
||||
usp -= USER_REDZONE_SIZE;
|
||||
|
||||
return (void __user *) (usp - len);
|
||||
}
|
||||
|
||||
/*
|
||||
* ipc64_perm is actually 32/64bit clean but since the compat layer refers to
|
||||
* it we may as well define it.
|
||||
|
|
|
@ -330,10 +330,10 @@
|
|||
256 64 sys_debug_setcontext sys_ni_syscall
|
||||
256 spu sys_debug_setcontext sys_ni_syscall
|
||||
# 257 reserved for vserver
|
||||
258 nospu migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
259 nospu mbind sys_mbind compat_sys_mbind
|
||||
260 nospu get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
261 nospu set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
258 nospu migrate_pages sys_migrate_pages
|
||||
259 nospu mbind sys_mbind
|
||||
260 nospu get_mempolicy sys_get_mempolicy
|
||||
261 nospu set_mempolicy sys_set_mempolicy
|
||||
262 nospu mq_open sys_mq_open compat_sys_mq_open
|
||||
263 nospu mq_unlink sys_mq_unlink
|
||||
264 32 mq_timedsend sys_mq_timedsend_time32
|
||||
|
@ -381,7 +381,7 @@
|
|||
298 common faccessat sys_faccessat
|
||||
299 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
|
||||
300 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
|
||||
301 common move_pages sys_move_pages compat_sys_move_pages
|
||||
301 common move_pages sys_move_pages
|
||||
302 common getcpu sys_getcpu
|
||||
303 nospu epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
304 32 utimensat sys_utimensat_time32
|
||||
|
|
|
@ -176,16 +176,6 @@ static inline int is_compat_task(void)
|
|||
return test_thread_flag(TIF_31BIT);
|
||||
}
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
unsigned long stack;
|
||||
|
||||
stack = KSTK_ESP(current);
|
||||
if (is_compat_task())
|
||||
stack &= 0x7fffffffUL;
|
||||
return (void __user *) (stack - len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
|
|
|
@ -227,9 +227,6 @@ static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long s
|
|||
__get_user(x, ptr); \
|
||||
})
|
||||
|
||||
unsigned long __must_check
|
||||
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n);
|
||||
|
||||
/*
|
||||
* Copy a null terminated string from userspace.
|
||||
*/
|
||||
|
|
|
@ -274,9 +274,9 @@
|
|||
265 common statfs64 sys_statfs64 compat_sys_statfs64
|
||||
266 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64
|
||||
267 common remap_file_pages sys_remap_file_pages sys_remap_file_pages
|
||||
268 common mbind sys_mbind compat_sys_mbind
|
||||
269 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
270 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
268 common mbind sys_mbind sys_mbind
|
||||
269 common get_mempolicy sys_get_mempolicy sys_get_mempolicy
|
||||
270 common set_mempolicy sys_set_mempolicy sys_set_mempolicy
|
||||
271 common mq_open sys_mq_open compat_sys_mq_open
|
||||
272 common mq_unlink sys_mq_unlink sys_mq_unlink
|
||||
273 common mq_timedsend sys_mq_timedsend sys_mq_timedsend_time32
|
||||
|
@ -293,7 +293,7 @@
|
|||
284 common inotify_init sys_inotify_init sys_inotify_init
|
||||
285 common inotify_add_watch sys_inotify_add_watch sys_inotify_add_watch
|
||||
286 common inotify_rm_watch sys_inotify_rm_watch sys_inotify_rm_watch
|
||||
287 common migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
287 common migrate_pages sys_migrate_pages sys_migrate_pages
|
||||
288 common openat sys_openat compat_sys_openat
|
||||
289 common mkdirat sys_mkdirat sys_mkdirat
|
||||
290 common mknodat sys_mknodat sys_mknodat
|
||||
|
@ -317,7 +317,7 @@
|
|||
307 common sync_file_range sys_sync_file_range compat_sys_s390_sync_file_range
|
||||
308 common tee sys_tee sys_tee
|
||||
309 common vmsplice sys_vmsplice sys_vmsplice
|
||||
310 common move_pages sys_move_pages compat_sys_move_pages
|
||||
310 common move_pages sys_move_pages sys_move_pages
|
||||
311 common getcpu sys_getcpu sys_getcpu
|
||||
312 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
313 common utimes sys_utimes sys_utimes_time32
|
||||
|
|
|
@ -204,69 +204,6 @@ unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long
|
|||
}
|
||||
EXPORT_SYMBOL(raw_copy_to_user);
|
||||
|
||||
static inline unsigned long copy_in_user_mvcos(void __user *to, const void __user *from,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
|
||||
tmp1 = -4096UL;
|
||||
/* FIXME: copy with reduced length. */
|
||||
asm volatile(
|
||||
" lgr 0,%[spec]\n"
|
||||
"0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n"
|
||||
" jz 2f\n"
|
||||
"1: algr %0,%3\n"
|
||||
" slgr %1,%3\n"
|
||||
" slgr %2,%3\n"
|
||||
" j 0b\n"
|
||||
"2:slgr %0,%0\n"
|
||||
"3: \n"
|
||||
EX_TABLE(0b,3b)
|
||||
: "+a" (size), "+a" (to), "+a" (from), "+a" (tmp1), "=a" (tmp2)
|
||||
: [spec] "d" (0x810081UL)
|
||||
: "cc", "memory", "0");
|
||||
return size;
|
||||
}
|
||||
|
||||
static inline unsigned long copy_in_user_mvc(void __user *to, const void __user *from,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long tmp1;
|
||||
|
||||
asm volatile(
|
||||
" sacf 256\n"
|
||||
" aghi %0,-1\n"
|
||||
" jo 5f\n"
|
||||
" bras %3,3f\n"
|
||||
"0: aghi %0,257\n"
|
||||
"1: mvc 0(1,%1),0(%2)\n"
|
||||
" la %1,1(%1)\n"
|
||||
" la %2,1(%2)\n"
|
||||
" aghi %0,-1\n"
|
||||
" jnz 1b\n"
|
||||
" j 5f\n"
|
||||
"2: mvc 0(256,%1),0(%2)\n"
|
||||
" la %1,256(%1)\n"
|
||||
" la %2,256(%2)\n"
|
||||
"3: aghi %0,-256\n"
|
||||
" jnm 2b\n"
|
||||
"4: ex %0,1b-0b(%3)\n"
|
||||
"5: slgr %0,%0\n"
|
||||
"6: sacf 768\n"
|
||||
EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b)
|
||||
: "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1)
|
||||
: : "cc", "memory");
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned long raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
if (copy_with_mvcos())
|
||||
return copy_in_user_mvcos(to, from, n);
|
||||
return copy_in_user_mvc(to, from, n);
|
||||
}
|
||||
EXPORT_SYMBOL(raw_copy_in_user);
|
||||
|
||||
static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size)
|
||||
{
|
||||
unsigned long tmp1, tmp2;
|
||||
|
|
|
@ -116,25 +116,6 @@ struct compat_statfs {
|
|||
|
||||
#define COMPAT_OFF_T_MAX 0x7fffffff
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
struct pt_regs *regs = current_thread_info()->kregs;
|
||||
unsigned long usp = regs->u_regs[UREG_I6];
|
||||
|
||||
if (test_thread_64bit_stack(usp))
|
||||
usp += STACK_BIAS;
|
||||
|
||||
if (test_thread_flag(TIF_32BIT))
|
||||
usp &= 0xffffffffUL;
|
||||
|
||||
usp -= len;
|
||||
usp &= ~0x7UL;
|
||||
|
||||
return (void __user *) usp;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct compat_ipc64_perm {
|
||||
compat_key_t key;
|
||||
__compat_uid32_t uid;
|
||||
|
|
|
@ -455,7 +455,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
|
|||
|
||||
distance = fp - psp;
|
||||
rval = (csp - distance);
|
||||
if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
|
||||
if (raw_copy_in_user((void __user *)rval, (void __user *)psp, distance))
|
||||
rval = 0;
|
||||
else if (!stack_64bit) {
|
||||
if (put_user(((u32)csp),
|
||||
|
|
|
@ -435,9 +435,9 @@ static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs,
|
|||
(_COMPAT_NSIG_WORDS - 1) * sizeof(unsigned int));
|
||||
|
||||
if (!wsaved) {
|
||||
err |= copy_in_user((u32 __user *)sf,
|
||||
(u32 __user *)(regs->u_regs[UREG_FP]),
|
||||
sizeof(struct reg_window32));
|
||||
err |= raw_copy_in_user((u32 __user *)sf,
|
||||
(u32 __user *)(regs->u_regs[UREG_FP]),
|
||||
sizeof(struct reg_window32));
|
||||
} else {
|
||||
struct reg_window *rp;
|
||||
|
||||
|
@ -567,9 +567,9 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs,
|
|||
err |= put_compat_sigset(&sf->mask, oldset, sizeof(compat_sigset_t));
|
||||
|
||||
if (!wsaved) {
|
||||
err |= copy_in_user((u32 __user *)sf,
|
||||
(u32 __user *)(regs->u_regs[UREG_FP]),
|
||||
sizeof(struct reg_window32));
|
||||
err |= raw_copy_in_user((u32 __user *)sf,
|
||||
(u32 __user *)(regs->u_regs[UREG_FP]),
|
||||
sizeof(struct reg_window32));
|
||||
} else {
|
||||
struct reg_window *rp;
|
||||
|
||||
|
|
|
@ -406,10 +406,10 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
|
|||
err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t));
|
||||
|
||||
if (!wsaved) {
|
||||
err |= copy_in_user((u64 __user *)sf,
|
||||
(u64 __user *)(regs->u_regs[UREG_FP] +
|
||||
STACK_BIAS),
|
||||
sizeof(struct reg_window));
|
||||
err |= raw_copy_in_user((u64 __user *)sf,
|
||||
(u64 __user *)(regs->u_regs[UREG_FP] +
|
||||
STACK_BIAS),
|
||||
sizeof(struct reg_window));
|
||||
} else {
|
||||
struct reg_window *rp;
|
||||
|
||||
|
|
|
@ -365,12 +365,12 @@
|
|||
299 common unshare sys_unshare
|
||||
300 common set_robust_list sys_set_robust_list compat_sys_set_robust_list
|
||||
301 common get_robust_list sys_get_robust_list compat_sys_get_robust_list
|
||||
302 common migrate_pages sys_migrate_pages compat_sys_migrate_pages
|
||||
303 common mbind sys_mbind compat_sys_mbind
|
||||
304 common get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
305 common set_mempolicy sys_set_mempolicy compat_sys_set_mempolicy
|
||||
302 common migrate_pages sys_migrate_pages
|
||||
303 common mbind sys_mbind
|
||||
304 common get_mempolicy sys_get_mempolicy
|
||||
305 common set_mempolicy sys_set_mempolicy
|
||||
306 common kexec_load sys_kexec_load compat_sys_kexec_load
|
||||
307 common move_pages sys_move_pages compat_sys_move_pages
|
||||
307 common move_pages sys_move_pages
|
||||
308 common getcpu sys_getcpu
|
||||
309 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait
|
||||
310 32 utimensat sys_utimensat_time32
|
||||
|
|
|
@ -286,7 +286,7 @@
|
|||
272 i386 fadvise64_64 sys_ia32_fadvise64_64
|
||||
273 i386 vserver
|
||||
274 i386 mbind sys_mbind
|
||||
275 i386 get_mempolicy sys_get_mempolicy compat_sys_get_mempolicy
|
||||
275 i386 get_mempolicy sys_get_mempolicy
|
||||
276 i386 set_mempolicy sys_set_mempolicy
|
||||
277 i386 mq_open sys_mq_open compat_sys_mq_open
|
||||
278 i386 mq_unlink sys_mq_unlink
|
||||
|
@ -328,7 +328,7 @@
|
|||
314 i386 sync_file_range sys_ia32_sync_file_range
|
||||
315 i386 tee sys_tee
|
||||
316 i386 vmsplice sys_vmsplice
|
||||
317 i386 move_pages sys_move_pages compat_sys_move_pages
|
||||
317 i386 move_pages sys_move_pages
|
||||
318 i386 getcpu sys_getcpu
|
||||
319 i386 epoll_pwait sys_epoll_pwait
|
||||
320 i386 utimensat sys_utimensat_time32
|
||||
|
|
|
@ -398,7 +398,7 @@
|
|||
530 x32 set_robust_list compat_sys_set_robust_list
|
||||
531 x32 get_robust_list compat_sys_get_robust_list
|
||||
532 x32 vmsplice sys_vmsplice
|
||||
533 x32 move_pages compat_sys_move_pages
|
||||
533 x32 move_pages sys_move_pages
|
||||
534 x32 preadv compat_sys_preadv64
|
||||
535 x32 pwritev compat_sys_pwritev64
|
||||
536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
|
||||
|
|
|
@ -156,19 +156,6 @@ struct compat_shmid64_ds {
|
|||
(!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT))
|
||||
#endif
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
compat_uptr_t sp = task_pt_regs(current)->sp;
|
||||
|
||||
/*
|
||||
* -128 for the x32 ABI redzone. For IA32, it is not strictly
|
||||
* necessary, but not harmful.
|
||||
*/
|
||||
sp -= 128;
|
||||
|
||||
return (void __user *)round_down(sp - len, 16);
|
||||
}
|
||||
|
||||
static inline bool in_x32_syscall(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
|
|
|
@ -58,13 +58,6 @@ raw_copy_to_user(void __user *dst, const void *src, unsigned long size)
|
|||
return copy_user_generic((__force void *)dst, src, size);
|
||||
}
|
||||
|
||||
static __always_inline __must_check
|
||||
unsigned long raw_copy_in_user(void __user *dst, const void __user *src, unsigned long size)
|
||||
{
|
||||
return copy_user_generic((__force void *)dst,
|
||||
(__force void *)src, size);
|
||||
}
|
||||
|
||||
extern long __copy_user_nocache(void *dst, const void __user *src,
|
||||
unsigned size, int zerorest);
|
||||
|
||||
|
|
|
@ -395,14 +395,6 @@ struct compat_kexec_segment;
|
|||
struct compat_mq_attr;
|
||||
struct compat_msgbuf;
|
||||
|
||||
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
|
||||
|
||||
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
|
||||
|
||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
unsigned long bitmap_size);
|
||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
unsigned long bitmap_size);
|
||||
void copy_siginfo_to_external32(struct compat_siginfo *to,
|
||||
const struct kernel_siginfo *from);
|
||||
int copy_siginfo_from_user32(kernel_siginfo_t *to,
|
||||
|
@ -519,8 +511,6 @@ extern long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||
|
||||
struct epoll_event; /* fortunately, this one is fixed-layout */
|
||||
|
||||
extern void __user *compat_alloc_user_space(unsigned long len);
|
||||
|
||||
int compat_restore_altstack(const compat_stack_t __user *uss);
|
||||
int __compat_save_altstack(compat_stack_t __user *, unsigned long);
|
||||
#define unsafe_compat_save_altstack(uss, sp, label) do { \
|
||||
|
@ -807,26 +797,6 @@ asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr
|
|||
/* mm/fadvise.c: No generic prototype for fadvise64_64 */
|
||||
|
||||
/* mm/, CONFIG_MMU only */
|
||||
asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
|
||||
compat_ulong_t mode,
|
||||
compat_ulong_t __user *nmask,
|
||||
compat_ulong_t maxnode, compat_ulong_t flags);
|
||||
asmlinkage long compat_sys_get_mempolicy(int __user *policy,
|
||||
compat_ulong_t __user *nmask,
|
||||
compat_ulong_t maxnode,
|
||||
compat_ulong_t addr,
|
||||
compat_ulong_t flags);
|
||||
asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
|
||||
compat_ulong_t maxnode);
|
||||
asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,
|
||||
compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes,
|
||||
const compat_ulong_t __user *new_nodes);
|
||||
asmlinkage long compat_sys_move_pages(pid_t pid, compat_ulong_t nr_pages,
|
||||
__u32 __user *pages,
|
||||
const int __user *nodes,
|
||||
int __user *status,
|
||||
int flags);
|
||||
|
||||
asmlinkage long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid,
|
||||
compat_pid_t pid, int sig,
|
||||
struct compat_siginfo __user *uinfo);
|
||||
|
@ -976,6 +946,15 @@ static inline bool in_compat_syscall(void) { return false; }
|
|||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
#define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t))
|
||||
|
||||
#define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
|
||||
|
||||
long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
unsigned long bitmap_size);
|
||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
unsigned long bitmap_size);
|
||||
|
||||
/*
|
||||
* Some legacy ABIs like the i386 one use less than natural alignment for 64-bit
|
||||
* types, and will need special compat treatment for that. Most architectures
|
||||
|
|
|
@ -858,6 +858,11 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
|
|||
|
||||
void hugetlb_report_usage(struct seq_file *m, struct mm_struct *mm);
|
||||
|
||||
static inline void hugetlb_count_init(struct mm_struct *mm)
|
||||
{
|
||||
atomic_long_set(&mm->hugetlb_usage, 0);
|
||||
}
|
||||
|
||||
static inline void hugetlb_count_add(long l, struct mm_struct *mm)
|
||||
{
|
||||
atomic_long_add(l, &mm->hugetlb_usage);
|
||||
|
@ -1042,6 +1047,10 @@ static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
|
|||
return &mm->page_table_lock;
|
||||
}
|
||||
|
||||
static inline void hugetlb_count_init(struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void hugetlb_report_usage(struct seq_file *f, struct mm_struct *m)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -101,14 +101,14 @@ static inline bool mmap_write_trylock(struct mm_struct *mm)
|
|||
|
||||
static inline void mmap_write_unlock(struct mm_struct *mm)
|
||||
{
|
||||
up_write(&mm->mmap_lock);
|
||||
__mmap_lock_trace_released(mm, true);
|
||||
up_write(&mm->mmap_lock);
|
||||
}
|
||||
|
||||
static inline void mmap_write_downgrade(struct mm_struct *mm)
|
||||
{
|
||||
downgrade_write(&mm->mmap_lock);
|
||||
__mmap_lock_trace_acquire_returned(mm, false, true);
|
||||
downgrade_write(&mm->mmap_lock);
|
||||
}
|
||||
|
||||
static inline void mmap_read_lock(struct mm_struct *mm)
|
||||
|
@ -140,8 +140,8 @@ static inline bool mmap_read_trylock(struct mm_struct *mm)
|
|||
|
||||
static inline void mmap_read_unlock(struct mm_struct *mm)
|
||||
{
|
||||
up_read(&mm->mmap_lock);
|
||||
__mmap_lock_trace_released(mm, false);
|
||||
up_read(&mm->mmap_lock);
|
||||
}
|
||||
|
||||
static inline bool mmap_read_trylock_non_owner(struct mm_struct *mm)
|
||||
|
@ -155,8 +155,8 @@ static inline bool mmap_read_trylock_non_owner(struct mm_struct *mm)
|
|||
|
||||
static inline void mmap_read_unlock_non_owner(struct mm_struct *mm)
|
||||
{
|
||||
up_read_non_owner(&mm->mmap_lock);
|
||||
__mmap_lock_trace_released(mm, false);
|
||||
up_read_non_owner(&mm->mmap_lock);
|
||||
}
|
||||
|
||||
static inline void mmap_assert_locked(struct mm_struct *mm)
|
||||
|
|
|
@ -200,16 +200,6 @@ copy_to_user(void __user *to, const void *from, unsigned long n)
|
|||
n = _copy_to_user(to, from, n);
|
||||
return n;
|
||||
}
|
||||
#ifdef CONFIG_COMPAT
|
||||
static __always_inline unsigned long __must_check
|
||||
copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
might_fault();
|
||||
if (access_ok(to, n) && access_ok(from, n))
|
||||
n = raw_copy_in_user(to, from, n);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef copy_mc_to_kernel
|
||||
/*
|
||||
|
|
|
@ -673,15 +673,15 @@ __SYSCALL(__NR_madvise, sys_madvise)
|
|||
#define __NR_remap_file_pages 234
|
||||
__SYSCALL(__NR_remap_file_pages, sys_remap_file_pages)
|
||||
#define __NR_mbind 235
|
||||
__SC_COMP(__NR_mbind, sys_mbind, compat_sys_mbind)
|
||||
__SYSCALL(__NR_mbind, sys_mbind)
|
||||
#define __NR_get_mempolicy 236
|
||||
__SC_COMP(__NR_get_mempolicy, sys_get_mempolicy, compat_sys_get_mempolicy)
|
||||
__SYSCALL(__NR_get_mempolicy, sys_get_mempolicy)
|
||||
#define __NR_set_mempolicy 237
|
||||
__SC_COMP(__NR_set_mempolicy, sys_set_mempolicy, compat_sys_set_mempolicy)
|
||||
__SYSCALL(__NR_set_mempolicy, sys_set_mempolicy)
|
||||
#define __NR_migrate_pages 238
|
||||
__SC_COMP(__NR_migrate_pages, sys_migrate_pages, compat_sys_migrate_pages)
|
||||
__SYSCALL(__NR_migrate_pages, sys_migrate_pages)
|
||||
#define __NR_move_pages 239
|
||||
__SC_COMP(__NR_move_pages, sys_move_pages, compat_sys_move_pages)
|
||||
__SYSCALL(__NR_move_pages, sys_move_pages)
|
||||
#endif
|
||||
|
||||
#define __NR_rt_tgsigqueueinfo 240
|
||||
|
|
|
@ -269,24 +269,3 @@ get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(get_compat_sigset);
|
||||
|
||||
/*
|
||||
* Allocate user-space memory for the duration of a single system call,
|
||||
* in order to marshall parameters inside a compat thunk.
|
||||
*/
|
||||
void __user *compat_alloc_user_space(unsigned long len)
|
||||
{
|
||||
void __user *ptr;
|
||||
|
||||
/* If len would occupy more than half of the entire compat space... */
|
||||
if (unlikely(len > (((compat_uptr_t)~0) >> 1)))
|
||||
return NULL;
|
||||
|
||||
ptr = arch_compat_alloc_user_space(len);
|
||||
|
||||
if (unlikely(!access_ok(ptr, len)))
|
||||
return NULL;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(compat_alloc_user_space);
|
||||
|
|
|
@ -1063,6 +1063,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
|
|||
mm->pmd_huge_pte = NULL;
|
||||
#endif
|
||||
mm_init_uprobes_state(mm);
|
||||
hugetlb_count_init(mm);
|
||||
|
||||
if (current->mm) {
|
||||
mm->flags = current->mm->flags & MMF_INIT_MASK;
|
||||
|
|
103
kernel/kexec.c
103
kernel/kexec.c
|
@ -19,26 +19,9 @@
|
|||
|
||||
#include "kexec_internal.h"
|
||||
|
||||
static int copy_user_segment_list(struct kimage *image,
|
||||
unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments)
|
||||
{
|
||||
int ret;
|
||||
size_t segment_bytes;
|
||||
|
||||
/* Read in the segments */
|
||||
image->nr_segments = nr_segments;
|
||||
segment_bytes = nr_segments * sizeof(*segments);
|
||||
ret = copy_from_user(image->segment, segments, segment_bytes);
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
|
||||
unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments,
|
||||
struct kexec_segment *segments,
|
||||
unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
|
@ -58,10 +41,8 @@ static int kimage_alloc_init(struct kimage **rimage, unsigned long entry,
|
|||
return -ENOMEM;
|
||||
|
||||
image->start = entry;
|
||||
|
||||
ret = copy_user_segment_list(image, nr_segments, segments);
|
||||
if (ret)
|
||||
goto out_free_image;
|
||||
image->nr_segments = nr_segments;
|
||||
memcpy(image->segment, segments, nr_segments * sizeof(*segments));
|
||||
|
||||
if (kexec_on_panic) {
|
||||
/* Enable special crash kernel control page alloc policy. */
|
||||
|
@ -104,12 +85,23 @@ out_free_image:
|
|||
}
|
||||
|
||||
static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
|
||||
struct kexec_segment __user *segments, unsigned long flags)
|
||||
struct kexec_segment *segments, unsigned long flags)
|
||||
{
|
||||
struct kimage **dest_image, *image;
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Because we write directly to the reserved memory region when loading
|
||||
* crash kernels we need a mutex here to prevent multiple crash kernels
|
||||
* from attempting to load simultaneously, and to prevent a crash kernel
|
||||
* from loading over the top of a in use crash kernel.
|
||||
*
|
||||
* KISS: always take the mutex.
|
||||
*/
|
||||
if (!mutex_trylock(&kexec_mutex))
|
||||
return -EBUSY;
|
||||
|
||||
if (flags & KEXEC_ON_CRASH) {
|
||||
dest_image = &kexec_crash_image;
|
||||
if (kexec_crash_image)
|
||||
|
@ -121,7 +113,8 @@ static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
|
|||
if (nr_segments == 0) {
|
||||
/* Uninstall image */
|
||||
kimage_free(xchg(dest_image, NULL));
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
if (flags & KEXEC_ON_CRASH) {
|
||||
/*
|
||||
|
@ -134,7 +127,7 @@ static int do_kexec_load(unsigned long entry, unsigned long nr_segments,
|
|||
|
||||
ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_unlock;
|
||||
|
||||
if (flags & KEXEC_PRESERVE_CONTEXT)
|
||||
image->preserve_context = 1;
|
||||
|
@ -171,6 +164,8 @@ out:
|
|||
arch_kexec_protect_crashkres();
|
||||
|
||||
kimage_free(image);
|
||||
out_unlock:
|
||||
mutex_unlock(&kexec_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -236,7 +231,8 @@ static inline int kexec_load_check(unsigned long nr_segments,
|
|||
SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
|
||||
struct kexec_segment __user *, segments, unsigned long, flags)
|
||||
{
|
||||
int result;
|
||||
struct kexec_segment *ksegments;
|
||||
unsigned long result;
|
||||
|
||||
result = kexec_load_check(nr_segments, flags);
|
||||
if (result)
|
||||
|
@ -247,20 +243,12 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
|
|||
((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
|
||||
return -EINVAL;
|
||||
|
||||
/* Because we write directly to the reserved memory
|
||||
* region when loading crash kernels we need a mutex here to
|
||||
* prevent multiple crash kernels from attempting to load
|
||||
* simultaneously, and to prevent a crash kernel from loading
|
||||
* over the top of a in use crash kernel.
|
||||
*
|
||||
* KISS: always take the mutex.
|
||||
*/
|
||||
if (!mutex_trylock(&kexec_mutex))
|
||||
return -EBUSY;
|
||||
ksegments = memdup_user(segments, nr_segments * sizeof(ksegments[0]));
|
||||
if (IS_ERR(ksegments))
|
||||
return PTR_ERR(ksegments);
|
||||
|
||||
result = do_kexec_load(entry, nr_segments, segments, flags);
|
||||
|
||||
mutex_unlock(&kexec_mutex);
|
||||
result = do_kexec_load(entry, nr_segments, ksegments, flags);
|
||||
kfree(ksegments);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -272,7 +260,7 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
|
|||
compat_ulong_t, flags)
|
||||
{
|
||||
struct compat_kexec_segment in;
|
||||
struct kexec_segment out, __user *ksegments;
|
||||
struct kexec_segment *ksegments;
|
||||
unsigned long i, result;
|
||||
|
||||
result = kexec_load_check(nr_segments, flags);
|
||||
|
@ -285,37 +273,26 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
|
|||
if ((flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_DEFAULT)
|
||||
return -EINVAL;
|
||||
|
||||
ksegments = compat_alloc_user_space(nr_segments * sizeof(out));
|
||||
ksegments = kmalloc_array(nr_segments, sizeof(ksegments[0]),
|
||||
GFP_KERNEL);
|
||||
if (!ksegments)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < nr_segments; i++) {
|
||||
result = copy_from_user(&in, &segments[i], sizeof(in));
|
||||
if (result)
|
||||
return -EFAULT;
|
||||
goto fail;
|
||||
|
||||
out.buf = compat_ptr(in.buf);
|
||||
out.bufsz = in.bufsz;
|
||||
out.mem = in.mem;
|
||||
out.memsz = in.memsz;
|
||||
|
||||
result = copy_to_user(&ksegments[i], &out, sizeof(out));
|
||||
if (result)
|
||||
return -EFAULT;
|
||||
ksegments[i].buf = compat_ptr(in.buf);
|
||||
ksegments[i].bufsz = in.bufsz;
|
||||
ksegments[i].mem = in.mem;
|
||||
ksegments[i].memsz = in.memsz;
|
||||
}
|
||||
|
||||
/* Because we write directly to the reserved memory
|
||||
* region when loading crash kernels we need a mutex here to
|
||||
* prevent multiple crash kernels from attempting to load
|
||||
* simultaneously, and to prevent a crash kernel from loading
|
||||
* over the top of a in use crash kernel.
|
||||
*
|
||||
* KISS: always take the mutex.
|
||||
*/
|
||||
if (!mutex_trylock(&kexec_mutex))
|
||||
return -EBUSY;
|
||||
|
||||
result = do_kexec_load(entry, nr_segments, ksegments, flags);
|
||||
|
||||
mutex_unlock(&kexec_mutex);
|
||||
|
||||
fail:
|
||||
kfree(ksegments);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -292,15 +292,10 @@ COND_SYSCALL(process_madvise);
|
|||
COND_SYSCALL(process_mrelease);
|
||||
COND_SYSCALL(remap_file_pages);
|
||||
COND_SYSCALL(mbind);
|
||||
COND_SYSCALL_COMPAT(mbind);
|
||||
COND_SYSCALL(get_mempolicy);
|
||||
COND_SYSCALL_COMPAT(get_mempolicy);
|
||||
COND_SYSCALL(set_mempolicy);
|
||||
COND_SYSCALL_COMPAT(set_mempolicy);
|
||||
COND_SYSCALL(migrate_pages);
|
||||
COND_SYSCALL_COMPAT(migrate_pages);
|
||||
COND_SYSCALL(move_pages);
|
||||
COND_SYSCALL_COMPAT(move_pages);
|
||||
|
||||
COND_SYSCALL(perf_event_open);
|
||||
COND_SYSCALL(accept4);
|
||||
|
|
5
mm/hmm.c
5
mm/hmm.c
|
@ -295,10 +295,13 @@ static int hmm_vma_handle_pte(struct mm_walk *walk, unsigned long addr,
|
|||
goto fault;
|
||||
|
||||
/*
|
||||
* Bypass devmap pte such as DAX page when all pfn requested
|
||||
* flags(pfn_req_flags) are fulfilled.
|
||||
* Since each architecture defines a struct page for the zero page, just
|
||||
* fall through and treat it like a normal page.
|
||||
*/
|
||||
if (pte_special(pte) && !is_zero_pfn(pte_pfn(pte))) {
|
||||
if (pte_special(pte) && !pte_devmap(pte) &&
|
||||
!is_zero_pfn(pte_pfn(pte))) {
|
||||
if (hmm_pte_need_fault(hmm_vma_walk, pfn_req_flags, 0)) {
|
||||
pte_unmap(ptep);
|
||||
return -EFAULT;
|
||||
|
|
|
@ -113,7 +113,8 @@
|
|||
#define BYTES_PER_POINTER sizeof(void *)
|
||||
|
||||
/* GFP bitmask for kmemleak internal allocations */
|
||||
#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC)) | \
|
||||
#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC | \
|
||||
__GFP_NOLOCKDEP)) | \
|
||||
__GFP_NORETRY | __GFP_NOMEMALLOC | \
|
||||
__GFP_NOWARN)
|
||||
|
||||
|
|
214
mm/mempolicy.c
214
mm/mempolicy.c
|
@ -1362,16 +1362,33 @@ mpol_out:
|
|||
/*
|
||||
* User space interface with variable sized bitmaps for nodelists.
|
||||
*/
|
||||
static int get_bitmap(unsigned long *mask, const unsigned long __user *nmask,
|
||||
unsigned long maxnode)
|
||||
{
|
||||
unsigned long nlongs = BITS_TO_LONGS(maxnode);
|
||||
int ret;
|
||||
|
||||
if (in_compat_syscall())
|
||||
ret = compat_get_bitmap(mask,
|
||||
(const compat_ulong_t __user *)nmask,
|
||||
maxnode);
|
||||
else
|
||||
ret = copy_from_user(mask, nmask,
|
||||
nlongs * sizeof(unsigned long));
|
||||
|
||||
if (ret)
|
||||
return -EFAULT;
|
||||
|
||||
if (maxnode % BITS_PER_LONG)
|
||||
mask[nlongs - 1] &= (1UL << (maxnode % BITS_PER_LONG)) - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy a node mask from user space. */
|
||||
static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask,
|
||||
unsigned long maxnode)
|
||||
{
|
||||
unsigned long k;
|
||||
unsigned long t;
|
||||
unsigned long nlongs;
|
||||
unsigned long endmask;
|
||||
|
||||
--maxnode;
|
||||
nodes_clear(*nodes);
|
||||
if (maxnode == 0 || !nmask)
|
||||
|
@ -1379,49 +1396,29 @@ static int get_nodes(nodemask_t *nodes, const unsigned long __user *nmask,
|
|||
if (maxnode > PAGE_SIZE*BITS_PER_BYTE)
|
||||
return -EINVAL;
|
||||
|
||||
nlongs = BITS_TO_LONGS(maxnode);
|
||||
if ((maxnode % BITS_PER_LONG) == 0)
|
||||
endmask = ~0UL;
|
||||
else
|
||||
endmask = (1UL << (maxnode % BITS_PER_LONG)) - 1;
|
||||
|
||||
/*
|
||||
* When the user specified more nodes than supported just check
|
||||
* if the non supported part is all zero.
|
||||
*
|
||||
* If maxnode have more longs than MAX_NUMNODES, check
|
||||
* the bits in that area first. And then go through to
|
||||
* check the rest bits which equal or bigger than MAX_NUMNODES.
|
||||
* Otherwise, just check bits [MAX_NUMNODES, maxnode).
|
||||
* if the non supported part is all zero, one word at a time,
|
||||
* starting at the end.
|
||||
*/
|
||||
if (nlongs > BITS_TO_LONGS(MAX_NUMNODES)) {
|
||||
for (k = BITS_TO_LONGS(MAX_NUMNODES); k < nlongs; k++) {
|
||||
if (get_user(t, nmask + k))
|
||||
return -EFAULT;
|
||||
if (k == nlongs - 1) {
|
||||
if (t & endmask)
|
||||
return -EINVAL;
|
||||
} else if (t)
|
||||
return -EINVAL;
|
||||
}
|
||||
nlongs = BITS_TO_LONGS(MAX_NUMNODES);
|
||||
endmask = ~0UL;
|
||||
}
|
||||
while (maxnode > MAX_NUMNODES) {
|
||||
unsigned long bits = min_t(unsigned long, maxnode, BITS_PER_LONG);
|
||||
unsigned long t;
|
||||
|
||||
if (maxnode > MAX_NUMNODES && MAX_NUMNODES % BITS_PER_LONG != 0) {
|
||||
unsigned long valid_mask = endmask;
|
||||
|
||||
valid_mask &= ~((1UL << (MAX_NUMNODES % BITS_PER_LONG)) - 1);
|
||||
if (get_user(t, nmask + nlongs - 1))
|
||||
if (get_bitmap(&t, &nmask[maxnode / BITS_PER_LONG], bits))
|
||||
return -EFAULT;
|
||||
if (t & valid_mask)
|
||||
|
||||
if (maxnode - bits >= MAX_NUMNODES) {
|
||||
maxnode -= bits;
|
||||
} else {
|
||||
maxnode = MAX_NUMNODES;
|
||||
t &= ~((1UL << (MAX_NUMNODES % BITS_PER_LONG)) - 1);
|
||||
}
|
||||
if (t)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (copy_from_user(nodes_addr(*nodes), nmask, nlongs*sizeof(unsigned long)))
|
||||
return -EFAULT;
|
||||
nodes_addr(*nodes)[nlongs-1] &= endmask;
|
||||
return 0;
|
||||
return get_bitmap(nodes_addr(*nodes), nmask, maxnode);
|
||||
}
|
||||
|
||||
/* Copy a kernel node mask to user space */
|
||||
|
@ -1430,6 +1427,10 @@ static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
|
|||
{
|
||||
unsigned long copy = ALIGN(maxnode-1, 64) / 8;
|
||||
unsigned int nbytes = BITS_TO_LONGS(nr_node_ids) * sizeof(long);
|
||||
bool compat = in_compat_syscall();
|
||||
|
||||
if (compat)
|
||||
nbytes = BITS_TO_COMPAT_LONGS(nr_node_ids) * sizeof(compat_long_t);
|
||||
|
||||
if (copy > nbytes) {
|
||||
if (copy > PAGE_SIZE)
|
||||
|
@ -1437,7 +1438,13 @@ static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
|
|||
if (clear_user((char __user *)mask + nbytes, copy - nbytes))
|
||||
return -EFAULT;
|
||||
copy = nbytes;
|
||||
maxnode = nr_node_ids;
|
||||
}
|
||||
|
||||
if (compat)
|
||||
return compat_put_bitmap((compat_ulong_t __user *)mask,
|
||||
nodes_addr(*nodes), maxnode);
|
||||
|
||||
return copy_to_user(mask, nodes_addr(*nodes), copy) ? -EFAULT : 0;
|
||||
}
|
||||
|
||||
|
@ -1642,116 +1649,6 @@ SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
|
|||
return kernel_get_mempolicy(policy, nmask, maxnode, addr, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
||||
COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
|
||||
compat_ulong_t __user *, nmask,
|
||||
compat_ulong_t, maxnode,
|
||||
compat_ulong_t, addr, compat_ulong_t, flags)
|
||||
{
|
||||
long err;
|
||||
unsigned long __user *nm = NULL;
|
||||
unsigned long nr_bits, alloc_size;
|
||||
DECLARE_BITMAP(bm, MAX_NUMNODES);
|
||||
|
||||
nr_bits = min_t(unsigned long, maxnode-1, nr_node_ids);
|
||||
alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
|
||||
|
||||
if (nmask)
|
||||
nm = compat_alloc_user_space(alloc_size);
|
||||
|
||||
err = kernel_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
|
||||
|
||||
if (!err && nmask) {
|
||||
unsigned long copy_size;
|
||||
copy_size = min_t(unsigned long, sizeof(bm), alloc_size);
|
||||
err = copy_from_user(bm, nm, copy_size);
|
||||
/* ensure entire bitmap is zeroed */
|
||||
err |= clear_user(nmask, ALIGN(maxnode-1, 8) / 8);
|
||||
err |= compat_put_bitmap(nmask, bm, nr_bits);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE3(set_mempolicy, int, mode, compat_ulong_t __user *, nmask,
|
||||
compat_ulong_t, maxnode)
|
||||
{
|
||||
unsigned long __user *nm = NULL;
|
||||
unsigned long nr_bits, alloc_size;
|
||||
DECLARE_BITMAP(bm, MAX_NUMNODES);
|
||||
|
||||
nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
|
||||
alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
|
||||
|
||||
if (nmask) {
|
||||
if (compat_get_bitmap(bm, nmask, nr_bits))
|
||||
return -EFAULT;
|
||||
nm = compat_alloc_user_space(alloc_size);
|
||||
if (copy_to_user(nm, bm, alloc_size))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return kernel_set_mempolicy(mode, nm, nr_bits+1);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE6(mbind, compat_ulong_t, start, compat_ulong_t, len,
|
||||
compat_ulong_t, mode, compat_ulong_t __user *, nmask,
|
||||
compat_ulong_t, maxnode, compat_ulong_t, flags)
|
||||
{
|
||||
unsigned long __user *nm = NULL;
|
||||
unsigned long nr_bits, alloc_size;
|
||||
nodemask_t bm;
|
||||
|
||||
nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
|
||||
alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
|
||||
|
||||
if (nmask) {
|
||||
if (compat_get_bitmap(nodes_addr(bm), nmask, nr_bits))
|
||||
return -EFAULT;
|
||||
nm = compat_alloc_user_space(alloc_size);
|
||||
if (copy_to_user(nm, nodes_addr(bm), alloc_size))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return kernel_mbind(start, len, mode, nm, nr_bits+1, flags);
|
||||
}
|
||||
|
||||
COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid,
|
||||
compat_ulong_t, maxnode,
|
||||
const compat_ulong_t __user *, old_nodes,
|
||||
const compat_ulong_t __user *, new_nodes)
|
||||
{
|
||||
unsigned long __user *old = NULL;
|
||||
unsigned long __user *new = NULL;
|
||||
nodemask_t tmp_mask;
|
||||
unsigned long nr_bits;
|
||||
unsigned long size;
|
||||
|
||||
nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES);
|
||||
size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
|
||||
if (old_nodes) {
|
||||
if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits))
|
||||
return -EFAULT;
|
||||
old = compat_alloc_user_space(new_nodes ? size * 2 : size);
|
||||
if (new_nodes)
|
||||
new = old + size / sizeof(unsigned long);
|
||||
if (copy_to_user(old, nodes_addr(tmp_mask), size))
|
||||
return -EFAULT;
|
||||
}
|
||||
if (new_nodes) {
|
||||
if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits))
|
||||
return -EFAULT;
|
||||
if (new == NULL)
|
||||
new = compat_alloc_user_space(size);
|
||||
if (copy_to_user(new, nodes_addr(tmp_mask), size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return kernel_migrate_pages(pid, nr_bits + 1, old, new);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
bool vma_migratable(struct vm_area_struct *vma)
|
||||
{
|
||||
if (vma->vm_flags & (VM_IO | VM_PFNMAP))
|
||||
|
@ -1979,17 +1876,26 @@ unsigned int mempolicy_slab_node(void)
|
|||
*/
|
||||
static unsigned offset_il_node(struct mempolicy *pol, unsigned long n)
|
||||
{
|
||||
unsigned nnodes = nodes_weight(pol->nodes);
|
||||
unsigned target;
|
||||
nodemask_t nodemask = pol->nodes;
|
||||
unsigned int target, nnodes;
|
||||
int i;
|
||||
int nid;
|
||||
/*
|
||||
* The barrier will stabilize the nodemask in a register or on
|
||||
* the stack so that it will stop changing under the code.
|
||||
*
|
||||
* Between first_node() and next_node(), pol->nodes could be changed
|
||||
* by other threads. So we put pol->nodes in a local stack.
|
||||
*/
|
||||
barrier();
|
||||
|
||||
nnodes = nodes_weight(nodemask);
|
||||
if (!nnodes)
|
||||
return numa_node_id();
|
||||
target = (unsigned int)n % nnodes;
|
||||
nid = first_node(pol->nodes);
|
||||
nid = first_node(nodemask);
|
||||
for (i = 0; i < target; i++)
|
||||
nid = next_node(nid, pol->nodes);
|
||||
nid = next_node(nid, nodemask);
|
||||
return nid;
|
||||
}
|
||||
|
||||
|
|
61
mm/migrate.c
61
mm/migrate.c
|
@ -960,7 +960,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
|
|||
int force, enum migrate_mode mode)
|
||||
{
|
||||
int rc = -EAGAIN;
|
||||
int page_was_mapped = 0;
|
||||
bool page_was_mapped = false;
|
||||
struct anon_vma *anon_vma = NULL;
|
||||
bool is_lru = !__PageMovable(page);
|
||||
|
||||
|
@ -1008,7 +1008,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
|
|||
}
|
||||
|
||||
/*
|
||||
* By try_to_unmap(), page->mapcount goes down to 0 here. In this case,
|
||||
* By try_to_migrate(), page->mapcount goes down to 0 here. In this case,
|
||||
* we cannot notice that anon_vma is freed while we migrates a page.
|
||||
* This get_anon_vma() delays freeing anon_vma pointer until the end
|
||||
* of migration. File cache pages are no problem because of page_lock()
|
||||
|
@ -1063,7 +1063,7 @@ static int __unmap_and_move(struct page *page, struct page *newpage,
|
|||
VM_BUG_ON_PAGE(PageAnon(page) && !PageKsm(page) && !anon_vma,
|
||||
page);
|
||||
try_to_migrate(page, 0);
|
||||
page_was_mapped = 1;
|
||||
page_was_mapped = true;
|
||||
}
|
||||
|
||||
if (!page_mapped(page))
|
||||
|
@ -1900,6 +1900,23 @@ set_status:
|
|||
mmap_read_unlock(mm);
|
||||
}
|
||||
|
||||
static int get_compat_pages_array(const void __user *chunk_pages[],
|
||||
const void __user * __user *pages,
|
||||
unsigned long chunk_nr)
|
||||
{
|
||||
compat_uptr_t __user *pages32 = (compat_uptr_t __user *)pages;
|
||||
compat_uptr_t p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < chunk_nr; i++) {
|
||||
if (get_user(p, pages32 + i))
|
||||
return -EFAULT;
|
||||
chunk_pages[i] = compat_ptr(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the nodes of a user array of pages and store it in
|
||||
* a user array of status.
|
||||
|
@ -1919,8 +1936,15 @@ static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
|
|||
if (chunk_nr > DO_PAGES_STAT_CHUNK_NR)
|
||||
chunk_nr = DO_PAGES_STAT_CHUNK_NR;
|
||||
|
||||
if (copy_from_user(chunk_pages, pages, chunk_nr * sizeof(*chunk_pages)))
|
||||
break;
|
||||
if (in_compat_syscall()) {
|
||||
if (get_compat_pages_array(chunk_pages, pages,
|
||||
chunk_nr))
|
||||
break;
|
||||
} else {
|
||||
if (copy_from_user(chunk_pages, pages,
|
||||
chunk_nr * sizeof(*chunk_pages)))
|
||||
break;
|
||||
}
|
||||
|
||||
do_pages_stat_array(mm, chunk_nr, chunk_pages, chunk_status);
|
||||
|
||||
|
@ -2023,28 +2047,6 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
|
|||
return kernel_move_pages(pid, nr_pages, pages, nodes, status, flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
|
||||
compat_uptr_t __user *, pages32,
|
||||
const int __user *, nodes,
|
||||
int __user *, status,
|
||||
int, flags)
|
||||
{
|
||||
const void __user * __user *pages;
|
||||
int i;
|
||||
|
||||
pages = compat_alloc_user_space(nr_pages * sizeof(void *));
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
compat_uptr_t p;
|
||||
|
||||
if (get_user(p, pages32 + i) ||
|
||||
put_user(compat_ptr(p), pages + i))
|
||||
return -EFAULT;
|
||||
}
|
||||
return kernel_move_pages(pid, nr_pages, pages, nodes, status, flags);
|
||||
}
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/*
|
||||
* Returns true if this is a safe migration target node for misplaced NUMA
|
||||
|
@ -2107,6 +2109,7 @@ out:
|
|||
static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
|
||||
{
|
||||
int page_lru;
|
||||
int nr_pages = thp_nr_pages(page);
|
||||
|
||||
VM_BUG_ON_PAGE(compound_order(page) && !PageTransHuge(page), page);
|
||||
|
||||
|
@ -2115,7 +2118,7 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
|
|||
return 0;
|
||||
|
||||
/* Avoid migrating to a node that is nearly full */
|
||||
if (!migrate_balanced_pgdat(pgdat, compound_nr(page)))
|
||||
if (!migrate_balanced_pgdat(pgdat, nr_pages))
|
||||
return 0;
|
||||
|
||||
if (isolate_lru_page(page))
|
||||
|
@ -2123,7 +2126,7 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
|
|||
|
||||
page_lru = page_is_file_lru(page);
|
||||
mod_node_page_state(page_pgdat(page), NR_ISOLATED_ANON + page_lru,
|
||||
thp_nr_pages(page));
|
||||
nr_pages);
|
||||
|
||||
/*
|
||||
* Isolating the page has taken another reference, so the
|
||||
|
|
|
@ -3428,8 +3428,10 @@ void free_unref_page_list(struct list_head *list)
|
|||
/* Prepare pages for freeing */
|
||||
list_for_each_entry_safe(page, next, list, lru) {
|
||||
pfn = page_to_pfn(page);
|
||||
if (!free_unref_page_prepare(page, pfn, 0))
|
||||
if (!free_unref_page_prepare(page, pfn, 0)) {
|
||||
list_del(&page->lru);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free isolated pages directly to the allocator, see
|
||||
|
|
|
@ -2715,7 +2715,7 @@ out:
|
|||
cgroup_size = max(cgroup_size, protection);
|
||||
|
||||
scan = lruvec_size - lruvec_size * protection /
|
||||
cgroup_size;
|
||||
(cgroup_size + 1);
|
||||
|
||||
/*
|
||||
* Minimally target SWAP_CLUSTER_MAX pages to keep
|
||||
|
|
48
mm/vmstat.c
48
mm/vmstat.c
|
@ -319,6 +319,16 @@ void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
|
|||
long x;
|
||||
long t;
|
||||
|
||||
/*
|
||||
* Accurate vmstat updates require a RMW. On !PREEMPT_RT kernels,
|
||||
* atomicity is provided by IRQs being disabled -- either explicitly
|
||||
* or via local_lock_irq. On PREEMPT_RT, local_lock_irq only disables
|
||||
* CPU migrations and preemption potentially corrupts a counter so
|
||||
* disable preemption.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
x = delta + __this_cpu_read(*p);
|
||||
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
|
@ -328,6 +338,9 @@ void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
|
|||
x = 0;
|
||||
}
|
||||
__this_cpu_write(*p, x);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(__mod_zone_page_state);
|
||||
|
||||
|
@ -350,6 +363,10 @@ void __mod_node_page_state(struct pglist_data *pgdat, enum node_stat_item item,
|
|||
delta >>= PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/* See __mod_node_page_state */
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
x = delta + __this_cpu_read(*p);
|
||||
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
|
@ -359,6 +376,9 @@ void __mod_node_page_state(struct pglist_data *pgdat, enum node_stat_item item,
|
|||
x = 0;
|
||||
}
|
||||
__this_cpu_write(*p, x);
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
EXPORT_SYMBOL(__mod_node_page_state);
|
||||
|
||||
|
@ -391,6 +411,10 @@ void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
|
|||
s8 __percpu *p = pcp->vm_stat_diff + item;
|
||||
s8 v, t;
|
||||
|
||||
/* See __mod_node_page_state */
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
v = __this_cpu_inc_return(*p);
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
if (unlikely(v > t)) {
|
||||
|
@ -399,6 +423,9 @@ void __inc_zone_state(struct zone *zone, enum zone_stat_item item)
|
|||
zone_page_state_add(v + overstep, zone, item);
|
||||
__this_cpu_write(*p, -overstep);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __inc_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
||||
|
@ -409,6 +436,10 @@ void __inc_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
|||
|
||||
VM_WARN_ON_ONCE(vmstat_item_in_bytes(item));
|
||||
|
||||
/* See __mod_node_page_state */
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
v = __this_cpu_inc_return(*p);
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
if (unlikely(v > t)) {
|
||||
|
@ -417,6 +448,9 @@ void __inc_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
|||
node_page_state_add(v + overstep, pgdat, item);
|
||||
__this_cpu_write(*p, -overstep);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __inc_zone_page_state(struct page *page, enum zone_stat_item item)
|
||||
|
@ -437,6 +471,10 @@ void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
|
|||
s8 __percpu *p = pcp->vm_stat_diff + item;
|
||||
s8 v, t;
|
||||
|
||||
/* See __mod_node_page_state */
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
v = __this_cpu_dec_return(*p);
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
if (unlikely(v < - t)) {
|
||||
|
@ -445,6 +483,9 @@ void __dec_zone_state(struct zone *zone, enum zone_stat_item item)
|
|||
zone_page_state_add(v - overstep, zone, item);
|
||||
__this_cpu_write(*p, overstep);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __dec_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
||||
|
@ -455,6 +496,10 @@ void __dec_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
|||
|
||||
VM_WARN_ON_ONCE(vmstat_item_in_bytes(item));
|
||||
|
||||
/* See __mod_node_page_state */
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_disable();
|
||||
|
||||
v = __this_cpu_dec_return(*p);
|
||||
t = __this_cpu_read(pcp->stat_threshold);
|
||||
if (unlikely(v < - t)) {
|
||||
|
@ -463,6 +508,9 @@ void __dec_node_state(struct pglist_data *pgdat, enum node_stat_item item)
|
|||
node_page_state_add(v - overstep, pgdat, item);
|
||||
__this_cpu_write(*p, overstep);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PREEMPT_RT))
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
|
||||
|
|
Загрузка…
Ссылка в новой задаче