Page 1 of 2

Protected Mode problem

Posted: Thu Feb 16, 2012 9:29 am
by sumanx
Okay, I am trying to make an OS that goes into protected mode, but I get a triple fault.

Here's the code (I do not use GRUB):

bootloader.asm

Code: Select all

[ORG 0x7c00]
[BITS 16]

jmp start


start:
mov ax,0x1000 ;code to read second sector(and second stage) from the floppy into memory location 0x1000:0 
mov es,ax
xor bx,bx
xor ax,ax

mov ah,2
mov dl,0
mov al,1
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 0x13

jump:
jmp 0x1000:0x0000 ;jump to the memory location


TIMES 510-($-$$) db 0
db 0x55
db 0xAA
Second Stage:

Code: Select all

[ORG 0x1000]

jmp main ;goto the main routine

;------------------------------------
;The GDT

gdt: ;main gdt function that sets up the gdt
cli 
lgdt [addr]
ret

addr: ; Calculate required information for the gdt
dw end - gdt_t -1
dd gdt_t

;----------------------------------------------------
gdt_t:
; the real gdt
;----------------
;Null Descriptor
dd 0
dd 0
;----------------
;Code Descriptor

codeDes equ $-

dw 0xFFFF
dw 0
db 0
db 00011010b
db 11001111b
db 0
;----------------
;Data Descriptor
dw 0xFFFF
dw 0
db 0
db 00010010b
db 11001111b
db 0
end:
;------------------------------------------------------------

main:
call gdt ; call main gdt function

mov eax,cr0
or eax,1
mov cr0,eax ; move into protected mode

jmp 0x08:begin ; jump to clear real mode garbage from cs

[BITS 32]
begin:
cli
hlt


I build using

Code: Select all

nasm boot.asm -f bin -o boot.bin
nasm kernel.asm -f bin -o kernel.bin
dd if=/dev/zero of=image.img count=2880 bs=512
dd if=boot.bin of=image.img conv=notrunc status=noxfer
dd if=kernel.bin of=image.img conv=notrunc status=noxfer seek=1
I test it using bochs.

But the problem lies in the jmp 0x08:begin instruction in the Second Stage File.
Whenever I remove that instruction, the OS doesn't triple fault and haults the cpu as expected.

Bochs log doesn't seem to be helpful either

Code: Select all

00126790189i[CPU0 ] CPU is in protected mode (active)
00126790189i[CPU0 ] CS.d_b = 16 bit
00126790189i[CPU0 ] SS.d_b = 16 bit
00126790189i[CPU0 ] EFER   = 0x00000000
00126790189i[CPU0 ] | RAX=0000000060000011  RBX=0000000000000000
00126790189i[CPU0 ] | RCX=0000000000090002  RDX=0000000000000000
00126790189i[CPU0 ] | RSP=000000000000ffd6  RBP=0000000000000000
00126790189i[CPU0 ] | RSI=00000000000e472c  RDI=000000000000ffac
00126790189i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00126790189i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00126790189i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00126790189i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00126790189i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00126790189i[CPU0 ] | SEG selector     base    limit G D
00126790189i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00126790189i[CPU0 ] |  CS:1000( 0004| 0|  0) 00010000 0000ffff 0 0
00126790189i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00126790189i[CPU0 ] |  SS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00126790189i[CPU0 ] |  ES:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00126790189i[CPU0 ] |  FS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00126790189i[CPU0 ] |  GS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00126790189i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00126790189i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00126790189i[CPU0 ] | RIP=0000000000000034 (0000000000000034)
00126790189i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00126790189i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00126790189i[CPU0 ] 0x0000000000000034>> jmp far 0008:1039 : EA39100800
00126790189e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00126790189i[SYS  ] bx_pc_system_c::Reset(HARDWARE) called
It justs says '3rd Exception with no resolution " and starts to reboot.

Please explain what the problem is. Thanks in advance.

Re: Protected Mode problem

Posted: Thu Feb 16, 2012 9:44 am
by bluemoon

Code: Select all

jmp 0x1000:0x0000 ;jump to the memory location

Second Stage:
[code]
[ORG 0x1000]
The ORG does not match your intended offset. The rest is of code not checked.

Re: Protected Mode problem

Posted: Thu Feb 16, 2012 9:53 am
by Velko
There's a problem with your GDT entries. You should set Present bits in Access bytes.

Re: Protected Mode problem

Posted: Thu Feb 16, 2012 10:08 am
by bubach
As previously mentioned, make sure your segment registers/org values work together. Can't see you setting up stack anywhere either, bochs log seems to have sp at 0xffff and ss at 0x0000, but you should set it and not count on some default.

Whats up with "codeDes equ $-" ?
Correct usage would be "codeDes equ $-gdt_t" and using it with "jmp codeDes:begin", or you could just remove it if you plan on going for the 0x08.

Also the GDT entries should look like this:

Code: Select all

......
db 10011010b ;changed first to 1
db 11001111b
db 0
;----------------
;Data Descriptor
dw 0xFFFF
dw 0
db 0
db 10010010b                   ; changed first to 1
db 11001111b
.......

Re: Protected Mode problem

Posted: Thu Feb 16, 2012 11:54 am
by Combuster
sumanx wrote:It justs says '3rd Exception with no resolution " and starts to reboot.
That is because you forgot to post the 5 lines before that dump even started. Bochs will give typically you an explanation for the cause of the reboot there.

Re: Protected Mode problem

Posted: Fri Feb 17, 2012 10:16 am
by sumanx
Thank you for your replies.
Here's the modified code, having listened to everybody who has posted.

Code: Select all

[ORG 0x7c00]
[BITS 16]

jmp start


start:
mov ax,0x1000 ;code to read second sector(and second stage) from the floppy into memory location 0x1000:0 
mov es,ax
xor bx,bx
xor ax,ax

mov ah,2
mov dl,0
mov al,1
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 0x13

jump:
jmp 0x1000:0x0000 ;jump to the memory location


TIMES 510-($-$$) db 0
db 0x55
db 0xAA
Second Stage.asm

Code: Select all

jmp main ;goto the main routine

;------------------------------------
;The GDT

gdt: ;main gdt function that sets up the gdt
cli 
lgdt [addr]
ret

addr: ; Calculate required information for the gdt
dw end - gdt_t -1
dd gdt_t

;----------------------------------------------------
gdt_t:
; the real gdt
;----------------
;Null Descriptor
dd 0
dd 0
;----------------
;Code Descriptor

dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
;----------------
;Data Descriptor
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
end:
;------------------------------------------------------------

main:
call gdt ; call main gdt function

mov eax,cr0
or eax,1
mov cr0,eax ; move into protected mode

jmp 0x08:begin ; jump to clear real mode garbage from cs

[BITS 32]
begin:
mov esp, 0xFFFFF
cli
hlt
And here's more of bochs dump

Code: Select all


00044099914i[PCI  ] 440FX PMC write to PAM register 59 (TLB Flush)
00044100642i[BIOS ] bios_table_cur_addr: 0x000fbb54
00056304945i[BIOS ] Booting from 0000:7c00
00056351192e[CPU0 ] jump_protected: gate type 0 unsupported
00056351192e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00056351192e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00056351192i[CPU0 ] CPU is in protected mode (active)
00056351192i[CPU0 ] CS.d_b = 16 bit
00056351192i[CPU0 ] SS.d_b = 16 bit
00056351192i[CPU0 ] EFER   = 0x00000000
00056351192i[CPU0 ] | RAX=0000000060000011  RBX=0000000000000000
00056351192i[CPU0 ] | RCX=0000000000090002  RDX=0000000000000000
00056351192i[CPU0 ] | RSP=000000000000ffd6  RBP=0000000000000000
00056351192i[CPU0 ] | RSI=00000000000e472c  RDI=000000000000ffac
00056351192i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00056351192i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00056351192i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00056351192i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00056351192i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00056351192i[CPU0 ] | SEG selector     base    limit G D
00056351192i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00056351192i[CPU0 ] |  CS:1000( 0004| 0|  0) 00010000 0000ffff 0 0
00056351192i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00056351192i[CPU0 ] |  SS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00056351192i[CPU0 ] |  ES:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00056351192i[CPU0 ] |  FS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00056351192i[CPU0 ] |  GS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00056351192i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00056351192i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00056351192i[CPU0 ] | RIP=0000000000000034 (0000000000000034)
00056351192i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00056351192i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00056351192i[CPU0 ] 0x0000000000000034>> jmp far 0008:0039 : EA39000800
00056351192e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00056351192i[SYS  ] bx_pc_system_c::Reset(HARDWARE) called
00056351192i[CPU0 ] cpu hardware reset

Re: Protected Mode problem

Posted: Fri Feb 17, 2012 10:49 am
by bluemoon

Code: Select all

addr: ; Calculate required information for the gdt
dw end - gdt_t -1
dd gdt_t
Despite the uncomfortable variable naming,...
Note that your second stage is at 1000:0000, the GDT is located at 1000:OFFSET gdt_t.
However you set the GDTR points to 0000:OFFSET gdt_t. Read the tutorials again.

Re: Protected Mode problem

Posted: Fri Feb 17, 2012 6:00 pm
by turdus
And in 1st stage, disable interrupts, set up proper stack etc. etc. etc. Why don't you mind reading the wiki?

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 9:00 am
by sumanx
bluemoon:
However you set the GDTR points to 0000:OFFSET gdt_t
I didn't quite understand why this happens. If you don't mind sir, would you please explain why it happens, and possibly the solution??
I didn't find anything like this in the wiki (I might have overlooked, I don't know)

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 9:37 am
by bluemoon
Intel Manual wrote:The source operand specifies a 6-byte memory location that contains the base address (a linear address) and the limit (size of table in bytes)
GDTR take a linear address, your segment base is ignored. You should read more of different addressing methods and their transformation formula.

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 11:00 am
by sumanx
Since we're still in real mode,

Linear Addess=(CS*16)+gdt_t
= 0x1000*16+gdt_t
=0x10000+gdt_t

but when the gdt address is like so

Code: Select all

addr:
dw end - gdt_t -1
dd 0x10000+gdt_t 
it still does not work.
Please help

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 11:03 am
by Combuster
[addr] = 16 * DS + addr = ...?

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 11:12 am
by VolTeK
Segment Offset addressing works like

10000,1000,1000,10 : 1000,100,10,1

Its not in tens, but the place value is what im trying to get at. When you move data from anywhere, its always
DataSegment:offset.

or

Say ive loaded my program to segment 0x0340:0100
Doing a far jump into the code, (setting the cs and eip) my offset should be 0x0100

my data segment (push cs, pop ds) should be 0x0340, say my variable is at 0x0100 (would be a problem, data execution, but its an example) mov ax, WORD variable it would actually do mov ax, WORD 0x0340:0x0100 or DS:Variable

By doing the calculation, the address to this variable is
(Ten thousand, thousand, hundred, ten)
0x0340
0x 0100 (Thousand, hundred, ten, one)
________
0x03500


If you also want to know why its offset is 0x0100 look up Program Segment Prefix. The program expected is a .COM file.

(if i got anything wrong, please note i woke up a couple minutes ago... good morning :) )

Re: Protected Mode problem

Posted: Sun Feb 19, 2012 1:01 pm
by bluemoon
The address is not correct when jumping to 32-bit begin:
You may consider doing ORG 0x10000 and write position independent stub to simplify address calculations

Re: Protected Mode problem

Posted: Sun Feb 26, 2012 1:35 am
by sumanx
Okay, I changed the code a bit
Here's what I did:

(In Second Stage.asm)

Code: Select all

gdt:
cli 
mov ax,cs
shl eax,4
add eax,gdt_t
mov [base],eax
mov ax,0
mov ds,ax
lgdt [addr]
ret

addr:
dw end - gdt_t -1
base:dd 0

But now, I get a new error :(

Code: Select all

00070439060e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x06)
00070439060e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00070439060e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
OSDev wiki says:
interrupt(): gate descriptor is not valid sys seg
You have not loaded an IDT, or the IDT is corrupt
Obvious from the code I have posted, there is no IDT.
So, should I setup an IDT before advancing?