You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
x86: rename the struct pt_regs members for 32/64-bit consistency
We have a lot of code which differs only by the naming of specific members of structures that contain registers. In order to enable additional unifications, this patch drops the e- or r- size prefix from the register names in struct pt_regs, and drops the x- prefixes for segment registers on the 32-bit side. This patch also performs the equivalent renames in some additional places that might be candidates for unification in the future. Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
committed by
Ingo Molnar
parent
53756d3722
commit
65ea5b0349
+15
-15
@@ -53,7 +53,7 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
|
|||||||
/* changed the size calculations - should hopefully work better. lbt */
|
/* changed the size calculations - should hopefully work better. lbt */
|
||||||
dump->magic = CMAGIC;
|
dump->magic = CMAGIC;
|
||||||
dump->start_code = 0;
|
dump->start_code = 0;
|
||||||
dump->start_stack = regs->rsp & ~(PAGE_SIZE - 1);
|
dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
|
||||||
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
|
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
|
||||||
dump->u_dsize = ((unsigned long)
|
dump->u_dsize = ((unsigned long)
|
||||||
(current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
(current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
||||||
@@ -75,22 +75,22 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
|
|||||||
dump->u_ssize = tmp >> PAGE_SHIFT;
|
dump->u_ssize = tmp >> PAGE_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
dump->regs.ebx = regs->rbx;
|
dump->regs.bx = regs->bx;
|
||||||
dump->regs.ecx = regs->rcx;
|
dump->regs.cx = regs->cx;
|
||||||
dump->regs.edx = regs->rdx;
|
dump->regs.dx = regs->dx;
|
||||||
dump->regs.esi = regs->rsi;
|
dump->regs.si = regs->si;
|
||||||
dump->regs.edi = regs->rdi;
|
dump->regs.di = regs->di;
|
||||||
dump->regs.ebp = regs->rbp;
|
dump->regs.bp = regs->bp;
|
||||||
dump->regs.eax = regs->rax;
|
dump->regs.ax = regs->ax;
|
||||||
dump->regs.ds = current->thread.ds;
|
dump->regs.ds = current->thread.ds;
|
||||||
dump->regs.es = current->thread.es;
|
dump->regs.es = current->thread.es;
|
||||||
asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs;
|
asm("movl %%fs,%0" : "=r" (fs)); dump->regs.fs = fs;
|
||||||
asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs;
|
asm("movl %%gs,%0" : "=r" (gs)); dump->regs.gs = gs;
|
||||||
dump->regs.orig_eax = regs->orig_rax;
|
dump->regs.orig_ax = regs->orig_ax;
|
||||||
dump->regs.eip = regs->rip;
|
dump->regs.ip = regs->ip;
|
||||||
dump->regs.cs = regs->cs;
|
dump->regs.cs = regs->cs;
|
||||||
dump->regs.eflags = regs->eflags;
|
dump->regs.flags = regs->flags;
|
||||||
dump->regs.esp = regs->rsp;
|
dump->regs.sp = regs->sp;
|
||||||
dump->regs.ss = regs->ss;
|
dump->regs.ss = regs->ss;
|
||||||
|
|
||||||
#if 1 /* FIXME */
|
#if 1 /* FIXME */
|
||||||
@@ -432,9 +432,9 @@ beyond_if:
|
|||||||
asm volatile("movl %0,%%fs" :: "r" (0)); \
|
asm volatile("movl %0,%%fs" :: "r" (0)); \
|
||||||
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS));
|
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS));
|
||||||
load_gs_index(0);
|
load_gs_index(0);
|
||||||
(regs)->rip = ex.a_entry;
|
(regs)->ip = ex.a_entry;
|
||||||
(regs)->rsp = current->mm->start_stack;
|
(regs)->sp = current->mm->start_stack;
|
||||||
(regs)->eflags = 0x200;
|
(regs)->flags = 0x200;
|
||||||
(regs)->cs = __USER32_CS;
|
(regs)->cs = __USER32_CS;
|
||||||
(regs)->ss = __USER32_DS;
|
(regs)->ss = __USER32_DS;
|
||||||
regs->r8 = regs->r9 = regs->r10 = regs->r11 =
|
regs->r8 = regs->r9 = regs->r10 = regs->r11 =
|
||||||
|
|||||||
+21
-21
@@ -73,22 +73,22 @@ struct file;
|
|||||||
/* Assumes current==process to be dumped */
|
/* Assumes current==process to be dumped */
|
||||||
#undef ELF_CORE_COPY_REGS
|
#undef ELF_CORE_COPY_REGS
|
||||||
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
|
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
|
||||||
pr_reg[0] = regs->rbx; \
|
pr_reg[0] = regs->bx; \
|
||||||
pr_reg[1] = regs->rcx; \
|
pr_reg[1] = regs->cx; \
|
||||||
pr_reg[2] = regs->rdx; \
|
pr_reg[2] = regs->dx; \
|
||||||
pr_reg[3] = regs->rsi; \
|
pr_reg[3] = regs->si; \
|
||||||
pr_reg[4] = regs->rdi; \
|
pr_reg[4] = regs->di; \
|
||||||
pr_reg[5] = regs->rbp; \
|
pr_reg[5] = regs->bp; \
|
||||||
pr_reg[6] = regs->rax; \
|
pr_reg[6] = regs->ax; \
|
||||||
pr_reg[7] = _GET_SEG(ds); \
|
pr_reg[7] = _GET_SEG(ds); \
|
||||||
pr_reg[8] = _GET_SEG(es); \
|
pr_reg[8] = _GET_SEG(es); \
|
||||||
pr_reg[9] = _GET_SEG(fs); \
|
pr_reg[9] = _GET_SEG(fs); \
|
||||||
pr_reg[10] = _GET_SEG(gs); \
|
pr_reg[10] = _GET_SEG(gs); \
|
||||||
pr_reg[11] = regs->orig_rax; \
|
pr_reg[11] = regs->orig_ax; \
|
||||||
pr_reg[12] = regs->rip; \
|
pr_reg[12] = regs->ip; \
|
||||||
pr_reg[13] = regs->cs; \
|
pr_reg[13] = regs->cs; \
|
||||||
pr_reg[14] = regs->eflags; \
|
pr_reg[14] = regs->flags; \
|
||||||
pr_reg[15] = regs->rsp; \
|
pr_reg[15] = regs->sp; \
|
||||||
pr_reg[16] = regs->ss;
|
pr_reg[16] = regs->ss;
|
||||||
|
|
||||||
|
|
||||||
@@ -205,9 +205,9 @@ do { \
|
|||||||
asm volatile("movl %0,%%fs" :: "r" (0)); \
|
asm volatile("movl %0,%%fs" :: "r" (0)); \
|
||||||
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); \
|
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); \
|
||||||
load_gs_index(0); \
|
load_gs_index(0); \
|
||||||
(regs)->rip = (new_rip); \
|
(regs)->ip = (new_rip); \
|
||||||
(regs)->rsp = (new_rsp); \
|
(regs)->sp = (new_rsp); \
|
||||||
(regs)->eflags = 0x200; \
|
(regs)->flags = X86_EFLAGS_IF; \
|
||||||
(regs)->cs = __USER32_CS; \
|
(regs)->cs = __USER32_CS; \
|
||||||
(regs)->ss = __USER32_DS; \
|
(regs)->ss = __USER32_DS; \
|
||||||
set_fs(USER_DS); \
|
set_fs(USER_DS); \
|
||||||
@@ -233,13 +233,13 @@ extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
|
|||||||
static void elf32_init(struct pt_regs *regs)
|
static void elf32_init(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct task_struct *me = current;
|
struct task_struct *me = current;
|
||||||
regs->rdi = 0;
|
regs->di = 0;
|
||||||
regs->rsi = 0;
|
regs->si = 0;
|
||||||
regs->rdx = 0;
|
regs->dx = 0;
|
||||||
regs->rcx = 0;
|
regs->cx = 0;
|
||||||
regs->rax = 0;
|
regs->ax = 0;
|
||||||
regs->rbx = 0;
|
regs->bx = 0;
|
||||||
regs->rbp = 0;
|
regs->bp = 0;
|
||||||
regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
|
regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
|
||||||
regs->r13 = regs->r14 = regs->r15 = 0;
|
regs->r13 = regs->r14 = regs->r15 = 0;
|
||||||
me->thread.fs = 0;
|
me->thread.fs = 0;
|
||||||
|
|||||||
+50
-50
@@ -154,7 +154,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
|
|||||||
}
|
}
|
||||||
seg = get_fs();
|
seg = get_fs();
|
||||||
set_fs(KERNEL_DS);
|
set_fs(KERNEL_DS);
|
||||||
ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp);
|
ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
|
||||||
set_fs(seg);
|
set_fs(seg);
|
||||||
if (ret >= 0 && uoss_ptr) {
|
if (ret >= 0 && uoss_ptr) {
|
||||||
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
|
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
|
||||||
@@ -195,7 +195,7 @@ struct rt_sigframe
|
|||||||
#define COPY(x) { \
|
#define COPY(x) { \
|
||||||
unsigned int reg; \
|
unsigned int reg; \
|
||||||
err |= __get_user(reg, &sc->e ##x); \
|
err |= __get_user(reg, &sc->e ##x); \
|
||||||
regs->r ## x = reg; \
|
regs->x = reg; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RELOAD_SEG(seg,mask) \
|
#define RELOAD_SEG(seg,mask) \
|
||||||
@@ -220,7 +220,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
|
|||||||
#if DEBUG_SIG
|
#if DEBUG_SIG
|
||||||
printk(KERN_DEBUG "SIG restore_sigcontext: "
|
printk(KERN_DEBUG "SIG restore_sigcontext: "
|
||||||
"sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
|
"sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
|
||||||
sc, sc->err, sc->eip, sc->cs, sc->eflags);
|
sc, sc->err, sc->ip, sc->cs, sc->flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -249,9 +249,9 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
|
|||||||
regs->ss |= 3;
|
regs->ss |= 3;
|
||||||
|
|
||||||
err |= __get_user(tmpflags, &sc->eflags);
|
err |= __get_user(tmpflags, &sc->eflags);
|
||||||
regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
|
regs->flags = (regs->flags & ~0x40DD5) | (tmpflags & 0x40DD5);
|
||||||
/* disable syscall checks */
|
/* disable syscall checks */
|
||||||
regs->orig_rax = -1;
|
regs->orig_ax = -1;
|
||||||
|
|
||||||
err |= __get_user(tmp, &sc->fpstate);
|
err |= __get_user(tmp, &sc->fpstate);
|
||||||
buf = compat_ptr(tmp);
|
buf = compat_ptr(tmp);
|
||||||
@@ -279,9 +279,9 @@ badframe:
|
|||||||
|
|
||||||
asmlinkage long sys32_sigreturn(struct pt_regs *regs)
|
asmlinkage long sys32_sigreturn(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8);
|
struct sigframe __user *frame = (struct sigframe __user *)(regs->sp-8);
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
unsigned int eax;
|
unsigned int ax;
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@@ -298,9 +298,9 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
|
|||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
if (ia32_restore_sigcontext(regs, &frame->sc, &eax))
|
if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
return eax;
|
return ax;
|
||||||
|
|
||||||
badframe:
|
badframe:
|
||||||
signal_fault(regs, frame, "32bit sigreturn");
|
signal_fault(regs, frame, "32bit sigreturn");
|
||||||
@@ -311,10 +311,10 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
struct rt_sigframe __user *frame;
|
struct rt_sigframe __user *frame;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
unsigned int eax;
|
unsigned int ax;
|
||||||
struct pt_regs tregs;
|
struct pt_regs tregs;
|
||||||
|
|
||||||
frame = (struct rt_sigframe __user *)(regs->rsp - 4);
|
frame = (struct rt_sigframe __user *)(regs->sp - 4);
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@@ -327,14 +327,14 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
|
|||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax))
|
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
tregs = *regs;
|
tregs = *regs;
|
||||||
if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
|
if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
return eax;
|
return ax;
|
||||||
|
|
||||||
badframe:
|
badframe:
|
||||||
signal_fault(regs, frame, "32bit rt sigreturn");
|
signal_fault(regs, frame, "32bit rt sigreturn");
|
||||||
@@ -361,21 +361,21 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
|
|||||||
__asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
|
__asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
|
||||||
err |= __put_user(tmp, (unsigned int __user *)&sc->es);
|
err |= __put_user(tmp, (unsigned int __user *)&sc->es);
|
||||||
|
|
||||||
err |= __put_user((u32)regs->rdi, &sc->edi);
|
err |= __put_user((u32)regs->di, &sc->edi);
|
||||||
err |= __put_user((u32)regs->rsi, &sc->esi);
|
err |= __put_user((u32)regs->si, &sc->esi);
|
||||||
err |= __put_user((u32)regs->rbp, &sc->ebp);
|
err |= __put_user((u32)regs->bp, &sc->ebp);
|
||||||
err |= __put_user((u32)regs->rsp, &sc->esp);
|
err |= __put_user((u32)regs->sp, &sc->esp);
|
||||||
err |= __put_user((u32)regs->rbx, &sc->ebx);
|
err |= __put_user((u32)regs->bx, &sc->ebx);
|
||||||
err |= __put_user((u32)regs->rdx, &sc->edx);
|
err |= __put_user((u32)regs->dx, &sc->edx);
|
||||||
err |= __put_user((u32)regs->rcx, &sc->ecx);
|
err |= __put_user((u32)regs->cx, &sc->ecx);
|
||||||
err |= __put_user((u32)regs->rax, &sc->eax);
|
err |= __put_user((u32)regs->ax, &sc->eax);
|
||||||
err |= __put_user((u32)regs->cs, &sc->cs);
|
err |= __put_user((u32)regs->cs, &sc->cs);
|
||||||
err |= __put_user((u32)regs->ss, &sc->ss);
|
err |= __put_user((u32)regs->ss, &sc->ss);
|
||||||
err |= __put_user(current->thread.trap_no, &sc->trapno);
|
err |= __put_user(current->thread.trap_no, &sc->trapno);
|
||||||
err |= __put_user(current->thread.error_code, &sc->err);
|
err |= __put_user(current->thread.error_code, &sc->err);
|
||||||
err |= __put_user((u32)regs->rip, &sc->eip);
|
err |= __put_user((u32)regs->ip, &sc->eip);
|
||||||
err |= __put_user((u32)regs->eflags, &sc->eflags);
|
err |= __put_user((u32)regs->flags, &sc->eflags);
|
||||||
err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
|
err |= __put_user((u32)regs->sp, &sc->esp_at_signal);
|
||||||
|
|
||||||
tmp = save_i387_ia32(current, fpstate, regs, 0);
|
tmp = save_i387_ia32(current, fpstate, regs, 0);
|
||||||
if (tmp < 0)
|
if (tmp < 0)
|
||||||
@@ -400,28 +400,28 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
|
|||||||
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||||
size_t frame_size)
|
size_t frame_size)
|
||||||
{
|
{
|
||||||
unsigned long rsp;
|
unsigned long sp;
|
||||||
|
|
||||||
/* Default to using normal stack */
|
/* Default to using normal stack */
|
||||||
rsp = regs->rsp;
|
sp = regs->sp;
|
||||||
|
|
||||||
/* This is the X/Open sanctioned signal stack switching. */
|
/* This is the X/Open sanctioned signal stack switching. */
|
||||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||||
if (sas_ss_flags(rsp) == 0)
|
if (sas_ss_flags(sp) == 0)
|
||||||
rsp = current->sas_ss_sp + current->sas_ss_size;
|
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the legacy signal stack switching. */
|
/* This is the legacy signal stack switching. */
|
||||||
else if ((regs->ss & 0xffff) != __USER_DS &&
|
else if ((regs->ss & 0xffff) != __USER_DS &&
|
||||||
!(ka->sa.sa_flags & SA_RESTORER) &&
|
!(ka->sa.sa_flags & SA_RESTORER) &&
|
||||||
ka->sa.sa_restorer)
|
ka->sa.sa_restorer)
|
||||||
rsp = (unsigned long) ka->sa.sa_restorer;
|
sp = (unsigned long) ka->sa.sa_restorer;
|
||||||
|
|
||||||
rsp -= frame_size;
|
sp -= frame_size;
|
||||||
/* Align the stack pointer according to the i386 ABI,
|
/* Align the stack pointer according to the i386 ABI,
|
||||||
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
|
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
|
||||||
rsp = ((rsp + 4) & -16ul) - 4;
|
sp = ((sp + 4) & -16ul) - 4;
|
||||||
return (void __user *) rsp;
|
return (void __user *) sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
||||||
@@ -486,13 +486,13 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
|||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/* Set up registers for signal handler */
|
/* Set up registers for signal handler */
|
||||||
regs->rsp = (unsigned long) frame;
|
regs->sp = (unsigned long) frame;
|
||||||
regs->rip = (unsigned long) ka->sa.sa_handler;
|
regs->ip = (unsigned long) ka->sa.sa_handler;
|
||||||
|
|
||||||
/* Make -mregparm=3 work */
|
/* Make -mregparm=3 work */
|
||||||
regs->rax = sig;
|
regs->ax = sig;
|
||||||
regs->rdx = 0;
|
regs->dx = 0;
|
||||||
regs->rcx = 0;
|
regs->cx = 0;
|
||||||
|
|
||||||
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
|
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
|
||||||
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
|
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
|
||||||
@@ -501,13 +501,13 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
|
|||||||
regs->ss = __USER32_DS;
|
regs->ss = __USER32_DS;
|
||||||
|
|
||||||
set_fs(USER_DS);
|
set_fs(USER_DS);
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
if (test_thread_flag(TIF_SINGLESTEP))
|
if (test_thread_flag(TIF_SINGLESTEP))
|
||||||
ptrace_notify(SIGTRAP);
|
ptrace_notify(SIGTRAP);
|
||||||
|
|
||||||
#if DEBUG_SIG
|
#if DEBUG_SIG
|
||||||
printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
|
printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
|
||||||
current->comm, current->pid, frame, regs->rip, frame->pretcode);
|
current->comm, current->pid, frame, regs->ip, frame->pretcode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -556,7 +556,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
err |= __put_user(0, &frame->uc.uc_flags);
|
err |= __put_user(0, &frame->uc.uc_flags);
|
||||||
err |= __put_user(0, &frame->uc.uc_link);
|
err |= __put_user(0, &frame->uc.uc_link);
|
||||||
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
|
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
|
||||||
err |= __put_user(sas_ss_flags(regs->rsp),
|
err |= __put_user(sas_ss_flags(regs->sp),
|
||||||
&frame->uc.uc_stack.ss_flags);
|
&frame->uc.uc_stack.ss_flags);
|
||||||
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
|
||||||
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
|
err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
|
||||||
@@ -581,18 +581,18 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
/* Set up registers for signal handler */
|
/* Set up registers for signal handler */
|
||||||
regs->rsp = (unsigned long) frame;
|
regs->sp = (unsigned long) frame;
|
||||||
regs->rip = (unsigned long) ka->sa.sa_handler;
|
regs->ip = (unsigned long) ka->sa.sa_handler;
|
||||||
|
|
||||||
/* Make -mregparm=3 work */
|
/* Make -mregparm=3 work */
|
||||||
regs->rax = sig;
|
regs->ax = sig;
|
||||||
regs->rdx = (unsigned long) &frame->info;
|
regs->dx = (unsigned long) &frame->info;
|
||||||
regs->rcx = (unsigned long) &frame->uc;
|
regs->cx = (unsigned long) &frame->uc;
|
||||||
|
|
||||||
/* Make -mregparm=3 work */
|
/* Make -mregparm=3 work */
|
||||||
regs->rax = sig;
|
regs->ax = sig;
|
||||||
regs->rdx = (unsigned long) &frame->info;
|
regs->dx = (unsigned long) &frame->info;
|
||||||
regs->rcx = (unsigned long) &frame->uc;
|
regs->cx = (unsigned long) &frame->uc;
|
||||||
|
|
||||||
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
|
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
|
||||||
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
|
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
|
||||||
@@ -601,13 +601,13 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
regs->ss = __USER32_DS;
|
regs->ss = __USER32_DS;
|
||||||
|
|
||||||
set_fs(USER_DS);
|
set_fs(USER_DS);
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
if (test_thread_flag(TIF_SINGLESTEP))
|
if (test_thread_flag(TIF_SINGLESTEP))
|
||||||
ptrace_notify(SIGTRAP);
|
ptrace_notify(SIGTRAP);
|
||||||
|
|
||||||
#if DEBUG_SIG
|
#if DEBUG_SIG
|
||||||
printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
|
printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
|
||||||
current->comm, current->pid, frame, regs->rip, frame->pretcode);
|
current->comm, current->pid, frame, regs->ip, frame->pretcode);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+22
-22
@@ -73,19 +73,19 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
|
|||||||
stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff;
|
stack[offsetof(struct pt_regs, cs)/8] = val & 0xffff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
R32(ebx, rbx);
|
R32(ebx, bx);
|
||||||
R32(ecx, rcx);
|
R32(ecx, cx);
|
||||||
R32(edx, rdx);
|
R32(edx, dx);
|
||||||
R32(edi, rdi);
|
R32(edi, di);
|
||||||
R32(esi, rsi);
|
R32(esi, si);
|
||||||
R32(ebp, rbp);
|
R32(ebp, bp);
|
||||||
R32(eax, rax);
|
R32(eax, ax);
|
||||||
R32(orig_eax, orig_rax);
|
R32(orig_eax, orig_ax);
|
||||||
R32(eip, rip);
|
R32(eip, ip);
|
||||||
R32(esp, rsp);
|
R32(esp, sp);
|
||||||
|
|
||||||
case offsetof(struct user32, regs.eflags): {
|
case offsetof(struct user32, regs.eflags): {
|
||||||
__u64 *flags = &stack[offsetof(struct pt_regs, eflags)/8];
|
__u64 *flags = &stack[offsetof(struct pt_regs, flags)/8];
|
||||||
|
|
||||||
val &= FLAG_MASK;
|
val &= FLAG_MASK;
|
||||||
/*
|
/*
|
||||||
@@ -145,22 +145,22 @@ static int getreg32(struct task_struct *child, unsigned regno, u32 *val)
|
|||||||
|
|
||||||
R32(cs, cs);
|
R32(cs, cs);
|
||||||
R32(ss, ss);
|
R32(ss, ss);
|
||||||
R32(ebx, rbx);
|
R32(ebx, bx);
|
||||||
R32(ecx, rcx);
|
R32(ecx, cx);
|
||||||
R32(edx, rdx);
|
R32(edx, dx);
|
||||||
R32(edi, rdi);
|
R32(edi, di);
|
||||||
R32(esi, rsi);
|
R32(esi, si);
|
||||||
R32(ebp, rbp);
|
R32(ebp, bp);
|
||||||
R32(eax, rax);
|
R32(eax, ax);
|
||||||
R32(orig_eax, orig_rax);
|
R32(orig_eax, orig_ax);
|
||||||
R32(eip, rip);
|
R32(eip, ip);
|
||||||
R32(esp, rsp);
|
R32(esp, sp);
|
||||||
|
|
||||||
case offsetof(struct user32, regs.eflags):
|
case offsetof(struct user32, regs.eflags):
|
||||||
/*
|
/*
|
||||||
* If the debugger set TF, hide it from the readout.
|
* If the debugger set TF, hide it from the readout.
|
||||||
*/
|
*/
|
||||||
*val = stack[offsetof(struct pt_regs, eflags)/8];
|
*val = stack[offsetof(struct pt_regs, flags)/8];
|
||||||
if (test_tsk_thread_flag(child, TIF_FORCED_TF))
|
if (test_tsk_thread_flag(child, TIF_FORCED_TF))
|
||||||
*val &= ~X86_EFLAGS_TF;
|
*val &= ~X86_EFLAGS_TF;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -816,11 +816,11 @@ asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv,
|
|||||||
asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
|
asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
void __user *parent_tid = (void __user *)regs->rdx;
|
void __user *parent_tid = (void __user *)regs->dx;
|
||||||
void __user *child_tid = (void __user *)regs->rdi;
|
void __user *child_tid = (void __user *)regs->di;
|
||||||
|
|
||||||
if (!newsp)
|
if (!newsp)
|
||||||
newsp = regs->rsp;
|
newsp = regs->sp;
|
||||||
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
|
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -344,13 +344,13 @@ do_suspend_lowlevel:
|
|||||||
call save_processor_state
|
call save_processor_state
|
||||||
|
|
||||||
movq $saved_context, %rax
|
movq $saved_context, %rax
|
||||||
movq %rsp, pt_regs_rsp(%rax)
|
movq %rsp, pt_regs_sp(%rax)
|
||||||
movq %rbp, pt_regs_rbp(%rax)
|
movq %rbp, pt_regs_bp(%rax)
|
||||||
movq %rsi, pt_regs_rsi(%rax)
|
movq %rsi, pt_regs_si(%rax)
|
||||||
movq %rdi, pt_regs_rdi(%rax)
|
movq %rdi, pt_regs_di(%rax)
|
||||||
movq %rbx, pt_regs_rbx(%rax)
|
movq %rbx, pt_regs_bx(%rax)
|
||||||
movq %rcx, pt_regs_rcx(%rax)
|
movq %rcx, pt_regs_cx(%rax)
|
||||||
movq %rdx, pt_regs_rdx(%rax)
|
movq %rdx, pt_regs_dx(%rax)
|
||||||
movq %r8, pt_regs_r8(%rax)
|
movq %r8, pt_regs_r8(%rax)
|
||||||
movq %r9, pt_regs_r9(%rax)
|
movq %r9, pt_regs_r9(%rax)
|
||||||
movq %r10, pt_regs_r10(%rax)
|
movq %r10, pt_regs_r10(%rax)
|
||||||
@@ -360,7 +360,7 @@ do_suspend_lowlevel:
|
|||||||
movq %r14, pt_regs_r14(%rax)
|
movq %r14, pt_regs_r14(%rax)
|
||||||
movq %r15, pt_regs_r15(%rax)
|
movq %r15, pt_regs_r15(%rax)
|
||||||
pushfq
|
pushfq
|
||||||
popq pt_regs_eflags(%rax)
|
popq pt_regs_flags(%rax)
|
||||||
|
|
||||||
movq $.L97, saved_rip(%rip)
|
movq $.L97, saved_rip(%rip)
|
||||||
|
|
||||||
@@ -391,15 +391,15 @@ do_suspend_lowlevel:
|
|||||||
movq %rbx, %cr2
|
movq %rbx, %cr2
|
||||||
movq saved_context_cr0(%rax), %rbx
|
movq saved_context_cr0(%rax), %rbx
|
||||||
movq %rbx, %cr0
|
movq %rbx, %cr0
|
||||||
pushq pt_regs_eflags(%rax)
|
pushq pt_regs_flags(%rax)
|
||||||
popfq
|
popfq
|
||||||
movq pt_regs_rsp(%rax), %rsp
|
movq pt_regs_sp(%rax), %rsp
|
||||||
movq pt_regs_rbp(%rax), %rbp
|
movq pt_regs_bp(%rax), %rbp
|
||||||
movq pt_regs_rsi(%rax), %rsi
|
movq pt_regs_si(%rax), %rsi
|
||||||
movq pt_regs_rdi(%rax), %rdi
|
movq pt_regs_di(%rax), %rdi
|
||||||
movq pt_regs_rbx(%rax), %rbx
|
movq pt_regs_bx(%rax), %rbx
|
||||||
movq pt_regs_rcx(%rax), %rcx
|
movq pt_regs_cx(%rax), %rcx
|
||||||
movq pt_regs_rdx(%rax), %rdx
|
movq pt_regs_dx(%rax), %rdx
|
||||||
movq pt_regs_r8(%rax), %r8
|
movq pt_regs_r8(%rax), %r8
|
||||||
movq pt_regs_r9(%rax), %r9
|
movq pt_regs_r9(%rax), %r9
|
||||||
movq pt_regs_r10(%rax), %r10
|
movq pt_regs_r10(%rax), %r10
|
||||||
|
|||||||
@@ -75,22 +75,22 @@ void foo(void)
|
|||||||
OFFSET(GDS_pad, Xgt_desc_struct, pad);
|
OFFSET(GDS_pad, Xgt_desc_struct, pad);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
||||||
OFFSET(PT_EBX, pt_regs, ebx);
|
OFFSET(PT_EBX, pt_regs, bx);
|
||||||
OFFSET(PT_ECX, pt_regs, ecx);
|
OFFSET(PT_ECX, pt_regs, cx);
|
||||||
OFFSET(PT_EDX, pt_regs, edx);
|
OFFSET(PT_EDX, pt_regs, dx);
|
||||||
OFFSET(PT_ESI, pt_regs, esi);
|
OFFSET(PT_ESI, pt_regs, si);
|
||||||
OFFSET(PT_EDI, pt_regs, edi);
|
OFFSET(PT_EDI, pt_regs, di);
|
||||||
OFFSET(PT_EBP, pt_regs, ebp);
|
OFFSET(PT_EBP, pt_regs, bp);
|
||||||
OFFSET(PT_EAX, pt_regs, eax);
|
OFFSET(PT_EAX, pt_regs, ax);
|
||||||
OFFSET(PT_DS, pt_regs, xds);
|
OFFSET(PT_DS, pt_regs, ds);
|
||||||
OFFSET(PT_ES, pt_regs, xes);
|
OFFSET(PT_ES, pt_regs, es);
|
||||||
OFFSET(PT_FS, pt_regs, xfs);
|
OFFSET(PT_FS, pt_regs, fs);
|
||||||
OFFSET(PT_ORIG_EAX, pt_regs, orig_eax);
|
OFFSET(PT_ORIG_EAX, pt_regs, orig_ax);
|
||||||
OFFSET(PT_EIP, pt_regs, eip);
|
OFFSET(PT_EIP, pt_regs, ip);
|
||||||
OFFSET(PT_CS, pt_regs, xcs);
|
OFFSET(PT_CS, pt_regs, cs);
|
||||||
OFFSET(PT_EFLAGS, pt_regs, eflags);
|
OFFSET(PT_EFLAGS, pt_regs, flags);
|
||||||
OFFSET(PT_OLDESP, pt_regs, esp);
|
OFFSET(PT_OLDESP, pt_regs, sp);
|
||||||
OFFSET(PT_OLDSS, pt_regs, xss);
|
OFFSET(PT_OLDSS, pt_regs, ss);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
||||||
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
|
OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
|
||||||
|
|||||||
@@ -83,14 +83,14 @@ int main(void)
|
|||||||
DEFINE(pbe_next, offsetof(struct pbe, next));
|
DEFINE(pbe_next, offsetof(struct pbe, next));
|
||||||
BLANK();
|
BLANK();
|
||||||
#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
|
#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
|
||||||
ENTRY(rbx);
|
ENTRY(bx);
|
||||||
ENTRY(rbx);
|
ENTRY(bx);
|
||||||
ENTRY(rcx);
|
ENTRY(cx);
|
||||||
ENTRY(rdx);
|
ENTRY(dx);
|
||||||
ENTRY(rsp);
|
ENTRY(sp);
|
||||||
ENTRY(rbp);
|
ENTRY(bp);
|
||||||
ENTRY(rsi);
|
ENTRY(si);
|
||||||
ENTRY(rdi);
|
ENTRY(di);
|
||||||
ENTRY(r8);
|
ENTRY(r8);
|
||||||
ENTRY(r9);
|
ENTRY(r9);
|
||||||
ENTRY(r10);
|
ENTRY(r10);
|
||||||
@@ -99,7 +99,7 @@ int main(void)
|
|||||||
ENTRY(r13);
|
ENTRY(r13);
|
||||||
ENTRY(r14);
|
ENTRY(r14);
|
||||||
ENTRY(r15);
|
ENTRY(r15);
|
||||||
ENTRY(eflags);
|
ENTRY(flags);
|
||||||
BLANK();
|
BLANK();
|
||||||
#undef ENTRY
|
#undef ENTRY
|
||||||
#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
|
#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
|
||||||
|
|||||||
@@ -634,7 +634,7 @@ void __init early_cpu_init(void)
|
|||||||
struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
|
struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
memset(regs, 0, sizeof(struct pt_regs));
|
memset(regs, 0, sizeof(struct pt_regs));
|
||||||
regs->xfs = __KERNEL_PERCPU;
|
regs->fs = __KERNEL_PERCPU;
|
||||||
return regs;
|
return regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,12 +110,12 @@ static void print_mce(struct mce *m)
|
|||||||
KERN_EMERG
|
KERN_EMERG
|
||||||
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
|
"CPU %d: Machine Check Exception: %16Lx Bank %d: %016Lx\n",
|
||||||
m->cpu, m->mcgstatus, m->bank, m->status);
|
m->cpu, m->mcgstatus, m->bank, m->status);
|
||||||
if (m->rip) {
|
if (m->ip) {
|
||||||
printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
|
printk(KERN_EMERG "RIP%s %02x:<%016Lx> ",
|
||||||
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
|
!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
|
||||||
m->cs, m->rip);
|
m->cs, m->ip);
|
||||||
if (m->cs == __KERNEL_CS)
|
if (m->cs == __KERNEL_CS)
|
||||||
print_symbol("{%s}", m->rip);
|
print_symbol("{%s}", m->ip);
|
||||||
printk("\n");
|
printk("\n");
|
||||||
}
|
}
|
||||||
printk(KERN_EMERG "TSC %Lx ", m->tsc);
|
printk(KERN_EMERG "TSC %Lx ", m->tsc);
|
||||||
@@ -156,16 +156,16 @@ static int mce_available(struct cpuinfo_x86 *c)
|
|||||||
static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
|
static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
if (regs && (m->mcgstatus & MCG_STATUS_RIPV)) {
|
if (regs && (m->mcgstatus & MCG_STATUS_RIPV)) {
|
||||||
m->rip = regs->rip;
|
m->ip = regs->ip;
|
||||||
m->cs = regs->cs;
|
m->cs = regs->cs;
|
||||||
} else {
|
} else {
|
||||||
m->rip = 0;
|
m->ip = 0;
|
||||||
m->cs = 0;
|
m->cs = 0;
|
||||||
}
|
}
|
||||||
if (rip_msr) {
|
if (rip_msr) {
|
||||||
/* Assume the RIP in the MSR is exact. Is this true? */
|
/* Assume the RIP in the MSR is exact. Is this true? */
|
||||||
m->mcgstatus |= MCG_STATUS_EIPV;
|
m->mcgstatus |= MCG_STATUS_EIPV;
|
||||||
rdmsrl(rip_msr, m->rip);
|
rdmsrl(rip_msr, m->ip);
|
||||||
m->cs = 0;
|
m->cs = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,7 +288,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
|
|||||||
* instruction which caused the MCE.
|
* instruction which caused the MCE.
|
||||||
*/
|
*/
|
||||||
if (m.mcgstatus & MCG_STATUS_EIPV)
|
if (m.mcgstatus & MCG_STATUS_EIPV)
|
||||||
user_space = panicm.rip && (panicm.cs & 3);
|
user_space = panicm.ip && (panicm.cs & 3);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we know that the error was in user space, send a
|
* If we know that the error was in user space, send a
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id)
|
|||||||
outb(0,0xF0);
|
outb(0,0xF0);
|
||||||
if (ignore_fpu_irq || !boot_cpu_data.hard_math)
|
if (ignore_fpu_irq || !boot_cpu_data.hard_math)
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
math_error((void __user *)get_irq_regs()->eip);
|
math_error((void __user *)get_irq_regs()->ip);
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1412,7 +1412,7 @@ static void irq_complete_move(unsigned int irq)
|
|||||||
if (likely(!cfg->move_in_progress))
|
if (likely(!cfg->move_in_progress))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vector = ~get_irq_regs()->orig_rax;
|
vector = ~get_irq_regs()->orig_ax;
|
||||||
me = smp_processor_id();
|
me = smp_processor_id();
|
||||||
if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
|
if ((vector == cfg->vector) && cpu_isset(me, cfg->domain)) {
|
||||||
cpumask_t cleanup_mask;
|
cpumask_t cleanup_mask;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||||||
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
|
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
|
||||||
* you'd need 8kB of bitmaps/process, which is a bit excessive.
|
* you'd need 8kB of bitmaps/process, which is a bit excessive.
|
||||||
*
|
*
|
||||||
* Here we just change the eflags value on the stack: we allow
|
* Here we just change the flags value on the stack: we allow
|
||||||
* only the super-user to do it. This depends on the stack-layout
|
* only the super-user to do it. This depends on the stack-layout
|
||||||
* on system-call entry - see also fork() and the signal handling
|
* on system-call entry - see also fork() and the signal handling
|
||||||
* code.
|
* code.
|
||||||
@@ -109,8 +109,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||||||
asmlinkage long sys_iopl(unsigned long regsp)
|
asmlinkage long sys_iopl(unsigned long regsp)
|
||||||
{
|
{
|
||||||
volatile struct pt_regs *regs = (struct pt_regs *)®sp;
|
volatile struct pt_regs *regs = (struct pt_regs *)®sp;
|
||||||
unsigned int level = regs->ebx;
|
unsigned int level = regs->bx;
|
||||||
unsigned int old = (regs->eflags >> 12) & 3;
|
unsigned int old = (regs->flags >> 12) & 3;
|
||||||
struct thread_struct *t = ¤t->thread;
|
struct thread_struct *t = ¤t->thread;
|
||||||
|
|
||||||
if (level > 3)
|
if (level > 3)
|
||||||
@@ -122,7 +122,7 @@ asmlinkage long sys_iopl(unsigned long regsp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
t->iopl = level << 12;
|
t->iopl = level << 12;
|
||||||
regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
|
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | t->iopl;
|
||||||
set_iopl_mask(t->iopl);
|
set_iopl_mask(t->iopl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||||||
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
|
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
|
||||||
* you'd need 8kB of bitmaps/process, which is a bit excessive.
|
* you'd need 8kB of bitmaps/process, which is a bit excessive.
|
||||||
*
|
*
|
||||||
* Here we just change the eflags value on the stack: we allow
|
* Here we just change the flags value on the stack: we allow
|
||||||
* only the super-user to do it. This depends on the stack-layout
|
* only the super-user to do it. This depends on the stack-layout
|
||||||
* on system-call entry - see also fork() and the signal handling
|
* on system-call entry - see also fork() and the signal handling
|
||||||
* code.
|
* code.
|
||||||
@@ -103,7 +103,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||||||
|
|
||||||
asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
|
asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned int old = (regs->eflags >> 12) & 3;
|
unsigned int old = (regs->flags >> 12) & 3;
|
||||||
|
|
||||||
if (level > 3)
|
if (level > 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -112,6 +112,6 @@ asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs)
|
|||||||
if (!capable(CAP_SYS_RAWIO))
|
if (!capable(CAP_SYS_RAWIO))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
regs->eflags = (regs->eflags &~ X86_EFLAGS_IOPL) | (level << 12);
|
regs->flags = (regs->flags &~ X86_EFLAGS_IOPL) | (level << 12);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -70,7 +70,7 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
struct pt_regs *old_regs;
|
struct pt_regs *old_regs;
|
||||||
/* high bit used in ret_from_ code */
|
/* high bit used in ret_from_ code */
|
||||||
int irq = ~regs->orig_eax;
|
int irq = ~regs->orig_ax;
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
struct irq_desc *desc = irq_desc + irq;
|
||||||
#ifdef CONFIG_4KSTACKS
|
#ifdef CONFIG_4KSTACKS
|
||||||
union irq_ctx *curctx, *irqctx;
|
union irq_ctx *curctx, *irqctx;
|
||||||
@@ -88,13 +88,13 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||||
/* Debugging check for stack overflow: is there less than 1KB free? */
|
/* Debugging check for stack overflow: is there less than 1KB free? */
|
||||||
{
|
{
|
||||||
long esp;
|
long sp;
|
||||||
|
|
||||||
__asm__ __volatile__("andl %%esp,%0" :
|
__asm__ __volatile__("andl %%esp,%0" :
|
||||||
"=r" (esp) : "0" (THREAD_SIZE - 1));
|
"=r" (sp) : "0" (THREAD_SIZE - 1));
|
||||||
if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
|
if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
|
||||||
printk("do_IRQ: stack overflow: %ld\n",
|
printk("do_IRQ: stack overflow: %ld\n",
|
||||||
esp - sizeof(struct thread_info));
|
sp - sizeof(struct thread_info));
|
||||||
dump_stack();
|
dump_stack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
* current stack (which is the irq stack already after all)
|
* current stack (which is the irq stack already after all)
|
||||||
*/
|
*/
|
||||||
if (curctx != irqctx) {
|
if (curctx != irqctx) {
|
||||||
int arg1, arg2, ebx;
|
int arg1, arg2, bx;
|
||||||
|
|
||||||
/* build the stack frame on the IRQ stack */
|
/* build the stack frame on the IRQ stack */
|
||||||
isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
|
isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
|
||||||
@@ -128,10 +128,10 @@ fastcall unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
|
(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
" xchgl %%ebx,%%esp \n"
|
" xchgl %%ebx,%%esp \n"
|
||||||
" call *%%edi \n"
|
" call *%%edi \n"
|
||||||
" movl %%ebx,%%esp \n"
|
" movl %%ebx,%%esp \n"
|
||||||
: "=a" (arg1), "=d" (arg2), "=b" (ebx)
|
: "=a" (arg1), "=d" (arg2), "=b" (bx)
|
||||||
: "0" (irq), "1" (desc), "2" (isp),
|
: "0" (irq), "1" (desc), "2" (isp),
|
||||||
"D" (desc->handle_irq)
|
"D" (desc->handle_irq)
|
||||||
: "memory", "cc"
|
: "memory", "cc"
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ static inline void stack_overflow_check(struct pt_regs *regs)
|
|||||||
u64 curbase = (u64)task_stack_page(current);
|
u64 curbase = (u64)task_stack_page(current);
|
||||||
static unsigned long warned = -60*HZ;
|
static unsigned long warned = -60*HZ;
|
||||||
|
|
||||||
if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
|
if (regs->sp >= curbase && regs->sp <= curbase + THREAD_SIZE &&
|
||||||
regs->rsp < curbase + sizeof(struct thread_info) + 128 &&
|
regs->sp < curbase + sizeof(struct thread_info) + 128 &&
|
||||||
time_after(jiffies, warned + 60*HZ)) {
|
time_after(jiffies, warned + 60*HZ)) {
|
||||||
printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n",
|
printk("do_IRQ: %s near stack overflow (cur:%Lx,sp:%lx)\n",
|
||||||
current->comm, curbase, regs->rsp);
|
current->comm, curbase, regs->sp);
|
||||||
show_stack(NULL,NULL);
|
show_stack(NULL,NULL);
|
||||||
warned = jiffies;
|
warned = jiffies;
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
|
|
||||||
/* high bit used in ret_from_ code */
|
/* high bit used in ret_from_ code */
|
||||||
unsigned vector = ~regs->orig_rax;
|
unsigned vector = ~regs->orig_ax;
|
||||||
unsigned irq;
|
unsigned irq;
|
||||||
|
|
||||||
exit_idle();
|
exit_idle();
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
|
|||||||
{
|
{
|
||||||
__get_cpu_var(current_kprobe) = p;
|
__get_cpu_var(current_kprobe) = p;
|
||||||
kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags
|
kcb->kprobe_saved_eflags = kcb->kprobe_old_eflags
|
||||||
= (regs->eflags & (TF_MASK | IF_MASK));
|
= (regs->flags & (TF_MASK | IF_MASK));
|
||||||
if (is_IF_modifier(p->opcode))
|
if (is_IF_modifier(p->opcode))
|
||||||
kcb->kprobe_saved_eflags &= ~IF_MASK;
|
kcb->kprobe_saved_eflags &= ~IF_MASK;
|
||||||
}
|
}
|
||||||
@@ -232,20 +232,20 @@ static __always_inline void restore_btf(void)
|
|||||||
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
clear_btf();
|
clear_btf();
|
||||||
regs->eflags |= TF_MASK;
|
regs->flags |= TF_MASK;
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->flags &= ~IF_MASK;
|
||||||
/*single step inline if the instruction is an int3*/
|
/*single step inline if the instruction is an int3*/
|
||||||
if (p->opcode == BREAKPOINT_INSTRUCTION)
|
if (p->opcode == BREAKPOINT_INSTRUCTION)
|
||||||
regs->eip = (unsigned long)p->addr;
|
regs->ip = (unsigned long)p->addr;
|
||||||
else
|
else
|
||||||
regs->eip = (unsigned long)p->ainsn.insn;
|
regs->ip = (unsigned long)p->ainsn.insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called with kretprobe_lock held */
|
/* Called with kretprobe_lock held */
|
||||||
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long *sara = (unsigned long *)®s->esp;
|
unsigned long *sara = (unsigned long *)®s->sp;
|
||||||
|
|
||||||
ri->ret_addr = (kprobe_opcode_t *) *sara;
|
ri->ret_addr = (kprobe_opcode_t *) *sara;
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
kprobe_opcode_t *addr;
|
kprobe_opcode_t *addr;
|
||||||
struct kprobe_ctlblk *kcb;
|
struct kprobe_ctlblk *kcb;
|
||||||
|
|
||||||
addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
|
addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't want to be preempted for the entire
|
* We don't want to be preempted for the entire
|
||||||
@@ -279,8 +279,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
if (p) {
|
if (p) {
|
||||||
if (kcb->kprobe_status == KPROBE_HIT_SS &&
|
if (kcb->kprobe_status == KPROBE_HIT_SS &&
|
||||||
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
|
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
regs->eflags |= kcb->kprobe_saved_eflags;
|
regs->flags |= kcb->kprobe_saved_eflags;
|
||||||
goto no_kprobe;
|
goto no_kprobe;
|
||||||
}
|
}
|
||||||
/* We have reentered the kprobe_handler(), since
|
/* We have reentered the kprobe_handler(), since
|
||||||
@@ -301,7 +301,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
* another cpu right after we hit, no further
|
* another cpu right after we hit, no further
|
||||||
* handling of this interrupt is appropriate
|
* handling of this interrupt is appropriate
|
||||||
*/
|
*/
|
||||||
regs->eip -= sizeof(kprobe_opcode_t);
|
regs->ip -= sizeof(kprobe_opcode_t);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto no_kprobe;
|
goto no_kprobe;
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
* Back up over the (now missing) int3 and run
|
* Back up over the (now missing) int3 and run
|
||||||
* the original instruction.
|
* the original instruction.
|
||||||
*/
|
*/
|
||||||
regs->eip -= sizeof(kprobe_opcode_t);
|
regs->ip -= sizeof(kprobe_opcode_t);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
/* Not one of ours: let kernel handle it */
|
/* Not one of ours: let kernel handle it */
|
||||||
@@ -344,7 +344,7 @@ ss_probe:
|
|||||||
if (p->ainsn.boostable == 1 && !p->post_handler){
|
if (p->ainsn.boostable == 1 && !p->post_handler){
|
||||||
/* Boost up -- we can execute copied instructions directly */
|
/* Boost up -- we can execute copied instructions directly */
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
regs->eip = (unsigned long)p->ainsn.insn;
|
regs->ip = (unsigned long)p->ainsn.insn;
|
||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ no_kprobe:
|
|||||||
asm volatile ( ".global kretprobe_trampoline\n"
|
asm volatile ( ".global kretprobe_trampoline\n"
|
||||||
"kretprobe_trampoline: \n"
|
"kretprobe_trampoline: \n"
|
||||||
" pushf\n"
|
" pushf\n"
|
||||||
/* skip cs, eip, orig_eax */
|
/* skip cs, ip, orig_ax */
|
||||||
" subl $12, %esp\n"
|
" subl $12, %esp\n"
|
||||||
" pushl %fs\n"
|
" pushl %fs\n"
|
||||||
" pushl %ds\n"
|
" pushl %ds\n"
|
||||||
@@ -382,10 +382,10 @@ no_kprobe:
|
|||||||
" pushl %ebx\n"
|
" pushl %ebx\n"
|
||||||
" movl %esp, %eax\n"
|
" movl %esp, %eax\n"
|
||||||
" call trampoline_handler\n"
|
" call trampoline_handler\n"
|
||||||
/* move eflags to cs */
|
/* move flags to cs */
|
||||||
" movl 52(%esp), %edx\n"
|
" movl 52(%esp), %edx\n"
|
||||||
" movl %edx, 48(%esp)\n"
|
" movl %edx, 48(%esp)\n"
|
||||||
/* save true return address on eflags */
|
/* save true return address on flags */
|
||||||
" movl %eax, 52(%esp)\n"
|
" movl %eax, 52(%esp)\n"
|
||||||
" popl %ebx\n"
|
" popl %ebx\n"
|
||||||
" popl %ecx\n"
|
" popl %ecx\n"
|
||||||
@@ -394,7 +394,7 @@ no_kprobe:
|
|||||||
" popl %edi\n"
|
" popl %edi\n"
|
||||||
" popl %ebp\n"
|
" popl %ebp\n"
|
||||||
" popl %eax\n"
|
" popl %eax\n"
|
||||||
/* skip eip, orig_eax, es, ds, fs */
|
/* skip ip, orig_ax, es, ds, fs */
|
||||||
" addl $20, %esp\n"
|
" addl $20, %esp\n"
|
||||||
" popf\n"
|
" popf\n"
|
||||||
" ret\n");
|
" ret\n");
|
||||||
@@ -415,9 +415,9 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
|
|||||||
spin_lock_irqsave(&kretprobe_lock, flags);
|
spin_lock_irqsave(&kretprobe_lock, flags);
|
||||||
head = kretprobe_inst_table_head(current);
|
head = kretprobe_inst_table_head(current);
|
||||||
/* fixup registers */
|
/* fixup registers */
|
||||||
regs->xcs = __KERNEL_CS | get_kernel_rpl();
|
regs->cs = __KERNEL_CS | get_kernel_rpl();
|
||||||
regs->eip = trampoline_address;
|
regs->ip = trampoline_address;
|
||||||
regs->orig_eax = 0xffffffff;
|
regs->orig_ax = 0xffffffff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It is possible to have multiple instances associated with a given
|
* It is possible to have multiple instances associated with a given
|
||||||
@@ -478,11 +478,11 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
|
|||||||
* interrupt. We have to fix up the stack as follows:
|
* interrupt. We have to fix up the stack as follows:
|
||||||
*
|
*
|
||||||
* 0) Except in the case of absolute or indirect jump or call instructions,
|
* 0) Except in the case of absolute or indirect jump or call instructions,
|
||||||
* the new eip is relative to the copied instruction. We need to make
|
* the new ip is relative to the copied instruction. We need to make
|
||||||
* it relative to the original instruction.
|
* it relative to the original instruction.
|
||||||
*
|
*
|
||||||
* 1) If the single-stepped instruction was pushfl, then the TF and IF
|
* 1) If the single-stepped instruction was pushfl, then the TF and IF
|
||||||
* flags are set in the just-pushed eflags, and may need to be cleared.
|
* flags are set in the just-pushed flags, and may need to be cleared.
|
||||||
*
|
*
|
||||||
* 2) If the single-stepped instruction was a call, the return address
|
* 2) If the single-stepped instruction was a call, the return address
|
||||||
* that is atop the stack is the address following the copied instruction.
|
* that is atop the stack is the address following the copied instruction.
|
||||||
@@ -493,11 +493,11 @@ fastcall void *__kprobes trampoline_handler(struct pt_regs *regs)
|
|||||||
static void __kprobes resume_execution(struct kprobe *p,
|
static void __kprobes resume_execution(struct kprobe *p,
|
||||||
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
|
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
|
||||||
{
|
{
|
||||||
unsigned long *tos = (unsigned long *)®s->esp;
|
unsigned long *tos = (unsigned long *)®s->sp;
|
||||||
unsigned long copy_eip = (unsigned long)p->ainsn.insn;
|
unsigned long copy_eip = (unsigned long)p->ainsn.insn;
|
||||||
unsigned long orig_eip = (unsigned long)p->addr;
|
unsigned long orig_eip = (unsigned long)p->addr;
|
||||||
|
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
switch (p->ainsn.insn[0]) {
|
switch (p->ainsn.insn[0]) {
|
||||||
case 0x9c: /* pushfl */
|
case 0x9c: /* pushfl */
|
||||||
*tos &= ~(TF_MASK | IF_MASK);
|
*tos &= ~(TF_MASK | IF_MASK);
|
||||||
@@ -508,8 +508,8 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||||||
case 0xca:
|
case 0xca:
|
||||||
case 0xcb:
|
case 0xcb:
|
||||||
case 0xcf:
|
case 0xcf:
|
||||||
case 0xea: /* jmp absolute -- eip is correct */
|
case 0xea: /* jmp absolute -- ip is correct */
|
||||||
/* eip is already adjusted, no more changes required */
|
/* ip is already adjusted, no more changes required */
|
||||||
p->ainsn.boostable = 1;
|
p->ainsn.boostable = 1;
|
||||||
goto no_change;
|
goto no_change;
|
||||||
case 0xe8: /* call relative - Fix return addr */
|
case 0xe8: /* call relative - Fix return addr */
|
||||||
@@ -522,14 +522,14 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||||||
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
|
if ((p->ainsn.insn[1] & 0x30) == 0x10) {
|
||||||
/*
|
/*
|
||||||
* call absolute, indirect
|
* call absolute, indirect
|
||||||
* Fix return addr; eip is correct.
|
* Fix return addr; ip is correct.
|
||||||
* But this is not boostable
|
* But this is not boostable
|
||||||
*/
|
*/
|
||||||
*tos = orig_eip + (*tos - copy_eip);
|
*tos = orig_eip + (*tos - copy_eip);
|
||||||
goto no_change;
|
goto no_change;
|
||||||
} else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
|
} else if (((p->ainsn.insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
|
||||||
((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
|
((p->ainsn.insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */
|
||||||
/* eip is correct. And this is boostable */
|
/* ip is correct. And this is boostable */
|
||||||
p->ainsn.boostable = 1;
|
p->ainsn.boostable = 1;
|
||||||
goto no_change;
|
goto no_change;
|
||||||
}
|
}
|
||||||
@@ -538,21 +538,21 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p->ainsn.boostable == 0) {
|
if (p->ainsn.boostable == 0) {
|
||||||
if ((regs->eip > copy_eip) &&
|
if ((regs->ip > copy_eip) &&
|
||||||
(regs->eip - copy_eip) + 5 < MAX_INSN_SIZE) {
|
(regs->ip - copy_eip) + 5 < MAX_INSN_SIZE) {
|
||||||
/*
|
/*
|
||||||
* These instructions can be executed directly if it
|
* These instructions can be executed directly if it
|
||||||
* jumps back to correct address.
|
* jumps back to correct address.
|
||||||
*/
|
*/
|
||||||
set_jmp_op((void *)regs->eip,
|
set_jmp_op((void *)regs->ip,
|
||||||
(void *)orig_eip + (regs->eip - copy_eip));
|
(void *)orig_eip + (regs->ip - copy_eip));
|
||||||
p->ainsn.boostable = 1;
|
p->ainsn.boostable = 1;
|
||||||
} else {
|
} else {
|
||||||
p->ainsn.boostable = -1;
|
p->ainsn.boostable = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
regs->eip = orig_eip + (regs->eip - copy_eip);
|
regs->ip = orig_eip + (regs->ip - copy_eip);
|
||||||
|
|
||||||
no_change:
|
no_change:
|
||||||
restore_btf();
|
restore_btf();
|
||||||
@@ -578,8 +578,8 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
resume_execution(cur, regs, kcb);
|
resume_execution(cur, regs, kcb);
|
||||||
regs->eflags |= kcb->kprobe_saved_eflags;
|
regs->flags |= kcb->kprobe_saved_eflags;
|
||||||
trace_hardirqs_fixup_flags(regs->eflags);
|
trace_hardirqs_fixup_flags(regs->flags);
|
||||||
|
|
||||||
/*Restore back the original saved kprobes variables and continue. */
|
/*Restore back the original saved kprobes variables and continue. */
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER) {
|
if (kcb->kprobe_status == KPROBE_REENTER) {
|
||||||
@@ -591,11 +591,11 @@ out:
|
|||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if somebody else is singlestepping across a probe point, eflags
|
* if somebody else is singlestepping across a probe point, flags
|
||||||
* will have TF set, in which case, continue the remaining processing
|
* will have TF set, in which case, continue the remaining processing
|
||||||
* of do_debug, as if this is not a probe hit.
|
* of do_debug, as if this is not a probe hit.
|
||||||
*/
|
*/
|
||||||
if (regs->eflags & TF_MASK)
|
if (regs->flags & TF_MASK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -612,12 +612,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
|||||||
/*
|
/*
|
||||||
* We are here because the instruction being single
|
* We are here because the instruction being single
|
||||||
* stepped caused a page fault. We reset the current
|
* stepped caused a page fault. We reset the current
|
||||||
* kprobe and the eip points back to the probe address
|
* kprobe and the ip points back to the probe address
|
||||||
* and allow the page fault handler to continue as a
|
* and allow the page fault handler to continue as a
|
||||||
* normal page fault.
|
* normal page fault.
|
||||||
*/
|
*/
|
||||||
regs->eip = (unsigned long)cur->addr;
|
regs->ip = (unsigned long)cur->addr;
|
||||||
regs->eflags |= kcb->kprobe_old_eflags;
|
regs->flags |= kcb->kprobe_old_eflags;
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER)
|
if (kcb->kprobe_status == KPROBE_REENTER)
|
||||||
restore_previous_kprobe(kcb);
|
restore_previous_kprobe(kcb);
|
||||||
else
|
else
|
||||||
@@ -703,7 +703,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||||
|
|
||||||
kcb->jprobe_saved_regs = *regs;
|
kcb->jprobe_saved_regs = *regs;
|
||||||
kcb->jprobe_saved_esp = ®s->esp;
|
kcb->jprobe_saved_esp = ®s->sp;
|
||||||
addr = (unsigned long)(kcb->jprobe_saved_esp);
|
addr = (unsigned long)(kcb->jprobe_saved_esp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -715,9 +715,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
|
memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
|
||||||
MIN_STACK_SIZE(addr));
|
MIN_STACK_SIZE(addr));
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->flags &= ~IF_MASK;
|
||||||
trace_hardirqs_off();
|
trace_hardirqs_off();
|
||||||
regs->eip = (unsigned long)(jp->entry);
|
regs->ip = (unsigned long)(jp->entry);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,15 +736,15 @@ void __kprobes jprobe_return(void)
|
|||||||
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||||
u8 *addr = (u8 *) (regs->eip - 1);
|
u8 *addr = (u8 *) (regs->ip - 1);
|
||||||
unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp);
|
unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_esp);
|
||||||
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
||||||
|
|
||||||
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
||||||
if (®s->esp != kcb->jprobe_saved_esp) {
|
if (®s->sp != kcb->jprobe_saved_esp) {
|
||||||
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
||||||
printk("current esp %p does not match saved esp %p\n",
|
printk("current sp %p does not match saved sp %p\n",
|
||||||
®s->esp, kcb->jprobe_saved_esp);
|
®s->sp, kcb->jprobe_saved_esp);
|
||||||
printk("Saved registers for jprobe %p\n", jp);
|
printk("Saved registers for jprobe %p\n", jp);
|
||||||
show_registers(saved_regs);
|
show_registers(saved_regs);
|
||||||
printk("Current registers\n");
|
printk("Current registers\n");
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
|
|||||||
{
|
{
|
||||||
__get_cpu_var(current_kprobe) = p;
|
__get_cpu_var(current_kprobe) = p;
|
||||||
kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags
|
kcb->kprobe_saved_rflags = kcb->kprobe_old_rflags
|
||||||
= (regs->eflags & (TF_MASK | IF_MASK));
|
= (regs->flags & (TF_MASK | IF_MASK));
|
||||||
if (is_IF_modifier(p->ainsn.insn))
|
if (is_IF_modifier(p->ainsn.insn))
|
||||||
kcb->kprobe_saved_rflags &= ~IF_MASK;
|
kcb->kprobe_saved_rflags &= ~IF_MASK;
|
||||||
}
|
}
|
||||||
@@ -271,20 +271,20 @@ static __always_inline void restore_btf(void)
|
|||||||
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
clear_btf();
|
clear_btf();
|
||||||
regs->eflags |= TF_MASK;
|
regs->flags |= TF_MASK;
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->flags &= ~IF_MASK;
|
||||||
/*single step inline if the instruction is an int3*/
|
/*single step inline if the instruction is an int3*/
|
||||||
if (p->opcode == BREAKPOINT_INSTRUCTION)
|
if (p->opcode == BREAKPOINT_INSTRUCTION)
|
||||||
regs->rip = (unsigned long)p->addr;
|
regs->ip = (unsigned long)p->addr;
|
||||||
else
|
else
|
||||||
regs->rip = (unsigned long)p->ainsn.insn;
|
regs->ip = (unsigned long)p->ainsn.insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called with kretprobe_lock held */
|
/* Called with kretprobe_lock held */
|
||||||
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long *sara = (unsigned long *)regs->rsp;
|
unsigned long *sara = (unsigned long *)regs->sp;
|
||||||
|
|
||||||
ri->ret_addr = (kprobe_opcode_t *) *sara;
|
ri->ret_addr = (kprobe_opcode_t *) *sara;
|
||||||
/* Replace the return addr with trampoline addr */
|
/* Replace the return addr with trampoline addr */
|
||||||
@@ -295,7 +295,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
struct kprobe *p;
|
struct kprobe *p;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t));
|
kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
|
||||||
struct kprobe_ctlblk *kcb;
|
struct kprobe_ctlblk *kcb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -311,8 +311,8 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
if (p) {
|
if (p) {
|
||||||
if (kcb->kprobe_status == KPROBE_HIT_SS &&
|
if (kcb->kprobe_status == KPROBE_HIT_SS &&
|
||||||
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
|
*p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
regs->eflags |= kcb->kprobe_saved_rflags;
|
regs->flags |= kcb->kprobe_saved_rflags;
|
||||||
goto no_kprobe;
|
goto no_kprobe;
|
||||||
} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
|
} else if (kcb->kprobe_status == KPROBE_HIT_SSDONE) {
|
||||||
/* TODO: Provide re-entrancy from
|
/* TODO: Provide re-entrancy from
|
||||||
@@ -321,7 +321,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
* the instruction of the new probe.
|
* the instruction of the new probe.
|
||||||
*/
|
*/
|
||||||
arch_disarm_kprobe(p);
|
arch_disarm_kprobe(p);
|
||||||
regs->rip = (unsigned long)p->addr;
|
regs->ip = (unsigned long)p->addr;
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
ret = 1;
|
ret = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -345,7 +345,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
* another cpu right after we hit, no further
|
* another cpu right after we hit, no further
|
||||||
* handling of this interrupt is appropriate
|
* handling of this interrupt is appropriate
|
||||||
*/
|
*/
|
||||||
regs->rip = (unsigned long)addr;
|
regs->ip = (unsigned long)addr;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto no_kprobe;
|
goto no_kprobe;
|
||||||
}
|
}
|
||||||
@@ -369,7 +369,7 @@ int __kprobes kprobe_handler(struct pt_regs *regs)
|
|||||||
* Back up over the (now missing) int3 and run
|
* Back up over the (now missing) int3 and run
|
||||||
* the original instruction.
|
* the original instruction.
|
||||||
*/
|
*/
|
||||||
regs->rip = (unsigned long)addr;
|
regs->ip = (unsigned long)addr;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
/* Not one of ours: let kernel handle it */
|
/* Not one of ours: let kernel handle it */
|
||||||
@@ -454,7 +454,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
kretprobe_assert(ri, orig_ret_address, trampoline_address);
|
kretprobe_assert(ri, orig_ret_address, trampoline_address);
|
||||||
regs->rip = orig_ret_address;
|
regs->ip = orig_ret_address;
|
||||||
|
|
||||||
reset_current_kprobe();
|
reset_current_kprobe();
|
||||||
spin_unlock_irqrestore(&kretprobe_lock, flags);
|
spin_unlock_irqrestore(&kretprobe_lock, flags);
|
||||||
@@ -484,11 +484,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
* interrupt. We have to fix up the stack as follows:
|
* interrupt. We have to fix up the stack as follows:
|
||||||
*
|
*
|
||||||
* 0) Except in the case of absolute or indirect jump or call instructions,
|
* 0) Except in the case of absolute or indirect jump or call instructions,
|
||||||
* the new rip is relative to the copied instruction. We need to make
|
* the new ip is relative to the copied instruction. We need to make
|
||||||
* it relative to the original instruction.
|
* it relative to the original instruction.
|
||||||
*
|
*
|
||||||
* 1) If the single-stepped instruction was pushfl, then the TF and IF
|
* 1) If the single-stepped instruction was pushfl, then the TF and IF
|
||||||
* flags are set in the just-pushed eflags, and may need to be cleared.
|
* flags are set in the just-pushed flags, and may need to be cleared.
|
||||||
*
|
*
|
||||||
* 2) If the single-stepped instruction was a call, the return address
|
* 2) If the single-stepped instruction was a call, the return address
|
||||||
* that is atop the stack is the address following the copied instruction.
|
* that is atop the stack is the address following the copied instruction.
|
||||||
@@ -497,7 +497,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
static void __kprobes resume_execution(struct kprobe *p,
|
static void __kprobes resume_execution(struct kprobe *p,
|
||||||
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
|
struct pt_regs *regs, struct kprobe_ctlblk *kcb)
|
||||||
{
|
{
|
||||||
unsigned long *tos = (unsigned long *)regs->rsp;
|
unsigned long *tos = (unsigned long *)regs->sp;
|
||||||
unsigned long copy_rip = (unsigned long)p->ainsn.insn;
|
unsigned long copy_rip = (unsigned long)p->ainsn.insn;
|
||||||
unsigned long orig_rip = (unsigned long)p->addr;
|
unsigned long orig_rip = (unsigned long)p->addr;
|
||||||
kprobe_opcode_t *insn = p->ainsn.insn;
|
kprobe_opcode_t *insn = p->ainsn.insn;
|
||||||
@@ -506,7 +506,7 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||||||
if (*insn >= 0x40 && *insn <= 0x4f)
|
if (*insn >= 0x40 && *insn <= 0x4f)
|
||||||
insn++;
|
insn++;
|
||||||
|
|
||||||
regs->eflags &= ~TF_MASK;
|
regs->flags &= ~TF_MASK;
|
||||||
switch (*insn) {
|
switch (*insn) {
|
||||||
case 0x9c: /* pushfl */
|
case 0x9c: /* pushfl */
|
||||||
*tos &= ~(TF_MASK | IF_MASK);
|
*tos &= ~(TF_MASK | IF_MASK);
|
||||||
@@ -538,7 +538,8 @@ static void __kprobes resume_execution(struct kprobe *p,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
regs->rip = orig_rip + (regs->rip - copy_rip);
|
regs->ip = orig_rip + (regs->ip - copy_rip);
|
||||||
|
|
||||||
no_change:
|
no_change:
|
||||||
restore_btf();
|
restore_btf();
|
||||||
|
|
||||||
@@ -559,8 +560,8 @@ int __kprobes post_kprobe_handler(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
resume_execution(cur, regs, kcb);
|
resume_execution(cur, regs, kcb);
|
||||||
regs->eflags |= kcb->kprobe_saved_rflags;
|
regs->flags |= kcb->kprobe_saved_rflags;
|
||||||
trace_hardirqs_fixup_flags(regs->eflags);
|
trace_hardirqs_fixup_flags(regs->flags);
|
||||||
|
|
||||||
/* Restore the original saved kprobes variables and continue. */
|
/* Restore the original saved kprobes variables and continue. */
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER) {
|
if (kcb->kprobe_status == KPROBE_REENTER) {
|
||||||
@@ -572,11 +573,11 @@ out:
|
|||||||
preempt_enable_no_resched();
|
preempt_enable_no_resched();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if somebody else is singlestepping across a probe point, eflags
|
* if somebody else is singlestepping across a probe point, flags
|
||||||
* will have TF set, in which case, continue the remaining processing
|
* will have TF set, in which case, continue the remaining processing
|
||||||
* of do_debug, as if this is not a probe hit.
|
* of do_debug, as if this is not a probe hit.
|
||||||
*/
|
*/
|
||||||
if (regs->eflags & TF_MASK)
|
if (regs->flags & TF_MASK)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -594,12 +595,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
|||||||
/*
|
/*
|
||||||
* We are here because the instruction being single
|
* We are here because the instruction being single
|
||||||
* stepped caused a page fault. We reset the current
|
* stepped caused a page fault. We reset the current
|
||||||
* kprobe and the rip points back to the probe address
|
* kprobe and the ip points back to the probe address
|
||||||
* and allow the page fault handler to continue as a
|
* and allow the page fault handler to continue as a
|
||||||
* normal page fault.
|
* normal page fault.
|
||||||
*/
|
*/
|
||||||
regs->rip = (unsigned long)cur->addr;
|
regs->ip = (unsigned long)cur->addr;
|
||||||
regs->eflags |= kcb->kprobe_old_rflags;
|
regs->flags |= kcb->kprobe_old_rflags;
|
||||||
if (kcb->kprobe_status == KPROBE_REENTER)
|
if (kcb->kprobe_status == KPROBE_REENTER)
|
||||||
restore_previous_kprobe(kcb);
|
restore_previous_kprobe(kcb);
|
||||||
else
|
else
|
||||||
@@ -629,9 +630,9 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
|
|||||||
* In case the user-specified fault handler returned
|
* In case the user-specified fault handler returned
|
||||||
* zero, try to fix up.
|
* zero, try to fix up.
|
||||||
*/
|
*/
|
||||||
fixup = search_exception_tables(regs->rip);
|
fixup = search_exception_tables(regs->ip);
|
||||||
if (fixup) {
|
if (fixup) {
|
||||||
regs->rip = fixup->fixup;
|
regs->ip = fixup->fixup;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +689,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||||
|
|
||||||
kcb->jprobe_saved_regs = *regs;
|
kcb->jprobe_saved_regs = *regs;
|
||||||
kcb->jprobe_saved_rsp = (long *) regs->rsp;
|
kcb->jprobe_saved_rsp = (long *) regs->sp;
|
||||||
addr = (unsigned long)(kcb->jprobe_saved_rsp);
|
addr = (unsigned long)(kcb->jprobe_saved_rsp);
|
||||||
/*
|
/*
|
||||||
* As Linus pointed out, gcc assumes that the callee
|
* As Linus pointed out, gcc assumes that the callee
|
||||||
@@ -699,9 +700,9 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
|
memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
|
||||||
MIN_STACK_SIZE(addr));
|
MIN_STACK_SIZE(addr));
|
||||||
regs->eflags &= ~IF_MASK;
|
regs->flags &= ~IF_MASK;
|
||||||
trace_hardirqs_off();
|
trace_hardirqs_off();
|
||||||
regs->rip = (unsigned long)(jp->entry);
|
regs->ip = (unsigned long)(jp->entry);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,15 +721,15 @@ void __kprobes jprobe_return(void)
|
|||||||
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||||
u8 *addr = (u8 *) (regs->rip - 1);
|
u8 *addr = (u8 *) (regs->ip - 1);
|
||||||
unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp);
|
unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_rsp);
|
||||||
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
||||||
|
|
||||||
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
if ((addr > (u8 *) jprobe_return) && (addr < (u8 *) jprobe_return_end)) {
|
||||||
if ((unsigned long *)regs->rsp != kcb->jprobe_saved_rsp) {
|
if ((unsigned long *)regs->sp != kcb->jprobe_saved_rsp) {
|
||||||
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
||||||
printk("current rsp %p does not match saved rsp %p\n",
|
printk("current sp %p does not match saved sp %p\n",
|
||||||
(long *)regs->rsp, kcb->jprobe_saved_rsp);
|
(long *)regs->sp, kcb->jprobe_saved_rsp);
|
||||||
printk("Saved registers for jprobe %p\n", jp);
|
printk("Saved registers for jprobe %p\n", jp);
|
||||||
show_registers(saved_regs);
|
show_registers(saved_regs);
|
||||||
printk("Current registers\n");
|
printk("Current registers\n");
|
||||||
|
|||||||
@@ -265,13 +265,13 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
|
|||||||
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
||||||
* capability.
|
* capability.
|
||||||
*/
|
*/
|
||||||
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
|
||||||
{
|
{
|
||||||
if (!need_resched()) {
|
if (!need_resched()) {
|
||||||
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (!need_resched())
|
if (!need_resched())
|
||||||
__mwait(eax, ecx);
|
__mwait(ax, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,15 +320,15 @@ void __show_registers(struct pt_regs *regs, int all)
|
|||||||
{
|
{
|
||||||
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
|
unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
|
||||||
unsigned long d0, d1, d2, d3, d6, d7;
|
unsigned long d0, d1, d2, d3, d6, d7;
|
||||||
unsigned long esp;
|
unsigned long sp;
|
||||||
unsigned short ss, gs;
|
unsigned short ss, gs;
|
||||||
|
|
||||||
if (user_mode_vm(regs)) {
|
if (user_mode_vm(regs)) {
|
||||||
esp = regs->esp;
|
sp = regs->sp;
|
||||||
ss = regs->xss & 0xffff;
|
ss = regs->ss & 0xffff;
|
||||||
savesegment(gs, gs);
|
savesegment(gs, gs);
|
||||||
} else {
|
} else {
|
||||||
esp = (unsigned long) (®s->esp);
|
sp = (unsigned long) (®s->sp);
|
||||||
savesegment(ss, ss);
|
savesegment(ss, ss);
|
||||||
savesegment(gs, gs);
|
savesegment(gs, gs);
|
||||||
}
|
}
|
||||||
@@ -341,17 +341,17 @@ void __show_registers(struct pt_regs *regs, int all)
|
|||||||
init_utsname()->version);
|
init_utsname()->version);
|
||||||
|
|
||||||
printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
|
printk("EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
|
||||||
0xffff & regs->xcs, regs->eip, regs->eflags,
|
0xffff & regs->cs, regs->ip, regs->flags,
|
||||||
smp_processor_id());
|
smp_processor_id());
|
||||||
print_symbol("EIP is at %s\n", regs->eip);
|
print_symbol("EIP is at %s\n", regs->ip);
|
||||||
|
|
||||||
printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
|
printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
|
||||||
regs->eax, regs->ebx, regs->ecx, regs->edx);
|
regs->ax, regs->bx, regs->cx, regs->dx);
|
||||||
printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
|
printk("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n",
|
||||||
regs->esi, regs->edi, regs->ebp, esp);
|
regs->si, regs->di, regs->bp, sp);
|
||||||
printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
|
printk(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n",
|
||||||
regs->xds & 0xffff, regs->xes & 0xffff,
|
regs->ds & 0xffff, regs->es & 0xffff,
|
||||||
regs->xfs & 0xffff, gs, ss);
|
regs->fs & 0xffff, gs, ss);
|
||||||
|
|
||||||
if (!all)
|
if (!all)
|
||||||
return;
|
return;
|
||||||
@@ -379,12 +379,12 @@ void __show_registers(struct pt_regs *regs, int all)
|
|||||||
void show_regs(struct pt_regs *regs)
|
void show_regs(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
__show_registers(regs, 1);
|
__show_registers(regs, 1);
|
||||||
show_trace(NULL, regs, ®s->esp);
|
show_trace(NULL, regs, ®s->sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This gets run with %ebx containing the
|
* This gets run with %bx containing the
|
||||||
* function to call, and %edx containing
|
* function to call, and %dx containing
|
||||||
* the "args".
|
* the "args".
|
||||||
*/
|
*/
|
||||||
extern void kernel_thread_helper(void);
|
extern void kernel_thread_helper(void);
|
||||||
@@ -398,16 +398,16 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
|
|||||||
|
|
||||||
memset(®s, 0, sizeof(regs));
|
memset(®s, 0, sizeof(regs));
|
||||||
|
|
||||||
regs.ebx = (unsigned long) fn;
|
regs.bx = (unsigned long) fn;
|
||||||
regs.edx = (unsigned long) arg;
|
regs.dx = (unsigned long) arg;
|
||||||
|
|
||||||
regs.xds = __USER_DS;
|
regs.ds = __USER_DS;
|
||||||
regs.xes = __USER_DS;
|
regs.es = __USER_DS;
|
||||||
regs.xfs = __KERNEL_PERCPU;
|
regs.fs = __KERNEL_PERCPU;
|
||||||
regs.orig_eax = -1;
|
regs.orig_ax = -1;
|
||||||
regs.eip = (unsigned long) kernel_thread_helper;
|
regs.ip = (unsigned long) kernel_thread_helper;
|
||||||
regs.xcs = __KERNEL_CS | get_kernel_rpl();
|
regs.cs = __KERNEL_CS | get_kernel_rpl();
|
||||||
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
|
regs.flags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
|
||||||
|
|
||||||
/* Ok, create the new process.. */
|
/* Ok, create the new process.. */
|
||||||
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
|
||||||
@@ -470,7 +470,7 @@ void prepare_to_copy(struct task_struct *tsk)
|
|||||||
unlazy_fpu(tsk);
|
unlazy_fpu(tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
|
||||||
unsigned long unused,
|
unsigned long unused,
|
||||||
struct task_struct * p, struct pt_regs * regs)
|
struct task_struct * p, struct pt_regs * regs)
|
||||||
{
|
{
|
||||||
@@ -480,8 +480,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
|||||||
|
|
||||||
childregs = task_pt_regs(p);
|
childregs = task_pt_regs(p);
|
||||||
*childregs = *regs;
|
*childregs = *regs;
|
||||||
childregs->eax = 0;
|
childregs->ax = 0;
|
||||||
childregs->esp = esp;
|
childregs->sp = sp;
|
||||||
|
|
||||||
p->thread.esp = (unsigned long) childregs;
|
p->thread.esp = (unsigned long) childregs;
|
||||||
p->thread.esp0 = (unsigned long) (childregs+1);
|
p->thread.esp0 = (unsigned long) (childregs+1);
|
||||||
@@ -508,7 +508,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
|
|||||||
*/
|
*/
|
||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
err = do_set_thread_area(p, -1,
|
err = do_set_thread_area(p, -1,
|
||||||
(struct user_desc __user *)childregs->esi, 0);
|
(struct user_desc __user *)childregs->si, 0);
|
||||||
|
|
||||||
if (err && p->thread.io_bitmap_ptr) {
|
if (err && p->thread.io_bitmap_ptr) {
|
||||||
kfree(p->thread.io_bitmap_ptr);
|
kfree(p->thread.io_bitmap_ptr);
|
||||||
@@ -527,7 +527,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
|
|||||||
/* changed the size calculations - should hopefully work better. lbt */
|
/* changed the size calculations - should hopefully work better. lbt */
|
||||||
dump->magic = CMAGIC;
|
dump->magic = CMAGIC;
|
||||||
dump->start_code = 0;
|
dump->start_code = 0;
|
||||||
dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
|
dump->start_stack = regs->sp & ~(PAGE_SIZE - 1);
|
||||||
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
|
dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
|
||||||
dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
|
||||||
dump->u_dsize -= dump->u_tsize;
|
dump->u_dsize -= dump->u_tsize;
|
||||||
@@ -538,23 +538,23 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
|
|||||||
if (dump->start_stack < TASK_SIZE)
|
if (dump->start_stack < TASK_SIZE)
|
||||||
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
|
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
|
||||||
|
|
||||||
dump->regs.ebx = regs->ebx;
|
dump->regs.ebx = regs->bx;
|
||||||
dump->regs.ecx = regs->ecx;
|
dump->regs.ecx = regs->cx;
|
||||||
dump->regs.edx = regs->edx;
|
dump->regs.edx = regs->dx;
|
||||||
dump->regs.esi = regs->esi;
|
dump->regs.esi = regs->si;
|
||||||
dump->regs.edi = regs->edi;
|
dump->regs.edi = regs->di;
|
||||||
dump->regs.ebp = regs->ebp;
|
dump->regs.ebp = regs->bp;
|
||||||
dump->regs.eax = regs->eax;
|
dump->regs.eax = regs->ax;
|
||||||
dump->regs.ds = regs->xds;
|
dump->regs.ds = regs->ds;
|
||||||
dump->regs.es = regs->xes;
|
dump->regs.es = regs->es;
|
||||||
dump->regs.fs = regs->xfs;
|
dump->regs.fs = regs->fs;
|
||||||
savesegment(gs,dump->regs.gs);
|
savesegment(gs,dump->regs.gs);
|
||||||
dump->regs.orig_eax = regs->orig_eax;
|
dump->regs.orig_eax = regs->orig_ax;
|
||||||
dump->regs.eip = regs->eip;
|
dump->regs.eip = regs->ip;
|
||||||
dump->regs.cs = regs->xcs;
|
dump->regs.cs = regs->cs;
|
||||||
dump->regs.eflags = regs->eflags;
|
dump->regs.eflags = regs->flags;
|
||||||
dump->regs.esp = regs->esp;
|
dump->regs.esp = regs->sp;
|
||||||
dump->regs.ss = regs->xss;
|
dump->regs.ss = regs->ss;
|
||||||
|
|
||||||
dump->u_fpvalid = dump_fpu (regs, &dump->i387);
|
dump->u_fpvalid = dump_fpu (regs, &dump->i387);
|
||||||
}
|
}
|
||||||
@@ -566,10 +566,10 @@ EXPORT_SYMBOL(dump_thread);
|
|||||||
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
|
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
|
||||||
{
|
{
|
||||||
struct pt_regs ptregs = *task_pt_regs(tsk);
|
struct pt_regs ptregs = *task_pt_regs(tsk);
|
||||||
ptregs.xcs &= 0xffff;
|
ptregs.cs &= 0xffff;
|
||||||
ptregs.xds &= 0xffff;
|
ptregs.ds &= 0xffff;
|
||||||
ptregs.xes &= 0xffff;
|
ptregs.es &= 0xffff;
|
||||||
ptregs.xss &= 0xffff;
|
ptregs.ss &= 0xffff;
|
||||||
|
|
||||||
elf_core_copy_regs(regs, &ptregs);
|
elf_core_copy_regs(regs, &ptregs);
|
||||||
|
|
||||||
@@ -684,7 +684,7 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
|||||||
* More important, however, is the fact that this allows us much
|
* More important, however, is the fact that this allows us much
|
||||||
* more flexibility.
|
* more flexibility.
|
||||||
*
|
*
|
||||||
* The return value (in %eax) will be the "prev" task after
|
* The return value (in %ax) will be the "prev" task after
|
||||||
* the task-switch, and shows up in ret_from_fork in entry.S,
|
* the task-switch, and shows up in ret_from_fork in entry.S,
|
||||||
* for example.
|
* for example.
|
||||||
*/
|
*/
|
||||||
@@ -771,7 +771,7 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
|||||||
|
|
||||||
asmlinkage int sys_fork(struct pt_regs regs)
|
asmlinkage int sys_fork(struct pt_regs regs)
|
||||||
{
|
{
|
||||||
return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
|
return do_fork(SIGCHLD, regs.sp, ®s, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int sys_clone(struct pt_regs regs)
|
asmlinkage int sys_clone(struct pt_regs regs)
|
||||||
@@ -780,12 +780,12 @@ asmlinkage int sys_clone(struct pt_regs regs)
|
|||||||
unsigned long newsp;
|
unsigned long newsp;
|
||||||
int __user *parent_tidptr, *child_tidptr;
|
int __user *parent_tidptr, *child_tidptr;
|
||||||
|
|
||||||
clone_flags = regs.ebx;
|
clone_flags = regs.bx;
|
||||||
newsp = regs.ecx;
|
newsp = regs.cx;
|
||||||
parent_tidptr = (int __user *)regs.edx;
|
parent_tidptr = (int __user *)regs.dx;
|
||||||
child_tidptr = (int __user *)regs.edi;
|
child_tidptr = (int __user *)regs.di;
|
||||||
if (!newsp)
|
if (!newsp)
|
||||||
newsp = regs.esp;
|
newsp = regs.sp;
|
||||||
return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr);
|
return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -801,7 +801,7 @@ asmlinkage int sys_clone(struct pt_regs regs)
|
|||||||
*/
|
*/
|
||||||
asmlinkage int sys_vfork(struct pt_regs regs)
|
asmlinkage int sys_vfork(struct pt_regs regs)
|
||||||
{
|
{
|
||||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
|
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.sp, ®s, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -812,13 +812,13 @@ asmlinkage int sys_execve(struct pt_regs regs)
|
|||||||
int error;
|
int error;
|
||||||
char * filename;
|
char * filename;
|
||||||
|
|
||||||
filename = getname((char __user *) regs.ebx);
|
filename = getname((char __user *) regs.bx);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename,
|
error = do_execve(filename,
|
||||||
(char __user * __user *) regs.ecx,
|
(char __user * __user *) regs.cx,
|
||||||
(char __user * __user *) regs.edx,
|
(char __user * __user *) regs.dx,
|
||||||
®s);
|
®s);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
/* Make sure we don't return using sysenter.. */
|
/* Make sure we don't return using sysenter.. */
|
||||||
@@ -834,24 +834,24 @@ out:
|
|||||||
|
|
||||||
unsigned long get_wchan(struct task_struct *p)
|
unsigned long get_wchan(struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned long ebp, esp, eip;
|
unsigned long bp, sp, ip;
|
||||||
unsigned long stack_page;
|
unsigned long stack_page;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
if (!p || p == current || p->state == TASK_RUNNING)
|
if (!p || p == current || p->state == TASK_RUNNING)
|
||||||
return 0;
|
return 0;
|
||||||
stack_page = (unsigned long)task_stack_page(p);
|
stack_page = (unsigned long)task_stack_page(p);
|
||||||
esp = p->thread.esp;
|
sp = p->thread.esp;
|
||||||
if (!stack_page || esp < stack_page || esp > top_esp+stack_page)
|
if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
|
||||||
return 0;
|
return 0;
|
||||||
/* include/asm-i386/system.h:switch_to() pushes ebp last. */
|
/* include/asm-i386/system.h:switch_to() pushes bp last. */
|
||||||
ebp = *(unsigned long *) esp;
|
bp = *(unsigned long *) sp;
|
||||||
do {
|
do {
|
||||||
if (ebp < stack_page || ebp > top_ebp+stack_page)
|
if (bp < stack_page || bp > top_ebp+stack_page)
|
||||||
return 0;
|
return 0;
|
||||||
eip = *(unsigned long *) (ebp+4);
|
ip = *(unsigned long *) (bp+4);
|
||||||
if (!in_sched_functions(eip))
|
if (!in_sched_functions(ip))
|
||||||
return eip;
|
return ip;
|
||||||
ebp = *(unsigned long *) ebp;
|
bp = *(unsigned long *) bp;
|
||||||
} while (count++ < 16);
|
} while (count++ < 16);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,13 +257,13 @@ void cpu_idle(void)
|
|||||||
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
* New with Core Duo processors, MWAIT can take some hints based on CPU
|
||||||
* capability.
|
* capability.
|
||||||
*/
|
*/
|
||||||
void mwait_idle_with_hints(unsigned long eax, unsigned long ecx)
|
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
|
||||||
{
|
{
|
||||||
if (!need_resched()) {
|
if (!need_resched()) {
|
||||||
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
__monitor((void *)¤t_thread_info()->flags, 0, 0);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
if (!need_resched())
|
if (!need_resched())
|
||||||
__mwait(eax, ecx);
|
__mwait(ax, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,16 +330,16 @@ void __show_regs(struct pt_regs * regs)
|
|||||||
init_utsname()->release,
|
init_utsname()->release,
|
||||||
(int)strcspn(init_utsname()->version, " "),
|
(int)strcspn(init_utsname()->version, " "),
|
||||||
init_utsname()->version);
|
init_utsname()->version);
|
||||||
printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->rip);
|
printk("RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
|
||||||
printk_address(regs->rip);
|
printk_address(regs->ip);
|
||||||
printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->rsp,
|
printk("RSP: %04lx:%016lx EFLAGS: %08lx\n", regs->ss, regs->sp,
|
||||||
regs->eflags);
|
regs->flags);
|
||||||
printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
|
printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
|
||||||
regs->rax, regs->rbx, regs->rcx);
|
regs->ax, regs->bx, regs->cx);
|
||||||
printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
|
printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
|
||||||
regs->rdx, regs->rsi, regs->rdi);
|
regs->dx, regs->si, regs->di);
|
||||||
printk("RBP: %016lx R08: %016lx R09: %016lx\n",
|
printk("RBP: %016lx R08: %016lx R09: %016lx\n",
|
||||||
regs->rbp, regs->r8, regs->r9);
|
regs->bp, regs->r8, regs->r9);
|
||||||
printk("R10: %016lx R11: %016lx R12: %016lx\n",
|
printk("R10: %016lx R11: %016lx R12: %016lx\n",
|
||||||
regs->r10, regs->r11, regs->r12);
|
regs->r10, regs->r11, regs->r12);
|
||||||
printk("R13: %016lx R14: %016lx R15: %016lx\n",
|
printk("R13: %016lx R14: %016lx R15: %016lx\n",
|
||||||
@@ -476,7 +476,7 @@ void prepare_to_copy(struct task_struct *tsk)
|
|||||||
unlazy_fpu(tsk);
|
unlazy_fpu(tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
|
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
|
||||||
unsigned long unused,
|
unsigned long unused,
|
||||||
struct task_struct * p, struct pt_regs * regs)
|
struct task_struct * p, struct pt_regs * regs)
|
||||||
{
|
{
|
||||||
@@ -488,10 +488,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
|
|||||||
(THREAD_SIZE + task_stack_page(p))) - 1;
|
(THREAD_SIZE + task_stack_page(p))) - 1;
|
||||||
*childregs = *regs;
|
*childregs = *regs;
|
||||||
|
|
||||||
childregs->rax = 0;
|
childregs->ax = 0;
|
||||||
childregs->rsp = rsp;
|
childregs->sp = sp;
|
||||||
if (rsp == ~0UL)
|
if (sp == ~0UL)
|
||||||
childregs->rsp = (unsigned long)childregs;
|
childregs->sp = (unsigned long)childregs;
|
||||||
|
|
||||||
p->thread.rsp = (unsigned long) childregs;
|
p->thread.rsp = (unsigned long) childregs;
|
||||||
p->thread.rsp0 = (unsigned long) (childregs+1);
|
p->thread.rsp0 = (unsigned long) (childregs+1);
|
||||||
@@ -525,7 +525,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
|
|||||||
#ifdef CONFIG_IA32_EMULATION
|
#ifdef CONFIG_IA32_EMULATION
|
||||||
if (test_thread_flag(TIF_IA32))
|
if (test_thread_flag(TIF_IA32))
|
||||||
err = do_set_thread_area(p, -1,
|
err = do_set_thread_area(p, -1,
|
||||||
(struct user_desc __user *)childregs->rsi, 0);
|
(struct user_desc __user *)childregs->si, 0);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8);
|
err = do_arch_prctl(p, ARCH_SET_FS, childregs->r8);
|
||||||
@@ -732,7 +732,7 @@ void set_personality_64bit(void)
|
|||||||
|
|
||||||
asmlinkage long sys_fork(struct pt_regs *regs)
|
asmlinkage long sys_fork(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL);
|
return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage long
|
asmlinkage long
|
||||||
@@ -740,7 +740,7 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|||||||
void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
|
void __user *parent_tid, void __user *child_tid, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
if (!newsp)
|
if (!newsp)
|
||||||
newsp = regs->rsp;
|
newsp = regs->sp;
|
||||||
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
|
return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -756,14 +756,14 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|||||||
*/
|
*/
|
||||||
asmlinkage long sys_vfork(struct pt_regs *regs)
|
asmlinkage long sys_vfork(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0,
|
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long get_wchan(struct task_struct *p)
|
unsigned long get_wchan(struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned long stack;
|
unsigned long stack;
|
||||||
u64 fp,rip;
|
u64 fp,ip;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (!p || p == current || p->state==TASK_RUNNING)
|
if (!p || p == current || p->state==TASK_RUNNING)
|
||||||
@@ -776,9 +776,9 @@ unsigned long get_wchan(struct task_struct *p)
|
|||||||
if (fp < (unsigned long)stack ||
|
if (fp < (unsigned long)stack ||
|
||||||
fp > (unsigned long)stack+THREAD_SIZE)
|
fp > (unsigned long)stack+THREAD_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
rip = *(u64 *)(fp+8);
|
ip = *(u64 *)(fp+8);
|
||||||
if (!in_sched_functions(rip))
|
if (!in_sched_functions(ip))
|
||||||
return rip;
|
return ip;
|
||||||
fp = *(u64 *)fp;
|
fp = *(u64 *)fp;
|
||||||
} while (count++ < 16);
|
} while (count++ < 16);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user