diff --git a/app/idt/Makefile b/app/idt/Makefile index 9a5a02c..3d7bcf5 100644 --- a/app/idt/Makefile +++ b/app/idt/Makefile @@ -25,7 +25,7 @@ LDFLAGS += -lsgx-step -lsgx_urts \ -lsgx_uae_service -pthread $(SUBDIRS:%=-L %) -L$(SGX_SDK)/lib64/ SOURCES = $(shell ls *.c) -OBJECTS = $(SOURCES:.c=.o) +OBJECTS = $(SOURCES:.c=.o) asm.o OUTPUT = app BUILDDIRS = $(SUBDIRS:%=build-%) diff --git a/app/idt/asm.S b/app/idt/asm.S new file mode 100644 index 0000000..db693da --- /dev/null +++ b/app/idt/asm.S @@ -0,0 +1,5 @@ + .text + .global call_gate_func +call_gate_func: + call say_hi + lretq diff --git a/app/idt/main.c b/app/idt/main.c index 57876b6..6b78e83 100644 --- a/app/idt/main.c +++ b/app/idt/main.c @@ -50,6 +50,12 @@ void hello_world(uint8_t *rsp) irq_fired = 1; } +void call_gate_func(void); +void say_hi(void) +{ + info("hello world from call gate!"); +} + int main( int argc, char **argv ) { idt_t idt = {0}; @@ -66,6 +72,12 @@ int main( int argc, char **argv ) #endif dump_gdt(&gdt); + info_event("Installing call gate @%p", call_gate_func); + install_user_call_gate(&gdt, call_gate_func, GDT_VECTOR); + dump_gate(get_gate_desc(&gdt, GDT_VECTOR), GDT_VECTOR); + do_far_user_call(GDT_VECTOR); + info("back from call gate!"); + info_event("Establishing user space IDT mapping"); map_idt(&idt); install_user_irq_handler(&idt, hello_world, IRQ_VECTOR); diff --git a/libsgxstep/config.h b/libsgxstep/config.h index 7214a8f..5858f7c 100644 --- a/libsgxstep/config.h +++ b/libsgxstep/config.h @@ -25,6 +25,7 @@ #define SINGLE_STEP_ENABLE 1 #define USER_IDT_ENABLE 1 #define IRQ_VECTOR 45 +#define GDT_VECTOR 13 #if (M32 != 1) #define APIC_CONFIG_MSR 1 #else diff --git a/libsgxstep/desc.h b/libsgxstep/desc.h index f4817f1..c9b6e88 100644 --- a/libsgxstep/desc.h +++ b/libsgxstep/desc.h @@ -23,6 +23,35 @@ #include +/* IA-64: 16-byte gate (from Linux kernel arch/x86/include/asm/desc_defs.h) */ +typedef struct { + uint16_t offset_low; + uint16_t segment; + unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; + uint16_t offset_middle; + uint32_t offset_high; + uint32_t zero1; +} __attribute__((packed)) gate_desc_t; + +enum { + GATE_INTERRUPT = 0xE, + GATE_TRAP = 0xF, + GATE_CALL = 0xC, + GATE_TASK = 0x5, +}; + +typedef struct { + uint32_t offset; + uint16_t segment; +} __attribute__((packed)) call_gate_pt_t; + +#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF) +#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF) +#define PTR_HIGH(x) ((unsigned long long)(x) >> 32) + +#define gate_offset(g) ((g)->offset_low | ((unsigned long)(g)->offset_middle << 16) | ((unsigned long)(g)->offset_high << 32)) +#define gate_ptr(base, idx) ((gate_desc_t*) (((void*) base) + idx*sizeof(gate_desc_t))) + /* * From Linux kernel arch/x86/include/asm/segment.h * arch/x86/include/asm/desc_defs.h diff --git a/libsgxstep/gdt.c b/libsgxstep/gdt.c index 4255335..c5b4ac5 100644 --- a/libsgxstep/gdt.c +++ b/libsgxstep/gdt.c @@ -44,3 +44,35 @@ desc_t *get_desc(gdt_t *gdt, int idx) return desc_ptr(gdt->base, idx); } + +gate_desc_t *get_gate_desc(gdt_t *gdt, int idx) +{ + /* System descriptors are expanded to 16 bytes (occupying the space of two entries). */ + ASSERT(idx >= 0 && idx < (gdt->entries-1)); + + return (gate_desc_t*) (desc_ptr(gdt->base, idx)); +} + +void install_user_call_gate(gdt_t *gdt, call_gate_cb_t handler, int vector) +{ + ASSERT(vector >= 0 && vector < (gdt->entries-1)); + ASSERT( !get_desc(gdt, vector)->p && !get_desc(gdt, vector+1)->p ); + + gate_desc_t *g = get_gate_desc(gdt, vector); + g->offset_low = PTR_LOW(handler); + g->offset_middle = PTR_MIDDLE(handler); + g->offset_high = PTR_HIGH(handler); + g->p = 1; + g->segment = USER_CS; + g->dpl = USER_DPL; + g->type = GATE_CALL; + g->ist = 0; +} + +void do_far_user_call(int gdt_idx) +{ + call_gate_pt_t p = { + .segment = (gdt_idx*8+USER_DPL) + }; + asm("lcall *%0\n\t"::"m"(p):); +} diff --git a/libsgxstep/gdt.h b/libsgxstep/gdt.h index f920193..9910066 100644 --- a/libsgxstep/gdt.h +++ b/libsgxstep/gdt.h @@ -44,10 +44,15 @@ typedef struct { size_t entries; } gdt_t; +typedef void (*call_gate_cb_t)(void); + void map_gdt(gdt_t *gdt); void dump_gdt(gdt_t *gdt); void dump_desc(desc_t *desc, int idx); +void install_user_call_gate(gdt_t *gdt, call_gate_cb_t handler, int vector); +void do_far_user_call(int call_gate_idx); desc_t *get_desc(gdt_t *gdt, int idx); +gate_desc_t *get_gate_desc(gdt_t *gdt, int idx); #endif diff --git a/libsgxstep/idt.c b/libsgxstep/idt.c index 1e8cdda..7f78782 100644 --- a/libsgxstep/idt.c +++ b/libsgxstep/idt.c @@ -7,7 +7,7 @@ extern void sgx_step_irq_entry(void); irq_cb_t sgx_step_irq_cb_table[256] = {0}; uint8_t sgx_step_vector_hack = 0; -void dump_gate(idt_gate_t *gate, int idx) +void dump_gate(gate_desc_t *gate, int idx) { info("IDT[%3d] @%p = %p (seg sel 0x%x); p=%d; dpl=%d; type=%02d; ist=%d", idx, gate, (void*) gate_offset(gate), gate->segment, gate->p, gate->dpl, gate->type, gate->ist); @@ -31,7 +31,7 @@ void map_idt(idt_t *idt) asm volatile ("sidt %0\n\t" :"=m"(idtr) :: ); - entries = (idtr.size+1)/sizeof(idt_gate_t); + entries = (idtr.size+1)/sizeof(gate_desc_t); dump_dtr(&idtr, entries); ASSERT( idtr.base ); @@ -39,7 +39,7 @@ void map_idt(idt_t *idt) libsgxstep_info("established user space IDT mapping at %p", idt_base); ASSERT(idt_base); - idt->base = (idt_gate_t*) idt_base; + idt->base = (gate_desc_t*) idt_base; idt->entries = entries; } @@ -55,7 +55,7 @@ void install_user_irq_handler(idt_t *idt, irq_cb_t handler, int vector) { ASSERT(vector >= 0 && vector < idt->entries); - idt_gate_t *gate = gate_ptr(idt->base, vector); + gate_desc_t *gate = gate_ptr(idt->base, vector); gate->offset_low = PTR_LOW(sgx_step_irq_entry); gate->offset_middle = PTR_MIDDLE(sgx_step_irq_entry); gate->offset_high = PTR_HIGH(sgx_step_irq_entry); diff --git a/libsgxstep/idt.h b/libsgxstep/idt.h index a0ac2fc..ebe5b82 100644 --- a/libsgxstep/idt.h +++ b/libsgxstep/idt.h @@ -24,32 +24,8 @@ #include "desc.h" #include "debug.h" -/* IA-64: 16-byte gate (from Linux kernel arch/x86/include/asm/desc_defs.h) */ typedef struct { - uint16_t offset_low; - uint16_t segment; - unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; - uint16_t offset_middle; - uint32_t offset_high; - uint32_t zero1; -} __attribute__((packed)) idt_gate_t; - -enum { - GATE_INTERRUPT = 0xE, - GATE_TRAP = 0xF, - GATE_CALL = 0xC, - GATE_TASK = 0x5, -}; - -#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF) -#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF) -#define PTR_HIGH(x) ((unsigned long long)(x) >> 32) - -#define gate_offset(g) ((g)->offset_low | ((unsigned long)(g)->offset_middle << 16) | ((unsigned long)(g)->offset_high << 32)) -#define gate_ptr(idt_base, idx) ((idt_gate_t*) (((void*) idt_base) + idx*sizeof(idt_gate_t))) - -typedef struct { - idt_gate_t *base; + gate_desc_t *base; size_t entries; } idt_t; @@ -57,7 +33,7 @@ typedef void (*irq_cb_t)(uint8_t *rsp); void map_idt(idt_t *idt); void dump_idt(idt_t *idt); -void dump_gate(idt_gate_t *gate, int idx); +void dump_gate(gate_desc_t *gate, int idx); void install_user_irq_handler(idt_t *idt, irq_cb_t handler, int vector);