About the ESP0 field...

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.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

About the ESP0 field...

Post by pcmattman »

I have finally been able to have a TSS segment in my GDT without crashing. Now I have a question: what do I put as the ESP0 field when a task switch happens? I know it should be the kernel stack pointer, but what value is that?
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

which ever value you choose. if you allocate a 16 Kilobyte block then you can use the pointer to that block as ESP0, keep in mind that the ESP0 should point to the end of the block.

so in pseudo code:

Code: Select all

char *  stack = kernel_alloc_pages(4);
tss->ESP0 = (int)&stack[16*1024];
Author of COBOS
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

OK... I get that now.

I also want to ask, how can I stop Invalid Opcode errors?

Edit: OK, I did some debugging and found that the ESP value is ok for the first reschedule, then it starts having issues when the ESP value isn't restored properly...

More debugging is going to follow, I'm going to have to figure out how ESP gets trashed. If anyone can peruse my code and point out better ways/problems than I would be extremely grateful.

Edit 2: Found the source of the ESP trashing. If I remove any function calls from tasks, there are no more issues. Now, how to fix it?

Edit 3: Found a really bad way to fix it... It's caused by functions getting pre-empted, stack getting trashed by the pre-emption etc... If I disable multitasking before each function call it works :D
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Can anyone help me here? I've got a rubbish multitasker that I would like to replace with a better one but all my attempts have failed.
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

Try giving each process or task it's own kernel stack. Before you switch tasks you can update the value of ss0 in the TSS. Of course this only makes a difference if the kernel is preemptible. Otherwise that is not the problem. I could show you some of the code from my working multitasking if you think that that it could help you.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

At the moment I'm writing some spaghetti code from the sixth pm mode tutorial (osdever.net) to try to get hardware multitasking working...

If I can get this to work (properly) then I'll implement it properly into my kernel. If not, well, it's back to the drawing board...

Edit: I have a problem. Every time I try to jump to the TSS selector my OS triple faults, Bochs log says:

Code: Select all

00029103836i[CPU0 ] task_switch: bad LDT fetch
00029103836i[CPU0 ] task switch: posting exception 10 after commit point
Any ideas? Do I need an LDT, or can I just get by by setting the TSS's LDT field to 0?
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

I downloaded the cvs repository using rsync, and I checkout out the latest copy from the local cvs repository but I am unable to find you're build scripts or some sort?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

I use batch files with hard-coded paths, so I figured I might save some people some time...

Newest happening: Bochs actually posts a panic (log is below)

Code: Select all

00030361472i[CPU0 ] task_switch: bad LDT fetch
00030361472i[CPU0 ] task switch: posting exception 10 after commit point
00030361472p[CPU0 ] >>PANIC<< fetch_raw_descriptor: LDTR.valid=0
00030361472i[CPU0 ] protected mode
00030361472i[CPU0 ] CS.d_b = 32 bit
00030361472i[CPU0 ] SS.d_b = 32 bit
00030361472i[CPU0 ] | EAX=f000efdf  EBX=f000ff53  ECX=c0001344  EDX=f000ff53
00030361472i[CPU0 ] | ESP=00177f00  EBP=f000ff53  ESI=f000ff53  EDI=f000ff53
00030361472i[CPU0 ] | IOPL=3 id vip vif ac vm RF NT OF DF IF TF sf ZF AF pf CF
00030361472i[CPU0 ] | SEG selector     base    limit G D
00030361472i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00030361472i[CPU0 ] |  CS:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] |  DS:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] |  SS:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] |  ES:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] |  FS:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] |  GS:ff53( 1fea| 0|  3) 00000000 000fffff 1 1
00030361472i[CPU0 ] | EIP=f00099ff (f00099ff)
00030361472i[CPU0 ] | CR0=0x00000019 CR1=0 CR2=0x00000000
00030361472i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00030361472i[CPU0 ] >> (invalid)  : FFFF
EVERYTHING there is wrong. The only time I can get the proper values for the GDT in Bochs debugger is when I put in a while( true ); loop...

Edit: also, the CVS hasn't been updated with my new work...

Edit 2: never mind, it's updated now.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

I tried compiling everything, and assembling anything I could into one big blob in a directory but it appears that some files might still be missing?

It seems like they are going to be some assembler source, or am I wrong?

The linker is having problems finding the isrXX routines, and quite a few others.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Assemble loader.asm, has to be linked in first, has to be elf.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

I think I will wait until you get a decent build script working.

I feel a little discouraged after finally getting it to link only to find that there are more errors and problem.


nasm loader.asm -f elf
gcc loader.o ./net/*.c ./stdlib/*.c ./hdd_pio/*.c ./fdc/*.c ./*.c -fleading-underscore -ffreestanding -o kernel -nostdlib -Xlinker link.link



objdump kernel -x > /tmp/x
grep "MultiBootHeader" /tmp/x

Code: Select all

080480c0 1 .text 00000000 MultiBootHeader
Never the less the whole experienced has bored me so much I am about to start jumping up and down.

\\edit\\
And. I just realized you put the MultiBootHeader in the .text section instead of the data as I was expecting with the linker script...
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

OK, I've been reading and it seems the LDT (according to some code I looked at) can be pointed to the NULL descriptor in the GDT... The problem is, Bochs still complains about an invalid LDT - 'Bad LDT Fetch...'.

I'm about to start pulling my hair out, I've tried so much stuff to make it work! The latest thing I've done is make an LDT with 2 entries which matched the CS and DS selectors in the GDT. I still have problems (Bochs panics, saying LDTR.valid = 0). I've looked at the Bochs source to try to figure out why it's not working but nothing has come up.

Can anyone tell me how to easily setup software multitasking that works, without crashing?

@frank - could you show me your scheduler and task creation code?

Edit: Ok, the problem is in this line:

Code: Select all

__asm__ __volatile__ ( "ljmp $0x20,$0" );
0x20 is the index of the first task's TSS entry n the GDT (ATM the GDT holds one TSS per task, just for testing purposes). Whenver this line executes I get the error.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Ok, here comes the easy list:

1. write some queue management code for the scheduler

2. allocate one stack for each thread, and store info, any required list pointers for the queues, and whatever somewhere. Easiest is at the beginning of the stack area, but separate table is fine as well.

3. write a routine that picks the first thread from the scheduler queue, and switches the current stack to the new threads stack, and stores the old ESP into the old threads info block, such that you can later switch back to it.. this is your scheduler now. it should also add the old thread back into the queue.

4. do some manual "co-operative" multi-threading in kernel without enabling interrupts to make sure everything works correctly and you can have at least three threads switch to each other multiple times. edit: my experience is that stuff that works with two threads might break with a third, but once it works with three, it probably works with ten

5. make sure you have working interrupts and a working clock

6. make the clock drive the scheduling, that is, call the scheduler from the clock interrupts (actually you want to count down a timeshare first, but that's easy to add)

7. test that it works, still without going out of kernel, but this time enable interrupts, and make sure every threads gets run for some time at some points (have one print 'A' and another print 'B' and so on, or something)

8. create a TSS, put it into GDT and load it with LDT. only relevant field is SS0 which should be kernel stack segment. ESP0 we fill in the next step.

9. every time your going out of the kernel, store the address of the byte immediately after the current threads stack in TSS's ESP0 field.. next time you'll come to kernel, it will become your stack again...

10. on kernel entry push all registers, on exit (return) pop them in the same order... you can leave them in the stack while you're in kernel, but get a pointer to them if you need to modify them (you can modify them while they are in the stack).

11. make sure it works.

---

The alternative is to use a single kernel thread, and not do multi-threading in kernel, in which case you can have the same value ESP0 all the time. I actually used that approach initially, but it becomes really mess really fast, and is harder to get working because you'll be debugging ten things at once.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

What you wrote is what I had.

Unfortunately, as I said earlier, the stack got trashed when function calls got pre-empted. I have no idea how to fix that, and I'm currently re-writing my multitasker (with all code in main(), until it works) to figure out how to make it work properly.
User avatar
mystran
Member
Member
Posts: 670
Joined: Thu Mar 08, 2007 11:08 am

Post by mystran »

Make pre-empted multi-threading in kernel work first, worry about TSS then. ESP0 isn't loaded if you get an interrupts while your in kernel, so no need to worry about that.
The real problem with goto is not with the control transfer, but with environments. Properly tail-recursive closures get both right.
Post Reply