OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 4:02 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: Qemu infinite restart after giving control to the kernel
PostPosted: Mon Dec 20, 2021 7:22 pm 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Hi,

I'm facing a problem where Qemu keeps restarting because of (I guess) an invalid address.. I've successfully managed to get into protected mode and my gdt is loaded correctly.
Here is my bootloader:

Code:
.intel_syntax noprefix
.code16 # use 16 bits
.global _start
.global _init
.text

_start:
  .space 80, 0 # Some BIOSes need a BPB, therefore we fill up space for a fake one
  jmp 0x0000, _init # in case BIOS set cs to 0x7c00. We work with cs:ip

_init:

  cld
  mov bp, 0x9000
  mov sp, bp

  xor ax, ax
  mov ds, ax
  mov ss, ax
  mov es, ax

  movb [BOOT_DRIVE], dl

  mov bx, offset flat:start_16_str
  call print

  mov bx, offset flat:read_disk_str
  call print

  mov dh, 0x1
  mov bx, 0x7e00 # memory location to load disk to
  call load_disk

  mov bx, offset flat:read_disk_success_str
  call print


  ljmp 0x0000:0x7e00


.include "print_16.S"
.include "read_disk.S"

start_16_str:
  .asciz "Starting in 16-bit mode"
read_disk_str:
  .asciz "Loading disk into memory"

read_disk_success_str:
  .asciz "Loaded disk successfully !"


.set BOOT_DRIVE, 0
.space 510-(.-_start), 0 # add zeroes to make it 510 bytes long
.word 0xaa55 # magic bytes that tell BIOS that this is bootable

secondstage:
  call .check_CPUID
  mov bx, offset flat:enable_a20_gate_str
  call print

  mov ax, 0x2401
  int 0x15
  call switch_to_protected_mode


.check_CPUID:
  pusha

   pushfd
   pop eax
   mov ecx, eax
   xor eax, (1 << 21)
   push eax
   popfd
   pushfd
   pop eax
   push ecx
   popfd
   xor eax, ecx
   jz .no_CPUID

  movb [cpuid_support], 1
  mov bx, offset flat:cpuid_success_str
  call print

  mov eax, 0x80000000
   cpuid
   cmp eax, 0x80000001
   jb .lm_error

  jmp .check_lm


.check_lm:
  mov eax, 0x80000001    #check if CPU supports Long Mode, abort if not
   cpuid
   test edx, (1 << 29)
   jz .lm_error

  movb [long_mode_support], 1
  mov ebx, offset flat:lm_success_str
  call print

  jmp lm_end

.no_CPUID:
  movb [cpuid_support], 0
  mov ebx, offset flat:cpuid_error_str
  call print
  jmp lm_end

.lm_error:
  movb [long_mode_support], 0
  mov ebx, offset flat:lm_error_str
  call print
  jmp lm_end

lm_end:
  popa
  ret

lm_error_str:
  .asciz "ERROR: CPU does not support Long Mode"

lm_success_str:
  .asciz "CHECK: CPU support Long mode "

cpuid_error_str:
  .asciz "ERROR: CPU does not support CPUID"

cpuid_success_str:
  .asciz "CHECK: CPU support CPUID"

enable_a20_gate_str:
  .asciz "WARNING: Enabling A20 gate"

.include "gdt.S"
.include "32bit_switch.S"
.include "32bit-print.S"

.code32
BEGIN_PM:

  mov ebx, offset flat:MSG_PROT_MODE
  call print_string_pm
  call 0x10000 # Here is where it fails

  jmp .

MSG_PROT_MODE:
.asciz "[SUCCESS] Giving control to the Kernel !"


.set cpuid_support, 0
.set long_mode_support, 0


Notice where it crashes :

Code:
.code32
BEGIN_PM:

  mov ebx, offset flat:MSG_PROT_MODE
  call print_string_pm
  call 0x10000

  jmp .


Also, here is where I switch to protected mode :

Code:
.intel_syntax noprefix
.code16 # use 16 bits
switch_to_protected_mode:
    cli
    lgdt [gdt_descriptor]
    mov eax, cr0
    or eax, 0x1
    mov cr0, eax
    ljmp CODE_SEG:init_pm
   
.code32
init_pm:
   
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
   
    mov ebp, 0x9000
    mov esp, ebp

    call BEGIN_PM


My linker script for the bootloader is this one (nothing too complicated) :
Code:
ENTRY(_start)

SECTIONS
{
   . = 0x7C00;

   .text : {
      *(.text*)
   }
   
   .rodata : {
      *(.rodata*)
   }

   .data : {
      *(.data*)
   }

   .bss : {
      *(.bss*)
   }
}


My kernel entry which calls the main function in another file :

Code:
.code32
.extern main

call main

jmp .


and it's linker script with .text at 0x10000
Code:
ENTRY(main)

SECTIONS
{
   . = 0x10000;

    .text : {
        KEEP(*(.text*))
    }

}


Now, I don't really understand why this shouldn't work as my kernek is loader at 0X10000 and in my bootloader I call this address. Also worth to note, in order to link my bootloader and my kenrel, I'm just using cat.

Thanks in advance !


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Mon Dec 20, 2021 8:16 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
liwinux wrote:
(I guess)

Don't guess! Add "-d int" and "-no-reboot" to your QEMU command line to get more information. (You may also need to disable KVM.)


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 4:48 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Octocontrabass wrote:
liwinux wrote:
(I guess)

Don't guess! Add "-d int" and "-no-reboot" to your QEMU command line to get more information. (You may also need to disable KVM.)

The truth is that I'm quite not understanding what Qemu returns as output ...:

Code:
check_exception old: 0xffffffff new 0x6
     0: v=06 e=0000 i=0 cpl=0 IP=0008:0009fc42 pc=0009fc42 SP=0010:00008ff8 env->regs[R_EAX]=00000010
EAX=00000010 EBX=00007fa3 ECX=00000000 EDX=00000180
ESI=00000000 EDI=00000000 EBP=00009000 ESP=00008ff8
EIP=0009fc42 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00007f2a 00000017
IDT=     00000000 000003ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=000000c3 CCO=ADDB   
EFER=0000000000000000
check_exception old: 0xffffffff new 0xd
     1: v=0d e=0032 i=0 cpl=0 IP=0008:0009fc42 pc=0009fc42 SP=0010:00008ff8 env->regs[R_EAX]=00000010
EAX=00000010 EBX=00007fa3 ECX=00000000 EDX=00000180
ESI=00000000 EDI=00000000 EBP=00009000 ESP=00008ff8
EIP=0009fc42 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00007f2a 00000017
IDT=     00000000 000003ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=000000c3 CCO=ADDB   
EFER=0000000000000000
check_exception old: 0xd new 0xd
     2: v=08 e=0000 i=0 cpl=0 IP=0008:0009fc42 pc=0009fc42 SP=0010:00008ff8 env->regs[R_EAX]=00000010
EAX=00000010 EBX=00007fa3 ECX=00000000 EDX=00000180
ESI=00000000 EDI=00000000 EBP=00009000 ESP=00008ff8
EIP=0009fc42 EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00007f2a 00000017
IDT=     00000000 000003ff
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
DR6=ffff0ff0 DR7=00000400
CCS=00000010 CCD=000000c3 CCO=ADDB   
EFER=0000000000000000
check_exception old: 0x8 new 0xd


Nothing refers to 0x10000 which is where my kernel should right after my bootloader... I case you are wondering, I've putted an infinite loop right before the call to my kernel and it doesn't reboot. So clearly the problem is the specific call to my kernel.

More infos I can give is that, thanks to gdb I can see that I'm successfully jumping to 0x10000, but there are no instructions at all at this address. So I'm wondering if it's a problem with my linker script for the kernel part. I wish I could use only one linker script for the bootloader and the kernel and therefore having to avoid using cat to bind both of them


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 5:09 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
I can not see in your code where are you reading your kernel from disk to address 0x10000.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 5:26 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Klakap wrote:
I can not see in your code where are you reading your kernel from disk to address 0x10000.

Actually it's right over here, I'm loading 1 sector after my bootloader :
Code:
mov dh, 0x1
  mov bx, 0x7e00 # memory location to load disk to
  call load_disk


and then after loading the gdt, I'm jumping to the kernel
Code:
.code32
BEGIN_PM:

  mov ebx, offset flat:MSG_PROT_MODE
  call print_string_pm
  call 0x10000 # Here is where it fails
  jmp .


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 6:02 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
So it do not work because you do not load your code. On 0x10000 there are no commands for processor, and it immediately cause some fault. You have to write code for loading your kernel from disk.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 6:15 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Klakap wrote:
So it do not work because you do not load your code. On 0x10000 there are no commands for processor, and it immediately cause some fault. You have to write code for loading your kernel from disk.


But isn’t what I have done with the interrupt 0x13 ? I don’t know how else I could do to load my code into memory… And if I’m not wrong, my second linker script tells to place my first kernel I striction at 0x10000 so technically there must be something over there right ?


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 7:13 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Yes, you load your code with interrupt 13h. But after start, BIOS load only one sector, bootloader to memory 0x7C00. You in your code call function to read second sector to memory 0x7E00. But it is not your kernel, it is only extended part of your bootloader. So you have to call your function for reading from disk again, with parameters for reading enough sectors where you have your kernel in disk to memory on 0x10000.

Example, if you have your kernel in sector 2, immediately after your extended bootloader, your reading code can look like:
Code:
mov ax, 0x1000
mov es, ax ;code will be loaded to segment 0x1000, what mean address 0x10000
mov bx, 0 ;code will be loaded to offset 0, what means that it will be on 0x1000*0x10+0=0x10000

mov ah, 0x2 ;read function of int 13h
mov al, 72 ;72 sectors is 36 KB, it is much more than enough to load your kernel
mov ch, 0 ;cylinder 0
mov dh, 0 ;head 0
mov cl, 3 ;sector 3
;dl is already set

int 13h ;this read 72 sectors from LBA sector 2 to memory 0x10000

After this, you have your code in memory and jump should be succesful.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 7:46 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Klakap wrote:
Yes, you load your code with interrupt 13h. But after start, BIOS load only one sector, bootloader to memory 0x7C00. You in your code call function to read second sector to memory 0x7E00. But it is not your kernel, it is only extended part of your bootloader. So you have to call your function for reading from disk again, with parameters for reading enough sectors where you have your kernel in disk to memory on 0x10000.

Example, if you have your kernel in sector 2, immediately after your extended bootloader, your reading code can look like:
Code:
mov ax, 0x1000
mov es, ax ;code will be loaded to segment 0x1000, what mean address 0x10000
mov bx, 0 ;code will be loaded to offset 0, what means that it will be on 0x1000*0x10+0=0x10000

mov ah, 0x2 ;read function of int 13h
mov al, 72 ;72 sectors is 36 KB, it is much more than enough to load your kernel
mov ch, 0 ;cylinder 0
mov dh, 0 ;head 0
mov cl, 3 ;sector 3
;dl is already set

int 13h ;this read 72 sectors from LBA sector 2 to memory 0x10000

After this, you have your code in memory and jump should be succesful.


That makes more sense indeed... So, If I undersand correctly what are saying, I should first load my extended bootloader, jump to it like I'm already doing. From there then, I load my kernel at offset 0X10000 before going into protected mode and after loading the gdt I jump to it. And in order to achieve that, I have to place my kernel at the 1536th byte since first 512 is the bootloader and 1024th is the extended bootloader right ?


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 8:11 am 
Offline
Member
Member

Joined: Sat Mar 10, 2018 10:16 am
Posts: 296
Yes, I use similar way in my bootloader.
Quote:
I have to place my kernel at the 1536th byte, right?

Yes. If you use linux, dd wil calculate this for you. Here is part of my compile script:
Code:
dd if=/dev/zero of=images/bleskos.hdd bs=1024 count=1440 #create new disk image
dd if=bootloader/bootloader.bin of=images/bleskos.hdd conv=notrunc seek=0 #this file is 1 sector bootloader + 4 sectors extended bootloader, so I write it from sector LBA 0
dd if=images/bleskos.bin of=images/bleskos.hdd conv=notrunc seek=5 #this is my whole code, I write it from LBA 5

After this in bleskos.hdd in LBA 0 is bootloader, in LBA 1 - LBA 4 is extended bootloader and from LBA 5 is code of my OS.

_________________
https://github.com/VendelinSlezak/BleskOS


Top
 Profile  
 
 Post subject: Re: Qemu infinite restart after giving control to the kernel
PostPosted: Tue Dec 21, 2021 8:55 am 
Offline
Member
Member

Joined: Sat Jun 12, 2021 4:13 pm
Posts: 46
Klakap wrote:
Yes, I use similar way in my bootloader.
Quote:
I have to place my kernel at the 1536th byte, right?

Yes. If you use linux, dd wil calculate this for you. Here is part of my compile script:
Code:
dd if=/dev/zero of=images/bleskos.hdd bs=1024 count=1440 #create new disk image
dd if=bootloader/bootloader.bin of=images/bleskos.hdd conv=notrunc seek=0 #this file is 1 sector bootloader + 4 sectors extended bootloader, so I write it from sector LBA 0
dd if=images/bleskos.bin of=images/bleskos.hdd conv=notrunc seek=5 #this is my whole code, I write it from LBA 5

After this in bleskos.hdd in LBA 0 is bootloader, in LBA 1 - LBA 4 is extended bootloader and from LBA 5 is code of my OS.


Many thanks, I managed to get my bootloader working by loading my kernel at 0x8000 for simplicity since my first stage is 512 bytes and so is my second stage so 0x7c00 + 1024 = 0x8000 <-- where my kernel will me loaded in memory !


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: belliash, Bing [Bot] and 62 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group