Add a few functions that will be used to manipulate various segment bases that are loaded via GDT. Signed-off-by: Maxim Levitsky <mlevitsk@xxxxxxxxxx> --- lib/x86/desc.c | 39 ++++++++++++++++++++++++++++++++------- lib/x86/desc.h | 5 +++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index d054899c6..52e33f201 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -338,7 +338,7 @@ bool exception_rflags_rf(void) static char intr_alt_stack[4096]; -void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) +void set_gdt_entry_base(int sel, unsigned long base) { gdt_entry_t *entry = &gdt[sel >> 3]; @@ -347,10 +347,6 @@ void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) entry->base2 = (base >> 16) & 0xFF; entry->base3 = (base >> 24) & 0xFF; - /* Setup the descriptor limits, type and flags */ - entry->limit1 = (limit & 0xFFFF); - entry->type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; - #ifdef __x86_64__ if (!entry->s) { struct system_desc64 *entry16 = (struct system_desc64 *)entry; @@ -360,6 +356,25 @@ void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) #endif } +void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) +{ + gdt_entry_t *entry = &gdt[sel >> 3]; + + /* Setup the descriptor limits, type and flags */ + entry->limit1 = (limit & 0xFFFF); + entry->type_limit_flags = ((limit & 0xF0000) >> 8) | ((flags & 0xF0) << 8) | type; + set_gdt_entry_base(sel, base); +} + +void clear_tss_busy(int sel) +{ + gdt_entry_t *entry = &gdt[sel >> 3]; + + entry->type_limit_flags &= ~0xFF; + entry->type_limit_flags |= 0x89; +} + + void load_gdt_tss(size_t tss_offset) { lgdt(&gdt_descr); @@ -483,14 +498,24 @@ void __set_exception_jmpbuf(jmp_buf *addr) exception_jmpbuf = addr; } -gdt_entry_t *get_tss_descr(void) +gdt_entry_t *get_gdt_entry(u16 sel) { struct descriptor_table_ptr gdt_ptr; gdt_entry_t *gdt; sgdt(&gdt_ptr); gdt = (gdt_entry_t *)gdt_ptr.base; - return &gdt[str() / 8]; + return &gdt[sel / 8]; +} + +gdt_entry_t *get_tss_descr(void) +{ + return get_gdt_entry(str()); +} + +gdt_entry_t *get_ldt_descr(void) +{ + return get_gdt_entry(sldt()); } unsigned long get_gdt_entry_base(gdt_entry_t *entry) diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 5349ea572..a50c8f61b 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -246,6 +246,8 @@ void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); void set_idt_dpl(int vec, u16 dpl); void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 access, u8 gran); +void set_gdt_entry_base(int sel, unsigned long base); +void clear_tss_busy(int sel); void load_gdt_tss(size_t tss_offset); void set_intr_alt_stack(int e, void *fn); void print_current_tss_info(void); @@ -268,7 +270,10 @@ static inline void *get_idt_addr(idt_entry_t *entry) return (void *)addr; } +extern gdt_entry_t *get_gdt_entry(u16 sel); extern gdt_entry_t *get_tss_descr(void); +gdt_entry_t *get_ldt_descr(void); + extern unsigned long get_gdt_entry_base(gdt_entry_t *entry); extern unsigned long get_gdt_entry_limit(gdt_entry_t *entry); -- 2.26.3