nuclear@7: #include nuclear@7: #include "segm.h" nuclear@10: #include "desc.h" nuclear@7: nuclear@8: /* bits for the 3rd 16bt part of the descriptor */ nuclear@7: #define BIT_ACCESSED (1 << 8) nuclear@7: #define BIT_WR (1 << 9) nuclear@7: #define BIT_RD (1 << 9) nuclear@7: #define BIT_EXP_DOWN (1 << 10) nuclear@7: #define BIT_CONFORMING (1 << 10) nuclear@7: #define BIT_CODE (1 << 11) nuclear@7: #define BIT_NOSYS (1 << 12) nuclear@7: #define BIT_PRESENT (1 << 15) nuclear@29: /* TSS busy bit */ nuclear@29: #define BIT_BUSY (1 << 9) nuclear@7: nuclear@8: /* bits for the last 16bit part of the descriptor */ nuclear@7: #define BIT_BIG (1 << 6) nuclear@7: #define BIT_DEFAULT (1 << 6) nuclear@7: #define BIT_GRAN (1 << 7) nuclear@7: nuclear@7: enum {TYPE_DATA, TYPE_CODE}; nuclear@7: nuclear@29: #define TSS_TYPE_BITS 0x900 nuclear@29: #define TSS_BUSY BIT_BUSY nuclear@29: nuclear@7: static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type); nuclear@29: static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, unsigned int busy); nuclear@7: nuclear@8: /* these functions are implemented in segm-asm.S */ nuclear@8: void setup_selectors(uint16_t code, uint16_t data); nuclear@8: void set_gdt(uint32_t addr, uint16_t limit); nuclear@7: nuclear@8: nuclear@8: /* our global descriptor table */ nuclear@29: static desc_t gdt[6]; nuclear@7: nuclear@7: nuclear@7: void init_segm(void) nuclear@7: { nuclear@7: memset(gdt, 0, sizeof gdt); nuclear@7: segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE); nuclear@7: segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA); nuclear@29: segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE); nuclear@29: segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA); nuclear@47: task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY); nuclear@7: nuclear@7: set_gdt((uint32_t)gdt, sizeof gdt - 1); nuclear@7: nuclear@7: setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0)); nuclear@7: } nuclear@7: nuclear@8: /* constructs a GDT selector based on index and priviledge level */ nuclear@7: uint16_t selector(int idx, int rpl) nuclear@7: { nuclear@7: return (idx << 3) | (rpl & 3); nuclear@7: } nuclear@7: nuclear@7: static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type) nuclear@7: { nuclear@7: desc->d[0] = limit & 0xffff; /* low order 16bits of limit */ nuclear@7: desc->d[1] = base & 0xffff; /* low order 16bits of base */ nuclear@7: nuclear@7: /* third 16bit part contains the last 8 bits of base, the 2 priviledge nuclear@7: * level bits starting on bit 13, present flag on bit 15, and type bits nuclear@7: * starting from bit 8 nuclear@7: */ nuclear@7: desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT | nuclear@7: BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE)); nuclear@7: nuclear@7: /* last 16bit part contains the last nibble of limit, the last byte of nuclear@7: * base, and the granularity and deafult/big flags in bits 23 and 22 resp. nuclear@7: */ nuclear@7: desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG; nuclear@7: } nuclear@29: nuclear@29: static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, unsigned int busy) nuclear@29: { nuclear@29: desc->d[0] = limit & 0xffff; nuclear@29: desc->d[1] = base & 0xffff; nuclear@29: nuclear@29: desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT | nuclear@29: TSS_TYPE_BITS | busy; nuclear@29: desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN; nuclear@29: }