So I switch into Pmode and I call my kernel when
So I switch into Pmode and I call my kernel when
BOCHS (and my systems) reboot. I setup the GDT properly and call everything correctly. All my PMode code is in my bootloader for now. (My RAW bootloader >: for now).
So it loads my kernel at 1000:0000 (0x10000) and then it opens the A20 gate, sets up the GDT, sets the 386 PM bit then clears the pipe. After that it sets up the other segment registers. Ok so were all happy for now. When I go to jump to my kernel it resets. Looking at the register dump it reveals to me:
[tt]
00000794840e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794840e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794840i[CPU0 ] protected mode
00000794840i[CPU0 ] CS.d_b = 32 bit
00000794840i[CPU0 ] SS.d_b = 32 bit
00000794840i[CPU0 ] | EAX=00000010 EBX=00000000 ECX=00000002 EDX=00000000
00000794840i[CPU0 ] | ESP=00015000 EBP=00000000 ESI=00007343 EDI=0000ffde
00000794840i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00000794840i[CPU0 ] | SEG selector base limit G D
00000794840i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00000794840i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | EIP=00007c73 (00007c73)
00000794840i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000794840i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00000794840i[CPU0 ] >> jmp far 1000:00000000 : EA000000000010
00000794840e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
[/tt]
Not a valid descriptor. It seems pretty valid to me
Now I want to get into the flat memory model like Windows NT and Linux.
My GDT is valid and all the segment registers contain the index value. Code = 08h and Data/Stack = 10h.
I think it is how my kernel is being called.
I do it like "jmp 0x1000:0000". NASM syntax. I know thats prolly whats causing this. But with assembly it could be anything. Can anyone help?
So it loads my kernel at 1000:0000 (0x10000) and then it opens the A20 gate, sets up the GDT, sets the 386 PM bit then clears the pipe. After that it sets up the other segment registers. Ok so were all happy for now. When I go to jump to my kernel it resets. Looking at the register dump it reveals to me:
[tt]
00000794840e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794840e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794840i[CPU0 ] protected mode
00000794840i[CPU0 ] CS.d_b = 32 bit
00000794840i[CPU0 ] SS.d_b = 32 bit
00000794840i[CPU0 ] | EAX=00000010 EBX=00000000 ECX=00000002 EDX=00000000
00000794840i[CPU0 ] | ESP=00015000 EBP=00000000 ESI=00007343 EDI=0000ffde
00000794840i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00000794840i[CPU0 ] | SEG selector base limit G D
00000794840i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00000794840i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794840i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794840i[CPU0 ] | EIP=00007c73 (00007c73)
00000794840i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000794840i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00000794840i[CPU0 ] >> jmp far 1000:00000000 : EA000000000010
00000794840e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
[/tt]
Not a valid descriptor. It seems pretty valid to me
Now I want to get into the flat memory model like Windows NT and Linux.
My GDT is valid and all the segment registers contain the index value. Code = 08h and Data/Stack = 10h.
I think it is how my kernel is being called.
I do it like "jmp 0x1000:0000". NASM syntax. I know thats prolly whats causing this. But with assembly it could be anything. Can anyone help?
Re:So I switch into Pmode and I call my kernel when
After you set protected mode on in CR0, segment registers require a valid selector in the GDT or LDT, not realmode segments (when the segment register is actually being used). So, you'd want to do jmp far 08:10000h rather then jmp far 1000:0000.REV wrote:00000794840i[CPU0 ] >> jmp far 1000:00000000 : EA000000000010
...
My GDT is valid and all the segment registers contain the index value. Code = 08h and Data/Stack = 10h.
Re:So I switch into Pmode and I call my kernel when
Well ok i'll try that.
I have to remove the "far".
Damn it reset! This is the line I put in the code.
[tt]
jmp 08h:10000h
[/tt]
And this is the BOCHS output.
[tt]
00000794842i[CPU0 ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842i[CPU0 ] protected mode
00000794842i[CPU0 ] CS.d_b = 32 bit
00000794842i[CPU0 ] SS.d_b = 32 bit
00000794842i[CPU0 ] | EAX=00000010 EBX=00000000 ECX=00000002 EDX=00000000
00000794842i[CPU0 ] | ESP=00014ffc EBP=00000000 ESI=00007343 EDI=0000ffde
00000794842i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00000794842i[CPU0 ] | SEG selector base limit G D
00000794842i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00000794842i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | EIP=f4fb00fe (f4fb00fe)
00000794842i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000794842i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00000794842i[CPU0 ] >> (invalid) : FFFF
00000794842e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
[/tt]
I have to remove the "far".
Damn it reset! This is the line I put in the code.
[tt]
jmp 08h:10000h
[/tt]
And this is the BOCHS output.
[tt]
00000794842i[CPU0 ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842i[CPU0 ] protected mode
00000794842i[CPU0 ] CS.d_b = 32 bit
00000794842i[CPU0 ] SS.d_b = 32 bit
00000794842i[CPU0 ] | EAX=00000010 EBX=00000000 ECX=00000002 EDX=00000000
00000794842i[CPU0 ] | ESP=00014ffc EBP=00000000 ESI=00007343 EDI=0000ffde
00000794842i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00000794842i[CPU0 ] | SEG selector base limit G D
00000794842i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00000794842i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00000794842i[CPU0 ] | ES:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | FS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | GS:0000( 0000| 0| 0) 00000000 0000ffff 0 0
00000794842i[CPU0 ] | EIP=f4fb00fe (f4fb00fe)
00000794842i[CPU0 ] | CR0=0x00000011 CR1=0 CR2=0x00000000
00000794842i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00000794842i[CPU0 ] >> (invalid) : FFFF
00000794842e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
[/tt]
Re:So I switch into Pmode and I call my kernel when
Notice that it gets exactly two instructions further? That means the jump succeeded but that there either was nothing at 0x10000 or that you mismapped something. The first "instruction" happened to work, the second didn't.REV wrote: Well ok i'll try that.
I have to remove the "far".
d*mn it reset! This is the line I put in the code.
[tt]
jmp 08h:10000h
[/tt]
And this is the BOCHS output.
[tt]
00000794842i[CPU0 ] WARNING: Encountered an unknown instruction (signalling illegal instruction)
[/tt]
Since you're in bochs, is the file that's loaded there pure assembly or did you make some other format?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re:So I switch into Pmode and I call my kernel when
Actually it could've executed any number of instructions... and any one of them could've sent your code out into nowhere00000794842i[CPU0 ] | EIP=f4fb00fe (f4fb00fe)
Try to use the bochs debugger to see where you (should not) end up. We can't fix things by just hearing "triple fault", and probably you know your code better than we do...
Re:So I switch into Pmode and I call my kernel when
That's a pretty good sight there. Since it's 2 instructions on and not one, I'm guessing that the instruction you jumped to (0x10000) is actually a jump or a call or such, that makes this value appear. Do you have a hexdump of the image there?Combuster wrote:Actually it could've executed any number of instructions... and any one of them could've sent your code out into nowhere00000794842i[CPU0 ] | EIP=f4fb00fe (f4fb00fe)
Try to use the bochs debugger to see where you (should not) end up. We can't fix things by just hearing "triple fault", and probably you know your code better than we do...
Re:So I switch into Pmode and I call my kernel when
Well it appears to be when I call my C/C++ code in my second stage code. Im using the orginal Watcom 11.0c for now. It compiles all functions with the underscore on the end. "main_". Im using JLOC as my linker and everything appears to be fine there. Well actually Watcom sticks some "CHK" crap in the objs but JLOC dosn't include them in the image.
I tried all sorts of varations. Jmp and Call don't work. What does one do?
I tried all sorts of varations. Jmp and Call don't work. What does one do?
Re:So I switch into Pmode and I call my kernel when
Do you properly relocate your code? I would expect such an EIP to come from an unrelocated jump to something, or telling your linker the wrong base address.
Also, could you post a hexdump of the first 64 bytes or so of your kernel? the object that's loaded at 0x10000 at least?
Also, could you post a hexdump of the first 64 bytes or so of your kernel? the object that's loaded at 0x10000 at least?
Re:So I switch into Pmode and I call my kernel when
The first 64 bytes give or take
[tt]
00000000 E9 F9 00 FA F4 68 0C 00 00 00 E8 F0 FF FE FF 52 ??.??h....?????R
00000010 68 8E 08 00 00 E8 CF 06 FF FF 83 C4 04 68 A1 08 h?...??.????.h?.
00000020 00 00 E8 C2 06 FF FF 83 C4 04 31 D2 B8 04 00 00 ..??.????.1??...
00000030 00 E8 55 01 FF FF 68 F4 08 00 00 E8 A9 06 FF FF .?U.??h?...??.??
00000040 83 C4 04 31 D2 B8 07 00 00 00 E8 3C 01 FF FF 68 ??.1??....?<.??h
00000050 11 09 00 00 E8 90 06 FF FF 83 C4 04 5A C3 68 08 ....??.????.Z?h.
00000060 00 00 00 E8 97 FF FE FF 80 3D 72 08 00 00 01 75 ...??????=r....u
00000070 07 68 45 09 00 00 EB 05 68 79 09 00 00 E8 67 06 .hE...?.hy...?g.
00000080 FF FF 83 C4 04 C3 68 04 00 00 00 E8 6F FF FE FF ????.?h....?o???
00000090 C3 68 10 00 00 00 E8 64 FF FE FF 51 52 68 B1 09 ?h....?d???QRh?.
000000A0 00 00 E8 42 06 FF FF 83 C4 04 31 C0 A0 7A 08 00 ..?B.????.1? z..
000000B0 00 8B 14 85 CF 0A 00 00 52 E8 2B 06 FF FF 83 C4 .?.??...R?+.????
000000C0 04 68 BB 09 00 00 E8 1E 06 FF FF 83 C4 04 31 C0 .h?...?..????.1?
000000D0 A0 7B 08 00 00 8B 0C 85 CF 0A 00 00 51 E8 07 06 {...?.??...Q?..
000000E0 FF FF 83 C4 04 5A 59 C3 68 04 00 00 00 E8 0D FF ????.ZY?h....?.?
[/tt]
They are all loaded at the same BASE address
[tt]
00000000 E9 F9 00 FA F4 68 0C 00 00 00 E8 F0 FF FE FF 52 ??.??h....?????R
00000010 68 8E 08 00 00 E8 CF 06 FF FF 83 C4 04 68 A1 08 h?...??.????.h?.
00000020 00 00 E8 C2 06 FF FF 83 C4 04 31 D2 B8 04 00 00 ..??.????.1??...
00000030 00 E8 55 01 FF FF 68 F4 08 00 00 E8 A9 06 FF FF .?U.??h?...??.??
00000040 83 C4 04 31 D2 B8 07 00 00 00 E8 3C 01 FF FF 68 ??.1??....?<.??h
00000050 11 09 00 00 E8 90 06 FF FF 83 C4 04 5A C3 68 08 ....??.????.Z?h.
00000060 00 00 00 E8 97 FF FE FF 80 3D 72 08 00 00 01 75 ...??????=r....u
00000070 07 68 45 09 00 00 EB 05 68 79 09 00 00 E8 67 06 .hE...?.hy...?g.
00000080 FF FF 83 C4 04 C3 68 04 00 00 00 E8 6F FF FE FF ????.?h....?o???
00000090 C3 68 10 00 00 00 E8 64 FF FE FF 51 52 68 B1 09 ?h....?d???QRh?.
000000A0 00 00 E8 42 06 FF FF 83 C4 04 31 C0 A0 7A 08 00 ..?B.????.1? z..
000000B0 00 8B 14 85 CF 0A 00 00 52 E8 2B 06 FF FF 83 C4 .?.??...R?+.????
000000C0 04 68 BB 09 00 00 E8 1E 06 FF FF 83 C4 04 31 C0 .h?...?..????.1?
000000D0 A0 7B 08 00 00 8B 0C 85 CF 0A 00 00 51 E8 07 06 {...?.??...Q?..
000000E0 FF FF 83 C4 04 5A 59 C3 68 04 00 00 00 E8 0D FF ????.ZY?h....?.?
[/tt]
They are all loaded at the same BASE address
Re:So I switch into Pmode and I call my kernel when
Theres also this, when you enter protected mode you should already remapped the PIC, or at least keep interrupts disabled until it has been remapped. And for the jmp 08:10000h I'm not sure how NASM assembles it, but its an invalid instruction which was ment for far jumps only, for a near jumps typically you need a label to jump to or a 32bit address reference somewhere in memory, for instance jmp dword ptr [esi] (in masm) where esi is the pointer.REV wrote:00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
Re:So I switch into Pmode and I call my kernel when
They are disabled. These two are the 1st and 2nd exception in a triple fault.Ryu wrote:Theres also this, when you enter protected mode you should already remapped the PIC, or at least keep interrupts disabled until it has been remapped.REV wrote:00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
00000794842e[CPU0 ] interrupt(): gate descriptor is not valid sys seg
The invalid instruction is AFTER the jump. Not the jump itself. That's not saying the jump is right, it might jump into oblivion, but the processor isn't faulting on the jump.And for the jmp 08:10000h I'm not sure how NASM assembles it, but its an invalid instruction which was ment for far jumps only, for a near jumps typically you need a label to jump to or a 32bit address reference somewhere in memory, for instance jmp dword ptr [esi] (in masm) where esi is the pointer.
Give or take... that's half a sector of data.REV wrote: The first 64 bytes give or take
[tt]
00000000 E9 F9 00 FA F4 68 0C 00 00 00 E8 F0 FF FE FF 52 ??.??h....?????R
00000010 68 8E 08 00 00 E8 CF 06 FF FF 83 C4 04 68 A1 08 h?...??.????.h?.
00000020 00 00 E8 C2 06 FF FF 83 C4 04 31 D2 B8 04 00 00 ..??.????.1??...
00000030 00 E8 55 01 FF FF 68 F4 08 00 00 E8 A9 06 FF FF .?U.??h?...??.??
[/tt]
They are all loaded at the same BASE address
The first 5 bytes tell you enough:
[tt]
00000000 E9 F9 00 FA F4
[/tt]
That's, in 16-bit asm or in 16-bit C, a jump to F9 ahead, or to 0x100FC. I guess FA is for an STI (might check, won't bother).
In 32-bit asm, it's a jump into oblivion, namely the oblivion at 0xF4FA00F9(jump relative 32-bit offset) + 0x10000 (current location) + 5 (length of current instruction) == 0xF4FB00FE, which is where your triple fault occured.
Compile your code for 32-bit pmode or switch to 16-bit pmode.
Re:So I switch into Pmode and I call my kernel when
I'm not sure what your mean by this exactly, if they are disabled then how come the two faults? I was about to check the opcode E9 but it seems you pin pointed it.Candy wrote: Theres also this, when you enter protected mode you should already remapped the PIC, or at least keep interrupts disabled until it has been remapped.
They are disabled. These two are the 1st and 2nd exception in a triple fault.
Re:So I switch into Pmode and I call my kernel when
1. You're executing an invalid opcode (unmapped memory in bochs reads all ones, 0xFFFF == invalid opcode).Ryu wrote:I'm not sure what your mean by this exactly, if they are disabled then how come the two faults? I was about to check the opcode E9 but it seems you pin pointed it.Candy wrote: Theres also this, when you enter protected mode you should already remapped the PIC, or at least keep interrupts disabled until it has been remapped.
They are disabled. These two are the 1st and 2nd exception in a triple fault.
2. You don't have an invalid opcode handler (double fault)
3. You don't have a double-fault handler (triple fault)
And then it triple faults. Attempted calls at 2. and 3. are the interrupts you see.
Just checked, FA F4 is cli;hlt. That's not coincidence and not a part of your jump.
Re:So I switch into Pmode and I call my kernel when
Well I do know it is jumping to the correct baseaddress and code. I'll write up all that interrupt handler when I can get it to print my C code so I know this actually works
Here is the code:
[tt]
[extern main_] ;NASM directive for the C function main()
[bits 32] ;NASM directive to use 32-bit instructions
SECTION .text ;NASM directive for code
jmp main_ ;Call the C/C++ code
cli ;Disable interrupts
hlt ;Halt the processor
[/tt]
Why would it be executing an invalid opcode? Im calling the fucntion main?
Here is the code:
[tt]
[extern main_] ;NASM directive for the C function main()
[bits 32] ;NASM directive to use 32-bit instructions
SECTION .text ;NASM directive for code
jmp main_ ;Call the C/C++ code
cli ;Disable interrupts
hlt ;Halt the processor
[/tt]
Why would it be executing an invalid opcode? Im calling the fucntion main?
Re:So I switch into Pmode and I call my kernel when
So again why is this happening when it shouldn't. All the instructions are 32-bit (at least I think so because in my NASM code they use the [bits 32] directive and all the C/C++ code is compiled using the WCC386 compiler from watcom) and all the kernel code starts at base address 0x10000 as linked by JLOC.