Switching Segments Causes Page Fault

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.
bluecode

Re:Switching Segments Causes Page Fault

Post by bluecode »

The error code must be poped of the stack before iret.
@Humble: indeed
TheChuckster

Re:Switching Segments Causes Page Fault

Post 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
B.E

Re:Switching Segments Causes Page Fault

Post 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
TheChuckster

Re:Switching Segments Causes Page Fault

Post 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?
Humble

Re:Switching Segments Causes Page Fault

Post by Humble »

Note:
if its an IRQ handler u should :

Code: Select all

mov   al, 20h
out   20h, al
this for the master pic
B.E

Re:Switching Segments Causes Page Fault

Post 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?
TheChuckster

Re:Switching Segments Causes Page Fault

Post 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!
B.E

Re:Switching Segments Causes Page Fault

Post 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.
TheChuckster

Re:Switching Segments Causes Page Fault

Post 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?
B.E

Re:Switching Segments Causes Page Fault

Post by B.E »

I wonder if your updating the esp value or CurrentTask is wrong
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Switching Segments Causes Page Fault

Post 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"
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Switching Segments Causes Page Fault

Post 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.
TheChuckster

Re:Switching Segments Causes Page Fault

Post 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?
TheChuckster

Re:Switching Segments Causes Page Fault

Post by TheChuckster »

Yeah. Now I'm even more confused than before. What is happening?

Should I be updating esp0 in my TSS?

Anyone?
UM

Re:Switching Segments Causes Page Fault

Post 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...
Post Reply