Open m-mueller678 opened 12 months ago
I think we automatically stripped debug symbols from the kernel ELF when creating the bootable disk image in v0.9. In the current version, we don't do this anymore as users have more control over the disk image creation now. So I suspect that the reason for the slow loading is that your kernel contains a lot of debug info.
Ideally, our loading code would only load the relevant parts of the ELF file into memory. However, this is currently diffcult since the loading needs to happen in real mode for BIOS booting, which limits the complexity of our loader because of memory size contraints.
So I recommend to strip the kernel executable to speed up the load process. You can do this via cargo by using the strip
profile setting (or maybe split-debuginfo
to write it to a separate file). Alternatively, you can also invoke the strip
executable on your kernel before passing it to the DiskImageBuilder
.
Let me know whether stripping the executable helps! If not, there might be some bug in our loading code...
I switched to UEFI as a workaround, that was much faster. Unfortunately, I don't have the BIOS code at hand anymore.
I am now using stripped binaries with BIOS, it is faster than unstripped with BIOS. 1.8s for 750KB, which still seems kind of slow to be honest.
Looks like the BIOS code directly uses the BIOS interfaces to load individual sectors using int 13h
. This is the most portable (supports SCSI, NVMe, USB, ... Especially USB is hard to implement.), but doesn't allow submitting multiple requests at the same time to mitigate latency. It may be possible to load multiple contiguous sectors at the same time though, which should help a lot when there is no disk fragmentation.
I think it already tries to load multiple contiguous sectors:
let sectors = u64::min(number_of_sectors, 32) as u16;
I'm not sure why it's limited to 32 though, Wikipedia says some BIOS implementations are limited to at most 127.
I'm not sure why it's limited to 32 though, Wikipedia says some BIOS implementations are limited to at most 127.
I don't remember either. We can try to increase the sector limit to 127 here: https://github.com/rust-osdev/bootloader/blob/751585c6fa7ad825f5d21b38c09d7154f4b8acb6/bios/stage-2/src/disk.rs#L37
I just tried it and it seems to work in QEMU. We should probably test it on some real world systems too though.
I am now using stripped binaries with BIOS, it is faster than unstripped with BIOS. 1.8s for 750KB, which still seems kind of slow to be honest.
How does it compare to v0.9? If I remember correctly, we loaded each sector separately in v0.9, so the kernel load should be faster in v0.11 even with the limit set to 32. There might be some additional fixed overhead in v0.10 because we're now reading things from a FAT partition, which requires some additional load operations.
I never measured it for 0.9, I remember it being practically instantaneous while following the OS dev tutorial. The first thing I did after is switching to the new bootloader, where I was surprised by the slow boot.
The bootloader is stuck on 'loading kernel...' (apparently in stage 2) for about 10 seconds. I am using qemu with kvm enabled, booting via bios.
qemu-system-x86_64 -enable-kvm -drive format=raw,file=os.img -serial stdio
I find this surprising, as on
0.9.23
it was practically instantaneous. Is this expected?
Use qemu-system-x86_64 -machine accel=kvm,type=q35
The bootloader is stuck on 'loading kernel...' (apparently in stage 2) for about 10 seconds. I am using qemu with kvm enabled, booting via bios.
I find this surprising, as on
0.9.23
it was practically instantaneous. Is this expected?