Page 1 of 1

BIG problem with kernel TSS.

Posted: Sun Feb 12, 2006 5:31 am
by xnix
I initialized GDT

Code: Select all

gdt[0]=0;     // not used
  gdt[1]=0;
  /*-------------*/
  gdt[2]=0x0000FFFF;    // code 8
  gdt[3]=0x00CF9A00; 
  /*-------------*/  
  gdt[4]=0x0000FFFF;    // data 10 
  gdt[5]=0x00CF9200;
  /*-------------*/
  gdt[6]=((TSS_KERNEL_MAIN<<16)&0xFFFF0000)|((sizeof( struct TSS))&0x0000FFFF); //18
  gdt[7]=(TSS_KERNEL_MAIN&0xFF000000)|0x8900|((TSS_KERNEL_MAIN>>16)&0x000000FF);
  /*-------------*/
  gdt[8]=0x0000FFFF;    // code 20
  gdt[9]=0x00CFFA80;   
  /*-------------*/
  gdt[10]=0x0000FFFF;    // data 28
  gdt[11]=0x00CFF280;
  /*-------------*/
  //gdt[12]=((TSS_APP<<16)&0xFFFF0000)|((sizeof(struct TSS))&0x0000FFFF); //30
  //gdt[13]=(TSS_APP&0xFF000000)|0x8900|((TSS_APP>>16)&0x000000FF);
  /*-------------*/
  // gdt[14]=((TSS_APP2<<16)&0xFFFF0000)|((sizeof(struct TSS))&0x0000FFFF); //38
  // gdt[15]=(TSS_APP2&0xFF000000)|0x8900|((TSS_APP2>>16)&0x000000FF);

  // TSS app
  g_gdtr[0]=(GDT_MAIN<<16)|0xFFFF;
  g_gdtr[1]=(GDT_MAIN>>16)&0xFFFF;
  //gdt_flush();
  asm("lgdt g_gdtr");
  gdt_flush();
then made

Code: Select all

struct TSS *m=TSS_KERNEL_MAIN;
m->ESP0=0x9000;
m->SS0=0x10;
asm("mov $0x18, %eax\n ltr %ax");
...And processor ignores it.

(0) Breakpoint 1, 0x10026f in ?? ()
Next at t=21701144
(0) [0x0010026f] 0008:0010026f (unk. ctxt): pushad ; 60
<bochs:4> dump_cpu
eax:0x0000000f, ebx:0x0000084f, ecx:0x000b8752, edx:0x000b86b2
ebp:0x00000000, esp:0x00007fac, esi:0x000b8000, edi:0x00000000
eip:0x0010026f, eflags:0x00000006, inhibit_mask:0
cs:s=0x0008, dl=0x0000ffff, dh=0x00cf9a00, valid=1
ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
ldtr:s=0x0000, dl=0x0000ffff, dh=0x00008200, valid=1
tr:s=0x0018, dl=0x1000006c, dh=0x00008907, valid=1
gdtr:base=0x00010000, limit=0xffff
idtr:base=0x00108140, limit=0x7ff
dr0:0x00000000, dr1:0x00000000, dr2:0x00000000
dr3:0x00000000, dr6:0xffff0ff0, dr7:0x00000400
cr0:0x00000011, cr1:0x00000000, cr2:0x00000000
cr3:0x00000000, cr4:0x00000000
done

You can see that esp is incorrect.

info gdt 1 5
GDT[0x01]=Code segment, linearaddr=00000000, len=fffff * 4Kbytes, Execute/Read, 32-bit addrs
GDT[0x02]=Data segment, linearaddr=00000000, len=fffff * 4Kbytes, Read/Write, Accessed
GDT[0x03]=32-Bit TSS (Busy) at 00071000, length 0x0006c
GDT[0x04]=Code segment, linearaddr=00800000, len=fffff * 4Kbytes, Execute/Read, 32-bit addrs
GDT[0x05]=Data segment, linearaddr=00800000, len=fffff * 4Kbytes, Read/Write

<bochs:6> x 0x71000
[bochs]:
0x00071000 <bogus+ 0>: 0x00000000
<bochs:7> x 0x71004
[bochs]:
0x00071004 <bogus+ 0>: 0x00009000
<bochs:8> x 0x71008
[bochs]:
0x00071008 <bogus+ 0>: 0x00000010

SO , I think, all set correct, but on interrupt esp0 doesn't restore.

<edit> please do use "[ code ] ... [ /code ]" to avoid weird display of your code </edit>

Re:BIG problem with kernel TSS.

Posted: Sun Feb 12, 2006 8:15 am
by xnix
I wrote new gdt code, but processor is still ignoring tss ???

#define DWORD unsigned long
struct TSS
{
DWORD back_link;
DWORD ESP0;
DWORD SS0;
DWORD ESP1;
DWORD SS1;
DWORD ESP2;
DWORD SS2;
DWORD CR3;
DWORD EIP;
DWORD EFLAGS;
DWORD EAX;
DWORD ECX;
DWORD EDX;
DWORD EBX;
DWORD ESP;
DWORD EBP;
DWORD ESI;
DWORD EDI;
DWORD ES;
DWORD CS;
DWORD SS;
DWORD DS;
DWORD FS;
DWORD GS;
DWORD LDT;
DWORD offset_andT;
DWORD IOPB;
//unsigned char bitmap[8192];
};

struct gdt_entry
{
unsigned short limit_low;
unsigned short base_low;
unsigned char base_middle;
unsigned char access;
unsigned char granularity;
unsigned char base_high;
} __attribute__((packed));

struct gdt_ptr
{
unsigned short limit;
unsigned int base;
} __attribute__((packed));

/* Our GDT, with 3 entries, and finally our special GDT pointer */
struct gdt_entry gdt[6];
struct gdt_ptr gp;


extern void gdt_flush();


void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran)
{

gdt[num].base_low = (base & 0xFFFF);
gdt[num].base_middle = (base >> 16) & 0xFF;
gdt[num].base_high = (base >> 24) & 0xFF;


gdt[num].limit_low = (limit & 0xFFFF);
gdt[num].granularity = ((limit >> 16) & 0x0F);


gdt[num].granularity |= (gran & 0xF0);
gdt[num].access = access;
}

struct TSS TSS;
void gdt_install()
{

gp.limit = (sizeof(struct gdt_entry) * 6) - 1;
gp.base = &gdt;
gdt_set_gate(0, 0, 0, 0, 0);

gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);

gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // user code
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // user data
gdt_set_gate(5, &TSS, sizeof(TSS), 0x89, 0xCF);
// for(;;);
gdt_flush();
//for(;;);

}

void init_TSS()
{
TSS.ESP0=0x9000;
TSS.SS0=0x10;

asm("mov $0x28, %eax\n ltr %ax");

}

Re:BIG problem with kernel TSS.

Posted: Mon Feb 13, 2006 12:10 am
by xenos
The contents of a TSS is NOT loaded into the registers upon an ltr instruction. The ltr instruction rather sets the TSS to some memory location where the registers are saved when a task switch occurs. The stack pointers SS0:ESP0 etc. are loaded when an interrupt into a different privilege level occurs.

To load the values from a TSS into the registers, you need to perform a far jump to that TSS, i.e. in your case "jmp far 0x28:0". You need to make sure that this TSS is marked as available in the GDT. And there must be a second TSS which has been previously loaded into the task register using the ltr instruction because the processor will save its register contents in this TSS.