Thing to note is that , some times it works and some times dont work.
Description with code is given below. I am sorry , its a big .
I am writing program for Task switching with Linking on x86 with help of FAR CALL (lcall) and IRET.
I have 3 TASKs ( T1,T2 & T3) with separate TSS and LDT for each task in GDT. I have also made kernel as TASK0 (i.e. T0) with its TSS0 and LDT0 in GDT table.
I have tried to give relevant code only to avoid confusion.
Kernel init code is given below.
Code: Select all
Kernel_init()
{
setGDT();
setIDT();
Init_Timer(); // to 0x20
Sched_init(); // Will initialize the GDT with TSS and LDT for each task and load TR register too
for(;;)
{
if(TimerFlag != 1){
// Wait for First TimerInterrupt ;
// Timer interrupt is used to change the priority
continue;
}
Scheduler();
}
}
Code: Select all
// file task.h
struct TSS_STRUCT {
uint32 back_link;
uint32 esp0, ss0;
uint32 esp1, ss1;
uint32 esp2, ss2;
uint32 cr3;
uint32 eip;
uint32 eflags;
uint32 eax,ecx,edx,ebx;
uint32 esp, ebp;
uint32 esi, edi;
uint32 es, cs, ss, ds, fs, gs;
uint32 ldt;
uint32 trace_bitmap;
};
/* structure of a task*/
struct TASK_STRUCT {
struct TSS_STRUCT tss;
uint64 tss_entry; //descriptor of the TSS entry//
uint64 ldt[2];
uint64 ldt_entry;
sint32 state;
sint32 priority;
ULONG task_tss_sel;
struct TASK_STRUCT *next;
};
Code: Select all
// file task.c
struct TASK_STRUCT *current = &TASK0; // initial setting
Scheduler()
{
unsigned int sel[2], eflags;
struct TASK_STRUCT *v = &TASK0, *tmp = 0;
unsigned int cp;
cp = current->priority;
// This to select task based on priority
for (; v; v = v->next) {
if (((v->state==TS_RUNABLE) && (cp>v->priority))){
tmp = v;
cp = v->priority;
}
}
if (tmp && (tmp != current)) {
current->state = TS_RUNABLE;
tmp->state = TS_RUNNING;
current = tmp;
sel[0]= 0;
sel[1]= current->task_tss_sel;
// Code to do FAR CALL
__asm__ ("lcall %0": :"m" (*sel));
}
}
void do_task3 ()
{
// Write to memory and return
WritetoMemory( 0x3333);
return;
}
Below is code for which T3's EIP is linked in T3's TSS structure.
Code: Select all
// file - task.s
task3_run:
call do_task3 //problem is here
iret
task3_end: jmp task3_run

Can you please help me and let me know , why the "push ebp" instruction is corrupting the GDT entries ?
Code: Select all
// After "push ebp" one GDT entry will look like :
0x00c0890000000067ULL ;// with TSS address as 0x0
// Before "push ebp", one GDT entry will look like :
0xffc089fedae00067ULL; // where fffedae0 is TSS address
Code: Select all
uint64 kgdt[MAX_GDT_ENTRIES] = {
0x0000000000000000ULL , // null -0
0x00cf9b000000FFFFULL, // cs -
0x00cf93000000ffffULL, // ds and ss -2
0x00c0890000000067ULL, // tss0 // 0x18
0x00c082000000000fULL , //ldt 0 //0x20
0x00c0890000000067ULL, // tss1 // 0x28
0x00c082000000000fULL, // ldt1 // 0x30
0x00c0890000000067ULL, // tss2 // 0x38
0x00c082000000000fULL, // ldt2 // 0x40
0x00c0890000000067ULL, // tss3 // 0x48
0x00c082000000000fULL, // ldt3 // 0x50
};