Software Task Switching

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
intel_breaker
Member
Member
Posts: 46
Joined: Tue Jan 04, 2005 12:00 am
Location: Poland
Contact:

Software Task Switching

Post by intel_breaker »

Hi, I've just implemented a Software Task Switching in my kernel. It's faster than tss but it is more difficult in implementation. I use processes in ring3 & ring0.

Before i enable scheduler, i make special tss called lizard.
It is in ring3 and have KERNEL_PAGE_DIRECTORY loaded in cr3 register. When kernel is finishing initialization, it executes long jump to the lizard process and sets sched_enabled varible to 1 (this means that the scheduler is enabled:)

Code: Select all

struct intr_handler_frame {
		UINT32 ds;
		UINT32 es;
		
		UINT32 fs;
		UINT32 gs;

		UINT32 edi;
		UINT32 esi;
		UINT32 ebp;
		UINT32 old_esp;
		UINT32 ebx;
		UINT32 edx;
		UINT32 ecx;
		UINT32 eax;

		UINT32 intr_index;
		UINT32 intr_ecode;

		UINT32 eip;
		UINT32 cs;
		UINT32 flags;
		UINT32 esp;
		UINT32 ss;
};
/**************** ASM INTERRUPT ENTER (MACRO)**************/

Code: Select all

__low_int_controller:
    pushal
	
    pushl	%gs
    pushl	%fs
    pushl	%es
    pushl	%ds

    movl	$0x18, %eax
    movw	%ax, %es
    movw	%ax, %ds
    movw	%ax, %fs
    movw	%ax, %gs
    movw        %ax, %ss

    call	interrupt_controler

    popl	%ds
    popl	%es
    popl	%fs
    popl	%gs

    popal
    
    addl	$8, %esp
    iret

#define INTERRUPT_HANDLER(name,nr)\
.global name; \
name: \
    cli; \
    pushl 	$0; \
    pushl $nr; \
    jmp __low_int_controller;[code]

example:
INTERRUPT_HANDLER(scheduler,0x20)
/******************************************/

Code: Select all

NORETURN interrupt_controler( UINT32 *stack ) {

struct intr_handler_frame *intr_frame = (struct intr_handler_frame *) &stack;
    
switch( intr_frame -> intr_index )
{

case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: case 0x9: case 0xA: case 0xB: case 0xC: case 0xD: case 0xE: case 0xF: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
		valid_exception( intr_frame -> intr_index );
		break;
			
			
case 0x20:
	software_scheduler( intr_frame );
	break;
			
			
case 0x21: case 0x22: case 0x23: case 0x24: case 0x25:
case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a:
case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
	IRQ_router( intr_frame -> intr_index - 0x20 );
	break;
								
case 0x80:
       syscalls_service(current_process, intr_frame -> edx);
       break;
		
default:
       printk("interrupt controler: unimplemented interrupt signal received!\n");
       break;
    }
}
/*************************************************/
/*****************SCHEDULER**********************/

Code: Select all

NORETURN software_scheduler( struct intr_handler_frame *frame ) {

	if (sched_enabled == 1) {
	
        /* saving process state */
	current_process -> frame_ptr = frame;
			
        /******* SCHEDULER ALOGHORITM CUTED ********/
        /******* SCHEDULER ALOGHORITM CUTED ********/

	current_process = current_process -> next;
    
        frame = current_process -> frame_ptr;

	lizard -> tss.esp0 = current_process -> travel_esp;

        /* Is this is necesery? */
	lizard -> tss.cs = frame -> cs;
	lizard -> tss.ds = frame -> ds;
	lizard -> tss.es = frame -> es;
	lizard -> tss.fs = frame -> fs;
	lizard -> tss.gs = frame -> gs;

	lizard -> tss.ss0 = current_process -> travel_ss;
	lizard -> tss.ss = frame -> ss;
	
	asm("movl %0, %%eax\n"
	    "movl %%eax, %%cr3" :: "m" (current_process -> user_cr3));
	    
	asm("movl %0, %%esp\n"
	    "popl %%ds\n"
    	    "popl %%es\n"
            "popl %%fs\n"
            "popl %%gs\n"
            "popal\n"
	    "addl $8, %%esp\n"
	    "iret" :: "r" (current_process -> frame_ptr));
	}
}
#define KERNEL_CS 0x10
#define KERNEL_DS 0x18
#define USER_CS 0x20 |3
#define USER_DS 0x28 |3


AND I HAVE _BIG_ PROBLEM:
It works - tasks are switching very well, but sometimes (I have program called 'faulter'), when I executes faulter and select invalid operation called 'Protection Fault' (it execeutes two instructions 'cli' & 'hlt' - faulter works in RING3)

Code: Select all

/*******************FAULTER.C*************************/
#define sysCall()                                            \
      __asm__ __volatile__ ("lcall $0x023B,$0x00000000 \n\t")

int main( void )
{
    char msg[2];
    printk("\nWhat kind of fault would you like to execute?\n\n");
    printk("1: memory fault\n");
    printk("2: port fault\n");
    printk("3: protection fault\n");
    printk("4: code fault\n");
    scanf(msg);
    
    if ( !strcmp(msg,"1") ) {
    	printk("You selected memory fault! (0xFFFF)\n");
    	int *a = 0xFFFF;
	*a = 1;
    } else
    if ( !strcmp(msg,"2") ) {
    	printk("You selected port fault!\n");
	asm("movw $0x20, %ax\n"
	    "outw %ax, $0x20\n");
    } else
    if ( !strcmp(msg,"3") ) {
    	printk("You selected protection fault!\n");
	asm("cli\n"
	    "hlt");
    } else
    if ( !strcmp(msg,"4") ) {
    	printk("You selected code fault!\n");
        sysCall();
    }
    printk("Ooops, it works! - better update the kernel!\n");
}

/**********************************************************/
I've got this result:

Ooops, it works! - better update the kernel!
and dump my exceptions handler code:

System Protection Fault on xx/xx/xx, at x:x:x

PANIC: Memory Fault!

*** access volation at address: 0xXXXXXXX (this is betwen 2GiB-3GiB) ****

/*************************************************/
This is very strange, because it is happening only sometimes
Meaby I've forgotten about something?
Please, help me:)
Osbios
Member
Member
Posts: 116
Joined: Fri Jun 10, 2005 11:00 pm

Re: Software Task Switching

Post by Osbios »

intel_breaker wrote:It's faster than tss but it is more difficult in implementation.
I think software tasks a much more easy to implement. And software task with save/restore all reg. a slower then hardware tasks!

Do you realy not use the TSS? I learnd that you need at last one TSS for ring 3..1-->0 Jumps because the ring0 ss:esp is saved inside the tss.

You forget a /code

And i cant C :P
Last edited by Osbios on Wed Jul 27, 2005 11:00 pm, edited 1 time in total.
dw 0xAA55
User avatar
intel_breaker
Member
Member
Posts: 46
Joined: Tue Jan 04, 2005 12:00 am
Location: Poland
Contact:

Re: Software Task Switching

Post by intel_breaker »

Problem solved. It was a bug in 'waitFor32APP' function in shell (two programs was working on one console:D )
Post Reply