--- /dev/null
+#include "desc.h"
+
+#define SEG_TYPE_SYSTEM 0
+#define SEG_TYPE_CODE 0x00001800
+#define SEG_TYPE_DATA 0x00001000
+#define SEG_TYPE_TSS 0x00000100
+#define SEG_TYPE_INTR 0x00000e00
+#define SEG_TYPE_TRAP 0x00000f00
+
+#define SEG_ACCESSED 0x00000100
+#define SEG_PRESENT 0x00008000
+#define SEG_AVL 0x00100000
+#define SEG_GRAN 0x00800000
+
+/* data segment type flags */
+#define SEG_WR 0x00000200
+#define SEG_EXPDN 0x00000400
+#define SEG_BIG 0x00400000
+/* code segment type flags */
+#define SEG_RD 0x00000200
+#define SEG_CONFORM 0x00000400
+#define SEG_DEF 0x00400000
+
+
+void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dpl)
+{
+ if(type == SEG_NULL) {
+ desc->d[0] = desc->d[1] = 0;
+ return;
+ }
+
+ desc->d[0] = (limit & 0xffff) | (base << 16);
+ desc->d[1] = ((base >> 16) & 0xff) | (type << 8) | SEG_PRESENT | (dpl << 13);
+ desc->d[1] |= (base & 0xff000000) | (limit & 0xf0000) | SEG_AVL | SEG_GRAN;
+
+ switch(type) {
+ case SEG_CODE:
+ desc->d[1] |= (3 << 11) | SEG_DEF | SEG_RD;
+ break;
+
+ case SEG_DATA:
+ desc->d[1] |= (2 << 11) | SEG_WR;
+ break;
+ }
+}
--- /dev/null
+#ifndef DESC_H_
+#define DESC_H_
+
+#include <stdint.h>
+
+struct desc {
+ uint32_t d[2];
+};
+
+enum { SEG_NULL, SEG_CODE, SEG_DATA, SEG_TSS };
+
+void desc_seg(struct desc *desc, int type, uint32_t base, uint32_t limit, int dpl);
+
+#endif /* DESC_H_ */
--- /dev/null
+#include "mem.h"
+#include "desc.h"
+
+void set_gdt(void *addr, uint16_t limit);
+
+enum {
+ SEG_NULL = 0,
+ SEG_KCODE = 1,
+ SEG_KDATA = 2
+};
+
+#define NUM_SEG 3
+static struct desc gdt[NUM_SEG] __attribute__((aligned(8)));
+
+void mem_init(void)
+{
+ desc_seg(gdt, SEG_NULL, 0, 0, 0);
+ desc_seg(gdt + SEG_KCODE, SEG_CODE, 0, 0xffffffff, 0);
+ desc_seg(gdt + SEG_KDATA, SEG_DATA, 0, 0xffffffff, 0);
+
+ set_gdt(gdt, sizeof gdt - 1);
+}