Does anyone have an basic (read: very simply) examples on how to do this?

I have read through the intel spec, and some examples from others - but I can't seem to get it.

The simplest example I could find uses 2 TSS', one for the main program and one for the 'child' process - This would work fine for me (if I could get it to work) as the 'main' process can be the IDLE loop, while the child can be the test app I want to load.

Step by step documentation on how to set it up would be great, but I'll take any help I can get :)

Thanks
Posted on 2004-04-13 23:24:17 by Sentient
Okay... first, I assume you are in proper 32bit mode, have set up your GDT with entries for the TSS'es you want to use, and second that you TSS structures are filled out properly :)

Next, before any task switching is done, you must initially load the task register - something along the lines of "mov ax, tsrs_ring0 / ltr ax / clts".

Now, you're basically ready to do a task switch. Depending on your OS kernel, your might do additional initialization either before or after setting up the initial task. I prefer setting up the initial task early, so various faults can be handled through TSS.

Anyway, iirc a taskswithc is as simple as a jmp imm16:imm32 - like "jmp mytss:0". But it's been a while since I messed with this stuff, so I might be wrong. (Oh, and keep in mind that this might be easier to encode in nasm or fasm than masm).
Posted on 2004-04-14 00:00:20 by f0dder
Im using nasm (which I never thought I'd like, but now I love it :) )

I have created a default GDT with 20 entries, with NULL, CODE, DATA, STACK and the rest are NULLS

I load this when I first enter PMode.

Because the file is relocated when its loaded, I dont know the values for the TSS descriptor until after the GDT is loaded - so I recalculate one of the NULL (at the end) descriptors and make it a valid TSS descriptor then reload the GDT via LGDT again. (Is this ok?) :)

Everything else you said makes sense to me, except one thing.

When issuing the:
JMP desc:0x0000

the system will attempt to update the current task's TSS - in particular clearing the Busy flag. How do I handle this?
Posted on 2004-04-14 01:03:19 by Sentient
If anyone can understand this, and spot the problem - it would be hugely appreciated.

When I execute the JMP 0x28:0, i get a GPF


-- START CODE --

GDTR:
DW 6*8-1 ; GDT = 6 Entries
DD BIG_GDT ; GDT Base
BIG_GDT:
; NULL (0x00)
DD 0x00000000
DD 0x00000000
; CODE (0x08)
DD 0x0000FFFF
DD 0x00CF9A00
; DATA (0x10)
DD 0x0000FFFF
DD 0x00CF9200
; STACK (0x18)
DD 0x00000040
DD 0x00C09210
; TASK SELECTOR (0x20)
DD 0x00000000
DD 0x00000000
; TASK SELECTOR (0x28)
DD 0x00000000
DD 0x00000000




ALIGN 16
KERNEL_SEL TIMES 26 DD 0
ALIGN 16
TASK_SEL TIMES 26 DD 0


; link, 00 [2]
; esp0, 04 [4]
; ss0, 08 [2]
; esp1, 0C [4]
; ss1, 10 [2]
; esp2, 14 [4]
; ss2, 18 [2]
; cr3, 1C [4]
; eip, 20 [4]
; eflags, 24 [4]
; eax, 28 [4]
; ecx, 2C [4]
; edx, 30 [4]
; ebx, 34 [4]
; esp, 38 [4]
; ebp, 3C [4]
; esi, 40 [4]
; edi, 44 [4]
; es, 48 [2]
; cs, 4C [2]
; ss, 50 [2]
; ds, 54 [2]
; fs, 58 [2]
; gs, 5C [2]
; ldtr; 60 [2]
; trace 64
; io_map_addr 66 [2]
; LENGTH = 68

;===============================================================================
; CREATE TASK DESCRIPTOR
; : EAX = START EIP
; : NONE
; : NONE
;===============================================================================

; BTW: EAX = MAIN: from another module.

TSS_SETUP:
MOV DWORD , EAX ; EIP

; SETUP KERNEL TSS

MOV WORD , 0 ; Trace
MOV WORD , 0x68 ; IO Map
MOV DWORD , 0x00 ; LDTR
MOV DWORD , 0x10 ; GS
MOV DWORD , 0x10 ; FS
MOV DWORD , 0x10 ; DS
MOV DWORD , 0x18 ; SS
MOV DWORD , 0x10 ; ES
MOV DWORD , 0x08 ; CS
MOV DWORD , 0x3FFFF; ESP
MOV DWORD , 0x202 ; FLAGS
MOV DWORD , 0x18 ; SS0
MOV DWORD , 0x3FFFF; ESP0

; SETUP SELECTOR 0x20
MOV WORD , 0x68
MOV DWORD , KERNEL_SEL
MOV BYTE , 0x89
MOV BYTE , 0x00
MOV EAX, KERNEL_SEL
SHR EAX, 24
MOV BYTE , AL

; SETUP TASK TSS

MOV WORD , 0 ; Trace
MOV WORD , 0x68 ; IO Map
MOV DWORD , 0x00 ; LDTR
MOV DWORD , 0x10 ; GS
MOV DWORD , 0x10 ; FS
MOV DWORD , 0x10 ; DS
MOV DWORD , 0x18 ; SS
MOV DWORD , 0x10 ; ES
MOV DWORD , 0x08 ; CS
MOV DWORD , 0xFFFF ; ESP0
MOV DWORD , 0x18 ; SS0
MOV DWORD , 0x202 ; FLAGS
MOV DWORD , 0xFFFF ; ESP

; SETUP SELECTOR 0x28
MOV WORD , 0x68
MOV DWORD , TASK_SEL
MOV BYTE , 0x89
MOV BYTE , 0x00
MOV EAX, TASK_SEL
SHR EAX, 24
MOV BYTE , AL

; RELOAD NEW DESCRIPTORS
LGDT

; LOAD NULL LDT
XOR EAX, EAX
LLDT AX

; LOAD CURRENT TASK INTO TR
MOV AX, 0x20
LTR AX

; JMP TO NEW TASK 0x28
JMP 0x28:0

RET


Any help greatly appreciated as from best I can tell, I am doing the same as everyone else and following the Intel docs.
Posted on 2004-04-14 04:33:09 by Sentient
Hi Sentient

Maybe the source code of the Menuet Operating System help you!
Install the Menuet in to a floppy disk and read the disk by
using Windows, because the file format of the disk is FAT.

Inside, there is a zip file with the source of the kernel.

The first version was made for NASM, but now is for FASM.

Good luck :alright:

Regards,
Opcode
Posted on 2004-04-14 07:21:53 by Opcode
Ooops,

Here is the link:

http://www.menuetos.org
Posted on 2004-04-14 07:22:37 by Opcode
Thank you for the link.

I just noticed it when I came back to say I had figured it out - not that I'm sure what the problem was.

I just went back to the completely idiot proof, super simple, leave nothing untouched theory and wrote 200+ lines of ASM to initalize everything. Works great now - pre-emptive multitasking with TSS working perfectly (well.. enough for what I wanted anyway) :)

Thanks for all your help guys - Hopefully I can return the favour one day

:alright:
Posted on 2004-04-14 07:50:26 by Sentient