A confusing exception of GP.

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
User avatar
fluray
Posts: 9
Joined: Thu May 15, 2014 2:04 am

A confusing exception of GP.

Post by fluray »

My code creates a confusing exception of #GP.
When using 'jmp $' raises #GP.
loader.asm

Code: Select all

;nasm loader.asm -o loader.bin
        org 0x8000
        bits 16

        cli
		   
        call _clear_screen_16           ;Clear screen
			
        in	al, 92h                     ;Enable A20
        or	al, 00000010b
        out	92h, al
		
        xor eax, eax
        xor ebx, ebx
        xor ecx, ecx
        xor edx, edx
        xor esi, esi
        xor edi, edi
        xor ebp, ebp
        mov ds, ax
        mov es, ax
        mov ss, ax
        mov fs, ax
        mov gs, ax
        mov sp, 0x7c00	
				
        call _load_kernel              ;loade kernel -> 0x9000    
			
        db 0x66
        lgdt [GDTR32]
        
		
        mov	eax, cr0
        or	eax, 1
        mov	cr0, eax


        jmp	r0_code32_sel:entry32      ;Refresh CS Selector
		
%include "load_kernel.asm"		
%include "clear_screen.asm"		
%include "system_data.asm"		                ; IDT/GDT/Selector/GDTR/LDTR
        bits 32
		
entry32:
        mov eax, r0_data32_sel		            ; Refresh DS ES FS GS
        mov ds, ax			
        mov es, ax
        mov fs, ax
        mov gs, ax
        mov ss, ax
        xor eax, eax
        xor ebx, ebx
        xor ecx, ecx
        xor edx, edx
        xor esi, esi
        xor edi, edi
        xor ebp, ebp
        mov esp, 0x7c00		
        	
        lidt [IDTR32]   
		
        mov WORD [tss32_desc], tss_len			; tss[15:0]  limit
        mov WORD [tss32_desc + 2], tss32        ; tss[39:16] base
        mov BYTE [tss32_desc + 5], 0x80 | 0x9   ; tss[40:63] attr
	
        mov	ax, tss32_sel
        ltr	ax
				
        mov esi, 3
        mov edi, BP_handler 
        call _set_interrupt_handler_DPL0        

        mov esi, 4
        mov edi, OF_handler 
        call _set_interrupt_handler_DPL0      
		
        mov esi, 13
        mov edi, GP_handler
        call _set_interrupt_handler_DPL0    

        mov esi, 14
        mov edi, PF_handler
        call _set_interrupt_handler_DPL0    
				
        mov esi, 0x9000   		                 ; start of kernel.bin
        mov edi, 0x100000		                 ; Destination address at the 1MiB mark
        mov ecx, 0x1000			                 ; kernel.bin length : 0x1000*4byte
        rep movsd		
		
        call _setup_paging                       ;Enable paging
		
        jmp 0x100000
		
%include "interrupt.asm"		
%include "page32.asm"
%include "print32.asm"	
system_data.asm

Code: Select all

GDTR32:					
dw gdt32_end - gdt32 - 1		
dq gdt32				


gdt32:
null_desc                       dw 0x0000, 0x0000, 0x0000, 0x0000	; Null desciptor      
;32-bit code descriptor          
r0_code32_desc				    dq 0x00cf9a000000ffff               ; non-conforming, DPL=0, P=1  limit=0xfffff	         
r0_data32_desc				    dw 0xFFFF, 0x0000, 0x9200, 0x00CF	; 32-bit data descriptor                                   							        
r3_code32_desc                  dw 0xffff,0x0000,0xf800,0x00cf      ; non-conforming, DPL=3, P=1 	
r3_data32_desc                  dw 0xffff,0x0000,0xf200,0x00cf      ; DPL=3, P=1, writeable, expand-up  
tss32_desc 						dq 0              
gdt32_end:


r0_code32_sel                   equ     0x08
r0_data32_sel                   equ     0x10
r3_code32_sel                   equ	    0x18
r3_data32_sel                   equ     0x20
tss32_sel                       equ     0x28


IDTR32:
dw  idt32_end - idt32 - 1
dd  idt32

idt32:
        times 0x100 dq 0                                             ; 0x100 vector
idt32_end:

tss32:
		dd	0			; Back
		dd	0xFFFF		; r0 esp
		dd	r0_data32_sel  ; ss selector
		dd	0			; 
		dd	0			; 
		dd	0			; 
		dd	0			; 
		dd	0			; CR3
		dd	0			; EIP
		dd	0			; EFLAGS
		dd	0			; EAX
		dd	0			; ECX
		dd	0			; EDX
		dd	0			; EBX
		dd	0			; ESP
		dd	0			; EBP
		dd	0			; ESI
		dd	0			; EDI
		dd	0			; ES
		dd	0			; CS
		dd	0			; SS
		dd	0			; DS
		dd	0			; FS
		dd	0			; GS
		dd	0			; LDT
		dw	0			; 
		dw	$ - tss32 + 2	; I/O bitmap base
		db	0ffh			
tss_len		equ	$ - tss32   
kernel.asm

Code: Select all

;nasm kernel.asm -o kernel.bin
    org 0x100000
	bits 32
	
	mov esi, msg
	call _puts
	
	jmp test_lable    ;No exception is thrown 
	nop
	nop
	nop
	nop
	
test_lable:
    call __println
	call __println
	mov esi, test_mag
	call _puts
	
test_loop:
    jmp test_loop      ; GP exception is thrown 
	
	;jmp $            ; GP exception is thrown 
	
test_msg  db 'Test...',0
msg     db 'Cos OS kernel 0.2...',0	
	
%include "print32.asm"

times 16384-($-$$) db 0	
VM Screenshot:
Image
It is no problem to run the code in bochs.
VM+IDA Debug Screenshot:
Image
Error Code:00000043h
Reference website:http://wiki.osdev.org/Exceptions#Genera ... tion_Fault
Image
But I do not understand the cause of the Fault.
Last edited by fluray on Fri May 30, 2014 10:04 pm, edited 3 times in total.
alexfru
Member
Member
Posts: 1112
Joined: Tue Mar 04, 2014 5:27 am

Re: A confusing exception of #GP.

Post by alexfru »

The jump has nothing to do with the exception. Look at the exception error code (external event=interrupt, IDT involved, index=8, which is the timer (PIT) interrupt unless you've remapped the interrupt vectors in the PIC). It hints at a problem with the interrupt descriptor table. The jump happily jumps to itself until an interrupt arrives, at which point the CPU fails to execute the appropriate for it ISR and, obviously, the jump appears as the instruction at which the interrupt and the exception occur as there's no other code executed at the moment.
User avatar
fluray
Posts: 9
Joined: Thu May 15, 2014 2:04 am

Re: A confusing exception of #GP.

Post by fluray »

alexfru wrote:The jump has nothing to do with the exception. Look at the exception error code (external event=interrupt, IDT involved, index=8, which is the timer (PIT) interrupt unless you've remapped the interrupt vectors in the PIC). It hints at a problem with the interrupt descriptor table. The jump happily jumps to itself until an interrupt arrives, at which point the CPU fails to execute the appropriate for it ISR and, obviously, the jump appears as the instruction at which the interrupt and the exception occur as there's no other code executed at the moment.
Thx.
I didn't think the processor in this tortuous way to tell us DF exception.
I always thought that if you do not set DF exception handling, when #DF is triggered, the machine will restart.
obviously,my idea is wrong.
Problem has been solved, thanks again.
loader.asm add some code

Code: Select all

  call _init8259A                          ; Mask all 
Or by another method:
kernel.asm add a Instruction

Code: Select all

cli
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: A confusing exception of #GP.

Post by JAAman »

fluray wrote: I didn't think the processor in this tortuous way to tell us DF exception.
I always thought that if you do not set DF exception handling, when #DF is triggered, the machine will restart.
it will, but this is not a #DF, it is an external interrupt (only one fault occurred, so it cannot be a double-fault),it might be using the same interrupt vector, but the CPU knows the difference between an internal exception and an external IRQ -- if a #DF did occur (with no valid #DF handler) then it would produce a triple-fault, and not a #GP

this distinction is very important, and is (part of) why hardware interrupts should always be remapped to another location before they are enabled
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: A confusing exception of #GP.

Post by Brendan »

Hi,
JAAman wrote:this distinction is very important, and is (part of) why hardware interrupts should always be remapped to another location before they are enabled
Also note that there's a common problem caused by disabling IRQs the wrong way. The scenario goes like this:
  • boot code disables IRQs using "CLI"
  • PIC detects an IRQ that is not masked in the PIC (e.g. IRQ0), and sends it to CPU (e.g. as interrupt 0x08)
  • CPU receives the PIC's IRQ, but IRQs are masked in the CPU so it just holds onto it until later
  • OS reprograms the PIC and/or masks all the IRQs
  • OS enables IRQs again using "STI"
  • OS receives the old pending IRQ (e.g. interrupt 0x08), even though IRQ are masked and/or mapped to different interrupts in the PIC
A more correct way (that solves the problem) is for boot code to disable IRQs by masking them in the PIC chips and then doing a few NOPs so that firmware can handle any IRQs that occurred before they were masked. In this case there shouldn't be a reason to use "CLI" at all (but it can't hurt if done after the NOPs).


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.
User avatar
fluray
Posts: 9
Joined: Thu May 15, 2014 2:04 am

Re: A confusing exception of #GP.

Post by fluray »

Thanks all,learned a lot from your post. :D
Post Reply