kern

annotate src/segm.c @ 49:50730d42d2d3

fuck yeah, now do priviledge levels and TSS
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 30 Jul 2011 07:21:54 +0300
parents 8ea6debe4265
children 4eaecb14fe31
rev   line source
nuclear@7 1 #include <string.h>
nuclear@7 2 #include "segm.h"
nuclear@10 3 #include "desc.h"
nuclear@7 4
nuclear@8 5 /* bits for the 3rd 16bt part of the descriptor */
nuclear@7 6 #define BIT_ACCESSED (1 << 8)
nuclear@7 7 #define BIT_WR (1 << 9)
nuclear@7 8 #define BIT_RD (1 << 9)
nuclear@7 9 #define BIT_EXP_DOWN (1 << 10)
nuclear@7 10 #define BIT_CONFORMING (1 << 10)
nuclear@7 11 #define BIT_CODE (1 << 11)
nuclear@7 12 #define BIT_NOSYS (1 << 12)
nuclear@7 13 #define BIT_PRESENT (1 << 15)
nuclear@29 14 /* TSS busy bit */
nuclear@29 15 #define BIT_BUSY (1 << 9)
nuclear@7 16
nuclear@8 17 /* bits for the last 16bit part of the descriptor */
nuclear@7 18 #define BIT_BIG (1 << 6)
nuclear@7 19 #define BIT_DEFAULT (1 << 6)
nuclear@7 20 #define BIT_GRAN (1 << 7)
nuclear@7 21
nuclear@7 22 enum {TYPE_DATA, TYPE_CODE};
nuclear@7 23
nuclear@29 24 #define TSS_TYPE_BITS 0x900
nuclear@29 25 #define TSS_BUSY BIT_BUSY
nuclear@29 26
nuclear@7 27 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
nuclear@29 28 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, unsigned int busy);
nuclear@7 29
nuclear@8 30 /* these functions are implemented in segm-asm.S */
nuclear@8 31 void setup_selectors(uint16_t code, uint16_t data);
nuclear@8 32 void set_gdt(uint32_t addr, uint16_t limit);
nuclear@7 33
nuclear@8 34
nuclear@8 35 /* our global descriptor table */
nuclear@29 36 static desc_t gdt[6];
nuclear@7 37
nuclear@7 38
nuclear@7 39 void init_segm(void)
nuclear@7 40 {
nuclear@7 41 memset(gdt, 0, sizeof gdt);
nuclear@7 42 segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE);
nuclear@7 43 segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA);
nuclear@29 44 segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE);
nuclear@29 45 segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA);
nuclear@47 46 task_desc(gdt + SEGM_TASK, 0, 0xffffffff, 3, TSS_BUSY);
nuclear@7 47
nuclear@7 48 set_gdt((uint32_t)gdt, sizeof gdt - 1);
nuclear@7 49
nuclear@7 50 setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0));
nuclear@7 51 }
nuclear@7 52
nuclear@8 53 /* constructs a GDT selector based on index and priviledge level */
nuclear@7 54 uint16_t selector(int idx, int rpl)
nuclear@7 55 {
nuclear@7 56 return (idx << 3) | (rpl & 3);
nuclear@7 57 }
nuclear@7 58
nuclear@7 59 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type)
nuclear@7 60 {
nuclear@7 61 desc->d[0] = limit & 0xffff; /* low order 16bits of limit */
nuclear@7 62 desc->d[1] = base & 0xffff; /* low order 16bits of base */
nuclear@7 63
nuclear@7 64 /* third 16bit part contains the last 8 bits of base, the 2 priviledge
nuclear@7 65 * level bits starting on bit 13, present flag on bit 15, and type bits
nuclear@7 66 * starting from bit 8
nuclear@7 67 */
nuclear@7 68 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
nuclear@7 69 BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE));
nuclear@7 70
nuclear@7 71 /* last 16bit part contains the last nibble of limit, the last byte of
nuclear@7 72 * base, and the granularity and deafult/big flags in bits 23 and 22 resp.
nuclear@7 73 */
nuclear@7 74 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG;
nuclear@7 75 }
nuclear@29 76
nuclear@29 77 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, unsigned int busy)
nuclear@29 78 {
nuclear@29 79 desc->d[0] = limit & 0xffff;
nuclear@29 80 desc->d[1] = base & 0xffff;
nuclear@29 81
nuclear@29 82 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
nuclear@29 83 TSS_TYPE_BITS | busy;
nuclear@29 84 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN;
nuclear@29 85 }