@@ -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
new file mode 100644
@@ -0,0 +1,159 @@
+#include "idt.h"
+#include "libcflat.h"
+#include "processor.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;
+#ifdef __x86_64__
+ unsigned offset2;
+ unsigned reserved;
+#endif
+} idt_entry_t;
+
+static idt_entry_t idt[256];
+
+void load_lidt(idt_entry_t *idt, int nentries)
+{
+ struct descriptor_table_ptr dt;
+
+ dt.limit = nentries * sizeof(*idt) - 1;
+ dt.base = (unsigned long)idt;
+ lidt(&dt);
+ asm volatile ("lidt %0" : : "m"(dt));
+}
+
+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();
+ e->ist = 0;
+ e->type = 14;
+ e->dpl = dpl;
+ e->p = 1;
+ e->offset1 = (unsigned long)addr >> 16;
+#ifdef __x86_64__
+ e->offset2 = (unsigned long)addr >> 32;
+#endif
+}
+
+struct ex_regs {
+ unsigned long rax, rcx, rdx, rbx;
+ unsigned long dummy, rbp, rsi, rdi;
+#ifdef __x86_64__
+ unsigned long r8, r9, r10, r11;
+ unsigned long r12, r13, r14, r15;
+#endif
+ 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);
+}
+
+#ifdef __x86_64__
+# define R "r"
+# define W "q"
+# define S "8"
+#else
+# define R "e"
+# define W "l"
+# define S "4"
+#endif
+
+asm (".pushsection .text \n\t"
+ "ud_fault: \n\t"
+ "push"W" $0 \n\t"
+ "push"W" $6 \n\t"
+ "jmp handle_exception \n\t"
+
+ "gp_fault: \n\t"
+ "push"W" $13 \n\t"
+ "jmp handle_exception \n\t"
+
+ "de_fault: \n\t"
+ "push"W" $0 \n\t"
+ "push"W" $0 \n\t"
+ "jmp handle_exception \n\t"
+
+ "handle_exception: \n\t"
+#ifdef __x86_64__
+ "push %r15; push %r14; push %r13; push %r12 \n\t"
+ "push %r11; push %r10; push %r9; push %r8 \n\t"
+#endif
+ "push %"R"di; push %"R"si; push %"R"bp; sub $"S", %"R"sp \n\t"
+ "push %"R"bx; push %"R"dx; push %"R"cx; push %"R"ax \n\t"
+ "mov %"R"sp, %"R"di \n\t"
+ "call do_handle_exception \n\t"
+ "pop %"R"ax; pop %"R"cx; pop %"R"dx; pop %"R"bx \n\t"
+ "add $"S", %"R"sp; pop %"R"bp; pop %"R"si; pop %"R"di \n\t"
+#ifdef __x86_64__
+ "pop %r8; pop %r9; pop %r10; pop %r11 \n\t"
+ "pop %r12; pop %r13; pop %r14; pop %r15 \n\t"
+#endif
+ "add $"S", %"R"sp \n\t"
+ "add $"S", %"R"sp \n\t"
+ "iret"W" \n\t"
+ ".popsection");
+
+
+void setup_idt(void)
+{
+ extern char ud_fault, gp_fault, de_fault;
+
+ 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)
+{
+ 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;
+}
@@ -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
deleted file mode 100644
@@ -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;
-}