Boot logic : shortcut ?

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.
Post Reply
JulienDarc
Member
Member
Posts: 97
Joined: Tue Mar 10, 2015 10:08 am

Boot logic : shortcut ?

Post by JulienDarc »

Hello,

I am concerned about the booting logic one can get in xv6. Specifically, I am interested in the x86_64 long mode.

https://github.com/swetland/xv6 (github happens to be not reachable at the moment of writing)

What is the root of my concern is that line, in entry64.S:

Code: Select all

  lgdt (gdtr64 - mboot_header + mboot_load_addr)
When i see this, I think : "okay, we did something hacky".

Isn't it possible to do the following :
1) probe the available physical ram and not just guess it.
2) always keep the low addresses as is (they are already mapped to physical memory) and put the root of the kernel at the very top of the physical memory.
3) Create the paging, pml4, gdt...
4) jump to long mode
5) The OS knows that it cannot assign any physical memory under 1MB and over the size of the kernel (say 512MB for a small kernel) thanks to the initial memory probing.
6) Obviously no limit for virtual memory, everything is done as usual, unrelated.

That way we get :
1) gdt for cpu0 starting exactly at 0x100000
2) gdt for cpuX start exactly at (0x100000 + sizeof(gdt)) * X
3) code starting from top of kernel (MAX PHYS - 512 MB as to keep with the example) and going down to 0 (as usual). So we have that "middle memory" for the user processes.

But how to be sure that we are not erasing anything (forcing the linker not to start eventual code at 0x100000 since we will use it for our gdts and we don't initialy know how many cpus we have (hence gdts)?

Is there something I am missing, that just asks to blast me out ?
JulienDarc
Member
Member
Posts: 97
Joined: Tue Mar 10, 2015 10:08 am

Re: Boot logic : shortcut ?

Post by JulienDarc »

This idea sucks after all..

Why did he put that line ?

Code: Select all

lgdt (gdtr64 - mboot_header + mboot_load_addr)
and not just

Code: Select all

lgdt (gdtr64)
?

Why the offset after all ? We don't care where it is.. Why take mboot_header specifically ?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Boot logic : shortcut ?

Post by Brendan »

Hi,
JulienDarc wrote:I am concerned about the booting logic one can get in xv6. Specifically, I am interested in the x86_64 long mode.

https://github.com/swetland/xv6 (github happens to be not reachable at the moment of writing)

What is the root of my concern is that line, in entry64.S:

Code: Select all

  lgdt (gdtr64 - mboot_header + mboot_load_addr)
When i see this, I think : "okay, we did something hacky".
Yes, it's a little hacky; but mostly because the load address/physical address is different to the virtual address (e.g. the load address is probably 0x00100000 while the virtual address is probably more like 0xFFFFFFFF80000000) and because this code runs before paging is enabled (and before the virtual addresses can be used).

Basically it's like "lgdt (gdtr64)", except that "gdtr64" is a virtual address and needs to be converted to a load address/physical address (where the "- mboot_header + mboot_load_addr" is the hacky part to convert the virtual address into a physical address).

Also note that the LGDT instruction must be done twice, once in 32-bit code (because you can't use a 64-bit virtual address for the GDT yet, where it's using the physical address of the GDT instead) and then again once you're in 64-bit code (where you can use a 64-bit virtual address for the GDT).
JulienDarc wrote:Isn't it possible to do the following :
1) probe the available physical ram and not just guess it.
2) always keep the low addresses as is (they are already mapped to physical memory) and put the root of the kernel at the very top of the physical memory.
3) Create the paging, pml4, gdt...
4) jump to long mode
5) The OS knows that it cannot assign any physical memory under 1MB and over the size of the kernel (say 512MB for a small kernel) thanks to the initial memory probing.
6) Obviously no limit for virtual memory, everything is done as usual, unrelated.
Erm. Never probe physical memory (use the data GRUB got from the firmware instead). GRUB is too stupid to load the kernel at the very top of physical memory and copying it is mostly pointless overhead because only the virtual address (and not the physical address) is what actually matters.

Mostly what I'm saying is that it is very hacky, but not for the reasons you think. It's hacky because:
  • For BIOS systems, there's no guarantee that the boot loader didn't put the "multiboot information structure" in the area that's being used for page tables, etc.
  • It'd need major changes to make it work for UEFI (where you can't assume that the area from 0x1000 to 0x5000 is usable RAM and not something completely different)
  • Reusing part of the same initialisation code for the BSP (which begins in 32-bit protected mode) and the AP CPUs (which begin in 16-bit real mode) is retarded at best. The "AP CPU startup" trampoline should be entirely separate.
  • Their "__deadloop" should be with a "cli; die: hlt; jmp die" (e.g. in case it's used to take CPUs offline, which is the only sane reason for it to exist at all)
  • The "wrmsr" doesn't belong in the "entry64.S" file at all (e.g. should probably be a macro containing inline assembly in a C header file in some sort of "/arch/x86_64" platform specific directly that doesn't exist).
A "slightly more correct maybe" way of fixing it would be to define a special "init" section and tell the linker that (for this special section) the virtual address is the same as the load address; and then put all the initialisation code in that special section, including code to copy data from the multi-boot information structure to somewhere safe, and code to check the physical memory layout and determine where page tables should actually be stored, and the (latter part of) the AP startup trampoline. Sadly, your typical C programmer is more interested in getting C working (and avoiding assembly) than actually doing anything correctly. ;)


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.
JulienDarc
Member
Member
Posts: 97
Joined: Tue Mar 10, 2015 10:08 am

Re: Boot logic : shortcut ?

Post by JulienDarc »

Thanks a lot Brendan :D
Post Reply