diff --git a/config-x86-common.mak b/config-x86-common.mak
index c5508b3..2269c4a 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -11,6 +11,7 @@ cflatobjs += \
 cflatobjs += lib/x86/fwcfg.o
 cflatobjs += lib/x86/apic.o
 cflatobjs += lib/x86/atomic.o
+cflatobjs += lib/x86/idt.o
 
 $(libcflat): LDFLAGS += -nostdlib
 $(libcflat): CFLAGS += -ffreestanding -I lib
@@ -50,7 +51,7 @@ $(TEST_DIR)/vmexit.elf: $(cstart.o) $(TEST_DIR)/vmexit.o
 $(TEST_DIR)/smptest.elf: $(cstart.o) $(TEST_DIR)/smptest.o
 
 $(TEST_DIR)/emulator.elf: $(cstart.o) $(TEST_DIR)/emulator.o \
-			   $(TEST_DIR)/vm.o $(TEST_DIR)/idt.o
+			   $(TEST_DIR)/vm.o
 
 $(TEST_DIR)/port80.elf: $(cstart.o) $(TEST_DIR)/port80.o
 
@@ -65,9 +66,9 @@ $(TEST_DIR)/realmode.o: bits = 32
 
 $(TEST_DIR)/msr.elf: $(cstart.o) $(TEST_DIR)/msr.o
 
-$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/idt_test.o
+$(TEST_DIR)/idt_test.elf: $(cstart.o) $(TEST_DIR)/idt_test.o
 
-$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/idt.o $(TEST_DIR)/xsave.o
+$(TEST_DIR)/xsave.elf: $(cstart.o) $(TEST_DIR)/xsave.o
 
 $(TEST_DIR)/rmap_chain.elf: $(cstart.o) $(TEST_DIR)/rmap_chain.o \
 			     $(TEST_DIR)/vm.o
diff --git a/lib/x86/idt.c b/lib/x86/idt.c
index ed2f4b0..b3e47d4 100644
--- a/lib/x86/idt.c
+++ b/lib/x86/idt.c
@@ -1,5 +1,6 @@
 #include "idt.h"
 #include "libcflat.h"
+#include "processor.h"
 
 typedef struct {
     unsigned short offset0;
@@ -19,30 +20,19 @@ typedef struct {
 
 static idt_entry_t idt[256];
 
-typedef struct {
-    unsigned short limit;
-    unsigned long linear_addr;
-} __attribute__((packed)) descriptor_table_t;
-
-void lidt(idt_entry_t *idt, int nentries)
+void load_lidt(idt_entry_t *idt, int nentries)
 {
-    descriptor_table_t dt;
+    struct descriptor_table_ptr dt;
 
     dt.limit = nentries * sizeof(*idt) - 1;
-    dt.linear_addr = (unsigned long)idt;
+    dt.base = (unsigned long)idt;
+    lidt(&dt);
     asm volatile ("lidt %0" : : "m"(dt));
 }
 
-unsigned short read_cs()
-{
-    unsigned short r;
-
-    asm volatile ("mov %%cs, %0" : "=r"(r));
-    return r;
-}
-
-void set_idt_entry(idt_entry_t *e, void *addr, int dpl)
+void set_idt_entry(int vec, void *addr, int dpl)
 {
+    idt_entry_t *e = &idt[vec];
     memset(e, 0, sizeof *e);
     e->offset0 = (unsigned long)addr;
     e->selector = read_cs();
@@ -146,10 +136,10 @@ void setup_idt(void)
 {
     extern char ud_fault, gp_fault, de_fault;
 
-    lidt(idt, 256);
-    set_idt_entry(&idt[0], &de_fault, 0);
-    set_idt_entry(&idt[6], &ud_fault, 0);
-    set_idt_entry(&idt[13], &gp_fault, 0);
+    load_lidt(idt, 256);
+    set_idt_entry(0, &de_fault, 0);
+    set_idt_entry(6, &ud_fault, 0);
+    set_idt_entry(13, &gp_fault, 0);
 }
 
 unsigned exception_vector(void)
diff --git a/lib/x86/idt.h b/lib/x86/idt.h
index 6babcb4..81b8944 100644
--- a/lib/x86/idt.h
+++ b/lib/x86/idt.h
@@ -15,5 +15,6 @@ void setup_idt(void);
 
 unsigned exception_vector(void);
 unsigned exception_error_code(void);
+void set_idt_entry(int vec, void *addr, int dpl);
 
 #endif
diff --git a/x86/idt.c b/x86/idt.c
deleted file mode 100644
index 4480833..0000000
--- a/x86/idt.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "idt.h"
-#include "libcflat.h"
-
-typedef struct {
-    unsigned short offset0;
-    unsigned short selector;
-    unsigned short ist : 3;
-    unsigned short : 5;
-    unsigned short type : 4;
-    unsigned short : 1;
-    unsigned short dpl : 2;
-    unsigned short p : 1;
-    unsigned short offset1;
-    unsigned offset2;
-    unsigned reserved;
-} idt_entry_t;
-
-static idt_entry_t idt[256];
-
-typedef struct {
-    unsigned short limit;
-    unsigned long linear_addr;
-} __attribute__((packed)) descriptor_table_t;
-
-void lidt(idt_entry_t *idt, int nentries)
-{
-    descriptor_table_t dt;
-
-    dt.limit = nentries * sizeof(*idt) - 1;
-    dt.linear_addr = (unsigned long)idt;
-    asm volatile ("lidt %0" : : "m"(dt));
-}
-
-unsigned short read_cs()
-{
-    unsigned short r;
-
-    asm volatile ("mov %%cs, %0" : "=r"(r));
-    return r;
-}
-
-void set_idt_entry(idt_entry_t *e, void *addr, int dpl)
-{
-    memset(e, 0, sizeof *e);
-    e->offset0 = (unsigned long)addr;
-    e->selector = read_cs();
-    e->ist = 0;
-    e->type = 14;
-    e->dpl = dpl;
-    e->p = 1;
-    e->offset1 = (unsigned long)addr >> 16;
-    e->offset2 = (unsigned long)addr >> 32;
-}
-
-struct ex_regs {
-    unsigned long rax, rcx, rdx, rbx;
-    unsigned long dummy, rbp, rsi, rdi;
-    unsigned long r8, r9, r10, r11;
-    unsigned long r12, r13, r14, r15;
-    unsigned long vector;
-    unsigned long error_code;
-    unsigned long rip;
-    unsigned long cs;
-    unsigned long rflags;
-};
-
-struct ex_record {
-    unsigned long rip;
-    unsigned long handler;
-};
-
-extern struct ex_record exception_table_start, exception_table_end;
-
-void do_handle_exception(struct ex_regs *regs)
-{
-    struct ex_record *ex;
-    unsigned ex_val;
-
-    ex_val = regs->vector | (regs->error_code << 16);
-
-    asm("mov %0, %%gs:4" : : "r"(ex_val));
-
-    for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
-        if (ex->rip == regs->rip) {
-            regs->rip = ex->handler;
-            return;
-        }
-    }
-    printf("unhandled excecption\n");
-    exit(7);
-}
-
-asm (".pushsection .text \n\t"
-     "ud_fault: \n\t"
-     "pushq $0 \n\t"
-     "pushq $6 \n\t"
-     "jmp handle_exception \n\t"
-
-     "gp_fault: \n\t"
-     "pushq $13 \n\t"
-     "jmp handle_exception \n\t"
-
-     "de_fault: \n\t"
-     "pushq $0 \n\t"
-     "pushq $0 \n\t"
-     "jmp handle_exception \n\t"
-
-     "handle_exception: \n\t"
-     "push %r15; push %r14; push %r13; push %r12 \n\t"
-     "push %r11; push %r10; push %r9; push %r8 \n\t"
-     "push %rdi; push %rsi; push %rbp; sub $8, %rsp \n\t"
-     "push %rbx; push %rdx; push %rcx; push %rax \n\t"
-     "mov %rsp, %rdi \n\t"
-     "call do_handle_exception \n\t"
-     "pop %rax; pop %rcx; pop %rdx; pop %rbx \n\t"
-     "add $8, %rsp; pop %rbp; pop %rsi; pop %rdi \n\t"
-     "pop %r8; pop %r9; pop %r10; pop %r11 \n\t"
-     "pop %r12; pop %r13; pop %r14; pop %r15 \n\t"
-     "add $16, %rsp \n\t"
-     "iretq \n\t"
-     ".popsection");
-
-
-void setup_idt(void)
-{
-    extern char ud_fault, gp_fault, de_fault;
-
-    lidt(idt, 256);
-    set_idt_entry(&idt[0], &de_fault, 0);
-    set_idt_entry(&idt[6], &ud_fault, 0);
-    set_idt_entry(&idt[13], &gp_fault, 0);
-}
-
-unsigned exception_vector(void)
-{
-    unsigned short vector;
-
-    asm("mov %%gs:4, %0" : "=rm"(vector));
-    return vector;
-}
-
-unsigned exception_error_code(void)
-{
-    unsigned short error_code;
-
-    asm("mov %%gs:6, %0" : "=rm"(error_code));
-    return error_code;
-}
