kern
diff src/segm.c @ 7:611b2d66420b
segment descriptors
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 16 Feb 2011 07:26:03 +0200 |
parents | |
children | 78d5c304ddd0 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/segm.c Wed Feb 16 07:26:03 2011 +0200 1.3 @@ -0,0 +1,57 @@ 1.4 +#include <string.h> 1.5 +#include "segm.h" 1.6 + 1.7 +#define BIT_ACCESSED (1 << 8) 1.8 +#define BIT_WR (1 << 9) 1.9 +#define BIT_RD (1 << 9) 1.10 +#define BIT_EXP_DOWN (1 << 10) 1.11 +#define BIT_CONFORMING (1 << 10) 1.12 +#define BIT_CODE (1 << 11) 1.13 +#define BIT_NOSYS (1 << 12) 1.14 +#define BIT_PRESENT (1 << 15) 1.15 + 1.16 +#define BIT_BIG (1 << 6) 1.17 +#define BIT_DEFAULT (1 << 6) 1.18 +#define BIT_GRAN (1 << 7) 1.19 + 1.20 +enum {TYPE_DATA, TYPE_CODE}; 1.21 + 1.22 +static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type); 1.23 + 1.24 + 1.25 +static desc_t gdt[4]; 1.26 + 1.27 + 1.28 +void init_segm(void) 1.29 +{ 1.30 + memset(gdt, 0, sizeof gdt); 1.31 + segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE); 1.32 + segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA); 1.33 + 1.34 + set_gdt((uint32_t)gdt, sizeof gdt - 1); 1.35 + 1.36 + setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0)); 1.37 +} 1.38 + 1.39 +uint16_t selector(int idx, int rpl) 1.40 +{ 1.41 + return (idx << 3) | (rpl & 3); 1.42 +} 1.43 + 1.44 +static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type) 1.45 +{ 1.46 + desc->d[0] = limit & 0xffff; /* low order 16bits of limit */ 1.47 + desc->d[1] = base & 0xffff; /* low order 16bits of base */ 1.48 + 1.49 + /* third 16bit part contains the last 8 bits of base, the 2 priviledge 1.50 + * level bits starting on bit 13, present flag on bit 15, and type bits 1.51 + * starting from bit 8 1.52 + */ 1.53 + desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT | 1.54 + BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE)); 1.55 + 1.56 + /* last 16bit part contains the last nibble of limit, the last byte of 1.57 + * base, and the granularity and deafult/big flags in bits 23 and 22 resp. 1.58 + */ 1.59 + desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG; 1.60 +}