Page 1 of 1

Higher half kernels

Posted: Sat Feb 09, 2013 2:13 am
by BMW
What is the point of a higher half kernel?

Because each process has its own virtual address space, so why not just put the kernel at 0x00 in its own address space????

It shouldn't matter where it is within its VAS, user space programs have their own VAS.

Re: Higher half kernels

Posted: Sat Feb 09, 2013 3:12 am
by gravaera
Yo:

The biggest reason is avoiding address space switches, and the TLB cooling that comes with switching address spaces constantly. If you map the kernel into every address space, then a syscall can be theoretically executed entirely within the calling process's address space. When you keep the kernel in its own address space, you every syscall requires you to do two address space switches -- one into the kernel's address space, and one back out into the userspace process' address space.

--Peace out,
gravaera

Re: Higher half kernels

Posted: Sat Feb 09, 2013 4:08 am
by OSwhatever
One benefit of having the kernel at high address is that you have the possibility to move the kernel without affecting the program and that way adjust how much each process has. An example of this is the 3GB switch in Windows that moves the kernel one gigabyte up in order to give the processes more virtual memory.

It's simply easier to move the kernel than the programs. Think about x86-64 where you have a "hole" in the middle of the virtual address space. Let's say they would decide to make this hole smaller one day. Then you don't need to modify your program that starts a 0 but, if the program would be on high address it would require a recompilation in order to take advantage of the larger virtual address space. Possible with relocation though but if you can avoid it......

Re: Higher half kernels

Posted: Sat Feb 09, 2013 4:27 am
by rdos
Personally, I can't see any valid reason why to place a program at address 0. Executable formats for 32 and 64 bits all have relocation information, and are usually not bound to a specific address, and at least not to 0. The reason why a user program should not execute at address 0 is that this is the address of null-pointers, which should be caught as invalid. The larger invalid space at the beginning, the lower risk of null pointers, or random integers casted to pointers, will be valid.

The same applies to kernels. They should not be a address 0, nor at the top of linear address space (since this allows negative integers to be casted to valid pointers in the kernel).

Re: Higher half kernels

Posted: Sat Feb 09, 2013 4:46 am
by dozniak
rdos wrote:Executable formats for 32 and 64 bits all have relocation information,
The more relocation information you have to process for a given program, the longer it takes to load and start. Compare:
- load program and jump to it

vs.

- load program
- process relocations for each executable section, process PLT entries
- process relocations for each data section, process GOT relocations
- jump to it

Process of relocation is usually linear with the size of program (has to patch every address) and touches a lot of memory pages (usually the entire executable space of the program), thus trashing the caches and being even less effective (vs. not doing that).

Re: Higher half kernels

Posted: Sat Feb 09, 2013 4:55 am
by bluemoon
rdos wrote:The reason why a user program should not execute at address 0 is that this is the address of null-pointers, which should be caught as invalid. The larger invalid space at the beginning, the lower risk of null pointers, or random integers casted to pointers, will be valid.
Agree. For this reason I set the first 4KB as absent, and map the first following few MB as kernel-access only (for process specific information block), and the application starts at 16MB.

Re: Higher half kernels

Posted: Sat Feb 09, 2013 5:00 am
by bluemoon
dozniak wrote:The more relocation information you have to process for a given program, the longer it takes to load and start.
However consider a typical scenario that an application consist of a base executable and a dozen of shared libraries.
The added time might not be as worst as you expect since all shared libraries require relocation on both cases.

Furthermore if you are doing address space randomization, you need to do relocations anyway.

Re: Higher half kernels

Posted: Sat Feb 09, 2013 6:16 am
by egos
If you use own libraries you can set different predefined base addresses for them to prevent its overlapping. Besides, in many projects the size of base executable module is larger than the size of all used shared libraries.

Re: Higher half kernels

Posted: Sat Feb 09, 2013 10:33 am
by rdos
dozniak wrote:
rdos wrote:Executable formats for 32 and 64 bits all have relocation information,
The more relocation information you have to process for a given program, the longer it takes to load and start. Compare:
- load program and jump to it

vs.

- load program
- process relocations for each executable section, process PLT entries
- process relocations for each data section, process GOT relocations
- jump to it

Process of relocation is usually linear with the size of program (has to patch every address) and touches a lot of memory pages (usually the entire executable space of the program), thus trashing the caches and being even less effective (vs. not doing that).
First, you can do demand-loading and relocation at the same time. Second, you can bind the executable at a non-zero address, and avoid relocation that way. In x86-64, I let the linker locate the executable far above 4G, and then I mark the entire first 4G as kernel-only.

Re: Higher half kernels

Posted: Sat Feb 09, 2013 2:34 pm
by bluemoon
egos wrote:If you use own libraries you can set different predefined base addresses for them to prevent its overlapping. Besides, in many projects the size of base executable module is larger than the size of all used shared libraries.
Let's check a few application on linux:

Code: Select all

$ ldd /bin/ls
	linux-vdso.so.1 =>  (0x00007fff77dff000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3979a6c000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3979864000)
	libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 (0x00007f397965b000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f397929c000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3979098000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3979ca2000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3978e7a000)
	libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007f3978c75000)
$ ldd /bin/sh
	linux-vdso.so.1 =>  (0x00007fff5bfff000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f633e3ac000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f633e782000)
$ ldd /bin/nano
	linux-vdso.so.1 =>  (0x00007fff62ba2000)
	libncursesw.so.5 => /lib/x86_64-linux-gnu/libncursesw.so.5 (0x00007f34d286f000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f34d24b0000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f34d22ab000)
	libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f34d2084000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f34d2ab3000)
With these sample I assume the number of libraries is significant per normal application.

Now, if you count the relocations entries, you may note that:
1. for normal application, you only need to do relocation for global objects (GOT). The PLT entry only exist if you has exported function on the base executable. The work for relocation is insignificant and however not related to the code size.
2. On the contrast, every shared libraries has tons of relocation.

You got my point.