Problems With Entering Long Mode
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Problems With Entering Long Mode
Hi,
I have been experimenting with developing a hobby OS and my aim is to boot from 16bit straight to 64bit.
Stage 1 works as expected however stage 2 is where the problem is. I am using the code that was provided by OSDEV.
Please find stage2.asm attached. I couldn't attach the logs from bochs so I have pasted the relevant section here...
03443845852i[BIOS ] Booting from 0000:7c00
03443858917e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
03443858917e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
03443858917i[CPU0 ] CPU is in compatibility mode (active)
03443858917i[CPU0 ] CS.mode = 16 bit
03443858917i[CPU0 ] SS.mode = 16 bit
03443858917i[CPU0 ] EFER = 0x00000500
03443858917i[CPU0 ] | RAX=0000000000000100 RBX=00000000e0000011
03443858917i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
03443858917i[CPU0 ] | RSP=000000000000fffe RBP=0000000000000000
03443858917i[CPU0 ] | RSI=00000000000effde RDI=0000000000000000
03443858917i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
03443858917i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
03443858917i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
03443858917i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
03443858917i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
03443858917i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
03443858917i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
03443858917i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
03443858917i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
03443858917i[CPU0 ] | ES:1000( 0005| 0| 0) 00010000 0000ffff 0 0
03443858917i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
03443858917i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
03443858917i[CPU0 ] | MSR_FS_BASE:0000000000000000
03443858917i[CPU0 ] | MSR_GS_BASE:0000000000000000
03443858917i[CPU0 ] | RIP=00000000000000bc (00000000000000bc)
03443858917i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000007ebc
03443858917i[CPU0 ] | CR3=0x00010000 CR4=0x000000a0
03443858917i[CPU0 ] 0x00000000000000bc: (instruction unavailable) page not present
03443858917e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
03443858917i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
03443858917i[CPU0 ] cpu hardware reset
Appreciate your help.
Thanks, Tony
I have been experimenting with developing a hobby OS and my aim is to boot from 16bit straight to 64bit.
Stage 1 works as expected however stage 2 is where the problem is. I am using the code that was provided by OSDEV.
Please find stage2.asm attached. I couldn't attach the logs from bochs so I have pasted the relevant section here...
03443845852i[BIOS ] Booting from 0000:7c00
03443858917e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
03443858917e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
03443858917i[CPU0 ] CPU is in compatibility mode (active)
03443858917i[CPU0 ] CS.mode = 16 bit
03443858917i[CPU0 ] SS.mode = 16 bit
03443858917i[CPU0 ] EFER = 0x00000500
03443858917i[CPU0 ] | RAX=0000000000000100 RBX=00000000e0000011
03443858917i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
03443858917i[CPU0 ] | RSP=000000000000fffe RBP=0000000000000000
03443858917i[CPU0 ] | RSI=00000000000effde RDI=0000000000000000
03443858917i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
03443858917i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
03443858917i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
03443858917i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
03443858917i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
03443858917i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
03443858917i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
03443858917i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
03443858917i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
03443858917i[CPU0 ] | ES:1000( 0005| 0| 0) 00010000 0000ffff 0 0
03443858917i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
03443858917i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
03443858917i[CPU0 ] | MSR_FS_BASE:0000000000000000
03443858917i[CPU0 ] | MSR_GS_BASE:0000000000000000
03443858917i[CPU0 ] | RIP=00000000000000bc (00000000000000bc)
03443858917i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000007ebc
03443858917i[CPU0 ] | CR3=0x00010000 CR4=0x000000a0
03443858917i[CPU0 ] 0x00000000000000bc: (instruction unavailable) page not present
03443858917e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
03443858917i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
03443858917i[CPU0 ] cpu hardware reset
Appreciate your help.
Thanks, Tony
- Attachments
-
- stage2.asm
- (5.52 KiB) Downloaded 60 times
Re: Problems With Entering Long Mode
Hi,
From the code, it looks like the problem is "lea eax, [es:di + 0x1000]". This instruction ignores segmentation (and the "es:" override does nothing). Because ES was set to 0x1000 (or, ES.base = 0x00010000) you'd have to do "lea eax, [0x00010000 + edi + 0x1000]" instead.
This same bug is repeated 3 times; and means that the first entry in the PML4 doesn't have the correct physical address of the PDPT, the first entry in the PDPT doesn't have the correct physical address of the PD, and the first entry in the PD doesn't have the correct physical address of the PT.
Also note that you know EDI is zero for these instructions, and you could just use "mov eax,0x00010000+0x1000" instead of "lea eax, [0x00010000 + edi + 0x1000]"; and you can do "mov eax,0x00010000+0x1000+PAGE_PRESENT | PAGE_WRITE" and delete the "or" instruction too.
More fun would be to define names for the tables, like this:
And then do:
Cheers,
Brendan
The logs look like the page at 0x00007EBC wasn't identity mapped so as soon as you entered long mode you got a page fault.Tony201300 wrote:Please find stage2.asm attached. I couldn't attach the logs from bochs so I have pasted the relevant section here...
From the code, it looks like the problem is "lea eax, [es:di + 0x1000]". This instruction ignores segmentation (and the "es:" override does nothing). Because ES was set to 0x1000 (or, ES.base = 0x00010000) you'd have to do "lea eax, [0x00010000 + edi + 0x1000]" instead.
This same bug is repeated 3 times; and means that the first entry in the PML4 doesn't have the correct physical address of the PDPT, the first entry in the PDPT doesn't have the correct physical address of the PD, and the first entry in the PD doesn't have the correct physical address of the PT.
Also note that you know EDI is zero for these instructions, and you could just use "mov eax,0x00010000+0x1000" instead of "lea eax, [0x00010000 + edi + 0x1000]"; and you can do "mov eax,0x00010000+0x1000+PAGE_PRESENT | PAGE_WRITE" and delete the "or" instruction too.
More fun would be to define names for the tables, like this:
Code: Select all
%define PML4_phys_address 0x00010000
%define PDPT_phys_address 0x00011000
%define PD_phys_address 0x00012000
%define PT_phys_address 0x00013000
Code: Select all
mov dword [dword es:PML4_phys_address-0x00010000],PDPT_phys_address|PAGE_PRESENT | PAGE_WRITE
mov dword [dword es:PDPT_phys_address-0x00010000],PD_phys_address|PAGE_PRESENT | PAGE_WRITE
mov dword [dword es:PD_phys_address-0x00010000],PT_phys_address|PAGE_PRESENT | PAGE_WRITE
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hello Brendan, many thanks for your quick reply.
I amended the code as you advised but still got the same errors in bochs.
Cheers
I amended the code as you advised but still got the same errors in bochs.
Cheers
Re: Problems With Entering Long Mode
Hello,
It might be a good idea to provide an updated copy of your current code given the number of suggestions as well as an update from the log. Please note that you will need to use these paging structures later (and create page tables) when mapping the kernel into the address space -- so knowing how paging works in detail is critical. The provided code only attempts to map the first 4MB of the address space. Try to keep the code clean and %define where the tables are as suggested above.
It might be a good idea to provide an updated copy of your current code given the number of suggestions as well as an update from the log. Please note that you will need to use these paging structures later (and create page tables) when mapping the kernel into the address space -- so knowing how paging works in detail is critical. The provided code only attempts to map the first 4MB of the address space. Try to keep the code clean and %define where the tables are as suggested above.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hello Neon,
Please find the file attached. The logs are below...
01291445734i[BIOS ] Booting from 0000:7c00
01291458793e[CPU0 ] check_cs(0x0008): not a valid code segment !
01291458793e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
01291458793e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
01291458793i[CPU0 ] CPU is in compatibility mode (active)
01291458793i[CPU0 ] CS.mode = 16 bit
01291458793i[CPU0 ] SS.mode = 16 bit
01291458793i[CPU0 ] EFER = 0x00000500
01291458793i[CPU0 ] | RAX=0000000000000100 RBX=00000000e0000011
01291458793i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
01291458793i[CPU0 ] | RSP=000000000000fffe RBP=0000000000000000
01291458793i[CPU0 ] | RSI=00000000000effde RDI=0000000000000000
01291458793i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
01291458793i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
01291458793i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
01291458793i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
01291458793i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
01291458793i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
01291458793i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
01291458793i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01291458793i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
01291458793i[CPU0 ] | ES:1000( 0005| 0| 0) 00010000 0000ffff 0 0
01291458793i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01291458793i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01291458793i[CPU0 ] | MSR_FS_BASE:0000000000000000
01291458793i[CPU0 ] | MSR_GS_BASE:0000000000000000
01291458793i[CPU0 ] | RIP=00000000000000ba (00000000000000ba)
01291458793i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000
01291458793i[CPU0 ] | CR3=0x00010000 CR4=0x000000a0
01291458793i[CPU0 ] 0x00000000000000ba>> jmpf 0x0008:00e0 : EAE0000800
01291458793e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
01291458793i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
01291458793i[CPU0 ] cpu hardware reset
Please find the file attached. The logs are below...
01291445734i[BIOS ] Booting from 0000:7c00
01291458793e[CPU0 ] check_cs(0x0008): not a valid code segment !
01291458793e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
01291458793e[CPU0 ] interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x0
01291458793i[CPU0 ] CPU is in compatibility mode (active)
01291458793i[CPU0 ] CS.mode = 16 bit
01291458793i[CPU0 ] SS.mode = 16 bit
01291458793i[CPU0 ] EFER = 0x00000500
01291458793i[CPU0 ] | RAX=0000000000000100 RBX=00000000e0000011
01291458793i[CPU0 ] | RCX=00000000c0000080 RDX=0000000000000000
01291458793i[CPU0 ] | RSP=000000000000fffe RBP=0000000000000000
01291458793i[CPU0 ] | RSI=00000000000effde RDI=0000000000000000
01291458793i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
01291458793i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
01291458793i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
01291458793i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
01291458793i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af PF cf
01291458793i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
01291458793i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
01291458793i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01291458793i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
01291458793i[CPU0 ] | ES:1000( 0005| 0| 0) 00010000 0000ffff 0 0
01291458793i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01291458793i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01291458793i[CPU0 ] | MSR_FS_BASE:0000000000000000
01291458793i[CPU0 ] | MSR_GS_BASE:0000000000000000
01291458793i[CPU0 ] | RIP=00000000000000ba (00000000000000ba)
01291458793i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000
01291458793i[CPU0 ] | CR3=0x00010000 CR4=0x000000a0
01291458793i[CPU0 ] 0x00000000000000ba>> jmpf 0x0008:00e0 : EAE0000800
01291458793e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
01291458793i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
01291458793i[CPU0 ] cpu hardware reset
- Attachments
-
- stage2.asm
- (5.98 KiB) Downloaded 59 times
Re: Problems With Entering Long Mode
Hi,
The problem is here:
The "dd GDT" uses the virtual address of the GDT, but the CPU needs the linear address of the GDT. The difference is segmentation again. Basically you need "dd GDT+0x7e00".
Don't forget that for 64-bit code the CPU ignores all segment register base addresses; which will make things very painful. For example, if SS isn't 0x0000 in real mode then SS:RSP will point to somewhere completely different after you've switched long mode, and any labels you use (e.g. "call foo") will need to be manually fixed (e.g. "call foo+0x7E00").
Alternatively; I'd strongly recommend using "org 0x7E00" and changing everything to suit that; including using "CS=DS=SS=0x0000" in real mode (instead of "CS=DS=SS=0x07E0"). This will avoid a lot of confusion/problems.
Cheers,
Brendan
This is a very different bug - you're now in long mode and paging is working correctly; but the CPU doesn't like your GDT (specifically, the CPU is saying that the second entry in the GDT is not a valid code segment).Tony201300 wrote:01291458793i[CPU0 ] 0x00000000000000ba>> jmpf 0x0008:00e0 : EAE0000800
01291458793e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
The problem is here:
Code: Select all
.Pointer:
dw $ - GDT - 1 ; 16-bit Size (Limit) of GDT.
dd GDT ; 32-bit Base Address of GDT. (CPU will zero extend to 64-bit)
Don't forget that for 64-bit code the CPU ignores all segment register base addresses; which will make things very painful. For example, if SS isn't 0x0000 in real mode then SS:RSP will point to somewhere completely different after you've switched long mode, and any labels you use (e.g. "call foo") will need to be manually fixed (e.g. "call foo+0x7E00").
Alternatively; I'd strongly recommend using "org 0x7E00" and changing everything to suit that; including using "CS=DS=SS=0x0000" in real mode (instead of "CS=DS=SS=0x07E0"). This will avoid a lot of confusion/problems.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hi Brendan,
After doing your suggested changes I get the following in the logs....
Booting from 0000:7c00
00018509614i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509617i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509619i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509621i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509623i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509625i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509627i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509629i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509631i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509633i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509635i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509637i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509639i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509641i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509643i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509645i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509647i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509649i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509651i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509653i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509655i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509657i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509659i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509661i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509663i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509665i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509667i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509669i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509671i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509673i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509675i[CPU0 ] MOV_EwSw: can't use this segment register 1
Not sure if I set up cs=ds=ss=0x0000 correctly. Attached is the asm again.
After doing your suggested changes I get the following in the logs....
Booting from 0000:7c00
00018509614i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509617i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509619i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509621i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509623i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509625i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509627i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509629i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509631i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509633i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509635i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509637i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509639i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509641i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509643i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509645i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509647i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509649i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509651i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509653i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509655i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509657i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509659i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509661i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509663i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509665i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509667i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509669i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509671i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509673i[CPU0 ] MOV_EwSw: can't use this segment register 1
00018509675i[CPU0 ] MOV_EwSw: can't use this segment register 1
Not sure if I set up cs=ds=ss=0x0000 correctly. Attached is the asm again.
- Attachments
-
- stage2.asm
- (6.05 KiB) Downloaded 24 times
Re: Problems With Entering Long Mode
Hi,
This would/should cause an invalid opcode exception in real mode; but most BIOSs don't have sane exception handlers and probably just treat the exception like an unsupported software interrupt (e.g. set carry flag and return) causing the same instruction to cause the same exception repeatedly forever.
Cheers,
Brendan
As far as I know; the "mov cs, ax" was a valid instruction on ancient 8086 CPUs (and is accepted by assemblers for that reason) but is not valid on any newer CPU (e.g. maybe 80286 or later?) and you have to use a far jump instead.Tony201300 wrote:Not sure if I set up cs=ds=ss=0x0000 correctly. Attached is the asm again.
This would/should cause an invalid opcode exception in real mode; but most BIOSs don't have sane exception handlers and probably just treat the exception like an unsupported software interrupt (e.g. set carry flag and return) causing the same instruction to cause the same exception repeatedly forever.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hi Brendan,
I have been changing the way cs=ds=ss=0x0000 is set and now bochs crashes immediately when the code is assembled and run.
I have changed the ORG to 0x7e00
Please find the asm attached. Logs are below and since bochs crashes I could only get nothing more then what you see below...
Booting from 0000:7c00
00018514076p[CPU0 ] >>PANIC<< prefetch: getHostMemAddr vetoed direct read, pAddr=0x0000000a0000
I have been changing the way cs=ds=ss=0x0000 is set and now bochs crashes immediately when the code is assembled and run.
I have changed the ORG to 0x7e00
Please find the asm attached. Logs are below and since bochs crashes I could only get nothing more then what you see below...
Booting from 0000:7c00
00018514076p[CPU0 ] >>PANIC<< prefetch: getHostMemAddr vetoed direct read, pAddr=0x0000000a0000
- Attachments
-
- stage2.asm
- (6.19 KiB) Downloaded 21 times
Re: Problems With Entering Long Mode
Hi,
This should be "add eax, 0x1000".
This bug means that virtual address 0x00001000 is the page at physical address 0x00010000 (and not physical address 0x00001000), and the virtual address 0x00007000 (the page of code you're executing when you enable long mode) is the page at physical address 0x00070000 (and not physical address 0x00007000). If you assume that the physical pages at 0x00070000, 0x00080000, 0x00090000 are full of zeros (which look like "add" instructions to the CPU) then as soon as you enable paging you'd be executing zeros in these pages until you get to virtual address 0x0000A000 which is physical address 0x000A0000, which is the VGA display memory (which Bochs doesn't like executing).
This tries to clear 0x10000*4 = 256 KiB of RAM, but it runs in real mode and uses DI which is only 16-bit, so DI will wrap around and it'd actually fill the same 64 KiB four times. This shouldn't have any effect (other than taking longer) because you only need to fill 16 KiB and nothing important is being overwritten.
Once you're in long mode; you've forgotten about SS and should load it.
Also note that in the BIOS may have left the value (e.g.) 0xFFFFFFFFFFFF1234 in RSP, and an instruction like "mov sp, 0x7e00" only effects the lowest 16 bits of this register (which would make RSP=0xFFFFFFFFFFFF7E00), and this is fine when you're in real mode because the CPU only cares about the lowest 16 bits. However; when you start using 64-bit code the CPU uses the entire register and now your stack might cause a page fault (depending on what the BIOS left in RSP). To fix/avoid this you want to do something like "movzx rsp, sp" to clear the highest bits of RSP and make sure the address of the stack stays the same.
Cheers,
Brendan
Tony201300 wrote:00018514076p[CPU0 ] >>PANIC<< prefetch: getHostMemAddr vetoed direct read, pAddr=0x0000000a0000
Code: Select all
; Build the Page Table.
.LoopPageTable:
mov [es:di], eax
add eax, 0x10000
add di, 8
cmp eax, 0x200000 ; If we did all 2MiB, end.
jb .LoopPageTable
This bug means that virtual address 0x00001000 is the page at physical address 0x00010000 (and not physical address 0x00001000), and the virtual address 0x00007000 (the page of code you're executing when you enable long mode) is the page at physical address 0x00070000 (and not physical address 0x00007000). If you assume that the physical pages at 0x00070000, 0x00080000, 0x00090000 are full of zeros (which look like "add" instructions to the CPU) then as soon as you enable paging you'd be executing zeros in these pages until you get to virtual address 0x0000A000 which is physical address 0x000A0000, which is the VGA display memory (which Bochs doesn't like executing).
Code: Select all
; Zero out the 16KiB buffer.
; Since we are doing a rep stosd, count should be bytes/4.
push di ; REP STOSD alters DI.
mov ecx, 0x10000
xor eax, eax
cld
rep stosd
pop di ; Get DI back.
Once you're in long mode; you've forgotten about SS and should load it.
Also note that in the BIOS may have left the value (e.g.) 0xFFFFFFFFFFFF1234 in RSP, and an instruction like "mov sp, 0x7e00" only effects the lowest 16 bits of this register (which would make RSP=0xFFFFFFFFFFFF7E00), and this is fine when you're in real mode because the CPU only cares about the lowest 16 bits. However; when you start using 64-bit code the CPU uses the entire register and now your stack might cause a page fault (depending on what the BIOS left in RSP). To fix/avoid this you want to do something like "movzx rsp, sp" to clear the highest bits of RSP and make sure the address of the stack stays the same.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hi there,
I have completely revamped stage 2 and now I just want to be able to switch to PM and print a message.
Bochs logs...
Booting from 0000:7c00
01440681804e[CPU0 ] jump_protected: gate type 15 unsupported
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
01440681804i[CPU0 ] CPU is in protected mode (active)
01440681804i[CPU0 ] CS.mode = 16 bit
01440681804i[CPU0 ] SS.mode = 16 bit
01440681804i[CPU0 ] EFER = 0x00000000
01440681804i[CPU0 ] | EAX=60000011 EBX=00008000 ECX=0000000c EDX=0000000c
01440681804i[CPU0 ] | ESP=00000000 EBP=00000000 ESI=000effde EDI=00000000
01440681804i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
01440681804i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
01440681804i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
01440681804i[CPU0 ] | ES:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01440681804i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01440681804i[CPU0 ] | EIP=00000023 (00000023)
01440681804i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
01440681804i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
01440681804i[CPU0 ] 0x0000000000000023>> jmpf 0x0008:0028 : EA28000800
01440681804e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
01440681804i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
01440681804i[CPU0 ] cpu hardware reset
I have bolded the lines that I think is telling us something. ASM is attached
Thanks
I have completely revamped stage 2 and now I just want to be able to switch to PM and print a message.
Bochs logs...
Booting from 0000:7c00
01440681804e[CPU0 ] jump_protected: gate type 15 unsupported
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
01440681804i[CPU0 ] CPU is in protected mode (active)
01440681804i[CPU0 ] CS.mode = 16 bit
01440681804i[CPU0 ] SS.mode = 16 bit
01440681804i[CPU0 ] EFER = 0x00000000
01440681804i[CPU0 ] | EAX=60000011 EBX=00008000 ECX=0000000c EDX=0000000c
01440681804i[CPU0 ] | ESP=00000000 EBP=00000000 ESI=000effde EDI=00000000
01440681804i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
01440681804i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
01440681804i[CPU0 ] | CS:07e0( 0004| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | DS:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
01440681804i[CPU0 ] | ES:07e0( 0005| 0| 0) 00007e00 0000ffff 0 0
01440681804i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01440681804i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
01440681804i[CPU0 ] | EIP=00000023 (00000023)
01440681804i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
01440681804i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
01440681804i[CPU0 ] 0x0000000000000023>> jmpf 0x0008:0028 : EA28000800
01440681804e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
01440681804i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
01440681804i[CPU0 ] cpu hardware reset
I have bolded the lines that I think is telling us something. ASM is attached
Thanks
- Attachments
-
- stage2-b.asm
- (2 KiB) Downloaded 51 times
Re: Problems With Entering Long Mode
It's telling you what's wrong:
What do you understand or not from that information?Tony201300 wrote:Hi there,
01440681804e[CPU0 ] jump_protected: gate type 15 unsupported
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
01440681804e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Hi Kiznit,
Could it be referring to IDT?
Could it be referring to IDT?
Re: Problems With Entering Long Mode
The code purposely loads a zero length idt (I am guessing to force a triple fault if an exception occurs.) The jump_protected: gate type 15 unsupported and #GPF though are very strong evidence of the initial cause being an invalid GDT.
Your current code is a bit confusing. Please try the following,
Your current code is a bit confusing. Please try the following,
Code: Select all
; starting in 16 bit code
cli
lgdt [GDTR32]
mov eax, cr0
or al, 0x01 ; enable protected mode
mov cr0, eax
jmp 0x08:complete_flush ;flush cs
align 16
GDTR32:
dw gdt32_end - gdt32 - 1
dq gdt32
align 16
gdt32:
dw 0x0000, 0x0000, 0x0000, 0x0000 ; Null desciptor
dw 0xFFFF, 0x0000, 0x9A00, 0x00CF ; 32-bit code descriptor
dw 0xFFFF, 0x0000, 0x9200, 0x00CF ; 32-bit data descriptor
gdt32_end:
bits 32
align 16
complete_flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; add code here.
cli ; halt cpu.
hlt
Last edited by neon on Thu Aug 13, 2015 11:40 pm, edited 1 time in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
-
- Posts: 12
- Joined: Wed May 27, 2015 9:19 pm
Re: Problems With Entering Long Mode
Thanks Neon.
I don't know what could possibly be wrong with the GDT. The only change I did now to fix it was to change dq to dw..as highlighted.
GDTR32: ; Global Descriptors Table Register Points to GDT
dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one)
dw gdt32 ; linear address of GDT
Bochs reported with exactly the same error as before.
Should an IDT be included with the GDT knowing it's 32bit at the moment
I don't know what could possibly be wrong with the GDT. The only change I did now to fix it was to change dq to dw..as highlighted.
GDTR32: ; Global Descriptors Table Register Points to GDT
dw gdt32_end - gdt32 - 1 ; limit of GDT (size minus one)
dw gdt32 ; linear address of GDT
Bochs reported with exactly the same error as before.
Should an IDT be included with the GDT knowing it's 32bit at the moment