kern

view src/segm.c @ 80:4db99a52863e

fixed the "endianess" of the text messages in the ATA identify info block. this is the first time I've seen wrong byteorder in ascii text, the ATA committee should be commended.
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 06 Dec 2011 13:35:39 +0200
parents 4eaecb14fe31
children
line source
1 #include <string.h>
2 #include "segm.h"
3 #include "desc.h"
4 #include "tss.h"
6 /* bits for the 3rd 16bt part of the descriptor */
7 #define BIT_ACCESSED (1 << 8)
8 #define BIT_WR (1 << 9)
9 #define BIT_RD (1 << 9)
10 #define BIT_EXP_DOWN (1 << 10)
11 #define BIT_CONFORMING (1 << 10)
12 #define BIT_CODE (1 << 11)
13 #define BIT_NOSYS (1 << 12)
14 #define BIT_PRESENT (1 << 15)
15 /* TSS busy bit */
16 #define BIT_BUSY (1 << 9)
18 /* bits for the last 16bit part of the descriptor */
19 #define BIT_BIG (1 << 6)
20 #define BIT_DEFAULT (1 << 6)
21 #define BIT_GRAN (1 << 7)
23 enum {TYPE_DATA, TYPE_CODE};
25 /* we need the following bit pattern at the 8th bit excluding the busy bit: 1001 */
26 #define TSS_TYPE_BITS (9 << 8)
28 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
29 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl);
31 /* these functions are implemented in segm-asm.S */
32 void setup_selectors(uint16_t code, uint16_t data);
33 void set_gdt(uint32_t addr, uint16_t limit);
34 void set_task_reg(uint16_t tss_selector);
37 /* our global descriptor table */
38 static desc_t gdt[6];
41 void init_segm(void)
42 {
43 memset(gdt, 0, sizeof gdt);
44 segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE);
45 segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA);
46 segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE);
47 segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA);
49 set_gdt((uint32_t)gdt, sizeof gdt - 1);
51 setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0));
52 }
54 /* constructs a GDT selector based on index and priviledge level */
55 uint16_t selector(int idx, int rpl)
56 {
57 return (idx << 3) | (rpl & 3);
58 }
60 void set_tss(uint32_t addr)
61 {
62 task_desc(gdt + SEGM_TASK, addr, sizeof(struct task_state) - 1, 3);
63 set_task_reg(selector(SEGM_TASK, 0));
64 }
66 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type)
67 {
68 desc->d[0] = limit & 0xffff; /* low order 16bits of limit */
69 desc->d[1] = base & 0xffff; /* low order 16bits of base */
71 /* third 16bit part contains the last 8 bits of base, the 2 priviledge
72 * level bits starting on bit 13, present flag on bit 15, and type bits
73 * starting from bit 8
74 */
75 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
76 BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE));
78 /* last 16bit part contains the last nibble of limit, the last byte of
79 * base, and the granularity and deafult/big flags in bits 23 and 22 resp.
80 */
81 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG;
82 }
84 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl)
85 {
86 desc->d[0] = limit & 0xffff;
87 desc->d[1] = base & 0xffff;
89 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
90 TSS_TYPE_BITS; /* XXX busy ? */
91 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN;
92 }
93 /*
94 static void dbg_print_gdt(void)
95 {
96 int i;
98 printf("Global Descriptor Table\n");
99 printf("-----------------------\n");
101 for(i=0; i<6; i++) {
102 print_desc(gdt + i);
103 }
104 }
106 static void print_desc(desc_t *desc)
107 {
108 uint32_t base, limit;
109 int dpl, g, db, l, avl, p, s, type;
110 char *type_str;
112 base = (uint32_t)desc->d[1] | ((uint32_t)(desc->d[2] & 0xff) << 16) | ((uint32_t)(desc->d[3] >> 8) << 24);
113 limit = (uint32_t)desc->d[0] | ((uint32_t)(desc->d[3] & 0xf) << 16);
114 dpl = (desc->d[2] >> 13) & 3;
115 type = (desc->d[2] >> 8) & 0xf;
116 g = (desc->d[3] >> 23) & 1;
117 db = (desc->d[3] >> 22) & 1;
118 l = (desc->d[3] >> 21) & 1;
119 avl = (desc->d[3] >> 20) & 1;
121 p = (desc->d[2] >> 15) & 1;
122 s = (desc->d[2] >> 12) & 1;
123 }
124 */