TSS problems
Posted: Fri Aug 30, 2002 11:20 am
I'm working on getting TSS task switching working in my OS, but am having a problem...
I relocate my GDT so that it starts at 0x500:
[tt]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; relocate the GDT to 0x500
mov esi, gdt
mov edi, 0x500
mov ecx, (gdt_end-gdt)
cld
rep movsd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lgdt [gdt_ptr]
[/tt]
My GDT looks like this(in the .data section):
[tt]
gdt: ;our descriptors
; NULL descriptor
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
[global _LINEAR_DATA_SEL]
_LINEAR_DATA_SEL equ $-gdt
dw 0FFFFh
dw 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
[global _LINEAR_CODE_SEL]
_LINEAR_CODE_SEL equ $-gdt
dw 0FFFFh
dw 0
db 0
db 9Ah ; present,ring 0,code,non-conforming,readable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
[global _TSS_ENTRY_0]
_TSS_ENTRY_0 equ $-gdt
desc TSS_START, TSS_SIZE, D_TSS
[global _TSS_ENTRY_1]
_TSS_ENTRY_1 equ $-gdt
desc TSS_START+TSS_SIZE, TSS_SIZE, D_TSS
gdt_end:
gdt_ptr:
dw gdt_end - gdt - 1
dd 0x500
[/tt]
TSS_START is 0x200000 and TSS_SIZE is 0x108.
I use a stucture and a pointer to access the actual TSS data:
[tt]
#pragma pack (push, 1) // this aligns the TSSes to a byte boundary(aligning to a page boundary isn't needed)
// TSS for 386 or higher
struct TSS {
unsigned int link;
unsigned long esp0;
unsigned int ss0;
unsigned long esp1;
unsigned int ss1;
unsigned long esp2;
unsigned int ss2;
unsigned long cr3;
unsigned int eip;
unsigned int eflags;
unsigned int eax;
unsigned int ecx;
unsigned int edx;
unsigned int ebx;
unsigned int esp;
unsigned int ebp;
unsigned int esi;
unsigned int edi;
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
unsigned int fs;
unsigned int gs;
unsigned int ldtr;
unsigned int trace;
unsigned int io_map_addr;
};
#pragma pack (pop) // sets us back to the way we were
struct TSS *our_tsses = (struct TSS *) 0x200000;
[/tt]
I setup 2 TSSes(the very first one stays zeroed 'cause I don't use it):
[tt]
our_tsses[1].cs = read_cs();
our_tsses[1].ss = our_tsses[1].ds = our_tsses[1].es = read_ds();
our_tsses[1].cr3 = 0x9C000;
our_tsses[1].esp = read_esp();
our_tsses[1].eip = (unsigned long)&task_1;
our_tsses[2].cs = read_cs();
our_tsses[2].ss = our_tsses[2].ds = our_tsses[2].es = read_ds();
our_tsses[2].cr3 = 0x9C000;
our_tsses[2].esp = read_esp();
our_tsses[2].eip = (unsigned long)&task_2;
[/tt]
Then, I also have a make descriptor C function and a stucture for descriptors. They may be found here and here.
I replace the last descriptor so it points to the 3rd TSS(our_tsses[2]) so that I can see if it truely works. It doesn't My code for doing this looks like this:
[tt]
DESCRIPTOR *tss_1_descriptor = (DESCRIPTOR *) 0x500;
make_descriptor(&tss_1_descriptor[4], &our_tsses[2], sizeof(our_tsses[2]), D_TSS);
[/tt]
This doesn't work though. When I do a jump to the TSS desciptor(_TSS_ENTRY_1) after modifying(or trying to modify) that descriptor I get a system fault. That does not happen if I don't modify the TSS descriptor. The entire source code may be found here:
http://osdev.neopages.net/downloads/kj/cvs/
if needed.
Thanks in advance,
K.J.
I relocate my GDT so that it starts at 0x500:
[tt]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; relocate the GDT to 0x500
mov esi, gdt
mov edi, 0x500
mov ecx, (gdt_end-gdt)
cld
rep movsd
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
lgdt [gdt_ptr]
[/tt]
My GDT looks like this(in the .data section):
[tt]
gdt: ;our descriptors
; NULL descriptor
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
[global _LINEAR_DATA_SEL]
_LINEAR_DATA_SEL equ $-gdt
dw 0FFFFh
dw 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
[global _LINEAR_CODE_SEL]
_LINEAR_CODE_SEL equ $-gdt
dw 0FFFFh
dw 0
db 0
db 9Ah ; present,ring 0,code,non-conforming,readable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
[global _TSS_ENTRY_0]
_TSS_ENTRY_0 equ $-gdt
desc TSS_START, TSS_SIZE, D_TSS
[global _TSS_ENTRY_1]
_TSS_ENTRY_1 equ $-gdt
desc TSS_START+TSS_SIZE, TSS_SIZE, D_TSS
gdt_end:
gdt_ptr:
dw gdt_end - gdt - 1
dd 0x500
[/tt]
TSS_START is 0x200000 and TSS_SIZE is 0x108.
I use a stucture and a pointer to access the actual TSS data:
[tt]
#pragma pack (push, 1) // this aligns the TSSes to a byte boundary(aligning to a page boundary isn't needed)
// TSS for 386 or higher
struct TSS {
unsigned int link;
unsigned long esp0;
unsigned int ss0;
unsigned long esp1;
unsigned int ss1;
unsigned long esp2;
unsigned int ss2;
unsigned long cr3;
unsigned int eip;
unsigned int eflags;
unsigned int eax;
unsigned int ecx;
unsigned int edx;
unsigned int ebx;
unsigned int esp;
unsigned int ebp;
unsigned int esi;
unsigned int edi;
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
unsigned int fs;
unsigned int gs;
unsigned int ldtr;
unsigned int trace;
unsigned int io_map_addr;
};
#pragma pack (pop) // sets us back to the way we were
struct TSS *our_tsses = (struct TSS *) 0x200000;
[/tt]
I setup 2 TSSes(the very first one stays zeroed 'cause I don't use it):
[tt]
our_tsses[1].cs = read_cs();
our_tsses[1].ss = our_tsses[1].ds = our_tsses[1].es = read_ds();
our_tsses[1].cr3 = 0x9C000;
our_tsses[1].esp = read_esp();
our_tsses[1].eip = (unsigned long)&task_1;
our_tsses[2].cs = read_cs();
our_tsses[2].ss = our_tsses[2].ds = our_tsses[2].es = read_ds();
our_tsses[2].cr3 = 0x9C000;
our_tsses[2].esp = read_esp();
our_tsses[2].eip = (unsigned long)&task_2;
[/tt]
Then, I also have a make descriptor C function and a stucture for descriptors. They may be found here and here.
I replace the last descriptor so it points to the 3rd TSS(our_tsses[2]) so that I can see if it truely works. It doesn't My code for doing this looks like this:
[tt]
DESCRIPTOR *tss_1_descriptor = (DESCRIPTOR *) 0x500;
make_descriptor(&tss_1_descriptor[4], &our_tsses[2], sizeof(our_tsses[2]), D_TSS);
[/tt]
This doesn't work though. When I do a jump to the TSS desciptor(_TSS_ENTRY_1) after modifying(or trying to modify) that descriptor I get a system fault. That does not happen if I don't modify the TSS descriptor. The entire source code may be found here:
http://osdev.neopages.net/downloads/kj/cvs/
if needed.
Thanks in advance,
K.J.