LTR doesn't like my TSS descriptor.

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.
mr. x2

LTR doesn't like my TSS descriptor.

Post by mr. x2 »

I'm feeding LTR with 0x20 (ti = 0, dpl = 0, index = 4).
My descriptor at entry 4 in the GDT is 0x4A800068 (00000000000000000000000000000000 1001010100000000000000001101000b).

The error from bochs is:
LTR: doesn't point to an available TSS descriptor!

There may be two's of stuff, but this code is just experimenting.

Code: Select all

int InitializeMemManager() {
        SetupGDTDescriptor(0, 0x0, 0x0, 0x0, 0x0, 0x0);
        SetupGDTDescriptor(1, 0x0, 0xFFFFF, GDT_DPL0|GDT_READABLE|GDT_SEG_CODE|GDT_PRESENT, GDT_286_CALL_GATE, 1);
        SetupGDTDescriptor(2, 0x0, 0xFFFFF, GDT_DPL0|GDT_READABLE|GDT_SEG_DATA|GDT_PRESENT, GDT_286_CALL_GATE, 1);

        InitTask(0, task1);

        SetGDTDesc(4, getTasks(), sizeof(tss_seg), 0x9, SEG_DESC_ATTR_PRESENT|SEG_DESC_ATTR_SYSTEM, SEG_DESC_ATTR2_32BIT);
        
        LoadGDTDescriptor(20);
        LoadTaskRegister(getSelector(4, 0, 0));
    
        return 0;
}

Code: Select all

#define SEG_DESC_ATTR_SYSTEM    0x1 // 0001b
#define SEG_DESC_ATTR_DPL0              0x0 // 0000b
#define SEG_DESC_ATTR_DPL1      0x2     // 0010b
#define SEG_DESC_ATTR_DPL2      0x4     // 0100b
#define SEG_DESC_ATTR_DPL3      0x6     // 0110b
#define SEG_DESC_ATTR_PRESENT   0x8     // 1000b

#define SEG_DESC_ATTR2_AVAIL    0x1     // 0001b
#define SEG_DESC_ATTR2_32BIT    0x4     // 0100b
#define SEG_DESC_ATTR2_GRAN             0x8     // 1000b


typedef struct {
        uint16 low_limit;
        uint16 low_base;
        uint8 middle_base;
        uint8 settings;
        uint8 high_limit:4;
        uint8 attributes:3;
        uint8 granularity:1;
        uint8 high_base;
} ATTR_PACKED x86_gdt;


typedef struct {
        uint16 limit;
        x86_gdt* base;
} ATTR_PACKED gdtr;


typedef struct {
        uint8 rpl:2;
        uint8 ti:1;
        uint16 index:13;
} ATTR_PACKED seg_selector;


typedef struct {
        uint16 limit_0_15;
        uint16 base_0_15;
        uint8 base_16_23;
        uint8 type:4;
        uint8 attr:4;
        uint8 limit_16_19:4;
        uint8 atrr2:4;
        uint8 base_24_31;
} ATTR_PACKED seg_descriptor;




x86_gdt g_GDT[256] = {0};

void SetGDTDesc(uint16 _num, uint32 _base, uint32 _limit, uint8 _type, uint8 _attr, uint8 _attr2) {
        seg_descriptor *pDesc = &g_GDT[_num];
        pDesc->base_0_15 = (uint16)_base;
        pDesc->base_16_23 = (uint8)(_base >> 16);
        pDesc->base_24_31 = (uint8)(_base >> 24);
        pDesc->limit_0_15 = (uint16)_limit;
        pDesc->limit_16_19 = (uint8)(_limit >> 16);
        pDesc->type = _type;
        pDesc->attr = _attr;
        pDesc->atrr2 = _attr2;


}

void SetupGDTDescriptor(uint32 _selector, uint32 _base, uint32 _limit, uint32 _settings, uint32 _attributes, uint8 _granul$
        _settings |= 0x10;

        g_GDT[_selector].attributes = _attributes;
        g_GDT[_selector].settings = _settings;
        g_GDT[_selector].granularity = _granularity;
        g_GDT[_selector].low_base = (uint16)_base;
        g_GDT[_selector].middle_base = (uint8)(_base >> 16);
        g_GDT[_selector].high_base = (uint8)(_base >> 24);
        g_GDT[_selector].low_limit = (uint16)_limit;
        g_GDT[_selector].high_limit = (uint8)(_limit >> 16);
}

Code: Select all

#define TSS_DPL0 0x00
#define TSS_DPL1 0x20
#define TSS_DPL2 0x40
#define TSS_DPL3 0x60

#define TSS_PRESENT 0x80

#define EFLAGS_V86 0x40000

typedef struct {
        uint8 reserved1;
        uint8 type:4;
        uint8 reserved2:1;
        uint8 dpl:2;
        uint8 p:1;
} ATTR_PACKED task_gate;




typedef struct {
        uint16 seg_limit_0_15;
        uint16 addr_0_15;
        uint8 addr_16_23;
        uint8 type;
        uint8 seg_limit_16_19;
        uint8 addr_24_31;
} ATTR_PACKED tss_desc;

typedef struct {
        uint16 backlink, _blh;
        uint32 esp0;
        uint16 ss0, _ss0h;
        uint32 esp1;
        uint16 ss1, _ss1h;
        uint32 esp2;
        uint16 ss2, _ss2h;
        uint32 cr3;
        uint32 eip;
        uint32 eflags;
        uint32 eax;
        uint32 ecx;
        uint32 edx;
        uint32 ebx;
        uint32 esp;
        uint32 ebp;
        uint32 esi;
        uint32 edi;
        uint16 es, _esh;
        uint16 cs, _csh;
        uint16 ss, _ssh;
        uint16 ds, _dsh;
        uint16 fs, _fsh;
        uint16 gs, _gsh;
        uint16 ldt, _ldth;
        uint16 trace, iomapbase;
} ATTR_PACKED tss_seg;


tss_seg g_Tasks[10];

void InitTask(uint8 _num, void *_task) {
        g_Tasks[_num].esp = 0xFFFF;
        g_Tasks[_num].es = 0x8;
        g_Tasks[_num].cs = 0x10;
        g_Tasks[_num].ss = 0x18;
        g_Tasks[_num].ds = 0x8;
        g_Tasks[_num].fs = 0x0;
        g_Tasks[_num].gs = 0x0;
        g_Tasks[_num].eip = _task;
        g_Tasks[_num].eflags = 0x0002;
        g_Tasks[_num].iomapbase = sizeof(tss_seg);
}




seraph9

Re:LTR doesn't like my TSS descriptor.

Post by seraph9 »

Code: Select all

[quote]
        
        LoadGDTDescriptor(20);

I couldn't completely understand the code, but shouldn't it be 0x20 instead of 20. Just guessing, 20 seems to be the odd one in there. please do correct me if I'm wrong.

Vivek[/quote]
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

It's worked all the time when it was 20, so that's not the problem :(
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:LTR doesn't like my TSS descriptor.

Post by Brendan »

Hi,
mr. x2 wrote: I'm feeding LTR with 0x20 (ti = 0, dpl = 0, index = 4).
My descriptor at entry 4 in the GDT is 0x4A800068 (00000000000000000000000000000000 01001010100000000000000001101000b).
I'm assuming (based on binary) that your GDT entry is 0x00000000:0x4a800068, which would imply that the base is 0x4a80 (can't check if that's right), the limit is 104 bytes (which is right), and that the type is 0x00 and it's not marked as present (which would cause your trouble).

Everything that creates this descriptor looks correct, but then I've no way of telling what the compiler is generating (I've heard some compilers don't pack structures as expected - ANSI C isn't very specific). In any case I'd recommend checking the assembly generated by the compiler (if my earlier assumption is right).

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

OK, the compiler packs data together correct and it's working for paging etc.
My descriptor is now low32:0x4A800068 high32:0x409914
low32: 1001010100000000000000001101000b
high32: 00000000010000001001100100010100b
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

Oh well, I think it's working now! It doesn't complain anyway!
The problem was that I entered a 1 where it should be a 0, and the present bit wasn't set.
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

Sorry for replying to my own thread this much, but there's another problem. I can't switch task :(

Code: Select all

InitTask(0, test);
InitTask(1, test2);

SwitchTask(getSelector(4, 0, 0));
Will result in this:
jump_protected: cs == 0
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

Oh, I forgot to post the SwitchTask function.

Code: Select all

void SwitchTask(uint16 _selector) {
        uint16 iSel[2];
        iSel[0] = _selector;

        asm("ljmp $0x8:%0"::"m"(*iSel));
}
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:LTR doesn't like my TSS descriptor.

Post by Brendan »

Hi,
mr. x2 wrote: Oh, I forgot to post the SwitchTask function.

Code: Select all

void SwitchTask(uint16 _selector) {
        uint16 iSel[2];
        iSel[0] = _selector;

        asm("ljmp $0x8:%0"::"m"(*iSel));
}
Is GDT offset 0x08 a TSS? Offset 0x08 would be GDT entry 1... From original code:

Code: Select all

        SetupGDTDescriptor(1, 0x0, 0xFFFFF,GDT_DPL0|GDT_READABLE|GDT_SEG_CODE|GDT_PRESENT, GDT_286_CALL_GATE, 1);
Perhaps you meant:

Code: Select all

        asm("ljmp $0x40:%0");

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

The ljmp was just an experiment ;), inline asm in GCC didn't want me to do that, "asm("ljmp %0")" would work though, but it would generate that error message later on.
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

Hahaha, I can't think!
asm("ljmp $0x20,0x0") is working, but it's now complaining about it's a busy task, but I'll see if I can fix that.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:LTR doesn't like my TSS descriptor.

Post by Brendan »

Hi,

So did you mean this?

Code: Select all

void SwitchTask(uint16 _selector) {
        uint32 iSel[2];
        iSel[1] = _selector * 8;

        asm("ljmp (%0)"::"m"(*iSel));
}
If this is a task switch then the offset is ignored. Also I've got no idea what "getSelector()" returns and inline GAS isn't my specialty (I usually use NASM)...

In NASM I'd do something like:

Code: Select all

            section .bss
currentTSS:    resw 1
            section .text

SwitchTask:
            mov [currentTSS],ax
            jmp far [currentTSS-4]

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

There's another problem now. (new problems pop up all the time :()
When I jump to a TSS I get a General Protection Fault followed by lots of page faults.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:LTR doesn't like my TSS descriptor.

Post by Pype.Clicker »

did you fill your TSS with correct value for segments (esp. stack & code ?)
are you trying to start user or kernel code through that TSS ?
mr. x2

Re:LTR doesn't like my TSS descriptor.

Post by mr. x2 »

Pype.Clicker wrote: did you fill your TSS with correct value for segments (esp. stack & code ?)
are you trying to start user or kernel code through that TSS ?
CS and SS and every segment register is the same as the kernel.
The code is kernel, and the task is a ring 0 one.
Post Reply