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 +}