Page 3 of 4

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 11:52 am
by bluecode
The error code must be poped of the stack before iret.
@Humble: indeed

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 2:17 pm
by TheChuckster
Thank you everybody especially Humble! At least I fixed something even though it still page faults. ;D

The LDTR is invalid from the start even before I multitask. Would fixing this fix my problem?

If so, how do I fix it?

Code: Select all

cs:s=0x0008, dl=0x0000ffff, dh=0x00cf9a00, valid=1
ss:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=7
ds:s=0x0010, dl=0x0000ffff, dh=0x00cf9200, valid=7
es:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
fs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
gs:s=0x0010, dl=0x0000ffff, dh=0x00cf9300, valid=1
ldtr:s=0x0000, dl=0x00000000, dh=0x00000000, valid=0
tr:s=0x0028, dl=0x003e0068, dh=0x00008910, valid=1
What does ldtr mean? Load Task Register? Here's how I'm loading it:

0x28 is my TSS gate descriptor.

mov ax, 0x28
ltr ax

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 4:16 pm
by B.E
ldtr is the Local Discriptor Table Register.
A segment register can either referance the GDT or the LDT for the segment discriptor. for more information see section 2.1.1 of manual 3

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 4:36 pm
by TheChuckster
Ah. I see. So it doesn't matter?

Back to square one. My user apps are writing to invalid addresses (extremely high). Could an invalid stack segment cause that?

If so, how would be stack segment go about being invalid?

Especially when my pushes and pops are FINE. Take a look for yourself.

Code: Select all

   pusha
   push ds
   push es
   push fs
   push gs

   mov eax, 0x10
   mov ds, eax
   mov es, eax
   mov fs, eax
   mov gs, eax

   push esp
   call TaskSwitch
   mov esp, eax

   pop gs
   pop fs
   pop es
   pop ds 
   popa

   iret

Code: Select all

pusha
    push byte 0
    push byte XX ; depends on the interrupt

    pusha
    push ds
    push es
    push fs
    push gs

    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov eax, esp
    push eax
    mov eax, irq_handler
    call eax
    pop eax

    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8
    iret

Code: Select all

isr_common_stub:
    push byte 0
    push byte XX ; depends on the interrupt
    pusha
    push ds
    push es
    push fs
    push gs

    mov ax, 0x10
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    mov eax, esp
    push eax
    mov eax, fault_handler
    call eax
    pop eax

    pop gs
    pop fs
    pop es
    pop ds
    popa

    add esp, 8

    iret
Wait a second? Don't I need a pop esp in the Task Switch?

If not, what are some other possibilities that may be causing this page fault if the isolating factor is merely the introduction of ring 3 tasks into the kernel?

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 4:54 pm
by Humble
Note:
if its an IRQ handler u should :

Code: Select all

mov   al, 20h
out   20h, al
this for the master pic

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 5:18 pm
by B.E
the fact that it is page faulting means that is going to a page that is not present.
how do you set up your page entries?

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 5:37 pm
by TheChuckster
I do send the EOI to the Master PIC via inline assembly in my task switching function. Ring 0 task switching works perfectly, paging and all!

Now as soon as go to Ring 3, my user code is suddenly trying to write to addresses like 0xFFFFFFFC8 (according to CR2 when the exception fires). Exactly the same user code is running -- just at a different priviledge level. How is ring 3 doing this to me?! My stack looks fine!

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 6:23 pm
by B.E

Code: Select all

   push esp
   call TaskSwitch
   mov esp, eax ;what is the value of eax
assigming that eax is zero.

Code: Select all

   pop gs  ;esp = -2 (0xFFFFFFFFE) 
   pop fs   ;esp = -4 (0xFFFFFFFFC) 
   pop es  ;esp = -6 (0xFFFFFFFFA) 
   pop ds  ;esp = -8 (0xFFFFFFFF8) 
   popa    ;esp = -56 (0xFFFFFFFC8)
which means it is a stack overflow.
assuming that your kernel is loaded at 0xC000000 and that the pages are maped as supervisor. the reason why it worked at CPL=0 is because. CPL=0 has complete can access any menory wither it is set to readyonly or not.

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 6:38 pm
by TheChuckster
Thank you. My task switcher returns a value of the stack it WANTS to change to:

return Tasks[CurrentTask].esp0;

By GCC calling conventions that SHOULD go in eax, but it's not. I checked the value of Tasks[CurrentTask].esp0. It is correct. Should I just do some inline assembly to move the value into esp instead?

My kernel is at the 1 MB mark. All RAM past 32 MB is marked unpresent. Surely it would have errored?

Re:Switching Segments Causes Page Fault

Posted: Mon Nov 28, 2005 6:55 pm
by B.E
I wonder if your updating the esp value or CurrentTask is wrong

Re:Switching Segments Causes Page Fault

Posted: Tue Nov 29, 2005 3:51 am
by Pype.Clicker
Ch. 6 " Task Management" , p. 6-7

"The limit field must have a value equal to or greater than 67H, one byte less than the minimum size of a TSS"

Re:Switching Segments Causes Page Fault

Posted: Tue Nov 29, 2005 4:06 am
by Candy
Pype.Clicker wrote: Ch. 6 " Task Management" , p. 6-7

"The limit field must have a value equal to or greater than 67H, one byte less than the minimum size of a TSS"
It probably assumes the G bit is off. If you enable the G-bit, you could probably get away with 67h / 1000h rounded up, or 1. That'd be a full page.

Note, I'm not sure it works with G-bit set.

Re:Switching Segments Causes Page Fault

Posted: Fri Dec 16, 2005 9:23 pm
by TheChuckster
I've revisited the problem today. I'm still absolutely confounded by it.

*--stack = (unsigned int)0x23; // CPL3 SS
*--stack = (unsigned int)Tasks[id].esp0; //ESP

*--stack = 0x200; //This is CPL3 EFLAGS
*--stack = 0x1B; //This is CPL3 CS
*--stack = (unsigned int)thread; //This is EIP

   *--stack = 0; //EAX
   *--stack = 0; //ESI
   *--stack = 0; //EBP
   *--stack = (unsigned int)Tasks[id].esp3; //ESP
   *--stack = 0; //EBX
   *--stack = 0; //EDX
   *--stack = 0; //ECX
   *--stack = 0; //EAX

   *--stack = 0x10; //DS
   *--stack = 0x10; //ES
   *--stack = 0x10; //FS
   *--stack = 0x10; //GS

This inital stack setup is probably the problem. It's just I don't know what to set the ESP field to. That's probably what's messing things up too as well. If said theory is correct that the stack is wrapping to the end of the memory, then the second line is wrong. Right?

Should I be offsetting my ESP0 to point to the END of the initial stack? That would be 64 bytes subtracted from it. Well I just tried it and my theory is wrong. The stack is still being smashed.

Can anyone nudge me on my way to enlightment?

Re:Switching Segments Causes Page Fault

Posted: Fri Dec 16, 2005 9:49 pm
by TheChuckster
Yeah. Now I'm even more confused than before. What is happening?

Should I be updating esp0 in my TSS?

Anyone?

Re:Switching Segments Causes Page Fault

Posted: Fri Dec 23, 2005 7:21 am
by UM
TheChuckster wrote:
*--stack = (unsigned int)Tasks[id].esp0; //ESP
I?m not very sure about this, but i think at this stack position should rather be esp3, not esp0. And because the stack normally grows downward to lower adresses, the esp for a new stack should point to the highest stack address...