arnaudmeauzoone / Small-Linux-Bootloader

2 stars 2 forks source link

Bootloader hangs when booting with --enable-kvm #1

Open fabiensiron opened 6 years ago

fabiensiron commented 6 years ago

Hi,

I read your article this morning (in Linux magazine) and I didn't understand how your bootloader achieves high memory access. For me, the a20 line should be enabled at least. But even with a20, only 1114096 bytes can be accessed. Thus a Linux kernel (almost always larger than 1 MB) couldn't be moved to high memory. I was quite surprised that qemu was okay with that but it doesn't seem that kvm is okay because the following command hangs: qemu-system-x86_64 --enable-kvm -cpu host disk

Cheers

arnaudmeauzoone commented 6 years ago

Hello Saruta

I am glad you read my article :) Hope you found it interesting.

This bootloader was a projet I did to understand more how work a bootloader and the kernel. It is not meant to be professional, and it is not bugproof at all :)

There is tree main memory segment in this article:

Memory below 0x100000 mbr and kernel header. Protected mode kernel above 0x100000 (1048576 octets). Uncompressed kernel at 0x1000000

In the first case to move data from the disk, I use the LBA method witch can only put data up to 1MB

https://wiki.osdev.org/LBA

In the second case I used a code to move data at 0x100000

So I think the problem you pointed is with this code. (Correct me if I am wrong.)

highmove_addr dd 0x100000
; source = 0x2000
; Once we have loaded data from disk to 0x2000
; We need to move it to 0x100000 (Protected-mode kernel)
highmove:
mov esi, 0x20000 ;From
mov edi, [highmove_addr] ;TO
mov edx, 512*127
mov ecx, 0 ; pointer
.loop:
mov eax, [esi] ;From
mov [edi], eax ;To
add esi, 4
add edi, 4
sub edx, 4
jnz highmove.loop
mov [highmove_addr], edi ; Increase disk pointer
ret

This is the code witch put the "protected mode kernel" above 0x100000 In this case we are still in real mode so the memory "addressable" is a little over 1 MB

https://wiki.osdev.org/Real_Mode

So how can we put the kernel at 0x100000 and above?

In fact I think for this little kernel QEMU deal with it. And it enables itself the A20 line. It might bug with --enable-kvm because you are much more closer to your real hardware and so in this case. you might have to enable the A20 gate and pass to protected mode to put the "protected mode kernel" at 0x100000

Then you may have to downgrade to reel mode to start the kernel. This need to be tested on real hardware to be sure.

For the third case this is the "uncompressing kernel header" who will go to protected mode.

https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html

And it will load the uncompressed kernel itself.

https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-5.html

Hope that helped you

Cheers

Arnaud Meauzoone

fabiensiron commented 6 years ago

Hi Arnaud,

I am glad you read my article :) Hope you found it interesting.

Yes, it was very interesting, thanks for writing it ^^

This bootloader was a projet I did to understand more how work a bootloader and the kernel. It is not meant to be professional, and it is not bugproof at all :)

There is tree main memory segment in this article:

Memory below 0x100000 mbr and kernel header. Protected mode kernel above 0x100000 (1048576 octets). Uncompressed kernel at 0x1000000

In the first case to move data from the disk, I use the LBA method witch can only put data up to 1MB

https://wiki.osdev.org/LBA

In the second case I used a code to move data at 0x100000

So I think the problem you pointed is with this code. (Correct me if I am wrong.)

highmove_addr dd 0x100000
; source = 0x2000
; Once we have loaded data from disk to 0x2000
; We need to move it to 0x100000 (Protected-mode kernel)
highmove:
mov esi, 0x20000 ;From
mov edi, [highmove_addr] ;TO
mov edx, 512*127
mov ecx, 0 ; pointer
.loop:
mov eax, [esi] ;From
mov [edi], eax ;To
add esi, 4
add edi, 4
sub edx, 4
jnz highmove.loop
mov [highmove_addr], edi ; Increase disk pointer
ret

This is the code witch put the "protected mode kernel" above 0x100000 In this case we are still in real mode so the memory "addressable" is a little over 1 MB

https://wiki.osdev.org/Real_Mode

So how can we put the kernel at 0x100000 and above?

In fact I think for this little kernel QEMU deal with it. And it enables itself the A20 line. It might bug with --enable-kvm because you are much more closer to your real hardware and so in this case. you might have to enable the A20 gate and pass to protected mode to put the "protected mode kernel" at 0x100000

Then you may have to downgrade to reel mode to start the kernel. This need to be tested on real hardware to be sure.

For the third case this is the "uncompressing kernel header" who will go to protected mode.

https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-3.html

And it will load the uncompressed kernel itself.

https://0xax.gitbooks.io/linux-insides/content/Booting/linux-bootstrap-5.html

Yes, you are totally right but I was wondering why qemu accepts that kind of memory access. Also, if you pass in protected mode, it seems better to write a dedicated disk driver as the bios service isn't available.

Thanks for the answer, Cheers,