kern

view src/segm.c @ 54:4eaecb14fe31

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