Example Higher Half x86_64 kernel @ -2GB

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.
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Example Higher Half x86_64 kernel @ -2GB

Post by proxy »

Hey guys,

I was just tinkering with my kernel and decided to move it from being loaded at 0xffff800000000000 (the half way point in the address space) to the -2GB. Since my page table knowledge has been a bit on the back burner, it took me a bit to get the 4 levels of entries quite right.

After looking on the wiki, I noticed that there was a good example of a higher half kernel on 32-bit, but nothing really spelling out getting it right on 64-bit. So I've cooked up a minimalist example for anyone who needs one.

https://github.com/eteran/os64

I hope that anyone who is looking for a simple, example kernel being loaded at the -2GB mark (0xffffffff80000000) can use this as a good place to start so they don't spend quite as much time as I did on those 4 levels of page tables ;-)

As a bonus, it is also a good example of using cmake for your kernel needs.
Last edited by proxy on Fri Apr 14, 2017 8:39 am, edited 1 time in total.
User avatar
Geri
Member
Member
Posts: 442
Joined: Sun Jul 14, 2013 6:01 pm

Re: Example Higher Half x86_64 kernel @ -2GB

Post by Geri »

may i ask what is the purpose of loading the kernel to special logical locations, if you have paging? you will have to do both an user mode memory manager (mallloc/free), and the kernel equivalent functions (kmalloc/kfree) and a function to load from/to kernel space / user space memory to serve your osapi calls.

the phisical location of your kernel blob will be oviously different from the location translated by system mode tables, so what is the point of translating it to the end, if you later will allocate the memory with your memory manager aniway, and the received pointers can be literally ANYTHING for both your kernel/drivers, and both the software running for the system? you just making your life harder for example the error detection, you will be in much harder situation to detect corrupt pointers if you check on the code by your eyes (whatever million gigabytes could be a legit area OR a garbage, you cant assume what is going on).
Operating system for SUBLEQ cpu architecture:
http://users.atw.hu/gerigeri/DawnOS/download.html
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: Example Higher Half x86_64 kernel @ -2GB

Post by proxy »

Um, it's not at any special physical location. This is an example of using paging to place it at the -2GB *virtual* address...

I think you have misunderstood the code. This is really just a 64 bit version of the "bare bones higher half" examples.
Last edited by proxy on Fri Apr 14, 2017 8:39 am, edited 1 time in total.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Example Higher Half x86_64 kernel @ -2GB

Post by iansjack »

Geri wrote:may i ask what is the purpose of loading the kernel to special logical locations, if you have paging?
There are some clear advantages to having a higher-half kernel ( http://wiki.osdev.org/Higher_Half_Kernel ). 2GB is probably more than enough space, so loading it 2GB below the top of the virtaul address space makes a lot of sense.

In other words - why not?
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: Example Higher Half x86_64 kernel @ -2GB

Post by proxy »

After re-reading your question, I think we were momentarily talking past each other. I'll do my best to answer your question.

There are a few distinct advantages to having a "higher half" kernel.

1. User space is a lot cleaner. On 64-bit, it basically means any address without the top bit set is user space, any address with it set is kernel space. Easy delineation.
2. User space addresses start at 0! This means that 32-bit applications can be supported, since they can't reasonably be above the 4GB mark. Sure you could load the code high, as long as it is PIC and put the data low. But that's just messy. If we KNOW the kernel is in the upper half, we can just load the 32-bit program where it wants to be.

So, we have some good reasons to want the kernel high, but why at -2GB specifically? Well, if you don't, you will run into issues with the code model. gcc (and I assume clang) will use different code models to determine how relocation work when linking. You can specify "large", which means that an address can be "anywhere", so it must emit code which is basically like this:

Code: Select all

mov address, %eax
callq *%eax
Which is terribly inefficient, but will work...

If we specify "small", it'll do things sanely, but you may run into mysterious linker issues about "relocation truncated to fit: R_X86_64_32..." which can be terrible to deal with. My motivation for this post was my kernel compiled fine in debug builds, but not release builds because gcc was choosing different relocation sizes than I wanted; and I was getting errors during linking :-(.

The solution is the "kernel" model, which is what the Linux kernel uses. It tells the compiler to "assume the code is loaded at -2GB", allowing it to use 32-bit relocations for all calls safely. You can still put data wherever you like of course. This makes things with the linker "just work".

I hope this answers your question.
User avatar
Geri
Member
Member
Posts: 442
Joined: Sun Jul 14, 2013 6:01 pm

Re: Example Higher Half x86_64 kernel @ -2GB

Post by Geri »

aha, the pointer trick basically makes some sense. i eliminated the translation and relocation problems through basically not using paging. my OS-es always using direct memory addressing. this removes 99% of the work with the memory and pointer management.
Operating system for SUBLEQ cpu architecture:
http://users.atw.hu/gerigeri/DawnOS/download.html
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Example Higher Half x86_64 kernel @ -2GB

Post by iansjack »

This thread is about 64-bit code. It is not an option to avoid paging.
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: Example Higher Half x86_64 kernel @ -2GB

Post by proxy »

iansjack wrote:This thread is about 64-bit code. It is not an option to avoid paging.
Well... You could identity map all detected RAM and pretend there is no paging :wink:
User avatar
JAAman
Member
Member
Posts: 879
Joined: Wed Oct 27, 2004 11:00 pm
Location: WA

Re: Example Higher Half x86_64 kernel @ -2GB

Post by JAAman »

Geri wrote:aha, the pointer trick basically makes some sense. i eliminated the translation and relocation problems through basically not using paging. my OS-es always using direct memory addressing. this removes 99% of the work with the memory and pointer management.
doesn't that increase the problems with translation and relocation? if you don't use paging, then you have to use the physical addresses... which will be different on every computer (there are no addresses where RAM is certain to be located on all computers), thus you will need to run load-time relocations on all your code to make sure it runs on the computer it is currently on.. with paging, on the other hand, the code is always loaded at the same address, and no relocations are necessary

of course modern systems they run relocations anyway in order to intentionally randomize the address layout

in general, memory management with paging is a lot easier, and a lot faster with paging than without paging
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Example Higher Half x86_64 kernel @ -2GB

Post by iansjack »

proxy wrote:
iansjack wrote:This thread is about 64-bit code. It is not an option to avoid paging.
Well... You could identity map all detected RAM and pretend there is no paging :wink:
Which would be very limiting upon where you place the kernel. Why throw away all the advantages of paging (yet still use it).
User avatar
proxy
Member
Member
Posts: 108
Joined: Wed Jan 19, 2005 12:00 am
Contact:

Re: Example Higher Half x86_64 kernel @ -2GB

Post by proxy »

iansjack wrote:
proxy wrote:
iansjack wrote:This thread is about 64-bit code. It is not an option to avoid paging.
Well... You could identity map all detected RAM and pretend there is no paging :wink:
Which would be very limiting upon where you place the kernel. Why throw away all the advantages of paging (yet still use it).
Heh, I agree 100%. It wasn't a serious suggestion.
onlyonemac
Member
Member
Posts: 1146
Joined: Sat Mar 01, 2014 2:59 pm

Re: Example Higher Half x86_64 kernel @ -2GB

Post by onlyonemac »

iansjack wrote:
proxy wrote:
iansjack wrote:This thread is about 64-bit code. It is not an option to avoid paging.
Well... You could identity map all detected RAM and pretend there is no paging :wink:
Which would be very limiting upon where you place the kernel. Why throw away all the advantages of paging (yet still use it).
It would simplify things, particular if paging doesn't fit the design of your operating system. I'm not going to say that everyone has to use paging, and I believe that there are some edge cases where using paging is more trouble than it's worth or where it could get in the way of the design.
When you start writing an OS you do the minimum possible to get the x86 processor in a usable state, then you try to get as far away from it as possible.

Syntax checkup:
Wrong: OS's, IRQ's, zero'ing
Right: OSes, IRQs, zeroing
User avatar
Geri
Member
Member
Posts: 442
Joined: Sun Jul 14, 2013 6:01 pm

Re: Example Higher Half x86_64 kernel @ -2GB

Post by Geri »

JAAman wrote:doesn't that increase the problems with translation and relocation? if you don't use paging, then you have to use the physical addresses... which will be different on every computer (there are no addresses where RAM is certain to be located on all computers), thus you will need to run load-time relocations on all your code to make sure it runs on the computer it is currently on.. with paging, on the other hand, the code is always loaded at the same address, and no relocations are necessary
yes, relocation must be done by hand. but thats only one place in the code. but you have a lot simplier time from that, you basically directly can pass the pointers, there is no future address translation is needed at all.
JAAman wrote: in general, memory management with paging is a lot easier, and a lot faster with paging than without paging
i had a pal who was writing his memory allocator for his protected mode kernel. after 2 months it still not worked, and he gave up it enterly.
Operating system for SUBLEQ cpu architecture:
http://users.atw.hu/gerigeri/DawnOS/download.html
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Example Higher Half x86_64 kernel @ -2GB

Post by iansjack »

Geri wrote: i had a pal who was writing his memory allocator for his protected mode kernel. after 2 months it still not worked, and he gave up it enterly.
I'm sure that we all know people who aren't very good at programming.
User avatar
Geri
Member
Member
Posts: 442
Joined: Sun Jul 14, 2013 6:01 pm

Re: Example Higher Half x86_64 kernel @ -2GB

Post by Geri »

he isnt a bad programmer overally.
Operating system for SUBLEQ cpu architecture:
http://users.atw.hu/gerigeri/DawnOS/download.html
Post Reply