// http://wiki.osdev.org/GDT_Tutorial #include "kernel/kernel.h" #include "kernel/gdt.h" #include #define GDT_SIZE 6 //https://wiki.osdev.org/Task_State_Segment tss_struct sys_tss[SMP_MAX_PROC]; //Define the TSS as a global structure void install_tss(uint32_t cpu,uint32_t esp0){ // now fill each value // set values necessary sys_tss[cpu].ss0 = 0x10; //kernel data sys_tss[cpu].esp0 = esp0; // now set the IO bitmap (not necessary, so set above limit) // sys_tss.iomap = ( unsigned short ) sizeof( tss_struct ); } typedef struct GDT_struct { uint32_t base; uint32_t limit; uint32_t type; }GDT; //alternative struct gdt_entry_bits { unsigned int limit_low:16; unsigned int base_low : 24; //attribute byte split into bitfields unsigned int accessed :1; unsigned int read_write :1; //readable for code, writable for data unsigned int conforming_expand_down :1; //conforming for code, expand down for data unsigned int code :1; //1 for code, 0 for data unsigned int always_1 :1; //should be 1 for everything but TSS and LDT unsigned int DPL :2; //priveledge level unsigned int present :1; //and now into granularity unsigned int limit_high :4; unsigned int available :1; unsigned int always_0 :1; //should always be 0 unsigned int big :1; //32bit opcodes for code, uint32_t stack for data unsigned int gran :1; //1 to use 4k page addressing, 0 for byte addressing unsigned int base_high :8; } __packed; //or __attribute__((packed)) /** * \param target A pointer to the 8-byte GDT entry * \param source An arbitrary structure describing the GDT entry */ void encodeGdtEntry(uint8_t *target, GDT source) { // Check the limit to make sure that it can be encoded if ((source.limit > 65536) && (source.limit & 0xFFF) != 0xFFF) { kpanic("trying to set an invalid GDT source.limit!"); } if (source.limit > 65536) { // Adjust granularity if required source.limit = source.limit >> 12; target[6] = 0xC0; } else { target[6] = 0x40; } // Encode the limit target[0] = source.limit & 0xFF; target[1] = (source.limit >> 8) & 0xFF; // Encode the base target[2] = source.base & 0xFF; target[3] = (source.base >> 8) & 0xFF; target[4] = (source.base >> 16) & 0xFF; target[7] = (source.base >> 24) & 0xFF; target[5] = source.type; target[6] |= (source.limit >> 16) & 0xF; // And... Type /* 0 1 dw 0xffff ;limit 2 3 dw 0x0 ;base 4 db 0x0 ;base 5 db 10011010b ;flags 6 db 11001111b ;flags & seg.limit 7 db 0x0 ;base */ } void gdt_init() { static int last_cpu=0; /* Pr=1 Privl 1 Exec DC RW Ac 0x9A == 1001 1010 == 1 00 1 1 0 1 0 0x92 == 1001 0010 == 1 00 1 0 0 1 0 0xFA == 1111 1010 == 1 11 1 1 0 1 0 0xF2 == 1111 0010 == 1 11 1 0 0 1 0 */ //static uint8_t gdt_struct[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE uint8_t *gdt_struct=kballoc(1); //[GDT_SIZE*8]; // GLOBAL DESCRIPTOR TABLE GDT myGDT[GDT_SIZE]; //selector 0x0 myGDT[0].base=0; myGDT[0].limit=0; myGDT[0].type=0; //selector 0x8 code myGDT[1].base=0; myGDT[1].limit=0xffffffff; myGDT[1].type=0x9a; //selector 0x10 data myGDT[2].base=0; myGDT[2].limit=0xffffffff; myGDT[2].type=0x92; //selector 0x18 code user myGDT[3].base=0; myGDT[3].limit=0xffffffff; myGDT[3].type=0xFa; //selector 0x20 data user myGDT[4].base=0; myGDT[4].limit=0xffffffff; myGDT[4].type=0xF2; //TSS 0x28 myGDT[5].base=&sys_tss[last_cpu]; //tss start myGDT[5].limit=sizeof(tss_struct); //tss end myGDT[5].type=0x89; // transcript to format the processor wants for(int i=0;i