summaryrefslogtreecommitdiff
path: root/kernel/x86/preempt.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/x86/preempt.c')
-rw-r--r--kernel/x86/preempt.c262
1 files changed, 0 insertions, 262 deletions
diff --git a/kernel/x86/preempt.c b/kernel/x86/preempt.c
deleted file mode 100644
index e59e3636..00000000
--- a/kernel/x86/preempt.c
+++ /dev/null
@@ -1,262 +0,0 @@
-
-#ifdef CONFIG_PREEMPT_NOTIFIERS_COMPAT
-
-#include <linux/sched.h>
-#include <linux/percpu.h>
-#include <linux/kvm.h>
-
-static DEFINE_SPINLOCK(pn_lock);
-static LIST_HEAD(pn_list);
-
-#define dprintk(fmt) do { \
- if (0) \
- printk("%s (%d/%d): " fmt, __FUNCTION__, \
- current->pid, raw_smp_processor_id()); \
- } while (0)
-
-#if !defined(CONFIG_X86_64) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
-#define debugreg(x) debugreg[x]
-#else
-#define debugreg(x) debugreg##x
-#endif
-
-static void preempt_enable_sched_out_notifiers(void)
-{
- asm volatile ("mov %0, %%db0" : : "r"(schedule));
- asm volatile ("mov %0, %%db7" : : "r"(0x701ul));
- current->thread.debugreg(7) = 0ul;
-#ifdef TIF_DEBUG
- clear_tsk_thread_flag(current, TIF_DEBUG);
-#endif
-}
-
-static void preempt_enable_sched_in_notifiers(void * addr)
-{
- asm volatile ("mov %0, %%db0" : : "r"(addr));
- asm volatile ("mov %0, %%db7" : : "r"(0x701ul));
- current->thread.debugreg(0) = (unsigned long) addr;
- current->thread.debugreg(7) = 0x701ul;
-#ifdef TIF_DEBUG
- set_tsk_thread_flag(current, TIF_DEBUG);
-#endif
-}
-
-void special_reload_dr7(void)
-{
-#ifndef KVM_CAP_SET_GUEST_DEBUG
- asm volatile ("mov %0, %%db7" : : "r"(0x701ul));
-#endif
-}
-EXPORT_SYMBOL_GPL(special_reload_dr7);
-
-static void __preempt_disable_notifiers(void)
-{
- asm volatile ("mov %0, %%db7" : : "r"(0ul));
-}
-
-static void preempt_disable_notifiers(void)
-{
- __preempt_disable_notifiers();
- current->thread.debugreg(7) = 0ul;
-#ifdef TIF_DEBUG
- clear_tsk_thread_flag(current, TIF_DEBUG);
-#endif
-}
-
-static void fastcall __attribute__((used)) preempt_notifier_trigger(void *** ip)
-{
- struct preempt_notifier *pn;
- int cpu = raw_smp_processor_id();
- int found = 0;
-
- dprintk(" - in\n");
- //dump_stack();
- spin_lock(&pn_lock);
- list_for_each_entry(pn, &pn_list, link)
- if (pn->tsk == current) {
- found = 1;
- break;
- }
- spin_unlock(&pn_lock);
-
- if (found) {
- if ((void *) *ip != schedule) {
- dprintk("sched_in\n");
- preempt_enable_sched_out_notifiers();
-
- preempt_disable();
- local_irq_enable();
- pn->ops->sched_in(pn, cpu);
- local_irq_disable();
- preempt_enable_no_resched();
- } else {
- void * sched_in_addr;
- dprintk("sched_out\n");
-#ifdef CONFIG_X86_64
- sched_in_addr = **(ip+3);
-#else
- /* no special debug stack switch on x86 */
- sched_in_addr = (void *) *(ip+3);
-#endif
- preempt_enable_sched_in_notifiers(sched_in_addr);
-
- preempt_disable();
- local_irq_enable();
- pn->ops->sched_out(pn, NULL);
- local_irq_disable();
- preempt_enable_no_resched();
- }
- } else
- __preempt_disable_notifiers();
- dprintk(" - out\n");
-}
-
-unsigned long orig_int1_handler;
-
-#ifdef CONFIG_X86_64
-
-#define SAVE_REGS \
- "push %rax; push %rbx; push %rcx; push %rdx; " \
- "push %rsi; push %rdi; push %rbp; " \
- "push %r8; push %r9; push %r10; push %r11; " \
- "push %r12; push %r13; push %r14; push %r15"
-
-#define RESTORE_REGS \
- "pop %r15; pop %r14; pop %r13; pop %r12; " \
- "pop %r11; pop %r10; pop %r9; pop %r8; " \
- "pop %rbp; pop %rdi; pop %rsi; " \
- "pop %rdx; pop %rcx; pop %rbx; pop %rax "
-
-#define TMP "%rax"
-
-#else
-
-#define SAVE_REGS "pusha"
-#define RESTORE_REGS "popa"
-#define TMP "%eax"
-
-#endif
-
-asm ("pn_int1_handler: \n\t"
- "push " TMP " \n\t"
- "mov %db7, " TMP " \n\t"
- "cmp $0x701, " TMP " \n\t"
- "pop " TMP " \n\t"
- "jnz .Lnotme \n\t"
- "push " TMP " \n\t"
- "mov %db6, " TMP " \n\t"
- "test $0x1, " TMP " \n\t"
- "pop " TMP " \n\t"
- "jz .Lnotme \n\t"
- SAVE_REGS "\n\t"
-#ifdef CONFIG_X86_64
- "leaq 120(%rsp),%rdi\n\t"
-#else
- "leal 32(%esp),%eax\n\t"
-#endif
- "call preempt_notifier_trigger \n\t"
- RESTORE_REGS "\n\t"
-#ifdef CONFIG_X86_64
- "orq $0x10000, 16(%rsp) \n\t"
- "iretq \n\t"
-#else
- "orl $0x10000, 8(%esp) \n\t"
- "iret \n\t"
-#endif
- ".Lnotme: \n\t"
-#ifdef CONFIG_X86_64
- "jmpq *orig_int1_handler\n\t"
-#else
- "jmpl *orig_int1_handler\n\t"
-#endif
- );
-
-void preempt_notifier_register(struct preempt_notifier *notifier)
-{
- unsigned long flags;
-
- dprintk(" - in\n");
- spin_lock_irqsave(&pn_lock, flags);
- preempt_enable_sched_out_notifiers();
- notifier->tsk = current;
- list_add(&notifier->link, &pn_list);
- spin_unlock_irqrestore(&pn_lock, flags);
- dprintk(" - out\n");
-}
-
-void preempt_notifier_unregister(struct preempt_notifier *notifier)
-{
- unsigned long flags;
-
- dprintk(" - in\n");
- spin_lock_irqsave(&pn_lock, flags);
- list_del(&notifier->link);
- spin_unlock_irqrestore(&pn_lock, flags);
- preempt_disable_notifiers();
- dprintk(" - out\n");
-}
-
-struct intr_gate {
- u16 offset0;
- u16 segment;
- u16 junk;
- u16 offset1;
-#ifdef CONFIG_X86_64
- u32 offset2;
- u32 blah;
-#endif
-} __attribute__((packed));
-
-struct idt_desc {
- u16 limit;
- struct intr_gate *gates;
-} __attribute__((packed));
-
-static struct intr_gate orig_int1_gate;
-
-void pn_int1_handler(void);
-
-void preempt_notifier_sys_init(void)
-{
- struct idt_desc idt_desc;
- struct intr_gate *int1_gate;
-
- printk("kvm: emulating preempt notifiers;"
- " do not benchmark on this machine\n");
- dprintk("\n");
- asm ("sidt %0" : "=m"(idt_desc));
- int1_gate = &idt_desc.gates[1];
- orig_int1_gate = *int1_gate;
- orig_int1_handler = int1_gate->offset0
- | ((u32)int1_gate->offset1 << 16);
-#ifdef CONFIG_X86_64
- orig_int1_handler |= (u64)int1_gate->offset2 << 32;
-#endif
- int1_gate->offset0 = (unsigned long)pn_int1_handler;
- int1_gate->offset1 = (unsigned long)pn_int1_handler >> 16;
-#ifdef CONFIG_X86_64
- int1_gate->offset2 = (unsigned long)pn_int1_handler >> 32;
-#endif
-}
-
-static void do_disable(void *blah)
-{
-#ifdef TIF_DEBUG
- if (!test_tsk_thread_flag(current, TIF_DEBUG))
-#else
- if (!current->thread.debugreg(7))
-#endif
- __preempt_disable_notifiers();
-}
-
-void preempt_notifier_sys_exit(void)
-{
- struct idt_desc idt_desc;
-
- dprintk("\n");
- kvm_on_each_cpu(do_disable, NULL, 1);
- asm ("sidt %0" : "=m"(idt_desc));
- idt_desc.gates[1] = orig_int1_gate;
-}
-
-#endif