Page 1 of 1

setting up TSS restarts

Posted: Mon Mar 31, 2003 12:00 am
by prasikumbhare
Hello to all,

my bootloader enters PM & jumps to image load address 0x600. GDT includes null,linear code(0x08) & linear data (0x10) descriptors.
C kernel  entry function (kmain()) adds to this GDT a TSS descriptor . Then it loads this TSS into task register using LTR. But now it restarts :

what goes wrong here ? is there anything  that needs to be done before setting up TSS.
I will be very greatful & thankful if anybody gives me the solution.


Thanks in advance........

Prasad.

I use gcc(i mean djgpp) , nasm & ld.

// ___________________global.h______________________
// some stuff is copied from alexfru os .

#define GDT_entries     4
#define ACS_PRESENT     0x80
#define ACS_CODE        0x18
#define ACS_DATA        0x10
#define ACS_EXP_DOWN    0x04
#define ACS_CONFORM     0x04
#define ACS_READABLE    0x02
#define ACS_WRITEABLE   0x02

#define ACS_CODE_SEG    (ACS_CODE | ACS_PRESENT)
#define ACS_DATA_SEG    (ACS_DATA | ACS_PRESENT | ACS_WRITEABLE)
#define ACS_STACK_SEG   ACS_DATA_SEG

#define ACS_IDT         ACS_DATA_SEG
#define ACS_INT         0x0E
#define ACS_TRAP        0x0F
#define ACS_TASK 0x05
#define ACS_INT_GATE    (ACS_INT | ACS_PRESENT)
#define ACS_TRAP_GATE   (ACS_TRAP | ACS_PRESENT)
#define ACS_TSS         (0x09 | ACS_PRESENT)
#define ACS_TASK_GATE   (ACS_TASK | ACS_PRESENT)


#define ACS_DPL_0       0x00
#define ACS_DPL_1       0x20
#define ACS_DPL_2       0x40
#define ACS_DPL_3       0x60

#define ATTR_32BIT      0x40
#define ATTR_BIG        0x40
#define ATTR_GRANUL     0x80

#define RPL_0           0x00
#define RPL_1           0x01
#define RPL_2           0x02
#define RPL_3           0x03

typedef struct SEG_DESCRIPTOR
{
  word limit;
  word base0_15;
  byte base16_23;
  byte attrs0_7;
  byte attrs8_15;
  byte base24_31;
} SEG_DESCRIPTOR;

typedef struct GDT_REG
{
word limit;
dword base;
}GDT_REG;

        typedef struct TSS
{
  dword link,
        esp0,
        ss0,
        esp1,
        ss1,
        esp2,
        ss2,
        cr3,
        eip,
        eflags,
        eax,
        ecx,
        edx,
        ebx,
        esp,
        ebp,
        esi,
        edi,
        es,
        cs,
        ss,
        ds,
        fs,
        gs,
        ldtr;
  word  trace,
        io_map_addr;
} TSS;

void kmain();
void setup_GDT();
void setup_IDT();
void setup_TSS();
.........  // other function declaration...
// asm routines are extern..

extern void LGDT  (GDT_REG *gdtr);
extern void SGDT (GDT_REG *gdtr);
extern void LIDT (IDT_REG *idtr);
extern void SIDT  (IDT_REG *idtr);
extern void LTR (dword sel);
extern dword STR();

// _________________ kernel.c __________________________

#include "global.h"

static SEG_DESCRIPTOR  gdt[4];
static INT_DESCRIPTOR  idt[0x31];
static GDT_REG         gdtr;
static IDT_REG         idtr;

TSS    tss;

void kmain()
{
      setup_GDT();
      setup_TSS();
      asm("hlt");      // it does not halt here.
//      setup_IDT();
//      remap_PIC(0x20,0x28);
//      enable_IRQ(1);
//      asm("hlt");          
}

void setup_TSS()
{
  memset (&tss, 0, sizeof(TSS));            // tested works correctly...
  tss.ss0 = 0x10;                     // linear data segment descriptor    

  LTR (0x18);                        // asm routine.  
// restarts now..... If asm("hlt");    is placed before LTR() , it
// hangs .            
// esp is set to oxffff & ss = 0x10 (i.e.linear data seg.desc) by bootloader.
// here is asm part :

}


static void setup_GDT() {
  SEG_DESCRIPTOR *old_gdt;
  GDT_REG old_gdtr;
  int i;

  /* let's copy contents of the old GDT to new GDT and set up the new one */

  SGDT (&old_gdtr);        // asm routine. works correctly.
  old_gdt = (SEG_DESCRIPTOR *) old_gdtr.base;

  for (i=0;i<3;i++)
    gdt[i] = old_gdt[i];

// TSS (18h)

  gdt[3].limit = sizeof(TSS)-1;
  gdt[3].base0_15 = ((dword)(&tss)) & 0xFFFF;
  gdt[3].base16_23 = (((dword)(&tss)) >> 16) & 0xFF;
  gdt[3].base24_31 = (((dword)(&tss)) >> 24) & 0xFF;
  gdt[3].attrs0_7 = ACS_TSS;
  gdt[3].attrs8_15 = 0;

  gdtr.base = (dword) &gdt;
  gdtr.limit = GDT_entries * sizeof(SEG_DESCRIPTOR) - 1;
  LGDT (&gdtr);                       // asm routine works correctly...
}

// here is  asm part

GLOBAL          _LGDT, _SGDT, _LTR, _STR

%define PARAM_1 ebp+8+4*0

[SECTION .text]
[BITS 32]

_LGDT:
        push    ebp
        mov     ebp, esp
        mov     eax, [PARAM_1]
        lgdt    [eax]
        pop     ebp
        ret

_SGDT:
        push    ebp
        mov     ebp, esp
        mov     eax, [PARAM_1]
        sgdt    [eax]
        pop     ebp
        ret

_LTR:
        push    ebp
        mov     ebp, esp
        ltr     [PARAM_1]
        pop     ebp
        ret