Task switch from a Task Gate

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
Dandee Yuyo
Member
Member
Posts: 47
Joined: Fri Nov 09, 2007 6:46 pm
Location: Argentina

Task switch from a Task Gate

Post by Dandee Yuyo »

Hi, guys. I'm trying to do task-switching from a task gate. To accomplish this I'm setting the back-link field of the interrupt gate TSS to the new task selector. But after the iret, the processor seems to continue to keep running the previous task. Do I need to modify the EIP and CS on the interupt stack frame too?

Here is the code of my isr0 interrupt that illustrates this:

Code: Select all

[GLOBAL _irq0_proc]
_irq0_proc:
	cli
_irq0_loop:	
	inc	dword [_ticks]		; tick
		
	mov	al, 0x20			; reset timer
	out	0x20, al
	
[EXTERN _irq0_task] ; IRQ0 TSS

	mov	eax, [_ticks]
	and	eax, dword 0x01
	cmp	eax, dword 0x01
	jz	resch1
		
	lea	eax, [_irq0_task]
	mov	[eax], dword 0x30	; switch to task 2
	mov 	[_gdt8 + 5], byte 0x8b ; set busy bit
	
	jmp	resch2
	
resch1:	

	lea	eax, [_irq0_task]
	mov	[eax], dword 0x20    ; switch to task 1
	mov 	[_gdt6 + 5], byte 0x8b ; set busy bit
	
resch2:
	iret	
	cli						; next time we are called we continue here!
	jmp   _irq0_loop
Keep in mind it's just a "proof of concept" code :D I plan scratch the next or "current" task descriptor instead of changing the selector in the isr tss... :roll:
NaN - Not a Nerd
Working on: Physical Memory Management with a 5-lod mipmap XD
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

You need to set the nested task bit in eflags. Bit 14 I believe.
User avatar
Dandee Yuyo
Member
Member
Posts: 47
Joined: Fri Nov 09, 2007 6:46 pm
Location: Argentina

Post by Dandee Yuyo »

It is already set. Is set when the processor calls de Interrupt Task. I cannot grasp what's missing.
NaN - Not a Nerd
Working on: Physical Memory Management with a 5-lod mipmap XD
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Also the task that you are trying to IRET to should have its busy bit set.
User avatar
Dandee Yuyo
Member
Member
Posts: 47
Joined: Fri Nov 09, 2007 6:46 pm
Location: Argentina

Post by Dandee Yuyo »

Well, this is already being done by:

Code: Select all

   mov    [_gdt8 + 5], byte 0x8b ; set busy bit 
and

Code: Select all

   mov    [_gdt6 + 5], byte 0x8b ; set busy bit 
If it would be that, I'll get an invalid TSS, which is not happening.

386 programer's reference says about IRET:

Code: Select all

ELSE (*PROTECTED MODE*)
   IF VM = 1
     ..
   ELSE
     IF NT = 1
     THEN GOTO TASK-RETURN;		// I HAVE FLAG 0x400 set
     ELSE
        ...
     FI;
   FI;
...


TASK-RETURN:
   Examine Back Link Selector in TSS addressed by the current task
      register:
      Must specify global in the local/global bit, else #TS(new TSS selector);
      Index must be within GDT limits, else #TS(new TSS selector);
      AR byte must specify TSS, else #TS(new TSS selector);
      New TSS must be busy, else #TS(new TSS selector);
      TSS must be present, else #NP(new TSS selector);
   SWITCH-TASKS without nesting to TSS specified by back link selector;
   Mark the task just abandoned as NOT BUSY;
   Instruction pointer must be within code segment limit ELSE #GP(0);
I don't get any "Invalid TSS" or GPF so all checks pass...

It also says on section 7.6.2 Modifying Task Linkages:
Any modification of the linkage order of tasks should be accomplished only
by software that can be trusted to correctly update the back-link and the
busy-bit. Such changes may be needed to resume an interrupted task before
the task that interrupted it. Trusted software that removes a task from the
back-link chain must follow one of the following policies:
1. First change the back-link field in the TSS of the interrupting task,
then clear the busy-bit in the TSS descriptor of the task removed from
the list.
2. Ensure that no interrupts occur between updating the back-link chain
and the busy bit.

Code: Select all

So I added this: 
	lea		eax, [_irq0_task]
	mov		[eax], dword 0x30
	mov 	[_gdt8 + 5], byte 0x8b ; set busy bit
	mov		[_gdt6 + 5], byte 0x89 ; clear current task busy bit
	jmp		resch2
	
resch1:

	lea		eax, [_irq0_task]
	mov		[eax], dword 0x20
	mov 	[_gdt6 + 5], byte 0x8b ; set busy bit
	mov		[_gdt8 + 5], byte 0x89 ; clear current task busy bit 
..but it still goes on running the previous task , not the next one "in schedule" by tampering the TSS back-link selector field. :shock:

I checked every single line with my own debug routines... there's nothing to do on the stack as with interrupt gates. I dumped the stack and it's clear and empty. All I got were the parameters I pushed myself for the dumpMem proc :D
NaN - Not a Nerd
Working on: Physical Memory Management with a 5-lod mipmap XD
User avatar
Dandee Yuyo
Member
Member
Posts: 47
Joined: Fri Nov 09, 2007 6:46 pm
Location: Argentina

Post by Dandee Yuyo »

Gosh I'm such an idiot. It's perfectly running and it has always been!!!. I was expecting to see "task2" appearing... but I was switching between "kernel idle" and task1... and it's working perfectly. Ouf, sometimes you are so deep in all this hardware details that you forgot what you were expecting as a result. Shame on me! :oops:

Thanks anyway for the chat
NaN - Not a Nerd
Working on: Physical Memory Management with a 5-lod mipmap XD
Post Reply