00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/init.h>
00015 #include <asm/segment.h>
00016 #include <agnix/adi/chips/cpu.h>
00017 #include <asm/desc.h>
00018 #include <agnix/memory.h>
00019 #include <agnix/console.h>
00020 #include <agnix/tasks.h>
00021
00022 extern int idle_task_init(void);
00023 extern struct tss_wrap_s init_tss[MAX_TASKS];
00024 extern struct main_memory_s main_memory;
00025
00026 struct list_head tss_list;
00027
00028 #define jmp_to_task(indirect) \
00029 __asm__ __volatile__ ( \
00030 "ljmp *(%%edi)\n\t" \
00031 : \
00032 :"D"(&indirect) \
00033 )
00034
00035 struct indirect_s {
00036 u32 offset;
00037 u16 segment;
00038 } task_indirect = { 0, 0 };
00039
00040 struct tss_wrap_s * get_free_tss(void)
00041 {
00042 struct tss_wrap_s *tss = 0;
00043
00044 if (!list_empty(&tss_list)) {
00045 if ((tss = list_entry(tss_list.next, struct tss_wrap_s, tss_list)) != 0) {
00046 list_del(tss_list.next);
00047 return tss;
00048 }
00049 }
00050
00051 return 0;
00052 }
00053
00054 void put_free_tss(struct tss_wrap_s *tss)
00055 {
00056 list_add_tail(&tss->tss_list, &tss_list);
00057 }
00058
00059 void task_switch(u16 nr_task)
00060 {
00061 #ifdef DEBUG_THREAD
00062 printk("jmp to %d\n", nr_task);
00063 printk("eip == %x\n", init_tss[nr_task].tss.eip);
00064 printk("cr3 == %x\n", init_tss[nr_task].tss.__cr3);
00065 printk("cs == %x\n", init_tss[nr_task].tss.cs);
00066 printk("ds == %x\n", init_tss[nr_task].tss.ds);
00067 printk("esp == %x\n", init_tss[nr_task].tss.esp);
00068 printk("ebp == %x\n", init_tss[nr_task].tss.ebp);
00069 printk("link == %x\n", init_tss[nr_task].tss.task_link);
00070 printk("trace == %x\n", init_tss[nr_task].tss.trace);
00071 #endif
00072
00073 task_indirect.segment = __TSS(nr_task) << 3;
00074 task_indirect.offset = 0;
00075
00076 jmp_to_task(task_indirect);
00077 }
00078
00079 void task_set_handler(struct task_s *task, u32 eip, u32 esp) {
00080 struct tss_s *tss = &(task->tss_wrap->tss);
00081
00082 tss->eip = eip;
00083 tss->esp = esp;
00084 }
00085
00086 void task_restore_state(struct task_s *task, struct task_state_s *state) {
00087
00088
00089
00090
00091 }
00092
00093 void task_save_state(struct task_s *task, struct task_state_s *state) {
00094
00095
00096
00097
00098 }
00099
00100 int task_set_user_mode(struct tss_s *tss, u32 eip, u32 esp)
00101 {
00102
00103
00104 tss->eip = eip;
00105 tss->esp = esp;
00106 tss->ss0 = __KERNEL_DS;
00107 tss->ss1 = __KERNEL_DS;
00108 tss->ss2 = __KERNEL_DS;
00109 tss->cs = __USER_CS;
00110 tss->ss = __USER_DS;
00111 tss->ds = __USER_DS;
00112 tss->es = __USER_DS;
00113 tss->fs = __USER_DS;
00114 tss->gs = __USER_DS;
00115
00116 return 0;
00117 }
00118
00119 u16 task_kernel_create(struct tss_wrap_s *tss_wrap, u32 eip, u32 esp)
00120 {
00121 struct tss_s *tss = &(tss_wrap->tss);
00122 u16 desc_nr;
00123 u16 entry;
00124
00125 entry = tss_wrap->tss_entry;
00126 desc_nr = __TSS(entry);
00127
00128 memset(tss, 0, sizeof(struct tss_s));
00129
00130 tss->eflags = CPU_EFLAGS_IF;
00131 tss->eip = eip;
00132 tss->esp = esp;
00133 tss->esp0 = esp;
00134 tss->esp1 = 0;
00135 tss->esp2 = 0;
00136 tss->ss0 = __KERNEL_DS;
00137 tss->ss1 = __KERNEL_DS;
00138 tss->ss2 = __KERNEL_DS;
00139 tss->cs = __KERNEL_CS;
00140 tss->ss = __KERNEL_DS;
00141 tss->ds = __KERNEL_DS;
00142 tss->es = __KERNEL_DS;
00143 tss->fs = __KERNEL_DS;
00144 tss->gs = __KERNEL_DS;
00145 tss->ldt = 0;
00146 tss->__cr3 = (u32)main_memory.pdbr - 0xC0000000;
00147 tss->bitmap = 0x8000;
00148 tss->io_bitmap[0] = ~0;
00149
00150 set_TSS_desc(desc_nr, (void *)&init_tss[entry].tss, 235, 0);
00151
00152 return entry;
00153 }
00154
00155 struct tss_wrap_s * task_fork(struct regs_s *regs, u32 esp)
00156 {
00157 struct tss_s *current_tss;
00158 struct tss_wrap_s *tss_wrap;
00159 struct tss_s *tss;
00160 u16 desc_nr;
00161 u16 entry;
00162
00163 current_tss = ¤t_task->tss_wrap->tss;
00164
00165 if ((tss_wrap = get_free_tss()) == 0)
00166 return 0;
00167
00168 tss = &tss_wrap->tss;
00169
00170 entry = tss_wrap->tss_entry;
00171 desc_nr = __TSS(entry);
00172
00173 memset(tss, 0, sizeof(struct tss_s));
00174
00175 tss->eax = regs->eax;
00176 tss->ebx = regs->ebx;
00177 tss->ecx = regs->ecx;
00178 tss->edx = regs->edx;
00179 tss->esp = esp;
00180 tss->esp0 = esp;
00181 tss->ss0 = __KERNEL_DS;
00182 tss->ss1 = __KERNEL_DS;
00183 tss->ss2 = __KERNEL_DS;
00184 tss->esi = regs->esi;
00185 tss->edi = regs->edi;
00186 tss->eip = regs->eip;
00187 tss->ebp = regs->ebp;
00188 tss->cs = current_tss->cs;
00189 tss->ss = current_tss->ss;
00190 tss->ds = current_tss->ds;
00191 tss->es = current_tss->es;
00192 tss->fs = current_tss->fs;
00193 tss->gs = current_tss->gs;
00194
00195 tss->__cr3 = (u32)main_memory.pdbr - 0xC0000000;
00196 tss->ldt = 0;
00197 tss->eflags = regs->eflags;
00198 tss->task_link = 0;
00199 tss->bitmap = 0x8000;
00200 tss->io_bitmap[0] = ~0;
00201
00202 set_TSS_desc(desc_nr, (void *)tss, 235, 0);
00203
00204 return tss_wrap;
00205 }
00206
00207 int task_exit(struct tss_wrap_s *tss_wrap)
00208 {
00209 u16 desc_nr;
00210 u16 entry;
00211
00212 put_free_tss(tss_wrap);
00213
00214 entry = tss_wrap->tss_entry;
00215 desc_nr = __TSS(entry);
00216
00217 set_TSS_desc(desc_nr, (void *)0, 235, 0);
00218
00219 return 0;
00220 }
00221
00222 int __init tasks_init(void)
00223 {
00224 int i;
00225
00226 INIT_LIST_HEAD(&tss_list);
00227
00228 for (i = 0; i < MAX_TASKS; i++) {
00229 INIT_LIST_HEAD(&init_tss[i].tss_list);
00230 init_tss[i].tss_entry = (u16)i;
00231 put_free_tss(&init_tss[i]);
00232 }
00233
00234 idle_task_init();
00235
00236 return 0;
00237 }
00238
00239 #undef DEBUG_THREAD