[Prev][Next][Index][Thread]
Why this code doesn't work?
Hi people,
I wrote a simple multi-task under oskit. My tasks run in
kernel mode (CPL=0). all things is ok in this manner.
But I wanted to run a user-mode task. so I defined USER_CS and
USER_DS descriptors as you see in following code.
unfortunately when I run my kernel the system being reset!
can anyone say me what is wrong in my code?
P.S. I got some part of this code from oskit mailing list. So
I apologize to owner of it if he/she doesn't like others
use his/her code without copyright.
#include <stdio.h>
#include <oskit/machine/base_cpu.h>
#include <oskit/x86/pmode.h>
#include <oskit/x86/base_gdt.h>
#include <oskit/machine/base_vm.h>
#include <oskit/x86/tss.h>
#include <oskit/x86/base_tss.h>
#include <oskit/dev/dev.h>
#include <oskit/x86/proc_reg.h>
#include <oskit/x86/base_idt.h>
#include <oskit/debug.h>
#include <oskit/x86/pio.h>
#include <oskit/x86/pc/pit.h>
#include <oskit/x86/eflags.h>
#include <oskit/x86/pc/base_irq.h>
#include <oskit/x86/base_trap.h>
#define SHARIF_TSS_2 0x58
#defien SHARIF_TSS 0x60;
CODE32
extern oskit_addr_t sharif_pdir_pa;
struct x86_tss scheduler_tss1;
struct x86_tss my_tss;
long dataseg[100];
long mydataseg[100];
void delay(void) {
unsigned int i,j, k;
for (i = 0; i < 30000; ++i)
for (j = 0; j < 5000; ++j)
k = k +1;
}
int sv = 0;
unsigned long count = 0;
void user_code(void) {
while (1) {
delay();
printf("User Code \n");
}
}
void scheduler(void)
{
while (1) {
if (++count > 500) {
count = 0;
sv++;
if (sv % 2 ) {
base_gdt[SHARIF_TSS / 8].access |=
ACC_TSS_BUSY;
scheduler_tss1.back_link = SHARIF_TSS;
} else {
scheduler_tss1.back_link = BASE_TSS;
base_gdt[BASE_TSS / 8].access |=
ACC_TSS_BUSY;
}
}
outb(0x20, 0x20);
asm ("iret");
}
}
void main (void) {
base_gdt_init();
base_gdt_load();
base_tss_init();
base_tss_load();
fill_descriptor(&base_gdt[SHARIF_TSS_2 / 8],
kvtolin(&scheduler_tss1), sizeof(scheduler_tss1) - 1,
ACC_PL_U | ACC_TSS | ACC_P, 0);
fill_descriptor(&base_gdt[SHARIF_TSS / 8],
kvtolin(&my_tss), sizeof(my_tss) - 1,
ACC_PL_U | ACC_TSS | ACC_P, 0);
fill_descriptor(&base_gdt[USER_CS / 8],
0x00000000, 0xffffffff,
ACC_PL_U | ACC_CODE_R, SZ_32);
fill_descriptor(&base_gdt[USER_DS / 8],
0x00000000, 0xffffffff,
ACC_PL_U | ACC_DATA_W, SZ_32);
base_tss.eflags = base_tss.eflags | 0x202 ;
scheduler_tss1.eip = (long)&scheduler;
scheduler_tss1.cs = KERNEL_CS;
scheduler_tss1.es = KERNEL_DS;
scheduler_tss1.ds = KERNEL_DS;
scheduler_tss1.ss = KERNEL_DS;
scheduler_tss1.fs = KERNEL_DS;
scheduler_tss1.gs = KERNEL_DS;
scheduler_tss1.ss0 = KERNEL_DS;
scheduler_tss1.ss1 = KERNEL_DS;
scheduler_tss1.ss2 = KERNEL_DS;
scheduler_tss1.esp = sizeof(dataseg) * 100 + (long)dataseg;
scheduler_tss1.esp0 = sizeof(dataseg) * 100 + (long)dataseg;
scheduler_tss1.esp1 = sizeof(dataseg) * 100 + (long)dataseg;
scheduler_tss1.esp2 = sizeof(dataseg) * 100 + (long)dataseg;
scheduler_tss1.io_bit_map_offset = sizeof(scheduler_tss1);
scheduler_tss1.ldt = 0;
scheduler_tss1.eflags = 0x202 | EFL_NT;
base_gdt[SHARIF_TSS_2 / 8].access &= ~ACC_TSS_BUSY;
/*
When I change KERNEL_xx to USER_xx,
system reset during execution of kernel.
*/
my_tss.eip = (long)&user_code;
my_tss.cs = KERNEL_CS;
my_tss.es = KERNEL_DS;
my_tss.ds = KERNEL_DS;
my_tss.ss = KERNEL_DS;
my_tss.fs = KERNEL_DS;
my_tss.gs = KERNEL_DS;
my_tss.ss0 = KERNEL_DS;
my_tss.ss1 = KERNEL_DS;
my_tss.ss2 = KERNEL_DS;
my_tss.esp = sizeof(mydataseg) * 100 + (long)mydataseg;
my_tss.esp0 = sizeof(mydataseg) * 100 + (long)mydataseg;
my_tss.esp1 = sizeof(mydataseg) * 100 + (long)mydataseg;
my_tss.esp2 = sizeof(mydataseg) * 100 + (long)mydataseg;
my_tss.io_bit_map_offset = sizeof(my_tss);
my_tss.ldt = 0;
my_tss.eflags = 0x202;
base_gdt[SHARIF_TSS / 8].access |= ACC_TSS_BUSY;
osenv_intr_disable();
fill_gate(&base_idt[irq_master_base + 0], 0, SHARIF_TSS_2,
ACC_TASK_GATE | ACC_PL_K, 0);
pit_init(100);
osenv_irq_enable(0);
osenv_intr_enable();
while (1) {
delay();
printf("Main TASK \n");
}
printf("Just in case...\n");
return;
}
With Regards,
--taghi
Follow-Ups: