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.
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 5:08 pm
Hello,
my OS is tripple faulting at 'ljmp $0x8, $ExecKMain'.
If I leave out the far jump the processor is halted.
Code: Select all
00056533559i[BIOS ] Booting from 0000:7c00
00056656013e[CPU0 ] check_cs(0x0008): not a valid code segment !
00056656013e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00056656013e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00056656013i[CPU0 ] CPU is in protected mode (active)
00056656013i[CPU0 ] CS.d_b = 16 bit
00056656013i[CPU0 ] SS.d_b = 16 bit
00056656013i[CPU0 ] EFER = 0x00000000
00056656013i[CPU0 ] | RAX=0000000060000011 RBX=0000000000000003
00056656013i[CPU0 ] | RCX=000000000009000a RDX=0000000000000301
00056656013i[CPU0 ] | RSP=000000000000ffd6 RBP=0000000000000117
00056656013i[CPU0 ] | RSI=00000000000e474c RDI=000000000000ffac
00056656013i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00056656013i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00056656013i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00056656013i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00056656013i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00056656013i[CPU0 ] | SEG selector base limit G D
00056656013i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00056656013i[CPU0 ] | CS:0050( 0004| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | DS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | SS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | ES:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | FS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | GS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00056656013i[CPU0 ] | MSR_FS_BASE:0000000000000500
00056656013i[CPU0 ] | MSR_GS_BASE:0000000000000500
00056656013i[CPU0 ] | RIP=0000000000000030 (0000000000000030)
00056656013i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00056656013i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00056656013i[CPU0 ] 0x0000000000000030>> jmp far 0008:0035 : EA35000800
00056656013e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00056656013i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00056656013i[CPU0 ] cpu hardware reset
Here is my code which is loaded to 0x50:0x0 by MBR using BIOS interrupts:
Code: Select all
.section .rodata
msg:
.asciz "kernel..."
msgend:
msglen:
.word (msgend - msg)
gdt:
# Null Descriptor
.word 0x0000
.word 0x0000
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x00
# Code Descriptor
.word 0xffff
.word 0x0000
.byte 0x00
.byte 0x9a
.byte 0xcf
.byte 0x00
# Data Descriptor
.word 0xffff
.word 0x0000
.byte 0x00
.byte 0x92
.byte 0xcf
.byte 0x00
gdt_end:
gdtptr:
.word (gdt_end - gdt - 1)
.long gdt
.section .text
.globl Start
Start:
.code16
PrintMsg:
mov $0x0050, %ax
mov %ax, %es # Set Extra Segment to 0x0050
mov $msg, %bp # Set base pointer to msg location
mov $0x13, %ah # Print String
mov $0x01, %al # Char only - Cursor moved
clr %bh # Page Number
mov $0x03, %bl # Color Black Blue
mov msglen, %cx # Message Length
mov $3, %dh # Row 3
mov $1, %dl # Column 1
int $0x10 # Video Interrupt
cli
SetA20:
inb $0x92, %al # Enable A20 Gate
testb $0x2, %al # to access to more than
outb %al, $0x92 # 1 Mega Byte of memory
LoadGDT:
lgdt gdtptr # Load Global Descriptor Table
EnterProtectedMode:
movl %cr0, %eax # Read from Control Register CR0
orl $0x1, %eax # Set Protected Mode Bit
movl %eax, %cr0 # Write to Control Register CR
# In Real Mode : ljmp Segment, Offset
# In Protected Mode : ljmp Selector, Offset
# Selector:
# 0x0 = NullDescriptor
# 0x8 = CodeDescriptor
# 0x10 = DataDescriptor
ljmp $0x8, $ExecKMain
.code32
ExecKMain:
sti
call kmain
cli
Hang:
hlt
jmp Hang
Griwes
Member
Posts: 374 Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:
Post
by Griwes » Wed Nov 14, 2012 5:14 pm
I would guess that this part is important:
Code: Select all
00056656013e[CPU0 ] check_cs(0x0008): not a valid code segment !
Reaver Project ::
Repository ::
Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 5:26 pm
Hii,
yep you are right, but why?
Am I loading garbage into the GDTR or is my GDT entry wrong?
In my boot loader I load 10 sectors to 0x50, 0x0, set registers (DS, ES, etc..),
then far jump to 0x50, 0x0.
The kernel freshly loaded to memory displays "kernel...", then tripple faults.
Can you show me what I need to put in my GDT entry Code and Data?
Thank you
Brendan
Member
Posts: 8561 Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:
Post
by Brendan » Wed Nov 14, 2012 5:43 pm
Hi,
teodori wrote: Here is my code which is loaded to 0x50:0x0 by MBR using BIOS interrupts:
teodori wrote: Code: Select all
gdtptr:
.word (gdt_end - gdt - 1)
.long gdt
For "gdtptr", the address of the GDT is a linear address (e.g. "gdt + 0x0050 * 16") and not a virtual address (e.g. "gdt").
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.
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 5:47 pm
yep so I loaded garbage into GDTR.
But if what you said is correct "kernel..." should also not be displayed?
Here is my boot loader:
Code: Select all
.section .rodata
msg:
.asciz "booting..."
msgend:
msglen:
.word (msgend - msg)
errmsg:
.asciz "disk error!"
errmsgend:
errmsglen:
.word (errmsgend - errmsg)
.section .text
.globl Start
Start:
.code16
SaveDriveNumber:
# Save Boot Device Number just before MBR load address
# This byte is set by the BIOS into registry DL
mov %dl, 0x7bff
SetVideoMode:
clr %ah # Set Video Mode
mov $0x03, %al # 3rd Mode -> 80x25
int $0x10 # Video Interrupt
PrintBootMsg:
mov $0x06, %ah # Clear Screen
clr %al # Lines to scroll (0 = clear -> CX & DX)
mov $0x0f, %bh # Color Black White
clr %cx # Upper Left Corner
mov $25, %dh # 25 Lines
mov $80, %dl # 80 Columns
int $0x10 # Video Interrupt
clr %ax
mov %ax, %es # Set Extra Segment to 0x0
mov $msg, %bp # Set base pointer to msg location
mov $0x13, %ah # Print String
mov $0x01, %al # Char only - Cursor moved
clr %bh # Page Number
mov $0x0f, %bl # Color Black White
mov msglen, %cx # Message Length
mov $1, %dh # Row 1
mov $1, %dl # Column 1
int $0x10 # Video Interrupt
ResetDisk:
clr %ah # Reset Disk
mov 0x7bff, %dl # Drive (from Memory Loacation)
int $0x13 # Disk Interrupt
jc PrintErrorMsg # If CF set jump to PrintErrorMsg
LoadFromDisk:
mov $0x0050, %ax
mov %ax, %es # Set Extra Segment to 0x0050
mov $0x02, %ah # Read Disk Sectors
mov $0x01, %al # Read one sector only (512 bytes per sector)
clr %bx # Offset 0 - Start of Segment
clr %ch # Track 0
mov $0x02, %cl # Sector 2
clr %dh # Head 0
mov 0x7bff, %dl # Drive (from Memory Loacation)
int $0x13 # Disk Interrupt
jc PrintErrorMsg # If CF set jump to PrintErrorMsg
SetupSegments:
mov $0x0050, %ax # Segment 0x0050
mov %ax, %ds # Set Data Segment
mov %ax, %es # Set Extra Segment
mov %ax, %fs # Set Data2 Segment
mov %ax, %gs # Set Data3 Segment
mov %ax, %ss # Set Stack Segment
ljmp $0x0050, $0x0 # Far Jump to CS:IP
PrintErrorMsg:
clr %ax
mov %ax, %es # Set Extra Segment to 0x0
mov $errmsg, %bp # Set base pointer to msg location
mov $0x13, %ah # Print String
mov $0x01, %al # Char only - Cursor moved
clr %bh # Page Number
mov $0x04, %bl # Color Black Red
mov errmsglen, %cx # Message Length
mov $3, %dh # Row 3
mov $1, %dl # Column 1
int $0x10 # Print Message
cli # Disable Interrupts
Hang:
hlt # Halt CPU
jmp Hang # Infinit loop if Halt does not work
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 5:57 pm
Thank you Brendan,
you pointed me to the right direction, I loaded garbage instead of my GDT, because I used a wrong address.
Griwes
Member
Posts: 374 Joined: Sat Jul 30, 2011 10:07 am
Libera.chat IRC: Griwes
Location: Wrocław/Racibórz, Poland
Contact:
Post
by Griwes » Wed Nov 14, 2012 6:02 pm
teodori wrote: yep so I loaded garbage into GDTR.
But if what you said is correct "kernel..." should also not be displayed?
There is a difference between how local data is accessed (as in, it takes segments into consideration), and how CPU loads GDT internally (without thinking about which segment you may have in mind). It just loads physical address specified by pointer.
Reaver Project ::
Repository ::
Ohloh project page
<klange> This is a horror story about what happens when you need a hammer and all you have is the skulls of the damned.
<drake1> as long as the lock is read and modified by atomic operations
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 7:17 pm
Sorry, next problem
but small victory: CS.d_b = 32 bit
Code: Select all
00042492025i[CPU0 ] LOCK prefix unallowed (op1=0x57, modrm=0x00)
00042492025e[CPU0 ] write_virtual_checks(): write beyond limit, r/w
00042492025e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00042492025e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00042492025i[CPU0 ] CPU is in protected mode (active)
00042492025i[CPU0 ] CS.d_b = 32 bit
00042492025i[CPU0 ] SS.d_b = 16 bit
00042492025i[CPU0 ] EFER = 0x00000000
00042492025i[CPU0 ] | RAX=0000000060000011 RBX=0000000000000003
00042492025i[CPU0 ] | RCX=000000000009000a RDX=0000000000000301
00042492025i[CPU0 ] | RSP=000000000000ffd6 RBP=0000000000000127
00042492025i[CPU0 ] | RSI=00000000000e474c RDI=000000000000ffac
00042492025i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00042492025i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00042492025i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00042492025i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00042492025i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00042492025i[CPU0 ] | SEG selector base limit G D
00042492025i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00042492025i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00042492025i[CPU0 ] | DS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00042492025i[CPU0 ] | SS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00042492025i[CPU0 ] | ES:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00042492025i[CPU0 ] | FS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00042492025i[CPU0 ] | GS:0050( 0005| 0| 0) 00000500 0000ffff 0 0
00042492025i[CPU0 ] | MSR_FS_BASE:0000000000000500
00042492025i[CPU0 ] | MSR_GS_BASE:0000000000000500
00042492025i[CPU0 ] | RIP=0000000000000035 (0000000000000035)
00042492025i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00042492025i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00042492025i[CPU0 ] 0x0000000000000035>> inc dword ptr ds:[eax] : FF00
00042492025e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00042492025i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00042492025i[CPU0 ] cpu hardware reset
Brendan
Member
Posts: 8561 Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:
Post
by Brendan » Wed Nov 14, 2012 7:48 pm
Hi,
teodori wrote: Code: Select all
# In Protected Mode : ljmp Selector, Offset
# Selector:
# 0x0 = NullDescriptor
# 0x8 = CodeDescriptor
# 0x10 = DataDescriptor
ljmp $0x8, $ExecKMain
.code32
ExecKMain:
sti
call kmain
cli
It's probably a good idea to load an IDT and setup valid (for protected mode) interrupt descriptors before you enable interrupts with STI. Otherwise the CPU gets all confused and thinks the real mode IVT (the one with 4-byte entries) is an IDT (with 8-byte entries) and can execute random code (or crash, or both).
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.
gerryg400
Member
Posts: 1801 Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia
Post
by gerryg400 » Wed Nov 14, 2012 7:48 pm
Don't use sti (enable interrupts) until you have a valid IDT.
If a trainstation is where trains stop, what is a workstation ?
teodori
Member
Posts: 103 Joined: Wed Nov 14, 2012 4:55 pm
Post
by teodori » Wed Nov 14, 2012 8:34 pm
Problem corrected the base address for code and data GDT was wrong set it to 0x0500, now it's working.
Brendan and gerryg400: you are right
that's exactly what I'll do now.
My idea is to write a bootloader and a small kernel using GNU tools (as, ld and gcc) for a tutorial,
so that anyone can understand how a PC boots and write an OS from scratch.
Here is the result:
Code: Select all
00014041550i[BIOS ] Booting from 0000:7c00
00014164025i[CPU0 ] WARNING: HLT instruction with IF=0!
00218284000p[SDL ] >>PANIC<< User requested shutdown.
00218284000i[CPU0 ] CPU is in protected mode (halted)
00218284000i[CPU0 ] CS.d_b = 32 bit
00218284000i[CPU0 ] SS.d_b = 32 bit
00218284000i[CPU0 ] EFER = 0x00000000
00218284000i[CPU0 ] | RAX=00000000000a0001 RBX=0000000000000003
00218284000i[CPU0 ] | RCX=000000000009000a RDX=0000000000000301
00218284000i[CPU0 ] | RSP=000000000000ffd6 RBP=000000000000012f
00218284000i[CPU0 ] | RSI=00000000000e474c RDI=000000000000ffac
00218284000i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00218284000i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00218284000i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00218284000i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00218284000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
00218284000i[CPU0 ] | SEG selector base limit G D
00218284000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00218284000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | FS:0010( 0002| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | GS:0010( 0002| 0| 0) 00000500 ffffffff 1 1
00218284000i[CPU0 ] | MSR_FS_BASE:0000000000000500
00218284000i[CPU0 ] | MSR_GS_BASE:0000000000000500
00218284000i[CPU0 ] | RIP=000000000000004b (000000000000004b)
00218284000i[CPU0 ] | CR0=0x60000011 CR2=0x0000000000000000
00218284000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00218284000i[CPU0 ] 0x000000000000004b>> jmp .-3 (0x0000054a) : EBFD
00218284000i[CMOS ] Last time is 1352946238 (Thu Nov 15 03:23:58 2012)
00218284000i[ ] restoring default signal behavior
00218284000i[CTRL ] quit_sim called with exit code 1