#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/interrupt.h>
+#include <linux/config.h>
#include <linux/utsname.h>
#include <linux/delay.h>
#include <linux/reboot.h>
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/random.h>
+#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
local_irq_enable();
if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
- current_thread_info()->status &= ~TS_POLLING;
+ clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb__after_clear_bit();
while (!need_resched()) {
local_irq_disable();
else
local_irq_enable();
}
- current_thread_info()->status |= TS_POLLING;
+ set_thread_flag(TIF_POLLING_NRFLAG);
} else {
while (!need_resched())
cpu_relax();
{
int cpu = smp_processor_id();
- current_thread_info()->status |= TS_POLLING;
+ set_thread_flag(TIF_POLLING_NRFLAG);
/* endless idle loop with no priority at all */
while (1) {
printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
print_symbol("EIP is at %s\n", regs->eip);
- if (user_mode_vm(regs))
+ if (user_mode(regs))
printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
printk(" EFLAGS: %08lx %s (%s %.*s)\n",
regs->eflags, print_tainted(), system_utsname.release,
cr3 = read_cr3();
cr4 = read_cr4_safe();
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
- show_trace(NULL, regs, ®s->esp);
+ show_trace(NULL, ®s->esp);
}
/*
* the "args".
*/
extern void kernel_thread_helper(void);
+__asm__(".section .text\n"
+ ".align 4\n"
+ "kernel_thread_helper:\n\t"
+ "movl %edx,%eax\n\t"
+ "pushl %edx\n\t"
+ "call *%ebx\n\t"
+ "pushl %eax\n\t"
+ "call do_exit\n"
+ ".previous");
/*
* Create a kernel thread
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct pt_regs regs;
- int err;
memset(®s, 0, sizeof(regs));
regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
/* Ok, create the new process.. */
- err = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
- if (err == 0) /* terminate kernel stack */
- task_pt_regs(current)->eip = 0;
- return err;
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
}
EXPORT_SYMBOL(kernel_thread);
*/
void exit_thread(void)
{
+ struct task_struct *tsk = current;
+ struct thread_struct *t = &tsk->thread;
+
+ /*
+ * Remove function-return probe instances associated with this task
+ * and put them back on the free list. Do not insert an exit probe for
+ * this function, it will be disabled by kprobe_flush_task if you do.
+ */
+ kprobe_flush_task(tsk);
+
/* The process may have allocated an io port bitmap... nuke it. */
- if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
- struct task_struct *tsk = current;
- struct thread_struct *t = &tsk->thread;
+ if (unlikely(NULL != t->io_bitmap_ptr)) {
int cpu = get_cpu();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL;
- clear_thread_flag(TIF_IO_BITMAP);
/*
* Careful, clear this in the TSS too:
*/
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
- clear_tsk_thread_flag(tsk, TIF_DEBUG);
/*
* Forget coprocessor state..
*/
savesegment(gs,p->thread.gs);
tsk = current;
- if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
+ if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!p->thread.io_bitmap_ptr) {
p->thread.io_bitmap_max = 0;
}
memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr,
IO_BITMAP_BYTES);
- set_tsk_thread_flag(p, TIF_IO_BITMAP);
}
/*
return 1;
}
-static noinline void __switch_to_xtra(struct task_struct *next_p,
- struct tss_struct *tss)
+static inline void
+handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
{
- struct thread_struct *next;
-
- next = &next_p->thread;
-
- if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
- set_debugreg(next->debugreg[0], 0);
- set_debugreg(next->debugreg[1], 1);
- set_debugreg(next->debugreg[2], 2);
- set_debugreg(next->debugreg[3], 3);
- /* no 4 and 5 */
- set_debugreg(next->debugreg[6], 6);
- set_debugreg(next->debugreg[7], 7);
- }
-
- if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+ if (!next->io_bitmap_ptr) {
/*
* Disable the bitmap via an invalid offset. We still cache
* the previous bitmap owner and the IO bitmap contents:
tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
return;
}
-
if (likely(next == tss->io_bitmap_owner)) {
/*
* Previous owner of the bitmap (hence the bitmap content)
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
__unlazy_fpu(prev_p);
- if (next_p->mm)
- load_user_cs_desc(cpu, next_p->mm);
/*
* Reload esp0.
set_iopl_mask(next->iopl);
/*
- * Now maybe handle debug registers and/or IO bitmaps
+ * Now maybe reload the debug registers
*/
- if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)
- || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)))
- __switch_to_xtra(next_p, tss);
+ if (unlikely(next->debugreg[7])) {
+ set_debugreg(next->debugreg[0], 0);
+ set_debugreg(next->debugreg[1], 1);
+ set_debugreg(next->debugreg[2], 2);
+ set_debugreg(next->debugreg[3], 3);
+ /* no 4 and 5 */
+ set_debugreg(next->debugreg[6], 6);
+ set_debugreg(next->debugreg[7], 7);
+ }
+
+ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
+ handle_io_bitmap(next, tss);
disable_tsc(prev_p, next_p);
} while (count++ < 16);
return 0;
}
+EXPORT_SYMBOL(get_wchan);
/*
* sys_alloc_thread_area: get a yet unused TLS descriptor index.
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
-
-void arch_add_exec_range(struct mm_struct *mm, unsigned long limit)
-{
- if (limit > mm->context.exec_limit) {
- mm->context.exec_limit = limit;
- set_user_cs(&mm->context.user_cs, limit);
- if (mm == current->mm) {
- preempt_disable();
- load_user_cs_desc(smp_processor_id(), mm);
- preempt_enable();
- }
- }
-}
-
-void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end)
-{
- struct vm_area_struct *vma;
- unsigned long limit = PAGE_SIZE;
-
- if (old_end == mm->context.exec_limit) {
- for (vma = mm->mmap; vma; vma = vma->vm_next)
- if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
- limit = vma->vm_end;
-
- mm->context.exec_limit = limit;
- set_user_cs(&mm->context.user_cs, limit);
- if (mm == current->mm) {
- preempt_disable();
- load_user_cs_desc(smp_processor_id(), mm);
- preempt_enable();
- }
- }
-}
-
-void arch_flush_exec_range(struct mm_struct *mm)
-{
- mm->context.exec_limit = 0;
- set_user_cs(&mm->context.user_cs, 0);
-}
-
-/*
- * Generate random brk address between 128MB and 196MB. (if the layout
- * allows it.)
- */
-void randomize_brk(unsigned long old_brk)
-{
- unsigned long new_brk, range_start, range_end;
-
- range_start = 0x08000000;
- if (current->mm->brk >= range_start)
- range_start = current->mm->brk;
- range_end = range_start + 0x02000000;
- new_brk = randomize_range(range_start, range_end, 0);
- if (new_brk)
- current->mm->brk = new_brk;
-}
-