[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: