Git pull request for linus
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIbBAABAgAGBQJQnM18AAoJENFylnOm3dTbxh8P92lymakR2CUNk7pJINluS9ay fbXHor+2KS31gWD6M1oqtdH9KLsiqDBNraTiyQwhzC5i6XeNnABN3KW6tJmi6ntl p8q3ZjflmoW9tMziulUmFKQ1nuDG8ii4OnGj2CShcAVU7BCRJeqT905epV2jRf6V AL2TpdAkYAWpjYI9JLOWCzu3WWxYvnnaDXDTsbNYMGE77zHSkAP76Or9fKo4jcj4 GORcgPumskB64W1RYqfGkvmhYCI5z0YaIVMTGLunrS+jXIbYsEsSyAP1zUudmkEI Mz/MQ3j8zyAXKGkGj2UW+LBs35T8UJeZVigkrieRS9trzWp9seNqx717CTVd1dro fwAj+pmeEYi1Z2NQ0DASBb/87t5QscWeeZU6k7FHhr1Ro84HJcZ16riknA3Zzd+i 1kWup/TyeApY2uecAYHykK2LaxM4qrn62B9Lg/fl/iU5mrHsrm8hrcSkX7FhmdrR N+/TeCte6RZwZnm4ZmnQPrNctdBYdp1pCmfBZbQcdhsTBDs0+UkQBeANHnxQJxmf +y84SoC4O2V+LC+ee/zHc3DuaOwcTnAlrf7APYUGf8Y9pOGvT5E5LG8otVrzfyeT 40YoN5fhddQfmKZksTvhTnBktg8eMr2MkBvg751qTgvX7zc7YpIvwc9T3k9fLy3M UAXx9XTmKGPLDPN1qvU= =de8m -----END PGP SIGNATURE----- Merge tag 'for-linus' of git://github.com/gxt/linux Pull unicore32 update from Guan Xuetao. * tag 'for-linus' of git://github.com/gxt/linux: arch/unicore32: remove CONFIG_EXPERIMENTAL unicore32: switch to generic sys_execve() unicore32: switch to generic kernel_thread()/kernel_execve() unicore32: Use Kbuild infrastructure for kvm_para.h UAPI: (Scripted) Disintegrate arch/unicore32/include/asm UniCore32-bugfix: Remove definitions in asm/bug.h to solve difference between native and cross compiler UniCore32-bugfix: fix mismatch return value of __xchg_bad_pointer UniCore32 bugfix: add missed CONFIG_ZONE_DMA unicore32/mm/fault.c: Port OOM changes to do_pf
This commit is contained in:
Коммит
c5e35d6c51
|
@ -16,6 +16,8 @@ config UNICORE32
|
|||
select ARCH_WANT_FRAME_POINTERS
|
||||
select GENERIC_IOMAP
|
||||
select MODULES_USE_ELF_REL
|
||||
select GENERIC_KERNEL_THREAD
|
||||
select GENERIC_KERNEL_EXECVE
|
||||
help
|
||||
UniCore-32 is 32-bit Instruction Set Architecture,
|
||||
including a series of low-power-consumption RISC chip
|
||||
|
@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY
|
|||
config ARCH_MAY_HAVE_PC_FDC
|
||||
bool
|
||||
|
||||
config ZONE_DMA
|
||||
def_bool y
|
||||
|
||||
config NEED_DMA_MAP_STATE
|
||||
def_bool y
|
||||
|
||||
|
@ -216,7 +221,7 @@ config PUV3_GPIO
|
|||
bool
|
||||
depends on !ARCH_FPGA
|
||||
select GENERIC_GPIO
|
||||
select GPIO_SYSFS if EXPERIMENTAL
|
||||
select GPIO_SYSFS
|
||||
default y
|
||||
|
||||
if PUV3_NB0916
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
include include/asm-generic/Kbuild.asm
|
||||
|
||||
generic-y += atomic.h
|
||||
generic-y += auxvec.h
|
||||
|
|
|
@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
|
|||
extern void uc32_notify_die(const char *str, struct pt_regs *regs,
|
||||
struct siginfo *info, unsigned long err, unsigned long trap);
|
||||
|
||||
extern asmlinkage void __backtrace(void);
|
||||
extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
|
||||
|
||||
extern void __show_regs(struct pt_regs *);
|
||||
|
||||
#endif /* __UNICORE_BUG_H__ */
|
||||
|
|
|
@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
|
|||
: "memory", "cc");
|
||||
break;
|
||||
default:
|
||||
ret = __xchg_bad_pointer();
|
||||
__xchg_bad_pointer();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include <asm-generic/kvm_para.h>
|
|
@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p);
|
|||
|
||||
#define cpu_relax() barrier()
|
||||
|
||||
/*
|
||||
* Create a new kernel thread
|
||||
*/
|
||||
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
|
||||
|
||||
#define task_pt_regs(p) \
|
||||
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
|
||||
|
||||
|
|
|
@ -12,80 +12,10 @@
|
|||
#ifndef __UNICORE_PTRACE_H__
|
||||
#define __UNICORE_PTRACE_H__
|
||||
|
||||
#define PTRACE_GET_THREAD_AREA 22
|
||||
|
||||
/*
|
||||
* PSR bits
|
||||
*/
|
||||
#define USER_MODE 0x00000010
|
||||
#define REAL_MODE 0x00000011
|
||||
#define INTR_MODE 0x00000012
|
||||
#define PRIV_MODE 0x00000013
|
||||
#define ABRT_MODE 0x00000017
|
||||
#define EXTN_MODE 0x0000001b
|
||||
#define SUSR_MODE 0x0000001f
|
||||
#define MODE_MASK 0x0000001f
|
||||
#define PSR_R_BIT 0x00000040
|
||||
#define PSR_I_BIT 0x00000080
|
||||
#define PSR_V_BIT 0x10000000
|
||||
#define PSR_C_BIT 0x20000000
|
||||
#define PSR_Z_BIT 0x40000000
|
||||
#define PSR_S_BIT 0x80000000
|
||||
|
||||
/*
|
||||
* Groups of PSR bits
|
||||
*/
|
||||
#define PSR_f 0xff000000 /* Flags */
|
||||
#define PSR_c 0x000000ff /* Control */
|
||||
#include <uapi/asm/ptrace.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* This struct defines the way the registers are stored on the
|
||||
* stack during a system call. Note that sizeof(struct pt_regs)
|
||||
* has to be a multiple of 8.
|
||||
*/
|
||||
struct pt_regs {
|
||||
unsigned long uregs[34];
|
||||
};
|
||||
|
||||
#define UCreg_asr uregs[32]
|
||||
#define UCreg_pc uregs[31]
|
||||
#define UCreg_lr uregs[30]
|
||||
#define UCreg_sp uregs[29]
|
||||
#define UCreg_ip uregs[28]
|
||||
#define UCreg_fp uregs[27]
|
||||
#define UCreg_26 uregs[26]
|
||||
#define UCreg_25 uregs[25]
|
||||
#define UCreg_24 uregs[24]
|
||||
#define UCreg_23 uregs[23]
|
||||
#define UCreg_22 uregs[22]
|
||||
#define UCreg_21 uregs[21]
|
||||
#define UCreg_20 uregs[20]
|
||||
#define UCreg_19 uregs[19]
|
||||
#define UCreg_18 uregs[18]
|
||||
#define UCreg_17 uregs[17]
|
||||
#define UCreg_16 uregs[16]
|
||||
#define UCreg_15 uregs[15]
|
||||
#define UCreg_14 uregs[14]
|
||||
#define UCreg_13 uregs[13]
|
||||
#define UCreg_12 uregs[12]
|
||||
#define UCreg_11 uregs[11]
|
||||
#define UCreg_10 uregs[10]
|
||||
#define UCreg_09 uregs[9]
|
||||
#define UCreg_08 uregs[8]
|
||||
#define UCreg_07 uregs[7]
|
||||
#define UCreg_06 uregs[6]
|
||||
#define UCreg_05 uregs[5]
|
||||
#define UCreg_04 uregs[4]
|
||||
#define UCreg_03 uregs[3]
|
||||
#define UCreg_02 uregs[2]
|
||||
#define UCreg_01 uregs[1]
|
||||
#define UCreg_00 uregs[0]
|
||||
#define UCreg_ORIG_00 uregs[33]
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define user_mode(regs) \
|
||||
(processor_mode(regs) == USER_MODE)
|
||||
|
||||
|
@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs)
|
|||
|
||||
#define instruction_pointer(regs) ((regs)->UCreg_pc)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
# UAPI Header export list
|
||||
include include/uapi/asm-generic/Kbuild.asm
|
||||
|
||||
header-y += byteorder.h
|
||||
header-y += kvm_para.h
|
||||
header-y += ptrace.h
|
||||
header-y += sigcontext.h
|
||||
header-y += unistd.h
|
||||
|
||||
generic-y += kvm_para.h
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* linux/arch/unicore32/include/asm/ptrace.h
|
||||
*
|
||||
* Code specific to PKUnity SoC and UniCore ISA
|
||||
*
|
||||
* Copyright (C) 2001-2010 GUAN Xue-tao
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef _UAPI__UNICORE_PTRACE_H__
|
||||
#define _UAPI__UNICORE_PTRACE_H__
|
||||
|
||||
#define PTRACE_GET_THREAD_AREA 22
|
||||
|
||||
/*
|
||||
* PSR bits
|
||||
*/
|
||||
#define USER_MODE 0x00000010
|
||||
#define REAL_MODE 0x00000011
|
||||
#define INTR_MODE 0x00000012
|
||||
#define PRIV_MODE 0x00000013
|
||||
#define ABRT_MODE 0x00000017
|
||||
#define EXTN_MODE 0x0000001b
|
||||
#define SUSR_MODE 0x0000001f
|
||||
#define MODE_MASK 0x0000001f
|
||||
#define PSR_R_BIT 0x00000040
|
||||
#define PSR_I_BIT 0x00000080
|
||||
#define PSR_V_BIT 0x10000000
|
||||
#define PSR_C_BIT 0x20000000
|
||||
#define PSR_Z_BIT 0x40000000
|
||||
#define PSR_S_BIT 0x80000000
|
||||
|
||||
/*
|
||||
* Groups of PSR bits
|
||||
*/
|
||||
#define PSR_f 0xff000000 /* Flags */
|
||||
#define PSR_c 0x000000ff /* Control */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* This struct defines the way the registers are stored on the
|
||||
* stack during a system call. Note that sizeof(struct pt_regs)
|
||||
* has to be a multiple of 8.
|
||||
*/
|
||||
struct pt_regs {
|
||||
unsigned long uregs[34];
|
||||
};
|
||||
|
||||
#define UCreg_asr uregs[32]
|
||||
#define UCreg_pc uregs[31]
|
||||
#define UCreg_lr uregs[30]
|
||||
#define UCreg_sp uregs[29]
|
||||
#define UCreg_ip uregs[28]
|
||||
#define UCreg_fp uregs[27]
|
||||
#define UCreg_26 uregs[26]
|
||||
#define UCreg_25 uregs[25]
|
||||
#define UCreg_24 uregs[24]
|
||||
#define UCreg_23 uregs[23]
|
||||
#define UCreg_22 uregs[22]
|
||||
#define UCreg_21 uregs[21]
|
||||
#define UCreg_20 uregs[20]
|
||||
#define UCreg_19 uregs[19]
|
||||
#define UCreg_18 uregs[18]
|
||||
#define UCreg_17 uregs[17]
|
||||
#define UCreg_16 uregs[16]
|
||||
#define UCreg_15 uregs[15]
|
||||
#define UCreg_14 uregs[14]
|
||||
#define UCreg_13 uregs[13]
|
||||
#define UCreg_12 uregs[12]
|
||||
#define UCreg_11 uregs[11]
|
||||
#define UCreg_10 uregs[10]
|
||||
#define UCreg_09 uregs[9]
|
||||
#define UCreg_08 uregs[8]
|
||||
#define UCreg_07 uregs[7]
|
||||
#define UCreg_06 uregs[6]
|
||||
#define UCreg_05 uregs[5]
|
||||
#define UCreg_04 uregs[4]
|
||||
#define UCreg_03 uregs[3]
|
||||
#define UCreg_02 uregs[2]
|
||||
#define UCreg_01 uregs[1]
|
||||
#define UCreg_00 uregs[0]
|
||||
#define UCreg_ORIG_00 uregs[33]
|
||||
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _UAPI__UNICORE_PTRACE_H__ */
|
|
@ -12,3 +12,4 @@
|
|||
|
||||
/* Use the standard ABI for syscalls. */
|
||||
#include <asm-generic/unistd.h>
|
||||
#define __ARCH_WANT_SYS_EXECVE
|
|
@ -573,17 +573,16 @@ ENDPROC(ret_to_user)
|
|||
*/
|
||||
ENTRY(ret_from_fork)
|
||||
b.l schedule_tail
|
||||
get_thread_info tsk
|
||||
ldw r1, [tsk+], #TI_FLAGS @ check for syscall tracing
|
||||
mov why, #1
|
||||
cand.a r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
|
||||
beq ret_slow_syscall
|
||||
mov r1, sp
|
||||
mov r0, #1 @ trace exit [IP = 1]
|
||||
b.l syscall_trace
|
||||
b ret_slow_syscall
|
||||
ENDPROC(ret_from_fork)
|
||||
|
||||
ENTRY(ret_from_kernel_thread)
|
||||
b.l schedule_tail
|
||||
mov r0, r5
|
||||
adr lr, ret_slow_syscall
|
||||
mov pc, r4
|
||||
ENDPROC(ret_from_kernel_thread)
|
||||
|
||||
/*=============================================================================
|
||||
* SWI handler
|
||||
*-----------------------------------------------------------------------------
|
||||
|
@ -669,11 +668,6 @@ __cr_alignment:
|
|||
#endif
|
||||
.ltorg
|
||||
|
||||
ENTRY(sys_execve)
|
||||
add r3, sp, #S_OFF
|
||||
b __sys_execve
|
||||
ENDPROC(sys_execve)
|
||||
|
||||
ENTRY(sys_clone)
|
||||
add ip, sp, #S_OFF
|
||||
stw ip, [sp+], #4
|
||||
|
|
|
@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task)
|
|||
}
|
||||
|
||||
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
|
||||
asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
|
||||
|
||||
int
|
||||
copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
||||
|
@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
|||
struct thread_info *thread = task_thread_info(p);
|
||||
struct pt_regs *childregs = task_pt_regs(p);
|
||||
|
||||
*childregs = *regs;
|
||||
childregs->UCreg_00 = 0;
|
||||
childregs->UCreg_sp = stack_start;
|
||||
|
||||
memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
|
||||
thread->cpu_context.sp = (unsigned long)childregs;
|
||||
thread->cpu_context.pc = (unsigned long)ret_from_fork;
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childregs->UCreg_16 = regs->UCreg_03;
|
||||
if (unlikely(!regs)) {
|
||||
thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
|
||||
thread->cpu_context.r4 = stack_start;
|
||||
thread->cpu_context.r5 = stk_sz;
|
||||
memset(childregs, 0, sizeof(struct pt_regs));
|
||||
} else {
|
||||
thread->cpu_context.pc = (unsigned long)ret_from_fork;
|
||||
*childregs = *regs;
|
||||
childregs->UCreg_00 = 0;
|
||||
childregs->UCreg_sp = stack_start;
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childregs->UCreg_16 = regs->UCreg_03;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
|
|||
}
|
||||
EXPORT_SYMBOL(dump_fpu);
|
||||
|
||||
/*
|
||||
* Shuffle the argument into the correct register before calling the
|
||||
* thread function. r1 is the thread argument, r2 is the pointer to
|
||||
* the thread function, and r3 points to the exit function.
|
||||
*/
|
||||
asm(".pushsection .text\n"
|
||||
" .align\n"
|
||||
" .type kernel_thread_helper, #function\n"
|
||||
"kernel_thread_helper:\n"
|
||||
" mov.a asr, r7\n"
|
||||
" mov r0, r4\n"
|
||||
" mov lr, r6\n"
|
||||
" mov pc, r5\n"
|
||||
" .size kernel_thread_helper, . - kernel_thread_helper\n"
|
||||
" .popsection");
|
||||
|
||||
/*
|
||||
* Create a kernel thread.
|
||||
*/
|
||||
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
|
||||
{
|
||||
struct pt_regs regs;
|
||||
|
||||
memset(®s, 0, sizeof(regs));
|
||||
|
||||
regs.UCreg_04 = (unsigned long)arg;
|
||||
regs.UCreg_05 = (unsigned long)fn;
|
||||
regs.UCreg_06 = (unsigned long)do_exit;
|
||||
regs.UCreg_07 = PRIV_MODE;
|
||||
regs.UCreg_pc = (unsigned long)kernel_thread_helper;
|
||||
regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
|
||||
|
||||
return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(kernel_thread);
|
||||
|
||||
unsigned long get_wchan(struct task_struct *p)
|
||||
{
|
||||
struct stackframe frame;
|
||||
|
|
|
@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
|
|||
extern void kernel_thread_helper(void);
|
||||
|
||||
extern void __init early_signal_init(void);
|
||||
|
||||
extern asmlinkage void __backtrace(void);
|
||||
extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
|
||||
|
||||
extern void __show_regs(struct pt_regs *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|||
parent_tid, child_tid);
|
||||
}
|
||||
|
||||
/* sys_execve() executes a new program.
|
||||
* This is called indirectly via a small wrapper
|
||||
*/
|
||||
asmlinkage long __sys_execve(const char __user *filename,
|
||||
const char __user *const __user *argv,
|
||||
const char __user *const __user *envp,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int error;
|
||||
struct filename *fn;
|
||||
|
||||
fn = getname(filename);
|
||||
error = PTR_ERR(fn);
|
||||
if (IS_ERR(fn))
|
||||
goto out;
|
||||
error = do_execve(fn->name, argv, envp, regs);
|
||||
putname(fn);
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
int kernel_execve(const char *filename,
|
||||
const char *const argv[],
|
||||
const char *const envp[])
|
||||
{
|
||||
struct pt_regs regs;
|
||||
int ret;
|
||||
|
||||
memset(®s, 0, sizeof(struct pt_regs));
|
||||
ret = do_execve(filename,
|
||||
(const char __user *const __user *)argv,
|
||||
(const char __user *const __user *)envp, ®s);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Save argc to the register structure for userspace.
|
||||
*/
|
||||
regs.UCreg_00 = ret;
|
||||
|
||||
/*
|
||||
* We were successful. We won't be returning to our caller, but
|
||||
* instead to user space by manipulating the kernel stack.
|
||||
*/
|
||||
asm("add r0, %0, %1\n\t"
|
||||
"mov r1, %2\n\t"
|
||||
"mov r2, %3\n\t"
|
||||
"mov r22, #0\n\t" /* not a syscall */
|
||||
"mov r23, %0\n\t" /* thread structure */
|
||||
"b.l memmove\n\t" /* copy regs to top of stack */
|
||||
"mov sp, r0\n\t" /* reposition stack pointer */
|
||||
"b ret_to_user"
|
||||
:
|
||||
: "r" (current_thread_info()),
|
||||
"Ir" (THREAD_START_SP - sizeof(regs)),
|
||||
"r" (®s),
|
||||
"Ir" (sizeof(regs))
|
||||
: "r0", "r1", "r2", "r3", "ip", "lr", "memory");
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note: used by the compat code even in 64-bit Linux. */
|
||||
SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
|
||||
unsigned long, prot, unsigned long, flags,
|
||||
|
|
|
@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
|
|||
}
|
||||
|
||||
static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
|
||||
struct task_struct *tsk)
|
||||
unsigned int flags, struct task_struct *tsk)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
int fault;
|
||||
|
@ -194,14 +194,7 @@ good_area:
|
|||
* If for any reason at all we couldn't handle the fault, make
|
||||
* sure we exit gracefully rather than endlessly redo the fault.
|
||||
*/
|
||||
fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
|
||||
(!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
|
||||
if (unlikely(fault & VM_FAULT_ERROR))
|
||||
return fault;
|
||||
if (fault & VM_FAULT_MAJOR)
|
||||
tsk->maj_flt++;
|
||||
else
|
||||
tsk->min_flt++;
|
||||
fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
|
||||
return fault;
|
||||
|
||||
check_stack:
|
||||
|
@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
int fault, sig, code;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
|
@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
if (!user_mode(regs)
|
||||
&& !search_exception_tables(regs->UCreg_pc))
|
||||
goto no_context;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
} else {
|
||||
/*
|
||||
|
@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
#endif
|
||||
}
|
||||
|
||||
fault = __do_pf(mm, addr, fsr, tsk);
|
||||
fault = __do_pf(mm, addr, fsr, flags, tsk);
|
||||
|
||||
/* If we need to retry but a fatal signal is pending, handle the
|
||||
* signal first. We do not need to release the mmap_sem because
|
||||
* it would already be released in __lock_page_or_retry in
|
||||
* mm/filemap.c. */
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
|
||||
return 0;
|
||||
|
||||
if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
|
||||
if (fault & VM_FAULT_MAJOR)
|
||||
tsk->maj_flt++;
|
||||
else
|
||||
tsk->min_flt++;
|
||||
if (fault & VM_FAULT_RETRY) {
|
||||
/* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
|
||||
* of starvation. */
|
||||
flags &= ~FAULT_FLAG_ALLOW_RETRY;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче