Strange long mode fault on real computer

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.
Post Reply
sevobal
Member
Member
Posts: 63
Joined: Sun Oct 22, 2006 7:11 am

Strange long mode fault on real computer

Post by sevobal »

Hey guys!
I'm having a strange bug in my system and I decided to ask you.
I've written a bootloader which enters protected mode (without paging), copies my Kernel to 0x00400000, enables the long mode after setting up PML4 and jumps to 00400000 where my Kernel is located. Everything works good till here.

But now I've a very strange problem. In virtual machines on Vmware Workstation, Vmware Fusion and Microsoft Hyper-V everything work as it should (Interrupts, Kernel and so on), but my real computer reboots directly after the first call instruction in my kernel and I dont know why. No exception, just a reboot.

So I decided to wirte a simple "test-kernel" to explorer this bug and I found out that the following code works perfectly on the real machine:

Code: Select all

[BITS 64]
[ORG 0x0000000000400000]
	

; configuration data for my os    
    mov dword [0x0000000000100000], 0x000B88C0
    mov byte [0x000000000010000C], 0x07
    mov byte [0x000000000010000D], 0x03
    mov byte [0x0000000000800000], 0x00
    mov r10, 0x0000000000000000
	
test_1:
	hlt
	jmp test_1
But simple code like this causes a direct reboot:

Code: Select all

[BITS 64]
[ORG 0x0000000000400000]
	

; configuration data for my os    
    mov dword [0x0000000000100000], 0x000B88C0
    mov byte [0x000000000010000C], 0x07
    mov byte [0x000000000010000D], 0x03
    mov byte [0x0000000000800000], 0x00
    mov r10, 0x0000000000000000

  call make_terminal

test_1:
	hlt
	jmp test_1

make_terminal_x64:
    mov r9, terminal
    call print.line
    
    mov dword ebx, [0x0000000000100000]
    sub ebx, 0xA0
    mov dword [0x0000000000100000], ebx
    
    mov r10, 0x0000000000000004
    mov al, 0xDB
    mov cl, 0x87
    call print.char.colored
    ret
The strange thing is that on emulated machines both codes are working as they should. Also my regular non "test-kernel" works as it should on emulated machines.
It's very difficult to locate the problem if my real machine just reboots. Because of this I decieded to show you my PML4, long mode GDT and long mode IDT. Maybe there is a problem I've not found.

PML4 Code:

Code: Select all

setup_PML4:
    ; *** Map the first 10 MB of memory ***
        
    ; PML4 located at 0x70000:
    mov dword [0x70000], 0x71000 + 111b                    ; 1st PML4 Entry -> PDP table.
    
	; PDP located at 0x71000:
    mov dword [0x71000], 72000h + 111b                    ; 1st PDP Entry -> PD table.
    
	; PD located at 0x72000:
    mov dword [0x72000 + (8*0)], 0x73000 + 111b   ; 1st PD Entry -> 0 MB
    mov dword [0x72000 + (8*1)], 0x74000 + 111b   ; 2nd PD Entry -> 2 MB
    mov dword [0x72000 + (8*2)], 0x75000 + 111b   ; 3rd PD Entry -> 4 MB
    mov dword [0x72000 + (8*3)], 0x76000 + 111b   ; 4th PD Entry -> 6 MB
    mov dword [0x72000 + (8*4)], 0x77000 + 111b   ; 5th PD Entry -> 8 MB
    ;          address   entry    frame      flags

    mov     edi,73000h              ; address of first page table 
    mov     eax,0 + 111b 
    mov     ecx,512                 ; number of pages to map (0-2 MB)
    call make_page_entries
    
    mov     edi,0x74000            
    mov     eax,0x200000 + 111b
	mov     ecx,512                 ; number of pages to map (2-4 MB)
    call make_page_entries
    
    mov     edi,0x75000              
    mov     eax,0x400000 + 111b
	mov     ecx,512                 ; number of pages to map (4-6 MB)
    call make_page_entries
    
    mov     edi,0x76000              
    mov     eax,0x600000 + 111b
	mov     ecx,512                 ; number of pages to map (6-8 MB)
    call make_page_entries
    
    mov     edi,0x77000              
	mov     eax,0x800000 + 111b
    mov     ecx,512                 ; number of pages to map (8-10 MB)
    call make_page_entries
	
    ret
     
make_page_entries: 
    stosd 
    add     edi,4 
    add     eax,1000h 
    loop    make_page_entries
    ret
long mode GDT code:

Code: Select all

gdtr_x64: dw gdt_end_x64 - gdt_x64 - 1	; GDT limit
			    dq gdt_x64                ; (GDT base gets set above)

gdt_x64:
    dw 0
    dw 0
    db 0
    db 0
    db 0
    db 0

LINEAR_SEL_X64 equ $-gdt_x64
    dw 0xFFFF
    dw 0x0000
    db 0x00
    db 10010010b
    db 0xAF
    db 0x00

SYS_CODE_SEL_X64 equ $-gdt_x64
gdt1_x64:
     dw 0xFFFF
     dw 0x0000
     db 0x00
     db 10011010b
     db 0xAF
     db 0x00
    
SYS_DATA_SEL_X64 equ $-gdt_x64
gdt2_x64:
    dw 0xFFFF
    dw 0x0000
    db 0x00
    db 10010010b
    db 0xAF
    db 0x00
    
gdt_end_x64:
long mode IDT:

Code: Select all

;*******************************************************************************************************
;* Interrupt Deskriptor Tabelle für den 64-Bit Modus von Project-K                                     *
;* Teil von "Project-K"                                                                                *
;* (c) 2007-2008 Sebastian Langer                                                                      *
;*******************************************************************************************************

%macro mkirqring0_x64 2 ;make exception interrupt for ring 0 (operatingsystem)
        dw %1  ;offset
        dw %2  ;selector
        db 0
        db 10001110b
        dw 0
        dq 0
%endmacro

%macro mkirqring0_x641 2 ;make hardware interrupt for ring 0 (operatingsystem)
        dw %1  ;offset
        dw %2  ;selector
        db 0
        db 10001111b
        dw 0
        dq 0
%endmacro

;*************************************
;* Die IDT mit und ihre Deskriptoren *
;*************************************
start_of_idt_X64:

;*****************************
;* Interrupts für Exceptions *
;*****************************
mkirqring0_x64 IRQ_00h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_01h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_02h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_03h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_04h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_05h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_06h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_07h_x64,SYS_CODE_SEL_X64 ;Interrupt 07 fpu nicht installiert
mkirqring0_x64 IRQ_08h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_09h_x64,SYS_CODE_SEL_X64 ;Interrupt 09 fpu register?berlauf und keyboard events
mkirqring0_x64 IRQ_0ah_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_0bh_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_0ch_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_0dh_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_0eh_x64,SYS_CODE_SEL_X64
dq 0                                        ;Reserviert
dq 0
mkirqring0_x64 IRQ_10h_x64,SYS_CODE_SEL_X64
mkirqring0_x64 IRQ_11h_x64,SYS_CODE_SEL_X64 ;
mkirqring0_x64 IRQ_12h_x64,SYS_CODE_SEL_X64 ;Machine-Check Exception (#MC)
mkirqring0_x64 IRQ_13h_x64,SYS_CODE_SEL_X64 ;SIMD Floating-Point Exception (#XM)
TIMES 24 dq 0                               ;Reserviert

;*******************************
;* Interrupts für die Hardware *
;*******************************
mkirqring0_x641 IRQ_20h_x64,SYS_CODE_SEL_X64 ; Timer
mkirqring0_x641 IRQ_21h_x64,SYS_CODE_SEL_X64 ; Tastatur
mkirqring0_x641 IRQ_22h_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_23h_x64,SYS_CODE_SEL_X64 ; Com 2
mkirqring0_x641 IRQ_24h_x64,SYS_CODE_SEL_X64 ; Com 1
mkirqring0_x641 IRQ_25h_x64,SYS_CODE_SEL_X64 ; LPT 2
mkirqring0_x641 IRQ_26h_x64,SYS_CODE_SEL_X64 ; FDD
mkirqring0_x641 IRQ_27h_x64,SYS_CODE_SEL_X64 ; LPT 1
mkirqring0_x641 IRQ_28h_x64,SYS_CODE_SEL_X64 ; CMOS Real Time Clock
mkirqring0_x641 IRQ_29h_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_2ah_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_2bh_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_2ch_x64,SYS_CODE_SEL_X64 ; PS / 2 Maus (u.U.)
mkirqring0_x641 IRQ_2dh_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_2eh_x64,SYS_CODE_SEL_X64 ; unbenutzt
mkirqring0_x641 IRQ_2fh_x64,SYS_CODE_SEL_X64 ; unbenutzt

;*********************************
;* Interrupts für die System API *
;*********************************
mkirqring0_x641 IRQ_30h_x64,SYS_CODE_SEL_X64

end_of_idt_X64:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; now for the IDT pointer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
idt_pointer_X64:
  dw end_of_idt_X64 - start_of_idt_X64 - 1
  dq start_of_idt_X64

IRQ_00h_x64:
  call make_bluescreen_x64
  call handle_irq00_x64
  cli
  hlt 

IRQ_01h_x64:
  call make_bluescreen_x64
  call handle_irq01_x64
  cli
  hlt

IRQ_02h_x64:
  call make_bluescreen_x64
  call handle_irq02_x64
  cli
  hlt

IRQ_03h_x64:
  call make_bluescreen_x64
  call handle_irq03_x64
  cli
  hlt

IRQ_04h_x64:
  call make_bluescreen_x64
  call handle_irq04_x64
  cli
  hlt

IRQ_05h_x64:
  call make_bluescreen_x64
  call handle_irq05_x64
  cli
  hlt

IRQ_06h_x64:
  call make_bluescreen_x64
  call handle_irq06_x64
  cli
  hlt
  
IRQ_07h_x64:
  call make_bluescreen_x64
  call handle_irq07_x64
  cli
  hlt

IRQ_08h_x64:
  call make_bluescreen_x64
  call handle_irq08_x64
  cli
  hlt

IRQ_09h_x64:
  call make_bluescreen_x64
  call handle_irq09_x64
  cli
  hlt

IRQ_0ah_x64:
  call make_bluescreen_x64
  call handle_irq0A_x64
  cli
  hlt

IRQ_0bh_x64:
  call make_bluescreen_x64
  call handle_irq0B_x64
  cli
  hlt

IRQ_0ch_x64:
  call make_bluescreen_x64
  call handle_irq0C_x64
  cli
  hlt

IRQ_0dh_x64:
  call make_bluescreen_x64
  call handle_irq0D_x64
  cli
  hlt

IRQ_0eh_x64:
  call make_bluescreen_x64
  call handle_irq0E_x64
  cli
  hlt

IRQ_10h_x64:
  call make_bluescreen_x64
  call handle_irq10_x64
  cli
  hlt

IRQ_11h_x64:
  call make_bluescreen_x64
  call handle_irq11_x64
  cli
  hlt
  
IRQ_12h_x64:
  call make_bluescreen_x64
  call handle_irq12_x64
  cli
  hlt
  
IRQ_13h_x64:
  call make_bluescreen_x64
  call handle_irq13_x64
  cli
  hlt
  	
IRQ_20h_x64:
  mov [s_rax_0x20], rax
  mov [s_rbx_0x20], rbx
  mov [s_rcx_0x20], rcx
  mov [s_rdx_0x20], rdx
  call 0x0000000000200000	 ;location of handler code
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  mov rax, [s_rax_0x20]
  mov rbx, [s_rbx_0x20]
  mov rcx, [s_rcx_0x20]
  mov rdx, [s_rdx_0x20]
  iretq

IRQ_21h_x64:
  mov [s_rax_0x21], rax
  mov [s_rbx_0x21], rbx
  mov [s_rcx_0x21], rcx
  mov [s_rdx_0x21], rdx
  call 0x0000000000300000	 ;location of keyboard driver
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  mov rax, [s_rax_0x21]
  mov rbx, [s_rbx_0x21]
  mov rcx, [s_rcx_0x21]
  mov rdx, [s_rdx_0x21]
  iretq
	
IRQ_22h_x64:
  mov byte [0xB8964], '3'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_23h_x64:
  mov byte [0xB8966], '4'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_24h_x64:
  mov byte [0xB8968], '5'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_25h_x64:
  mov byte [0xB896A], '6'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_26h_x64:
  mov byte [0xB896C], '7'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_27h_x64:
  mov byte [0xB896E], '8'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq

IRQ_28h_x64:
  mov byte [0xB8970], '9'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_29h_x64:
  mov byte [0xB8972], 'A'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iret

IRQ_2ah_x64:
  mov byte [0xB8974], 'B'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq

IRQ_2bh_x64:
  mov byte [0xB8976], 'C'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_2ch_x64:
  mov byte [0xB8978], 'D'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_2dh_x64:
  mov byte [0xB897A], 'E'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_2eh_x64:
  mov byte [0xB897C], 'F'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_2fh_x64:
  mov byte [0xB897E], 'G'
  mov     al,20H             ;send End-Of-Interrupt signal
  out     20H,al
  iretq
  
IRQ_30h_x64: ; screen and text interactions
	mov [s_rax_0x30], rax
  mov [s_rbx_0x30], rbx
  mov [s_rcx_0x30], rcx
  mov [s_rdx_0x30], rdx
	call 0x000000000020063D
	mov rax, [s_rax_0x30]
  mov rbx, [s_rbx_0x30]
  mov rcx, [s_rcx_0x30]
  mov rdx, [s_rdx_0x30]
	iretq

s_rax_0x20 dq 0
s_rbx_0x20 dq 0
s_rcx_0x20 dq 0
s_rdx_0x20 dq 0

s_rax_0x21 dq 0
s_rbx_0x21 dq 0
s_rcx_0x21 dq 0
s_rdx_0x21 dq 0

s_rax_0x30 dq 0
s_rbx_0x30 dq 0
s_rcx_0x30 dq 0
s_rdx_0x30 dq 0

%include "./system/x64/basic/bluescreen.inc"
%include "./system/x64/basic/IRQs/00.inc"
%include "./system/x64/basic/IRQs/01.inc"
%include "./system/x64/basic/IRQs/02.inc"
%include "./system/x64/basic/IRQs/03.inc"
%include "./system/x64/basic/IRQs/04.inc"
%include "./system/x64/basic/IRQs/05.inc"
%include "./system/x64/basic/IRQs/06.inc"
%include "./system/x64/basic/IRQs/07.inc"
%include "./system/x64/basic/IRQs/08.inc"
%include "./system/x64/basic/IRQs/09.inc"
%include "./system/x64/basic/IRQs/0A.inc"
%include "./system/x64/basic/IRQs/0B.inc"
%include "./system/x64/basic/IRQs/0C.inc"
%include "./system/x64/basic/IRQs/0D.inc"
%include "./system/x64/basic/IRQs/0E.inc"
%include "./system/x64/basic/IRQs/10.inc"
%include "./system/x64/basic/IRQs/11.inc"
%include "./system/x64/basic/IRQs/12.inc"
%include "./system/x64/basic/IRQs/13.inc"
That's it. Mabe one of you have a clue what's going wrong.

Thank you very much for your support :)
User avatar
Troy Martin
Member
Member
Posts: 1686
Joined: Fri Apr 18, 2008 4:40 pm
Location: Langley, Vancouver, BC, Canada
Contact:

Re: Strange long mode fault on real computer

Post by Troy Martin »

Obvious question: are you sure the computer has a 64-bit processor?
Image
Image
Solar wrote:It keeps stunning me how friendly we - as a community - are towards people who start programming "their first OS" who don't even have a solid understanding of pointers, their compiler, or how a OS is structured.
I wish I could add more tex
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Re: Strange long mode fault on real computer

Post by 01000101 »

It's 11:25; do you know where your stack pointer is? </lame>

I'd check to see where your stack is, or if you've even set one up. Also, as TroyMartin said, is the CPU 64-bit compatible?
sevobal
Member
Member
Posts: 63
Joined: Sun Oct 22, 2006 7:11 am

Re: Strange long mode fault on real computer

Post by sevobal »

Hey guys,
of course the cpu supports 64 Bit code. I'm running Vista x64 on it and my os checks if the cpu is able to execute 64-bit coe before I switch.
But the stack...I think this could be the problem. I'll go and check this.

Thank you.
sevobal
Member
Member
Posts: 63
Joined: Sun Oct 22, 2006 7:11 am

Re: Strange long mode fault on real computer

Post by sevobal »

So after checking my code I'm not sure if the stack is the problem. Following code of my bootloader gets execute after enabling long mode and jumping into a 64 bit ode section. These code works perfectly on real machines and emulated machines AND they contain call-instructions:

Code: Select all


...

[BITS 64]

do_long:

	mov ax, SYS_DATA_SEL_X64
	mov ds, ax
	mov ss, ax

	mov ax,LINEAR_SEL_X64
	mov es,ax

   	mov rsp, 0x00001000

   	mov rbx, 0xB8784
    mov rdx, x64_idt_msg
    call print_lm
	
	lidt[idt_pointer_X64]			; load IDT register
	sti
	  
	mov rbx, 0xB8818
    call done_lm
	  
	mov rbx, 0xB8820
    mov rdx, x64_native_msg
    call print_lm
    
    mov rbx, 0xB88B6
    call ready_lm

    ;jump to my kernel	
    jmp 0x0000000000400000
So the strange thing is that call instructions in the 64 bit section of the bootloader works perfectly, but call instructions in my kernel code only work in emulated machines and not on my real machine.
I hope this peace of code can help you a bit more to get a clue of the problem.

EDIT: The real machine only reboots on far-calls. Normal calls are working oO
User avatar
Combuster
Member
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: Strange long mode fault on real computer

Post by Combuster »

mov ax, SYS_DATA_SEL_X64
mov ds, ax
mov ss, ax

mov ax,LINEAR_SEL_X64
mov es,ax
That's like, messing up long mode with protected mode. What are you actually trying to achieve with this? :shock:
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
sevobal
Member
Member
Posts: 63
Joined: Sun Oct 22, 2006 7:11 am

Re: Strange long mode fault on real computer

Post by sevobal »

Combuster wrote:
mov ax, SYS_DATA_SEL_X64
mov ds, ax
mov ss, ax

mov ax,LINEAR_SEL_X64
mov es,ax
That's like, messing up long mode with protected mode. What are you actually trying to achieve with this? :shock:
Oh that was just a thing I tried because of this strange reboot bug. But it doesn't make any difference if I do it with or without this code, because my real machine still reboots.
The emulated one didn't reboot. I have only one real machine with x64 support so it's difficult to find out if it's a problem with my code (I guess it is) or if it only affects my machine. And you were right, it seems to be a problem with the stack. But what did I wrong?
sevobal
Member
Member
Posts: 63
Joined: Sun Oct 22, 2006 7:11 am

Re: Strange long mode fault on real computer

Post by sevobal »

Hey,
so... now I know where the problem is, but not how to solve it. If an interrupt or exception fires up the handler of these exceptions calls routines like "make_bluescreen", "handle_irq00_x64" and so on. And just these calls causes the machine to reboot. Has anyone an idea where the problem is? My IDT setup is okay, because removing the call "make_bluescreen" and putting the code directly in the exception handler works perfect.
Post Reply