[solved] Problem with setting up initial 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
AdMiNeK
Posts: 8
Joined: Wed Jul 02, 2008 1:52 pm
Location: Brodnica, Poland
Contact:

[solved] Problem with setting up initial TSS

Post by AdMiNeK »

Hi,
Sorry for my bad English.
I'm trying to set up initial TSS for my Higher Half Kernel by this code:

Code: Select all

struct tss
{
    unsigned long backlink;
    unsigned long esp0;
    unsigned long ss0;
    unsigned long esp1;
    unsigned long ss1;
    unsigned long esp2;
    unsigned long ss2;
    unsigned long cr3;
    unsigned long eip;
    unsigned long eflags;
    unsigned long eax;
    unsigned long ecx;
    unsigned long edx;
    unsigned long ebx;
    unsigned long esp;
    unsigned long ebp;
    unsigned long esi;
    unsigned long edi;
    unsigned long es;
    unsigned long cs;
    unsigned long ss;
    unsigned long ds;
    unsigned long fs;
    unsigned long gs;
    unsigned long ldt;
    unsigned long bmoffset;
};

void init_tss( struct tss * tss )
{
    printf( "Task State Segment at 0x%X\n", (unsigned long)tss );
    tss -> esp0 = get_esp();
    tss -> ss0 = 0x10;
    tss -> cr3 = get_cr3();
    tss -> es = 0x10;
    tss -> ds = 0x10;
    tss -> fs = 0x10;
    tss -> gs = 0x10;
    tss -> ss = 0x10;
    tss -> cs = 0x08;
    tss -> ldt = 0;
    tss -> bmoffset = 0xFFFF;
}

Code: Select all

struct gdt_desc {
    unsigned short len15_0;
    unsigned short base15_0; 
    unsigned char base23_16; 
    unsigned char flags1; 
    unsigned char flags2;
    unsigned char base31_24;
};

struct gdtr {
    unsigned short size;
    unsigned long * addr;
};

#define ltr(n) __asm__("ltr %%ax"::"a" (n))
#define lgdt(n) __asm__("lgdt (%%eax)"::"a" (n))

void gdt_set_segment( struct gdt_desc * desc, unsigned long base, unsigned long len, unsigned char flags1, unsigned char flags2 )
{
    desc -> len15_0 = (unsigned short)( len & 0xFFFF );
    desc -> base15_0 = (unsigned short)( base & 0xFFFF );
    desc -> base23_16 = (unsigned char)( ( base >> 16 ) & 0xFF );
    desc -> flags1 = flags1;
    desc -> flags2 = flags2 | ( ( len >> 16 ) & 0xF );
    desc -> base31_24 = (unsigned char)( ( base ) >> 24 );
}

void init_gdt( void )
{
    printf( "GDT at 0x%X\n", (unsigned long *)CPU -> gdt );

    gdt_set_segment( &CPU -> gdt[0], 0, 0, 0, 0 ); //Null descriptor
    gdt_set_segment( &CPU -> gdt[1], 0x0, 0xFFFFF, GDT_PRESENT | GDT_APP | GDT_WRITE | GDT_CODE | GDT_DPL0, GDT_GRANULARITY | GDT_USE32 );
    gdt_set_segment( &CPU -> gdt[2], 0x0, 0xFFFFF, GDT_PRESENT | GDT_APP | GDT_WRITE | GDT_DPL0, GDT_GRANULARITY | GDT_USE32 );
    gdt_set_segment( &CPU -> gdt[3], 0x0, 0xFFFFF, GDT_PRESENT | GDT_APP | GDT_WRITE | GDT_CODE | GDT_DPL3, GDT_GRANULARITY | GDT_USE32 );
    gdt_set_segment( &CPU -> gdt[4], 0x0, 0xFFFFF, GDT_PRESENT | GDT_APP | GDT_WRITE | GDT_DPL3, GDT_GRANULARITY | GDT_USE32 );
    init_tss( &CPU -> tss );
    gdt_set_segment( &CPU -> gdt[5], (unsigned long)&CPU -> tss, sizeof( struct tss ), GDT_PRESENT | GDT_SYS | GDT_TSS32, GDT_USE32 );
    
    CPU -> gdtr.size = GDT_MAX * 8 - 1;
    CPU -> gdtr.addr = (unsigned long *)&CPU -> gdt;
    
    lgdt( (unsigned long)&CPU -> gdtr );
    ltr( 5 << 3 );
}
Bochs returns:

Code: Select all

00014043604i[CPU0 ] >> ltr ax : 0F00D8
00014043604p[CPU0 ] >>PANIC<< exception(): 3rd (14) exception with no resolution
00014043604i[CPU0 ] CPU is in protected mode (active)
00014043604i[CPU0 ] CS.d_b = 32 bit
00014043604i[CPU0 ] SS.d_b = 32 bit
00014043604i[CPU0 ] | EAX=00000028  EBX=0002b1a0  ECX=00000040  EDX=000007ff
00014043604i[CPU0 ] | ESP=c012b1f0  EBP=c012b224  ESI=00103000  EDI=0002b317
00014043604i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af pf cf
00014043604i[CPU0 ] | SEG selector     base    limit G D
00014043604i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00014043604i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00014043604i[CPU0 ] | EIP=c010122f (c010122f)
00014043604i[CPU0 ] | CR0=0x80000011 CR1=0 CR2=0x00000040
00014043604i[CPU0 ] | CR3=0x0012d000 CR4=0x00000010
Where I do wrong?
Last edited by AdMiNeK on Thu Jul 03, 2008 11:50 am, edited 1 time in total.
oscoder
Member
Member
Posts: 59
Joined: Mon Mar 27, 2006 12:00 am
Location: UK

Re: Problem with setting up initial TSS

Post by oscoder »

Do you know precisely where the error happens? You could try using bochs in debugging mode, or printing more messages to the screen, to find this out. Out of interest, what output does your OS give to the screen?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with setting up initial TSS

Post by Combuster »

The location of the error is obvious - LTR AX, where AX points to the appropriate GDT entry.

The usual errors are because of the wrong GDT contents. By the looks of it you are setting the D bit where it is reserved (GDT_USE32)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
AdMiNeK
Posts: 8
Joined: Wed Jul 02, 2008 1:52 pm
Location: Brodnica, Poland
Contact:

Re: Problem with setting up initial TSS

Post by AdMiNeK »

Combuster wrote:(...) The usual errors are because of the wrong GDT contents. By the looks of it you are setting the D bit where it is reserved (GDT_USE32)
I've removed GDT_USE32 from TSS descriptor, but I have the same problem again.
oscoder wrote:(...) Out of interest, what output does your OS give to the screen?
OS print:

Code: Select all

GDT at 0xC01050E0
Task State Segment at 0xC01060E0
First 4MB is mapped to 0xC0000000.
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Problem with setting up initial TSS

Post by jnc100 »

Bochs debugger: run 'info gdt' prior to ltr ax.

Regards,
John.
ChristianF
Member
Member
Posts: 79
Joined: Sun Jun 10, 2007 11:36 am

Re: Problem with setting up initial TSS

Post by ChristianF »

Mmmhhh....
I think the Problem is in this line:

Code: Select all

ltr( 5 << 3 );
Remember you start with 0, so it should be 6 instead of 5, because you have 6 Entries and the sixth Entry is the tss.

Code: Select all

ltr( 6 << 3 );

Hope it helps! :lol:
Cheers Christian


*EDIT*
hummmm
Do you want to use Hardware Multitasking?
42
AdMiNeK
Posts: 8
Joined: Wed Jul 02, 2008 1:52 pm
Location: Brodnica, Poland
Contact:

Re: Problem with setting up initial TSS

Post by AdMiNeK »

jnc100 wrote:Bochs debugger: run 'info gdt' prior to ltr ax.

Regards,
John.
Bochs returns:

Code: Select all

Global Descriptor Table (base=0x50e00000, limit=47):
bx_dbg_read_linear: physical address not available for linear 0x50e00000
error: GDTR+8*0 points to invalid linear address 0x 50e00000
bx_dbg_read_linear: physical address not available for linear 0x50e00008
error: GDTR+8*1 points to invalid linear address 0x 50e00000
bx_dbg_read_linear: physical address not available for linear 0x50e00010
error: GDTR+8*2 points to invalid linear address 0x 50e00000
bx_dbg_read_linear: physical address not available for linear 0x50e00018
error: GDTR+8*3 points to invalid linear address 0x 50e00000
bx_dbg_read_linear: physical address not available for linear 0x50e00020
error: GDTR+8*4 points to invalid linear address 0x 50e00000
bx_dbg_read_linear: physical address not available for linear 0x50e00028
error: GDTR+8*5 points to invalid linear address 0x 50e00000
You can list individual entries with 'info gdt [NUM]' or groups with 'info gdt [NUM] [NUM]'
I think base should be 0xC01050E0, but it isn't.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with setting up initial TSS

Post by Combuster »

AdMiNeK wrote:I think base should be 0xC01050E0, but it isn't.
Then fix it :wink:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
AdMiNeK
Posts: 8
Joined: Wed Jul 02, 2008 1:52 pm
Location: Brodnica, Poland
Contact:

Re: Problem with setting up initial TSS

Post by AdMiNeK »

Combuster wrote:
AdMiNeK wrote:I think base should be 0xC01050E0, but it isn't.
Then fix it :wink:
But code looks OK:

Code: Select all

    CPU -> gdtr.size = GDT_MAX * 8 - 1;
    CPU -> gdtr.addr = (unsigned long)&CPU -> gdt;
    lgdt( &CPU -> gdtr );
I added line to check it:

Code: Select all

printf( "0x%X\n", CPU -> gdtr.addr );
but it prints valid address (0xC01050E0)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Problem with setting up initial TSS

Post by Combuster »

Remember that GCC aligns struct members:

2 bytes size (word-aligned)
2 bytes padding
4 bytes offset (dword-aligned)

Which the CPU obviously does not like. Try helping GCC with __attribute__ ((packed))
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
AdMiNeK
Posts: 8
Joined: Wed Jul 02, 2008 1:52 pm
Location: Brodnica, Poland
Contact:

Re: Problem with setting up initial TSS

Post by AdMiNeK »

Combuster wrote:Remember that GCC aligns struct members:

2 bytes size (word-aligned)
2 bytes padding
4 bytes offset (dword-aligned)

Which the CPU obviously does not like. Try helping GCC with __attribute__ ((packed))
It's work! :D

Thank you very much!
Post Reply