BIG problem with kernel TSS.

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
xnix

BIG problem with kernel TSS.

Post 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>
xnix

Re:BIG problem with kernel TSS.

Post 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");

}
xenos

Re:BIG problem with kernel TSS.

Post 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.
Post Reply