Warning, cross-references for /kernel/kernel.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "arch/i386.h"
0019 #include "kernel.h"
0020 #include "smp/spinlock.h"
0021 #include "util/printf.h"
0022 #include "util/screen.h"
0023 #include "util/debug.h"
0024 #include "mem/virtual.h"
0025 #include "mem/physical.h"
0026 #include "sched/sched.h"
0027
0028 static spinlock kernel_lock ALIGNED(LOCK_ALIGNMENT) = SPINLOCK_INIT;
0029
0030
0031 uint32 ul_stack[NR_MODS][1024] ALIGNED (0x1000);
0032
0033
0034 uint32 ul_tss[NR_MODS][1024] ALIGNED (0x1000);
0035
0036
0037 uint32 pg_dir[NR_MODS][1024] ALIGNED (0x1000);
0038
0039
0040 uint32 pg_table[NR_MODS][1024] ALIGNED (0x1000);
0041
0042
0043 uint32 kl_stack[NR_MODS][1024] ALIGNED (0x1000);
0044
0045
0046 uint32 kls_pg_table[NR_MODS][1024] ALIGNED (0x1000);
0047
0048
0049 quest_tss idleTSS[MAX_CPUS];
0050 uint16 idleTSS_selector[MAX_CPUS];
0051
0052
0053 tss cpuTSS[MAX_CPUS];
0054 uint16 cpuTSS_selector[MAX_CPUS];
0055
0056 char *pchVideo = (char *) KERN_SCR;
0057
0058
0059 void panic (char *sz)
0060 {
0061 print ("kernel panic: ");
0062 print (sz);
0063
0064 cli ();
0065 hlt ();
0066 }
0067
0068
0069 void
0070 lock_kernel (void)
0071 {
0072 spinlock_lock (&kernel_lock);
0073 }
0074
0075 void
0076 unlock_kernel (void)
0077 {
0078 spinlock_unlock (&kernel_lock);
0079 }
0080
0081
0082
0083 extern quest_tss *
0084 lookup_TSS (uint16 selector)
0085 {
0086
0087 descriptor *ad = (descriptor *) KERN_GDT;
0088
0089 return (quest_tss *) (ad[selector >> 3].pBase0 |
0090 (ad[selector >> 3].pBase1 << 16) |
0091 (ad[selector >> 3].pBase2 << 24));
0092 }
0093
0094 extern void *
0095 lookup_GDT_selector (uint16 selector)
0096 {
0097
0098 descriptor *ad = (descriptor *) KERN_GDT;
0099
0100 return (void *) (ad[selector >> 3].pBase0 |
0101 (ad[selector >> 3].pBase1 << 16) |
0102 (ad[selector >> 3].pBase2 << 24));
0103 }
0104
0105 extern void
0106 get_GDT_descriptor (uint16 selector, descriptor *ad)
0107 {
0108 *ad = ((descriptor *) KERN_GDT)[selector >> 3];
0109 }
0110
0111
0112 void
0113 idle_task (void)
0114 {
0115 unlock_kernel ();
0116 sti ();
0117 for (;;) {
0118 asm volatile ("pause");
0119 }
0120 }
0121
0122
0123 void
0124 disable_idt (void)
0125 {
0126 uint16 len = KERN_IDT_LEN;
0127 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0128 uint16 i;
0129
0130 for (i = 0; i < (len >> 3); i++) {
0131 if (ptr[i].pBase0)
0132 ptr[i].fPresent = 0;
0133 }
0134 }
0135
0136
0137 void
0138 enable_idt (void)
0139 {
0140 uint16 len = KERN_IDT_LEN;
0141 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0142 uint16 i;
0143
0144 for (i = 0; i < (len >> 3); i++) {
0145 if (ptr[i].pBase0)
0146 ptr[i].fPresent = 1;
0147 }
0148 }
0149
0150
0151 void
0152 enable_idt_entry (uint16 i)
0153 {
0154 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0155 if (ptr[i].pBase0)
0156 ptr[i].fPresent = 1;
0157 }
0158
0159
0160
0161 void
0162 set_idt_descriptor_by_addr (uint8 n, void *addr, uint8 dpl)
0163 {
0164 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0165
0166 ptr[n].fPresent = 0;
0167 ptr[n].pBase1 = ((uint32) addr & 0xFFFF0000) >> 16;
0168 ptr[n].pBase0 = ((uint32) addr & 0x0000FFFF);
0169 ptr[n].pSeg = 0x08;
0170 ptr[n].fZero0 = 0;
0171 ptr[n].fZero1 = 0;
0172 ptr[n].fReserved = 0;
0173 ptr[n].fType = 0x6;
0174 ptr[n].f32bit = 1;
0175 ptr[n].uDPL = dpl;
0176 ptr[n].fPresent = 1;
0177 }
0178
0179
0180 void
0181 get_idt_descriptor (uint8 n, idt_descriptor * d)
0182 {
0183 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0184
0185 *d = ptr[n];
0186 }
0187
0188
0189 void
0190 set_idt_descriptor (uint8 n, idt_descriptor * d)
0191 {
0192 idt_descriptor *ptr = (idt_descriptor *) KERN_IDT;
0193
0194 ptr[n] = *d;
0195 }
0196
0197 static bool kernel_threads_running = FALSE;
0198 static task_id kernel_thread_waitq = 0;
0199
0200 task_id
0201 create_kernel_thread_args (uint eip, uint esp, bool run, uint n, ...)
0202 {
0203 task_id pid;
0204 uint32 eflags;
0205 extern u32 *pgd;
0206 void *page_dir = &pgd;
0207 uint *stack, i;
0208 va_list args;
0209
0210 asm volatile ("pushfl\n" "pop %0\n":"=r" (eflags):);
0211
0212 esp -= sizeof (void *) * (n + 1);
0213 stack = (uint *) esp;
0214
0215
0216 va_start (args, n);
0217 for (i=0; i<n; i++)
0218 stack[i+1] = va_arg (args, uint);
0219 va_end (args);
0220
0221 stack[0] = (uint) exit_kernel_thread;
0222
0223
0224 pid = duplicate_TSS (0, NULL,
0225 eip, 0, esp,
0226 eflags, (uint32) page_dir);
0227
0228 lookup_TSS (pid)->priority = 0x1f;
0229
0230 if (run) {
0231 if (kernel_threads_running)
0232 wakeup (pid);
0233 else
0234 queue_append (&kernel_thread_waitq, pid);
0235 }
0236
0237 return pid;
0238 }
0239
0240 task_id
0241 start_kernel_thread (uint eip, uint esp)
0242 {
0243 return create_kernel_thread_args (eip, esp, TRUE, 0);
0244 }
0245
0246 void
0247 begin_kernel_threads (void)
0248 {
0249 if (kernel_threads_running == FALSE) {
0250 wakeup_queue (&kernel_thread_waitq);
0251 kernel_threads_running = TRUE;
0252 }
0253 }
0254
0255 void
0256 exit_kernel_thread (void)
0257 {
0258 uint8 LAPIC_get_physical_ID (void);
0259 quest_tss *tss;
0260 uint tss_frame;
0261 task_id waiter;
0262
0263 for (;;)
0264 sched_usleep (1000000);
0265
0266 tss = lookup_TSS (str ());
0267 tss_frame = (uint) get_phys_addr (tss);
0268
0269
0270 while ((waiter = queue_remove_head (&tss->waitqueue)))
0271 wakeup (waiter);
0272
0273
0274 memset (tss, 0, sizeof (quest_tss));
0275 unmap_virtual_page (tss);
0276 free_phys_frame (tss_frame);
0277
0278
0279 ltr (0);
0280
0281 schedule ();
0282
0283 panic ("exit_kernel_thread: unreachable");
0284 }
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295