kern

annotate src/segm.c @ 56:0be4615594df

finally, runqueues, blocking, waking up, idle loop etc, all seem to work fine on a single user process... Next up: try forking another one :)
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 15 Aug 2011 06:17:58 +0300
parents 4eaecb14fe31
children
rev   line source
nuclear@7 1 #include <string.h>
nuclear@7 2 #include "segm.h"
nuclear@10 3 #include "desc.h"
nuclear@55 4 #include "tss.h"
nuclear@7 5
nuclear@8 6 /* bits for the 3rd 16bt part of the descriptor */
nuclear@7 7 #define BIT_ACCESSED (1 << 8)
nuclear@7 8 #define BIT_WR (1 << 9)
nuclear@7 9 #define BIT_RD (1 << 9)
nuclear@7 10 #define BIT_EXP_DOWN (1 << 10)
nuclear@7 11 #define BIT_CONFORMING (1 << 10)
nuclear@7 12 #define BIT_CODE (1 << 11)
nuclear@7 13 #define BIT_NOSYS (1 << 12)
nuclear@7 14 #define BIT_PRESENT (1 << 15)
nuclear@29 15 /* TSS busy bit */
nuclear@29 16 #define BIT_BUSY (1 << 9)
nuclear@7 17
nuclear@8 18 /* bits for the last 16bit part of the descriptor */
nuclear@7 19 #define BIT_BIG (1 << 6)
nuclear@7 20 #define BIT_DEFAULT (1 << 6)
nuclear@7 21 #define BIT_GRAN (1 << 7)
nuclear@7 22
nuclear@7 23 enum {TYPE_DATA, TYPE_CODE};
nuclear@7 24
nuclear@55 25 /* we need the following bit pattern at the 8th bit excluding the busy bit: 1001 */
nuclear@55 26 #define TSS_TYPE_BITS (9 << 8)
nuclear@29 27
nuclear@7 28 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type);
nuclear@55 29 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl);
nuclear@7 30
nuclear@8 31 /* these functions are implemented in segm-asm.S */
nuclear@8 32 void setup_selectors(uint16_t code, uint16_t data);
nuclear@8 33 void set_gdt(uint32_t addr, uint16_t limit);
nuclear@54 34 void set_task_reg(uint16_t tss_selector);
nuclear@7 35
nuclear@8 36
nuclear@8 37 /* our global descriptor table */
nuclear@29 38 static desc_t gdt[6];
nuclear@7 39
nuclear@7 40
nuclear@7 41 void init_segm(void)
nuclear@7 42 {
nuclear@7 43 memset(gdt, 0, sizeof gdt);
nuclear@7 44 segm_desc(gdt + SEGM_KCODE, 0, 0xffffffff, 0, TYPE_CODE);
nuclear@7 45 segm_desc(gdt + SEGM_KDATA, 0, 0xffffffff, 0, TYPE_DATA);
nuclear@29 46 segm_desc(gdt + SEGM_UCODE, 0, 0xffffffff, 3, TYPE_CODE);
nuclear@29 47 segm_desc(gdt + SEGM_UDATA, 0, 0xffffffff, 3, TYPE_DATA);
nuclear@7 48
nuclear@7 49 set_gdt((uint32_t)gdt, sizeof gdt - 1);
nuclear@7 50
nuclear@7 51 setup_selectors(selector(SEGM_KCODE, 0), selector(SEGM_KDATA, 0));
nuclear@7 52 }
nuclear@7 53
nuclear@8 54 /* constructs a GDT selector based on index and priviledge level */
nuclear@7 55 uint16_t selector(int idx, int rpl)
nuclear@7 56 {
nuclear@7 57 return (idx << 3) | (rpl & 3);
nuclear@7 58 }
nuclear@7 59
nuclear@54 60 void set_tss(uint32_t addr)
nuclear@54 61 {
nuclear@55 62 task_desc(gdt + SEGM_TASK, addr, sizeof(struct task_state) - 1, 3);
nuclear@54 63 set_task_reg(selector(SEGM_TASK, 0));
nuclear@54 64 }
nuclear@54 65
nuclear@7 66 static void segm_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl, int type)
nuclear@7 67 {
nuclear@7 68 desc->d[0] = limit & 0xffff; /* low order 16bits of limit */
nuclear@7 69 desc->d[1] = base & 0xffff; /* low order 16bits of base */
nuclear@7 70
nuclear@7 71 /* third 16bit part contains the last 8 bits of base, the 2 priviledge
nuclear@7 72 * level bits starting on bit 13, present flag on bit 15, and type bits
nuclear@7 73 * starting from bit 8
nuclear@7 74 */
nuclear@7 75 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
nuclear@7 76 BIT_NOSYS | (type == TYPE_DATA ? BIT_WR : (BIT_RD | BIT_CODE));
nuclear@7 77
nuclear@7 78 /* last 16bit part contains the last nibble of limit, the last byte of
nuclear@7 79 * base, and the granularity and deafult/big flags in bits 23 and 22 resp.
nuclear@7 80 */
nuclear@7 81 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN | BIT_BIG;
nuclear@7 82 }
nuclear@29 83
nuclear@55 84 static void task_desc(desc_t *desc, uint32_t base, uint32_t limit, int dpl)
nuclear@29 85 {
nuclear@29 86 desc->d[0] = limit & 0xffff;
nuclear@29 87 desc->d[1] = base & 0xffff;
nuclear@29 88
nuclear@29 89 desc->d[2] = ((base >> 16) & 0xff) | ((dpl & 3) << 13) | BIT_PRESENT |
nuclear@55 90 TSS_TYPE_BITS; /* XXX busy ? */
nuclear@29 91 desc->d[3] = ((limit >> 16) & 0xf) | ((base >> 16) & 0xff00) | BIT_GRAN;
nuclear@29 92 }
nuclear@55 93 /*
nuclear@55 94 static void dbg_print_gdt(void)
nuclear@55 95 {
nuclear@55 96 int i;
nuclear@55 97
nuclear@55 98 printf("Global Descriptor Table\n");
nuclear@55 99 printf("-----------------------\n");
nuclear@55 100
nuclear@55 101 for(i=0; i<6; i++) {
nuclear@55 102 print_desc(gdt + i);
nuclear@55 103 }
nuclear@55 104 }
nuclear@55 105
nuclear@55 106 static void print_desc(desc_t *desc)
nuclear@55 107 {
nuclear@55 108 uint32_t base, limit;
nuclear@55 109 int dpl, g, db, l, avl, p, s, type;
nuclear@55 110 char *type_str;
nuclear@55 111
nuclear@55 112 base = (uint32_t)desc->d[1] | ((uint32_t)(desc->d[2] & 0xff) << 16) | ((uint32_t)(desc->d[3] >> 8) << 24);
nuclear@55 113 limit = (uint32_t)desc->d[0] | ((uint32_t)(desc->d[3] & 0xf) << 16);
nuclear@55 114 dpl = (desc->d[2] >> 13) & 3;
nuclear@55 115 type = (desc->d[2] >> 8) & 0xf;
nuclear@55 116 g = (desc->d[3] >> 23) & 1;
nuclear@55 117 db = (desc->d[3] >> 22) & 1;
nuclear@55 118 l = (desc->d[3] >> 21) & 1;
nuclear@55 119 avl = (desc->d[3] >> 20) & 1;
nuclear@55 120
nuclear@55 121 p = (desc->d[2] >> 15) & 1;
nuclear@55 122 s = (desc->d[2] >> 12) & 1;
nuclear@55 123 }
nuclear@55 124 */