Merge branch 'akpm' (patches from Andrew)
Merge third set of updates from Andrew Morton: - the rest of MM [ This includes getting rid of the numa hinting bits, in favor of just generic protnone logic. Yay. - Linus ] - core kernel - procfs - some of lib/ (lots of lib/ material this time) * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (104 commits) lib/lcm.c: replace include lib/percpu_ida.c: remove redundant includes lib/strncpy_from_user.c: replace module.h include lib/stmp_device.c: replace module.h include lib/sort.c: move include inside #if 0 lib/show_mem.c: remove redundant include lib/radix-tree.c: change to simpler include lib/plist.c: remove redundant include lib/nlattr.c: remove redundant include lib/kobject_uevent.c: remove redundant include lib/llist.c: remove redundant include lib/md5.c: simplify include lib/list_sort.c: rearrange includes lib/genalloc.c: remove redundant include lib/idr.c: remove redundant include lib/halfmd4.c: simplify includes lib/dynamic_queue_limits.c: simplify includes lib/sort.c: use simpler includes lib/interval_tree.c: simplify includes hexdump: make it return number of bytes placed in buffer ...
This commit is contained in:
commit
818099574b
5
.gitignore
vendored
5
.gitignore
vendored
@ -52,6 +52,11 @@ Module.symvers
|
||||
#
|
||||
/debian/
|
||||
|
||||
#
|
||||
# tar directory (make tar*-pkg)
|
||||
#
|
||||
/tar-install/
|
||||
|
||||
#
|
||||
# git files that we don't want to ignore even it they are dot-files
|
||||
#
|
||||
|
@ -145,6 +145,8 @@ Table 1-1: Process specific entries in /proc
|
||||
stack Report full stack trace, enable via CONFIG_STACKTRACE
|
||||
smaps a extension based on maps, showing the memory consumption of
|
||||
each mapping and flags associated with it
|
||||
numa_maps an extension based on maps, showing the memory locality and
|
||||
binding policy as well as mem usage (in pages) of each mapping.
|
||||
..............................................................................
|
||||
|
||||
For example, to get the status information of a process, all you have to do is
|
||||
@ -489,12 +491,47 @@ To clear the bits for the file mapped pages associated with the process
|
||||
To clear the soft-dirty bit
|
||||
> echo 4 > /proc/PID/clear_refs
|
||||
|
||||
To reset the peak resident set size ("high water mark") to the process's
|
||||
current value:
|
||||
> echo 5 > /proc/PID/clear_refs
|
||||
|
||||
Any other value written to /proc/PID/clear_refs will have no effect.
|
||||
|
||||
The /proc/pid/pagemap gives the PFN, which can be used to find the pageflags
|
||||
using /proc/kpageflags and number of times a page is mapped using
|
||||
/proc/kpagecount. For detailed explanation, see Documentation/vm/pagemap.txt.
|
||||
|
||||
The /proc/pid/numa_maps is an extension based on maps, showing the memory
|
||||
locality and binding policy, as well as the memory usage (in pages) of
|
||||
each mapping. The output follows a general format where mapping details get
|
||||
summarized separated by blank spaces, one mapping per each file line:
|
||||
|
||||
address policy mapping details
|
||||
|
||||
00400000 default file=/usr/local/bin/app mapped=1 active=0 N3=1 kernelpagesize_kB=4
|
||||
00600000 default file=/usr/local/bin/app anon=1 dirty=1 N3=1 kernelpagesize_kB=4
|
||||
3206000000 default file=/lib64/ld-2.12.so mapped=26 mapmax=6 N0=24 N3=2 kernelpagesize_kB=4
|
||||
320621f000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
|
||||
3206220000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
|
||||
3206221000 default anon=1 dirty=1 N3=1 kernelpagesize_kB=4
|
||||
3206800000 default file=/lib64/libc-2.12.so mapped=59 mapmax=21 active=55 N0=41 N3=18 kernelpagesize_kB=4
|
||||
320698b000 default file=/lib64/libc-2.12.so
|
||||
3206b8a000 default file=/lib64/libc-2.12.so anon=2 dirty=2 N3=2 kernelpagesize_kB=4
|
||||
3206b8e000 default file=/lib64/libc-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
|
||||
3206b8f000 default anon=3 dirty=3 active=1 N3=3 kernelpagesize_kB=4
|
||||
7f4dc10a2000 default anon=3 dirty=3 N3=3 kernelpagesize_kB=4
|
||||
7f4dc10b4000 default anon=2 dirty=2 active=1 N3=2 kernelpagesize_kB=4
|
||||
7f4dc1200000 default file=/anon_hugepage\040(deleted) huge anon=1 dirty=1 N3=1 kernelpagesize_kB=2048
|
||||
7fff335f0000 default stack anon=3 dirty=3 N3=3 kernelpagesize_kB=4
|
||||
7fff3369d000 default mapped=1 mapmax=35 active=0 N3=1 kernelpagesize_kB=4
|
||||
|
||||
Where:
|
||||
"address" is the starting address for the mapping;
|
||||
"policy" reports the NUMA memory policy set for the mapping (see vm/numa_memory_policy.txt);
|
||||
"mapping details" summarizes mapping data such as mapping type, page usage counters,
|
||||
node locality page counters (N0 == node0, N1 == node1, ...) and the kernel page
|
||||
size, in KB, that is backing the mapping up.
|
||||
|
||||
1.2 Kernel data
|
||||
---------------
|
||||
|
||||
|
@ -27,8 +27,6 @@ struct thread_info {
|
||||
int bpt_nsaved;
|
||||
unsigned long bpt_addr[2]; /* breakpoint handling */
|
||||
unsigned int bpt_insn[2];
|
||||
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -40,9 +38,6 @@ struct thread_info {
|
||||
.exec_domain = &default_exec_domain, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -150,7 +150,7 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
|
||||
struct switch_stack *sw = (struct switch_stack *)regs - 1;
|
||||
long i, err = __get_user(regs->pc, &sc->sc_pc);
|
||||
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
sw->r26 = (unsigned long) ret_from_sys_call;
|
||||
|
||||
|
@ -46,7 +46,6 @@ struct thread_info {
|
||||
struct exec_domain *exec_domain;/* execution domain */
|
||||
__u32 cpu; /* current CPU */
|
||||
unsigned long thr_ptr; /* TLS ptr */
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -62,9 +61,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -104,7 +104,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* Since we stacked the signal on a word boundary,
|
||||
* then 'sp' should be word aligned here. If it's
|
||||
|
@ -257,7 +257,10 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
|
||||
#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
|
||||
|
||||
/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
|
||||
#define pmd_mknotpresent(pmd) (__pmd(0))
|
||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
||||
{
|
||||
return __pmd(0);
|
||||
}
|
||||
|
||||
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
|
||||
{
|
||||
|
@ -68,7 +68,6 @@ struct thread_info {
|
||||
#ifdef CONFIG_ARM_THUMBEE
|
||||
unsigned long thumbee_state; /* ThumbEE Handler Base register */
|
||||
#endif
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
@ -81,9 +80,6 @@ struct thread_info {
|
||||
.cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
|
||||
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
|
||||
domain_val(DOMAIN_IO, DOMAIN_CLIENT), \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -191,7 +191,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
|
||||
struct sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 64-bit boundary,
|
||||
@ -221,7 +221,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
||||
struct rt_sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 64-bit boundary,
|
||||
|
@ -48,7 +48,6 @@ struct thread_info {
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
struct task_struct *task; /* main task structure */
|
||||
struct exec_domain *exec_domain; /* execution domain */
|
||||
struct restart_block restart_block;
|
||||
int preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
int cpu; /* cpu */
|
||||
};
|
||||
@ -60,9 +59,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -131,7 +131,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
||||
struct rt_sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 128-bit boundary, then 'sp' should
|
||||
|
@ -347,7 +347,7 @@ asmlinkage int compat_sys_sigreturn(struct pt_regs *regs)
|
||||
struct compat_sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 64-bit boundary,
|
||||
@ -381,7 +381,7 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
|
||||
struct compat_rt_sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 64-bit boundary,
|
||||
|
@ -30,7 +30,6 @@ struct thread_info {
|
||||
saved by debug handler
|
||||
when setting up
|
||||
trampoline */
|
||||
struct restart_block restart_block;
|
||||
__u8 supervisor_stack[0];
|
||||
};
|
||||
|
||||
@ -41,9 +40,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall \
|
||||
} \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -18,7 +18,6 @@ void foo(void)
|
||||
OFFSET(TI_preempt_count, thread_info, preempt_count);
|
||||
OFFSET(TI_rar_saved, thread_info, rar_saved);
|
||||
OFFSET(TI_rsr_saved, thread_info, rsr_saved);
|
||||
OFFSET(TI_restart_block, thread_info, restart_block);
|
||||
BLANK();
|
||||
OFFSET(TSK_active_mm, task_struct, active_mm);
|
||||
BLANK();
|
||||
|
@ -69,7 +69,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
||||
sigset_t set;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
frame = (struct rt_sigframe __user *)regs->sp;
|
||||
pr_debug("SIG return: frame = %p\n", frame);
|
||||
|
@ -42,7 +42,6 @@ struct thread_info {
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
struct restart_block restart_block;
|
||||
#ifndef CONFIG_SMP
|
||||
struct l1_scratch_task_info l1_task_info;
|
||||
#endif
|
||||
@ -58,9 +57,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
#define init_stack (init_thread_union.stack)
|
||||
|
@ -44,7 +44,7 @@ rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *p
|
||||
int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
#define RESTORE(x) err |= __get_user(regs->x, &sc->sc_##x)
|
||||
|
||||
|
@ -45,7 +45,6 @@ struct thread_info {
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 = preemptable, <0 = BUG */
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -61,9 +60,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -68,7 +68,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
|
||||
sigset_t set;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a dword boundary,
|
||||
|
@ -67,7 +67,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
|
||||
unsigned long old_usp;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* restore the regs from &sc->regs (same as sc, since regs is first)
|
||||
* (sc is already checked for VERIFY_READ since the sigframe was
|
||||
|
@ -59,7 +59,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
|
||||
unsigned long old_usp;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Restore the registers from &sc->regs. sc is already checked
|
||||
|
@ -38,7 +38,6 @@ struct thread_info {
|
||||
0-0xBFFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
__u8 supervisor_stack[0];
|
||||
};
|
||||
|
||||
@ -56,9 +55,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -33,7 +33,6 @@ extern void *memcpy(void *, const void *, __kernel_size_t);
|
||||
#define __HAVE_ARCH_STRNCAT 1
|
||||
#define __HAVE_ARCH_STRCMP 1
|
||||
#define __HAVE_ARCH_STRNCMP 1
|
||||
#define __HAVE_ARCH_STRNICMP 1
|
||||
#define __HAVE_ARCH_STRCHR 1
|
||||
#define __HAVE_ARCH_STRRCHR 1
|
||||
#define __HAVE_ARCH_STRSTR 1
|
||||
|
@ -41,7 +41,6 @@ struct thread_info {
|
||||
* 0-0xBFFFFFFF for user-thead
|
||||
* 0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
|
||||
__u8 supervisor_stack[0];
|
||||
};
|
||||
@ -65,9 +64,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -40,7 +40,6 @@ void foo(void)
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count);
|
||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||
OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
|
||||
BLANK();
|
||||
|
||||
/* offsets into register file storage */
|
||||
|
@ -62,7 +62,7 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8)
|
||||
unsigned long tbr, psr;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
tbr = user->i.tbr;
|
||||
psr = user->i.psr;
|
||||
|
@ -10,29 +10,6 @@ extern const void __memset_end, __memset_user_error_lr, __memset_user_error_hand
|
||||
extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
|
||||
extern spinlock_t modlist_lock;
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static inline unsigned long search_one_table(const struct exception_table_entry *first,
|
||||
const struct exception_table_entry *last,
|
||||
unsigned long value)
|
||||
{
|
||||
while (first <= last) {
|
||||
const struct exception_table_entry __attribute__((aligned(8))) *mid;
|
||||
long diff;
|
||||
|
||||
mid = (last - first) / 2 + first;
|
||||
diff = mid->insn - value;
|
||||
if (diff == 0)
|
||||
return mid->fixup;
|
||||
else if (diff < 0)
|
||||
first = mid + 1;
|
||||
else
|
||||
last = mid - 1;
|
||||
}
|
||||
return 0;
|
||||
} /* end search_one_table() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
|
@ -56,7 +56,6 @@ struct thread_info {
|
||||
* used for syscalls somehow;
|
||||
* seems to have a function pointer and four arguments
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
/* Points to the current pt_regs frame */
|
||||
struct pt_regs *regs;
|
||||
/*
|
||||
@ -83,9 +82,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = 1, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
.sp = 0, \
|
||||
.regs = NULL, \
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ asmlinkage int sys_rt_sigreturn(void)
|
||||
sigset_t blocked;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
frame = (struct rt_sigframe __user *)pt_psp(regs);
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
|
@ -27,7 +27,6 @@ struct thread_info {
|
||||
__u32 status; /* Thread synchronous flags */
|
||||
mm_segment_t addr_limit; /* user-level address space limit */
|
||||
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
|
||||
struct restart_block restart_block;
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
|
||||
__u64 ac_stamp;
|
||||
__u64 ac_leave;
|
||||
@ -46,9 +45,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#ifndef ASM_OFFSETS_C
|
||||
|
@ -46,7 +46,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
|
||||
long err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* restore scratch that always needs gets updated during signal delivery: */
|
||||
err = __get_user(flags, &sc->sc_flags);
|
||||
|
@ -34,7 +34,6 @@ struct thread_info {
|
||||
0-0xBFFFFFFF for user-thread
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
|
||||
__u8 supervisor_stack[0];
|
||||
};
|
||||
@ -49,7 +48,6 @@ struct thread_info {
|
||||
#define TI_CPU 0x00000010
|
||||
#define TI_PRE_COUNT 0x00000014
|
||||
#define TI_ADDR_LIMIT 0x00000018
|
||||
#define TI_RESTART_BLOCK 0x000001C
|
||||
|
||||
#endif
|
||||
|
||||
@ -68,9 +66,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -48,7 +48,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
|
||||
unsigned int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
|
||||
COPY(r4);
|
||||
|
@ -31,7 +31,6 @@ struct thread_info {
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
__u32 cpu; /* should always be 0 on m68k */
|
||||
unsigned long tp_value; /* thread pointer */
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
@ -41,9 +40,6 @@ struct thread_info {
|
||||
.exec_domain = &default_exec_domain, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_stack (init_thread_union.stack)
|
||||
|
@ -655,7 +655,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
|
||||
int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* get previous context */
|
||||
if (copy_from_user(&context, usc, sizeof(context)))
|
||||
@ -693,7 +693,7 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err = __get_user(temp, &uc->uc_mcontext.version);
|
||||
if (temp != MCONTEXT_VERSION)
|
||||
|
@ -35,9 +35,8 @@ struct thread_info {
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
struct restart_block restart_block;
|
||||
|
||||
u8 supervisor_stack[0];
|
||||
u8 supervisor_stack[0] __aligned(8);
|
||||
};
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
@ -74,9 +73,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -48,7 +48,7 @@ static int restore_sigcontext(struct pt_regs *regs,
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err = metag_gp_regs_copyin(regs, 0, sizeof(struct user_gp_regs), NULL,
|
||||
&sc->regs);
|
||||
|
@ -71,7 +71,6 @@ struct thread_info {
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
struct restart_block restart_block;
|
||||
|
||||
struct cpu_context cpu_context;
|
||||
};
|
||||
@ -87,9 +86,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -89,7 +89,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
||||
int rval;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
@ -34,7 +34,6 @@ struct thread_info {
|
||||
* 0x7fffffff for user-thead
|
||||
* 0xffffffff for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
struct pt_regs *regs;
|
||||
long syscall; /* syscall number */
|
||||
};
|
||||
@ -50,9 +49,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -98,7 +98,6 @@ void output_thread_info_defines(void)
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||
OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
|
||||
OFFSET(TI_REGS, thread_info, regs);
|
||||
DEFINE(_THREAD_SIZE, THREAD_SIZE);
|
||||
DEFINE(_THREAD_MASK, THREAD_MASK);
|
||||
|
@ -243,7 +243,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
|
||||
int i;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
||||
|
||||
|
@ -220,7 +220,7 @@ static int restore_sigcontext32(struct pt_regs *regs,
|
||||
int i;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
|
||||
err |= __get_user(regs->hi, &sc->sc_mdhi);
|
||||
|
@ -50,7 +50,6 @@ struct thread_info {
|
||||
0-0xBFFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
|
||||
__u8 supervisor_stack[0];
|
||||
};
|
||||
@ -80,9 +79,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -28,7 +28,6 @@ void foo(void)
|
||||
OFFSET(TI_cpu, thread_info, cpu);
|
||||
OFFSET(TI_preempt_count, thread_info, preempt_count);
|
||||
OFFSET(TI_addr_limit, thread_info, addr_limit);
|
||||
OFFSET(TI_restart_block, thread_info, restart_block);
|
||||
BLANK();
|
||||
|
||||
OFFSET(REG_D0, pt_regs, d0);
|
||||
|
@ -40,7 +40,7 @@ static int restore_sigcontext(struct pt_regs *regs,
|
||||
unsigned int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (is_using_fpu(current))
|
||||
fpu_kill_state(current);
|
||||
|
@ -57,7 +57,6 @@ struct thread_info {
|
||||
0-0x7FFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct restart_block restart_block;
|
||||
__u8 supervisor_stack[0];
|
||||
|
||||
/* saved context data */
|
||||
@ -79,9 +78,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = 1, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
.ksp = 0, \
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ static int restore_sigcontext(struct pt_regs *regs,
|
||||
int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Restore the regs from &sc->regs.
|
||||
|
@ -14,7 +14,6 @@ struct thread_info {
|
||||
mm_segment_t addr_limit; /* user-level address space limit */
|
||||
__u32 cpu; /* current CPU */
|
||||
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
@ -25,9 +24,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall \
|
||||
} \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -99,7 +99,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
||||
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
|
||||
#endif
|
||||
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* Unwind the user stack to get the rt_sigframe structure. */
|
||||
frame = (struct rt_sigframe __user *)
|
||||
|
@ -40,63 +40,27 @@ static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK)
|
||||
static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); }
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
static inline int pte_present(pte_t pte)
|
||||
{
|
||||
return pte_val(pte) & _PAGE_NUMA_MASK;
|
||||
}
|
||||
|
||||
#define pte_present_nonuma pte_present_nonuma
|
||||
static inline int pte_present_nonuma(pte_t pte)
|
||||
{
|
||||
return pte_val(pte) & (_PAGE_PRESENT);
|
||||
}
|
||||
|
||||
#define ptep_set_numa ptep_set_numa
|
||||
static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr,
|
||||
pte_t *ptep)
|
||||
{
|
||||
if ((pte_val(*ptep) & _PAGE_PRESENT) == 0)
|
||||
VM_BUG_ON(1);
|
||||
|
||||
pte_update(mm, addr, ptep, _PAGE_PRESENT, _PAGE_NUMA, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#define pmdp_set_numa pmdp_set_numa
|
||||
static inline void pmdp_set_numa(struct mm_struct *mm, unsigned long addr,
|
||||
pmd_t *pmdp)
|
||||
{
|
||||
if ((pmd_val(*pmdp) & _PAGE_PRESENT) == 0)
|
||||
VM_BUG_ON(1);
|
||||
|
||||
pmd_hugepage_update(mm, addr, pmdp, _PAGE_PRESENT, _PAGE_NUMA);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic NUMA pte helpers expect pteval_t and pmdval_t types to exist
|
||||
* which was inherited from x86. For the purposes of powerpc pte_basic_t and
|
||||
* pmd_t are equivalent
|
||||
* These work without NUMA balancing but the kernel does not care. See the
|
||||
* comment in include/asm-generic/pgtable.h . On powerpc, this will only
|
||||
* work for user pages and always return true for kernel pages.
|
||||
*/
|
||||
#define pteval_t pte_basic_t
|
||||
#define pmdval_t pmd_t
|
||||
static inline pteval_t ptenuma_flags(pte_t pte)
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return pte_val(pte) & _PAGE_NUMA_MASK;
|
||||
return (pte_val(pte) &
|
||||
(_PAGE_PRESENT | _PAGE_USER)) == _PAGE_PRESENT;
|
||||
}
|
||||
|
||||
static inline pmdval_t pmdnuma_flags(pmd_t pmd)
|
||||
static inline int pmd_protnone(pmd_t pmd)
|
||||
{
|
||||
return pmd_val(pmd) & _PAGE_NUMA_MASK;
|
||||
return pte_protnone(pmd_pte(pmd));
|
||||
}
|
||||
|
||||
# else
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
static inline int pte_present(pte_t pte)
|
||||
{
|
||||
return pte_val(pte) & _PAGE_PRESENT;
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
/* Conversion functions: convert a page and protection to a page entry,
|
||||
* and a page entry and page directory to the page they refer to.
|
||||
|
@ -104,11 +104,6 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
|
||||
_PAGE_USER | _PAGE_ACCESSED | _PAGE_RO | \
|
||||
_PAGE_RW | _PAGE_HWWRITE | _PAGE_DIRTY | _PAGE_EXEC)
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/* Mask of bits that distinguish present and numa ptes */
|
||||
#define _PAGE_NUMA_MASK (_PAGE_NUMA|_PAGE_PRESENT)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We define 2 sets of base prot bits, one for basic pages (ie,
|
||||
* cacheable kernel and user pages) and one for non cacheable
|
||||
|
@ -27,12 +27,6 @@
|
||||
#define _PAGE_RW 0x0200 /* software: user write access allowed */
|
||||
#define _PAGE_BUSY 0x0800 /* software: PTE & hash are busy */
|
||||
|
||||
/*
|
||||
* Used for tracking numa faults
|
||||
*/
|
||||
#define _PAGE_NUMA 0x00000010 /* Gather numa placement stats */
|
||||
|
||||
|
||||
/* No separate kernel read-only */
|
||||
#define _PAGE_KERNEL_RW (_PAGE_RW | _PAGE_DIRTY) /* user access blocked by key */
|
||||
#define _PAGE_KERNEL_RO _PAGE_KERNEL_RW
|
||||
|
@ -43,7 +43,6 @@ struct thread_info {
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 => preemptable,
|
||||
<0 => BUG */
|
||||
struct restart_block restart_block;
|
||||
unsigned long local_flags; /* private flags for thread */
|
||||
|
||||
/* low level flags - has atomic operations done on it */
|
||||
@ -59,9 +58,6 @@ struct thread_info {
|
||||
.exec_domain = &default_exec_domain, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
.flags = 0, \
|
||||
}
|
||||
|
||||
|
@ -1231,7 +1231,7 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|
||||
int tm_restore = 0;
|
||||
#endif
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
rt_sf = (struct rt_sigframe __user *)
|
||||
(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16);
|
||||
@ -1504,7 +1504,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|
||||
#endif
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
sf = (struct sigframe __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
|
||||
sc = &sf->sctx;
|
||||
|
@ -666,7 +666,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
|
||||
#endif
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, uc, sizeof(*uc)))
|
||||
goto badframe;
|
||||
|
@ -621,6 +621,38 @@ unsigned long long sched_clock(void)
|
||||
return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PPC_PSERIES
|
||||
|
||||
/*
|
||||
* Running clock - attempts to give a view of time passing for a virtualised
|
||||
* kernels.
|
||||
* Uses the VTB register if available otherwise a next best guess.
|
||||
*/
|
||||
unsigned long long running_clock(void)
|
||||
{
|
||||
/*
|
||||
* Don't read the VTB as a host since KVM does not switch in host
|
||||
* timebase into the VTB when it takes a guest off the CPU, reading the
|
||||
* VTB would result in reading 'last switched out' guest VTB.
|
||||
*
|
||||
* Host kernels are often compiled with CONFIG_PPC_PSERIES checked, it
|
||||
* would be unsafe to rely only on the #ifdef above.
|
||||
*/
|
||||
if (firmware_has_feature(FW_FEATURE_LPAR) &&
|
||||
cpu_has_feature(CPU_FTR_ARCH_207S))
|
||||
return mulhdu(get_vtb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
|
||||
|
||||
/*
|
||||
* This is a next best approximation without a VTB.
|
||||
* On a host which is running bare metal there should never be any stolen
|
||||
* time and on a host which doesn't do any virtualisation TB *should* equal
|
||||
* VTB so it makes no difference anyway.
|
||||
*/
|
||||
return local_clock() - cputime_to_nsecs(kcpustat_this_cpu->cpustat[CPUTIME_STEAL]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init get_freq(char *name, int cells, unsigned long *val)
|
||||
{
|
||||
struct device_node *cpu;
|
||||
|
@ -212,7 +212,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
|
||||
/* Look up the Linux PTE for the backing page */
|
||||
pte_size = psize;
|
||||
pte = lookup_linux_pte_and_update(pgdir, hva, writing, &pte_size);
|
||||
if (pte_present(pte) && !pte_numa(pte)) {
|
||||
if (pte_present(pte) && !pte_protnone(pte)) {
|
||||
if (writing && !pte_write(pte))
|
||||
/* make the actual HPTE be read-only */
|
||||
ptel = hpte_make_readonly(ptel);
|
||||
|
@ -64,10 +64,14 @@ int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto out_unlock;
|
||||
} else {
|
||||
if (dsisr & DSISR_PROTFAULT)
|
||||
goto out_unlock;
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto out_unlock;
|
||||
/*
|
||||
* protfault should only happen due to us
|
||||
* mapping a region readonly temporarily. PROT_NONE
|
||||
* is also covered by the VMA check above.
|
||||
*/
|
||||
WARN_ON_ONCE(dsisr & DSISR_PROTFAULT);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -389,19 +389,6 @@ good_area:
|
||||
#endif /* CONFIG_8xx */
|
||||
|
||||
if (is_exec) {
|
||||
#ifdef CONFIG_PPC_STD_MMU
|
||||
/* Protection fault on exec go straight to failure on
|
||||
* Hash based MMUs as they either don't support per-page
|
||||
* execute permission, or if they do, it's handled already
|
||||
* at the hash level. This test would probably have to
|
||||
* be removed if we change the way this works to make hash
|
||||
* processors use the same I/D cache coherency mechanism
|
||||
* as embedded.
|
||||
*/
|
||||
if (error_code & DSISR_PROTFAULT)
|
||||
goto bad_area;
|
||||
#endif /* CONFIG_PPC_STD_MMU */
|
||||
|
||||
/*
|
||||
* Allow execution from readable areas if the MMU does not
|
||||
* provide separate controls over reading and executing.
|
||||
@ -416,6 +403,14 @@ good_area:
|
||||
(cpu_has_feature(CPU_FTR_NOEXECUTE) ||
|
||||
!(vma->vm_flags & (VM_READ | VM_WRITE))))
|
||||
goto bad_area;
|
||||
#ifdef CONFIG_PPC_STD_MMU
|
||||
/*
|
||||
* protfault should only happen due to us
|
||||
* mapping a region readonly temporarily. PROT_NONE
|
||||
* is also covered by the VMA check above.
|
||||
*/
|
||||
WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
|
||||
#endif /* CONFIG_PPC_STD_MMU */
|
||||
/* a write */
|
||||
} else if (is_write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
@ -423,11 +418,9 @@ good_area:
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
/* a read */
|
||||
} else {
|
||||
/* protection fault */
|
||||
if (error_code & 0x08000000)
|
||||
goto bad_area;
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
|
||||
goto bad_area;
|
||||
WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -172,9 +172,14 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma,
|
||||
void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
||||
pte_t pte)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_VM
|
||||
WARN_ON(pte_val(*ptep) & _PAGE_PRESENT);
|
||||
#endif
|
||||
/*
|
||||
* When handling numa faults, we already have the pte marked
|
||||
* _PAGE_PRESENT, but we can be sure that it is not in hpte.
|
||||
* Hence we can use set_pte_at for them.
|
||||
*/
|
||||
VM_WARN_ON((pte_val(*ptep) & (_PAGE_PRESENT | _PAGE_USER)) ==
|
||||
(_PAGE_PRESENT | _PAGE_USER));
|
||||
|
||||
/* Note: mm->context.id might not yet have been assigned as
|
||||
* this context might not have been activated yet when this
|
||||
* is called.
|
||||
|
@ -718,7 +718,8 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
|
||||
pmd_t *pmdp, pmd_t pmd)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_VM
|
||||
WARN_ON(pmd_val(*pmdp) & _PAGE_PRESENT);
|
||||
WARN_ON((pmd_val(*pmdp) & (_PAGE_PRESENT | _PAGE_USER)) ==
|
||||
(_PAGE_PRESENT | _PAGE_USER));
|
||||
assert_spin_locked(&mm->page_table_lock);
|
||||
WARN_ON(!pmd_trans_huge(pmd));
|
||||
#endif
|
||||
|
@ -44,7 +44,6 @@ extern char *strstr(const char *, const char *);
|
||||
#undef __HAVE_ARCH_STRCHR
|
||||
#undef __HAVE_ARCH_STRNCHR
|
||||
#undef __HAVE_ARCH_STRNCMP
|
||||
#undef __HAVE_ARCH_STRNICMP
|
||||
#undef __HAVE_ARCH_STRPBRK
|
||||
#undef __HAVE_ARCH_STRSEP
|
||||
#undef __HAVE_ARCH_STRSPN
|
||||
|
@ -39,7 +39,6 @@ struct thread_info {
|
||||
unsigned long sys_call_table; /* System call table address */
|
||||
unsigned int cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
struct restart_block restart_block;
|
||||
unsigned int system_call;
|
||||
__u64 user_timer;
|
||||
__u64 system_timer;
|
||||
@ -56,9 +55,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -209,7 +209,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
|
||||
int i;
|
||||
|
||||
/* Alwys make any pending restarted system call return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (__copy_from_user(&user_sregs, &sregs->regs, sizeof(user_sregs)))
|
||||
return -EFAULT;
|
||||
|
@ -162,7 +162,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
|
||||
_sigregs user_sregs;
|
||||
|
||||
/* Alwys make any pending restarted system call return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (__copy_from_user(&user_sregs, sregs, sizeof(user_sregs)))
|
||||
return -EFAULT;
|
||||
|
@ -42,7 +42,6 @@ struct thread_info {
|
||||
* 0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
mm_segment_t addr_limit;
|
||||
struct restart_block restart_block;
|
||||
struct pt_regs *regs;
|
||||
};
|
||||
|
||||
@ -58,9 +57,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = 1, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -106,7 +106,6 @@ void output_thread_info_defines(void)
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||
OFFSET(TI_RESTART_BLOCK, thread_info, restart_block);
|
||||
OFFSET(TI_REGS, thread_info, regs);
|
||||
DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
|
||||
DEFINE(KERNEL_STACK_MASK, THREAD_MASK);
|
||||
|
@ -141,7 +141,7 @@ score_rt_sigreturn(struct pt_regs *regs)
|
||||
int sig;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
frame = (struct rt_sigframe __user *) regs->regs[0];
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
|
@ -33,7 +33,6 @@ struct thread_info {
|
||||
__u32 cpu;
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
struct restart_block restart_block;
|
||||
unsigned long previous_sp; /* sp of previous stack in case
|
||||
of nested IRQ stacks */
|
||||
__u8 supervisor_stack[0];
|
||||
@ -63,9 +62,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -25,7 +25,6 @@ int main(void)
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
|
||||
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
|
||||
DEFINE(TI_SIZE, sizeof(struct thread_info));
|
||||
|
||||
#ifdef CONFIG_HIBERNATION
|
||||
|
@ -156,7 +156,7 @@ asmlinkage int sys_sigreturn(void)
|
||||
int r0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
@ -186,7 +186,7 @@ asmlinkage int sys_rt_sigreturn(void)
|
||||
int r0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
@ -260,7 +260,7 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
|
||||
long long ret;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
@ -294,7 +294,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
|
||||
long long ret;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
@ -47,8 +47,6 @@ struct thread_info {
|
||||
struct reg_window32 reg_window[NSWINS]; /* align for ldd! */
|
||||
unsigned long rwbuf_stkptrs[NSWINS];
|
||||
unsigned long w_saved;
|
||||
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -62,9 +60,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
@ -103,7 +98,6 @@ register struct thread_info *current_thread_info_reg asm("g6");
|
||||
#define TI_REG_WINDOW 0x30
|
||||
#define TI_RWIN_SPTRS 0x230
|
||||
#define TI_W_SAVED 0x250
|
||||
/* #define TI_RESTART_BLOCK 0x25n */ /* Nobody cares */
|
||||
|
||||
/*
|
||||
* thread information flag bit numbers
|
||||
|
@ -58,8 +58,6 @@ struct thread_info {
|
||||
unsigned long gsr[7];
|
||||
unsigned long xfsr[7];
|
||||
|
||||
struct restart_block restart_block;
|
||||
|
||||
struct pt_regs *kern_una_regs;
|
||||
unsigned int kern_una_insn;
|
||||
|
||||
@ -92,10 +90,9 @@ struct thread_info {
|
||||
#define TI_RWIN_SPTRS 0x000003c8
|
||||
#define TI_GSR 0x00000400
|
||||
#define TI_XFSR 0x00000438
|
||||
#define TI_RESTART_BLOCK 0x00000470
|
||||
#define TI_KUNA_REGS 0x000004a0
|
||||
#define TI_KUNA_INSN 0x000004a8
|
||||
#define TI_FPREGS 0x000004c0
|
||||
#define TI_KUNA_REGS 0x00000470
|
||||
#define TI_KUNA_INSN 0x00000478
|
||||
#define TI_FPREGS 0x00000480
|
||||
|
||||
/* We embed this in the uppermost byte of thread_info->flags */
|
||||
#define FAULT_CODE_WRITE 0x01 /* Write access, implies D-TLB */
|
||||
@ -124,9 +121,6 @@ struct thread_info {
|
||||
.current_ds = ASI_P, \
|
||||
.exec_domain = &default_exec_domain, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -150,7 +150,7 @@ void do_sigreturn32(struct pt_regs *regs)
|
||||
int err, i;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
synchronize_user_stack();
|
||||
|
||||
@ -235,7 +235,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
||||
int err, i;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
synchronize_user_stack();
|
||||
regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;
|
||||
|
@ -70,7 +70,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
synchronize_user_stack();
|
||||
|
||||
|
@ -254,7 +254,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
synchronize_user_stack ();
|
||||
sf = (struct rt_signal_frame __user *)
|
||||
|
@ -2730,8 +2730,6 @@ void __init trap_init(void)
|
||||
TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
|
||||
TI_CURRENT_DS != offsetof(struct thread_info,
|
||||
current_ds) ||
|
||||
TI_RESTART_BLOCK != offsetof(struct thread_info,
|
||||
restart_block) ||
|
||||
TI_KUNA_REGS != offsetof(struct thread_info,
|
||||
kern_una_regs) ||
|
||||
TI_KUNA_INSN != offsetof(struct thread_info,
|
||||
|
@ -36,7 +36,6 @@ struct thread_info {
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space
|
||||
(KERNEL_DS or USER_DS) */
|
||||
struct restart_block restart_block;
|
||||
struct single_step_state *step_state; /* single step state
|
||||
(if non-zero) */
|
||||
int align_ctl; /* controls unaligned access */
|
||||
@ -57,9 +56,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
.step_state = NULL, \
|
||||
.align_ctl = 0, \
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ int restore_sigcontext(struct pt_regs *regs,
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Enforce that sigcontext is like pt_regs, and doesn't mess
|
||||
|
@ -22,7 +22,6 @@ struct thread_info {
|
||||
mm_segment_t addr_limit; /* thread address space:
|
||||
0-0xBFFFFFFF for user
|
||||
0-0xFFFFFFFF for kernel */
|
||||
struct restart_block restart_block;
|
||||
struct thread_info *real_thread; /* Points to non-IRQ stack */
|
||||
};
|
||||
|
||||
@ -34,9 +33,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
.real_thread = NULL, \
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,6 @@ struct thread_info {
|
||||
#ifdef CONFIG_UNICORE_FPU_F64
|
||||
struct fp_state fpstate __attribute__((aligned(8)));
|
||||
#endif
|
||||
struct restart_block restart_block;
|
||||
};
|
||||
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
@ -89,9 +88,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -105,7 +105,7 @@ asmlinkage int __sys_rt_sigreturn(struct pt_regs *regs)
|
||||
struct rt_sigframe __user *frame;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/*
|
||||
* Since we stacked the signal on a 64-bit boundary,
|
||||
|
@ -169,7 +169,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
|
||||
u32 tmp;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
get_user_try {
|
||||
/*
|
||||
|
@ -132,13 +132,7 @@ static inline int pte_exec(pte_t pte)
|
||||
|
||||
static inline int pte_special(pte_t pte)
|
||||
{
|
||||
/*
|
||||
* See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h.
|
||||
* On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 ==
|
||||
* __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL.
|
||||
*/
|
||||
return (pte_flags(pte) & _PAGE_SPECIAL) &&
|
||||
(pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE));
|
||||
return pte_flags(pte) & _PAGE_SPECIAL;
|
||||
}
|
||||
|
||||
static inline unsigned long pte_pfn(pte_t pte)
|
||||
@ -300,7 +294,7 @@ static inline pmd_t pmd_mkwrite(pmd_t pmd)
|
||||
|
||||
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
|
||||
{
|
||||
return pmd_clear_flags(pmd, _PAGE_PRESENT);
|
||||
return pmd_clear_flags(pmd, _PAGE_PRESENT | _PAGE_PROTNONE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
|
||||
@ -442,13 +436,6 @@ static inline int pte_same(pte_t a, pte_t b)
|
||||
}
|
||||
|
||||
static inline int pte_present(pte_t a)
|
||||
{
|
||||
return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE |
|
||||
_PAGE_NUMA);
|
||||
}
|
||||
|
||||
#define pte_present_nonuma pte_present_nonuma
|
||||
static inline int pte_present_nonuma(pte_t a)
|
||||
{
|
||||
return pte_flags(a) & (_PAGE_PRESENT | _PAGE_PROTNONE);
|
||||
}
|
||||
@ -459,7 +446,7 @@ static inline bool pte_accessible(struct mm_struct *mm, pte_t a)
|
||||
if (pte_flags(a) & _PAGE_PRESENT)
|
||||
return true;
|
||||
|
||||
if ((pte_flags(a) & (_PAGE_PROTNONE | _PAGE_NUMA)) &&
|
||||
if ((pte_flags(a) & _PAGE_PROTNONE) &&
|
||||
mm_tlb_flush_pending(mm))
|
||||
return true;
|
||||
|
||||
@ -479,10 +466,25 @@ static inline int pmd_present(pmd_t pmd)
|
||||
* the _PAGE_PSE flag will remain set at all times while the
|
||||
* _PAGE_PRESENT bit is clear).
|
||||
*/
|
||||
return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE |
|
||||
_PAGE_NUMA);
|
||||
return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/*
|
||||
* These work without NUMA balancing but the kernel does not care. See the
|
||||
* comment in include/asm-generic/pgtable.h
|
||||
*/
|
||||
static inline int pte_protnone(pte_t pte)
|
||||
{
|
||||
return pte_flags(pte) & _PAGE_PROTNONE;
|
||||
}
|
||||
|
||||
static inline int pmd_protnone(pmd_t pmd)
|
||||
{
|
||||
return pmd_flags(pmd) & _PAGE_PROTNONE;
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
static inline int pmd_none(pmd_t pmd)
|
||||
{
|
||||
/* Only check low word on 32-bit platforms, since it might be
|
||||
@ -539,11 +541,6 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
|
||||
|
||||
static inline int pmd_bad(pmd_t pmd)
|
||||
{
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/* pmd_numa check */
|
||||
if ((pmd_flags(pmd) & (_PAGE_NUMA|_PAGE_PRESENT)) == _PAGE_NUMA)
|
||||
return 0;
|
||||
#endif
|
||||
return (pmd_flags(pmd) & ~_PAGE_USER) != _KERNPG_TABLE;
|
||||
}
|
||||
|
||||
@ -862,19 +859,16 @@ static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
|
||||
#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
|
||||
static inline pte_t pte_swp_mksoft_dirty(pte_t pte)
|
||||
{
|
||||
VM_BUG_ON(pte_present_nonuma(pte));
|
||||
return pte_set_flags(pte, _PAGE_SWP_SOFT_DIRTY);
|
||||
}
|
||||
|
||||
static inline int pte_swp_soft_dirty(pte_t pte)
|
||||
{
|
||||
VM_BUG_ON(pte_present_nonuma(pte));
|
||||
return pte_flags(pte) & _PAGE_SWP_SOFT_DIRTY;
|
||||
}
|
||||
|
||||
static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
|
||||
{
|
||||
VM_BUG_ON(pte_present_nonuma(pte));
|
||||
return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
|
||||
}
|
||||
#endif
|
||||
|
@ -142,12 +142,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
|
||||
|
||||
/* Encode and de-code a swap entry */
|
||||
#define SWP_TYPE_BITS 5
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/* Automatic NUMA balancing needs to be distinguishable from swap entries */
|
||||
#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 2)
|
||||
#else
|
||||
#define SWP_OFFSET_SHIFT (_PAGE_BIT_PROTNONE + 1)
|
||||
#endif
|
||||
|
||||
#define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS)
|
||||
|
||||
|
@ -27,14 +27,6 @@
|
||||
#define _PAGE_BIT_SOFT_DIRTY _PAGE_BIT_SOFTW3 /* software dirty tracking */
|
||||
#define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */
|
||||
|
||||
/*
|
||||
* Swap offsets on configurations that allow automatic NUMA balancing use the
|
||||
* bits after _PAGE_BIT_GLOBAL. To uniquely distinguish NUMA hinting PTEs from
|
||||
* swap entries, we use the first bit after _PAGE_BIT_GLOBAL and shrink the
|
||||
* maximum possible swap space from 16TB to 8TB.
|
||||
*/
|
||||
#define _PAGE_BIT_NUMA (_PAGE_BIT_GLOBAL+1)
|
||||
|
||||
/* If _PAGE_BIT_PRESENT is clear, we use these: */
|
||||
/* - if the user mapped it with PROT_NONE; pte_present gives true */
|
||||
#define _PAGE_BIT_PROTNONE _PAGE_BIT_GLOBAL
|
||||
@ -75,21 +67,6 @@
|
||||
#define _PAGE_SOFT_DIRTY (_AT(pteval_t, 0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* _PAGE_NUMA distinguishes between a numa hinting minor fault and a page
|
||||
* that is not present. The hinting fault gathers numa placement statistics
|
||||
* (see pte_numa()). The bit is always zero when the PTE is not present.
|
||||
*
|
||||
* The bit picked must be always zero when the pmd is present and not
|
||||
* present, so that we don't lose information when we set it while
|
||||
* atomically clearing the present bit.
|
||||
*/
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
#define _PAGE_NUMA (_AT(pteval_t, 1) << _PAGE_BIT_NUMA)
|
||||
#else
|
||||
#define _PAGE_NUMA (_AT(pteval_t, 0))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Tracking soft dirty bit when a page goes to a swap is tricky.
|
||||
* We need a bit which can be stored in pte _and_ not conflict
|
||||
@ -122,8 +99,8 @@
|
||||
/* Set of bits not changed in pte_modify */
|
||||
#define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
|
||||
_PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY | \
|
||||
_PAGE_SOFT_DIRTY | _PAGE_NUMA)
|
||||
#define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE | _PAGE_NUMA)
|
||||
_PAGE_SOFT_DIRTY)
|
||||
#define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE)
|
||||
|
||||
/*
|
||||
* The cache modes defined here are used to translate between pure SW usage
|
||||
@ -324,20 +301,6 @@ static inline pteval_t pte_flags(pte_t pte)
|
||||
return native_pte_val(pte) & PTE_FLAGS_MASK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NUMA_BALANCING
|
||||
/* Set of bits that distinguishes present, prot_none and numa ptes */
|
||||
#define _PAGE_NUMA_MASK (_PAGE_NUMA|_PAGE_PROTNONE|_PAGE_PRESENT)
|
||||
static inline pteval_t ptenuma_flags(pte_t pte)
|
||||
{
|
||||
return pte_flags(pte) & _PAGE_NUMA_MASK;
|
||||
}
|
||||
|
||||
static inline pmdval_t pmdnuma_flags(pmd_t pmd)
|
||||
{
|
||||
return pmd_flags(pmd) & _PAGE_NUMA_MASK;
|
||||
}
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
#define pgprot_val(x) ((x).pgprot)
|
||||
#define __pgprot(x) ((pgprot_t) { (x) } )
|
||||
|
||||
|
@ -31,7 +31,6 @@ struct thread_info {
|
||||
__u32 cpu; /* current CPU */
|
||||
int saved_preempt_count;
|
||||
mm_segment_t addr_limit;
|
||||
struct restart_block restart_block;
|
||||
void __user *sysenter_return;
|
||||
unsigned int sig_on_uaccess_error:1;
|
||||
unsigned int uaccess_err:1; /* uaccess failed */
|
||||
@ -45,9 +44,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.saved_preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -168,7 +168,7 @@ static void _hpet_print_config(const char *function, int line)
|
||||
#define hpet_print_config() \
|
||||
do { \
|
||||
if (hpet_verbose) \
|
||||
_hpet_print_config(__FUNCTION__, __LINE__); \
|
||||
_hpet_print_config(__func__, __LINE__); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -49,11 +49,11 @@ int mach_set_rtc_mmss(const struct timespec *now)
|
||||
retval = set_rtc_time(&tm);
|
||||
if (retval)
|
||||
printk(KERN_ERR "%s: RTC write failed with error %d\n",
|
||||
__FUNCTION__, retval);
|
||||
__func__, retval);
|
||||
} else {
|
||||
printk(KERN_ERR
|
||||
"%s: Invalid RTC value: write of %lx to RTC failed\n",
|
||||
__FUNCTION__, nowtime);
|
||||
__func__, nowtime);
|
||||
retval = -EINVAL;
|
||||
}
|
||||
return retval;
|
||||
|
@ -69,7 +69,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
|
||||
unsigned int err = 0;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
get_user_try {
|
||||
|
||||
|
@ -84,7 +84,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
|
||||
struct page *page;
|
||||
|
||||
/* Similar to the PMD case, NUMA hinting must take slow path */
|
||||
if (pte_numa(pte)) {
|
||||
if (pte_protnone(pte)) {
|
||||
pte_unmap(ptep);
|
||||
return 0;
|
||||
}
|
||||
@ -178,7 +178,7 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
|
||||
* slowpath for accounting purposes and so that they
|
||||
* can be serialised against THP migration.
|
||||
*/
|
||||
if (pmd_numa(pmd))
|
||||
if (pmd_protnone(pmd))
|
||||
return 0;
|
||||
if (!gup_huge_pmd(pmd, addr, next, write, pages, nr))
|
||||
return 0;
|
||||
|
@ -110,7 +110,7 @@ int vrtc_set_mmss(const struct timespec *now)
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
} else {
|
||||
pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n",
|
||||
__FUNCTION__, now->tv_sec);
|
||||
__func__, now->tv_sec);
|
||||
retval = -EINVAL;
|
||||
}
|
||||
return retval;
|
||||
|
@ -157,7 +157,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
|
||||
int err, pid;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err = copy_from_user(&sc, from, sizeof(sc));
|
||||
if (err)
|
||||
|
@ -51,7 +51,6 @@ struct thread_info {
|
||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
struct restart_block restart_block;
|
||||
|
||||
unsigned long cpenable;
|
||||
|
||||
@ -72,7 +71,6 @@ struct thread_info {
|
||||
#define TI_CPU 0x00000010
|
||||
#define TI_PRE_COUNT 0x00000014
|
||||
#define TI_ADDR_LIMIT 0x00000018
|
||||
#define TI_RESTART_BLOCK 0x000001C
|
||||
|
||||
#endif
|
||||
|
||||
@ -90,9 +88,6 @@ struct thread_info {
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define init_thread_info (init_thread_union.thread_info)
|
||||
|
@ -245,7 +245,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
|
||||
int ret;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
current->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
if (regs->depc > 64)
|
||||
panic("rt_sigreturn in double exception!\n");
|
||||
|
@ -111,8 +111,8 @@ void acpi_ut_track_stack_ptr(void)
|
||||
* RETURN: Updated pointer to the function name
|
||||
*
|
||||
* DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
|
||||
* This allows compiler macros such as __FUNCTION__ to be used
|
||||
* with no change to the debug output.
|
||||
* This allows compiler macros such as __func__ to be used with no
|
||||
* change to the debug output.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -1391,7 +1391,7 @@ static int blkfront_probe(struct xenbus_device *dev,
|
||||
if (major != XENVBD_MAJOR) {
|
||||
printk(KERN_INFO
|
||||
"%s: HVM does not support vbd %d as xen block device\n",
|
||||
__FUNCTION__, vdevice);
|
||||
__func__, vdevice);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ static ssize_t name##_show(struct device *d, \
|
||||
} \
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
static inline int init_done(struct zram *zram)
|
||||
static inline bool init_done(struct zram *zram)
|
||||
{
|
||||
return zram->meta != NULL;
|
||||
return zram->disksize;
|
||||
}
|
||||
|
||||
static inline struct zram *dev_to_zram(struct device *dev)
|
||||
@ -307,42 +307,67 @@ static inline int valid_io_request(struct zram *zram,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void zram_meta_free(struct zram_meta *meta)
|
||||
static void zram_meta_free(struct zram_meta *meta, u64 disksize)
|
||||
{
|
||||
size_t num_pages = disksize >> PAGE_SHIFT;
|
||||
size_t index;
|
||||
|
||||
/* Free all pages that are still in this zram device */
|
||||
for (index = 0; index < num_pages; index++) {
|
||||
unsigned long handle = meta->table[index].handle;
|
||||
|
||||
if (!handle)
|
||||
continue;
|
||||
|
||||
zs_free(meta->mem_pool, handle);
|
||||
}
|
||||
|
||||
zs_destroy_pool(meta->mem_pool);
|
||||
vfree(meta->table);
|
||||
kfree(meta);
|
||||
}
|
||||
|
||||
static struct zram_meta *zram_meta_alloc(u64 disksize)
|
||||
static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize)
|
||||
{
|
||||
size_t num_pages;
|
||||
char pool_name[8];
|
||||
struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
|
||||
|
||||
if (!meta)
|
||||
goto out;
|
||||
return NULL;
|
||||
|
||||
num_pages = disksize >> PAGE_SHIFT;
|
||||
meta->table = vzalloc(num_pages * sizeof(*meta->table));
|
||||
if (!meta->table) {
|
||||
pr_err("Error allocating zram address table\n");
|
||||
goto free_meta;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
meta->mem_pool = zs_create_pool(GFP_NOIO | __GFP_HIGHMEM);
|
||||
snprintf(pool_name, sizeof(pool_name), "zram%d", device_id);
|
||||
meta->mem_pool = zs_create_pool(pool_name, GFP_NOIO | __GFP_HIGHMEM);
|
||||
if (!meta->mem_pool) {
|
||||
pr_err("Error creating memory pool\n");
|
||||
goto free_table;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
return meta;
|
||||
|
||||
free_table:
|
||||
out_error:
|
||||
vfree(meta->table);
|
||||
free_meta:
|
||||
kfree(meta);
|
||||
meta = NULL;
|
||||
out:
|
||||
return meta;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool zram_meta_get(struct zram *zram)
|
||||
{
|
||||
if (atomic_inc_not_zero(&zram->refcount))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void zram_meta_put(struct zram *zram)
|
||||
{
|
||||
atomic_dec(&zram->refcount);
|
||||
}
|
||||
|
||||
static void update_position(u32 *index, int *offset, struct bio_vec *bvec)
|
||||
@ -704,10 +729,11 @@ static void zram_bio_discard(struct zram *zram, u32 index,
|
||||
}
|
||||
}
|
||||
|
||||
static void zram_reset_device(struct zram *zram, bool reset_capacity)
|
||||
static void zram_reset_device(struct zram *zram)
|
||||
{
|
||||
size_t index;
|
||||
struct zram_meta *meta;
|
||||
struct zcomp *comp;
|
||||
u64 disksize;
|
||||
|
||||
down_write(&zram->init_lock);
|
||||
|
||||
@ -719,36 +745,30 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
|
||||
}
|
||||
|
||||
meta = zram->meta;
|
||||
/* Free all pages that are still in this zram device */
|
||||
for (index = 0; index < zram->disksize >> PAGE_SHIFT; index++) {
|
||||
unsigned long handle = meta->table[index].handle;
|
||||
if (!handle)
|
||||
continue;
|
||||
comp = zram->comp;
|
||||
disksize = zram->disksize;
|
||||
/*
|
||||
* Refcount will go down to 0 eventually and r/w handler
|
||||
* cannot handle further I/O so it will bail out by
|
||||
* check zram_meta_get.
|
||||
*/
|
||||
zram_meta_put(zram);
|
||||
/*
|
||||
* We want to free zram_meta in process context to avoid
|
||||
* deadlock between reclaim path and any other locks.
|
||||
*/
|
||||
wait_event(zram->io_done, atomic_read(&zram->refcount) == 0);
|
||||
|
||||
zs_free(meta->mem_pool, handle);
|
||||
}
|
||||
|
||||
zcomp_destroy(zram->comp);
|
||||
zram->max_comp_streams = 1;
|
||||
|
||||
zram_meta_free(zram->meta);
|
||||
zram->meta = NULL;
|
||||
/* Reset stats */
|
||||
memset(&zram->stats, 0, sizeof(zram->stats));
|
||||
|
||||
zram->disksize = 0;
|
||||
if (reset_capacity)
|
||||
zram->max_comp_streams = 1;
|
||||
set_capacity(zram->disk, 0);
|
||||
|
||||
up_write(&zram->init_lock);
|
||||
|
||||
/*
|
||||
* Revalidate disk out of the init_lock to avoid lockdep splat.
|
||||
* It's okay because disk's capacity is protected by init_lock
|
||||
* so that revalidate_disk always sees up-to-date capacity.
|
||||
*/
|
||||
if (reset_capacity)
|
||||
revalidate_disk(zram->disk);
|
||||
/* I/O operation under all of CPU are done so let's free */
|
||||
zram_meta_free(meta, disksize);
|
||||
zcomp_destroy(comp);
|
||||
}
|
||||
|
||||
static ssize_t disksize_store(struct device *dev,
|
||||
@ -765,7 +785,7 @@ static ssize_t disksize_store(struct device *dev,
|
||||
return -EINVAL;
|
||||
|
||||
disksize = PAGE_ALIGN(disksize);
|
||||
meta = zram_meta_alloc(disksize);
|
||||
meta = zram_meta_alloc(zram->disk->first_minor, disksize);
|
||||
if (!meta)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -784,6 +804,8 @@ static ssize_t disksize_store(struct device *dev,
|
||||
goto out_destroy_comp;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&zram->io_done);
|
||||
atomic_set(&zram->refcount, 1);
|
||||
zram->meta = meta;
|
||||
zram->comp = comp;
|
||||
zram->disksize = disksize;
|
||||
@ -803,7 +825,7 @@ out_destroy_comp:
|
||||
up_write(&zram->init_lock);
|
||||
zcomp_destroy(comp);
|
||||
out_free_meta:
|
||||
zram_meta_free(meta);
|
||||
zram_meta_free(meta, disksize);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -821,8 +843,9 @@ static ssize_t reset_store(struct device *dev,
|
||||
if (!bdev)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&bdev->bd_mutex);
|
||||
/* Do not reset an active device! */
|
||||
if (bdev->bd_holders) {
|
||||
if (bdev->bd_openers) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@ -838,12 +861,16 @@ static ssize_t reset_store(struct device *dev,
|
||||
|
||||
/* Make sure all pending I/O is finished */
|
||||
fsync_bdev(bdev);
|
||||
zram_reset_device(zram);
|
||||
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
revalidate_disk(zram->disk);
|
||||
bdput(bdev);
|
||||
|
||||
zram_reset_device(zram, true);
|
||||
return len;
|
||||
|
||||
out:
|
||||
mutex_unlock(&bdev->bd_mutex);
|
||||
bdput(bdev);
|
||||
return ret;
|
||||
}
|
||||
@ -909,23 +936,21 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio)
|
||||
{
|
||||
struct zram *zram = queue->queuedata;
|
||||
|
||||
down_read(&zram->init_lock);
|
||||
if (unlikely(!init_done(zram)))
|
||||
if (unlikely(!zram_meta_get(zram)))
|
||||
goto error;
|
||||
|
||||
if (!valid_io_request(zram, bio->bi_iter.bi_sector,
|
||||
bio->bi_iter.bi_size)) {
|
||||
atomic64_inc(&zram->stats.invalid_io);
|
||||
goto error;
|
||||
goto put_zram;
|
||||
}
|
||||
|
||||
__zram_make_request(zram, bio);
|
||||
up_read(&zram->init_lock);
|
||||
|
||||
zram_meta_put(zram);
|
||||
return;
|
||||
|
||||
put_zram:
|
||||
zram_meta_put(zram);
|
||||
error:
|
||||
up_read(&zram->init_lock);
|
||||
bio_io_error(bio);
|
||||
}
|
||||
|
||||
@ -947,21 +972,19 @@ static void zram_slot_free_notify(struct block_device *bdev,
|
||||
static int zram_rw_page(struct block_device *bdev, sector_t sector,
|
||||
struct page *page, int rw)
|
||||
{
|
||||
int offset, err;
|
||||
int offset, err = -EIO;
|
||||
u32 index;
|
||||
struct zram *zram;
|
||||
struct bio_vec bv;
|
||||
|
||||
zram = bdev->bd_disk->private_data;
|
||||
if (unlikely(!zram_meta_get(zram)))
|
||||
goto out;
|
||||
|
||||
if (!valid_io_request(zram, sector, PAGE_SIZE)) {
|
||||
atomic64_inc(&zram->stats.invalid_io);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
down_read(&zram->init_lock);
|
||||
if (unlikely(!init_done(zram))) {
|
||||
err = -EIO;
|
||||
goto out_unlock;
|
||||
err = -EINVAL;
|
||||
goto put_zram;
|
||||
}
|
||||
|
||||
index = sector >> SECTORS_PER_PAGE_SHIFT;
|
||||
@ -972,8 +995,9 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector,
|
||||
bv.bv_offset = 0;
|
||||
|
||||
err = zram_bvec_rw(zram, &bv, index, offset, rw);
|
||||
out_unlock:
|
||||
up_read(&zram->init_lock);
|
||||
put_zram:
|
||||
zram_meta_put(zram);
|
||||
out:
|
||||
/*
|
||||
* If I/O fails, just return error(ie, non-zero) without
|
||||
* calling page_endio.
|
||||
@ -1039,19 +1063,19 @@ static struct attribute_group zram_disk_attr_group = {
|
||||
|
||||
static int create_device(struct zram *zram, int device_id)
|
||||
{
|
||||
struct request_queue *queue;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
init_rwsem(&zram->init_lock);
|
||||
|
||||
zram->queue = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!zram->queue) {
|
||||
queue = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!queue) {
|
||||
pr_err("Error allocating disk queue for device %d\n",
|
||||
device_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
blk_queue_make_request(zram->queue, zram_make_request);
|
||||
zram->queue->queuedata = zram;
|
||||
blk_queue_make_request(queue, zram_make_request);
|
||||
|
||||
/* gendisk structure */
|
||||
zram->disk = alloc_disk(1);
|
||||
@ -1064,7 +1088,8 @@ static int create_device(struct zram *zram, int device_id)
|
||||
zram->disk->major = zram_major;
|
||||
zram->disk->first_minor = device_id;
|
||||
zram->disk->fops = &zram_devops;
|
||||
zram->disk->queue = zram->queue;
|
||||
zram->disk->queue = queue;
|
||||
zram->disk->queue->queuedata = zram;
|
||||
zram->disk->private_data = zram;
|
||||
snprintf(zram->disk->disk_name, 16, "zram%d", device_id);
|
||||
|
||||
@ -1115,20 +1140,35 @@ out_free_disk:
|
||||
del_gendisk(zram->disk);
|
||||
put_disk(zram->disk);
|
||||
out_free_queue:
|
||||
blk_cleanup_queue(zram->queue);
|
||||
blk_cleanup_queue(queue);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void destroy_device(struct zram *zram)
|
||||
static void destroy_devices(unsigned int nr)
|
||||
{
|
||||
struct zram *zram;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
zram = &zram_devices[i];
|
||||
/*
|
||||
* Remove sysfs first, so no one will perform a disksize
|
||||
* store while we destroy the devices
|
||||
*/
|
||||
sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
|
||||
&zram_disk_attr_group);
|
||||
|
||||
zram_reset_device(zram);
|
||||
|
||||
blk_cleanup_queue(zram->disk->queue);
|
||||
del_gendisk(zram->disk);
|
||||
put_disk(zram->disk);
|
||||
}
|
||||
|
||||
blk_cleanup_queue(zram->queue);
|
||||
kfree(zram_devices);
|
||||
unregister_blkdev(zram_major, "zram");
|
||||
pr_info("Destroyed %u device(s)\n", nr);
|
||||
}
|
||||
|
||||
static int __init zram_init(void)
|
||||
@ -1138,64 +1178,39 @@ static int __init zram_init(void)
|
||||
if (num_devices > max_num_devices) {
|
||||
pr_warn("Invalid value for num_devices: %u\n",
|
||||
num_devices);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
zram_major = register_blkdev(0, "zram");
|
||||
if (zram_major <= 0) {
|
||||
pr_warn("Unable to get major number\n");
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Allocate the device array and initialize each one */
|
||||
zram_devices = kzalloc(num_devices * sizeof(struct zram), GFP_KERNEL);
|
||||
if (!zram_devices) {
|
||||
ret = -ENOMEM;
|
||||
goto unregister;
|
||||
unregister_blkdev(zram_major, "zram");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (dev_id = 0; dev_id < num_devices; dev_id++) {
|
||||
ret = create_device(&zram_devices[dev_id], dev_id);
|
||||
if (ret)
|
||||
goto free_devices;
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
pr_info("Created %u device(s) ...\n", num_devices);
|
||||
|
||||
pr_info("Created %u device(s)\n", num_devices);
|
||||
return 0;
|
||||
|
||||
free_devices:
|
||||
while (dev_id)
|
||||
destroy_device(&zram_devices[--dev_id]);
|
||||
kfree(zram_devices);
|
||||
unregister:
|
||||
unregister_blkdev(zram_major, "zram");
|
||||
out:
|
||||
out_error:
|
||||
destroy_devices(dev_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit zram_exit(void)
|
||||
{
|
||||
int i;
|
||||
struct zram *zram;
|
||||
|
||||
for (i = 0; i < num_devices; i++) {
|
||||
zram = &zram_devices[i];
|
||||
|
||||
destroy_device(zram);
|
||||
/*
|
||||
* Shouldn't access zram->disk after destroy_device
|
||||
* because destroy_device already released zram->disk.
|
||||
*/
|
||||
zram_reset_device(zram, false);
|
||||
}
|
||||
|
||||
unregister_blkdev(zram_major, "zram");
|
||||
|
||||
kfree(zram_devices);
|
||||
pr_debug("Cleanup done!\n");
|
||||
destroy_devices(num_devices);
|
||||
}
|
||||
|
||||
module_init(zram_init);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user