izac89
izac89

Reputation: 3930

Linux kernel code optimization

From Understanding Linux Kernel 3rd edition In the chapter that describes kernel fixed mapping, there is a function which uses the following enumorator-

Each fix-mapped linear address is represented by a small integer index defined in the enum fixed_addresses data structure:

 enum fixed_addresses {
 FIX_HOLE,
 FIX_VSYSCALL,
 FIX_APIC_BASE,
 FIX_IO_APIC_BASE_0,
 [...]
 _ _end_of_fixed_addresses
 };

and giving this enumerator, the following function will compile-

Fix-mapped linear addresses are placed at the end of the fourth gigabyte of linear addresses. The fix_to_virt( ) function computes the constant linear address starting from the index:

inline unsigned long fix_to_virt(const unsigned int idx)
{
    if (idx >= _ _end_of_fixed_addresses)
        _ _this_fixmap_does_not_exist( );
    return (0xfffff000UL - (idx << PAGE_SHIFT));
}

Now, take a look at the following explanation regarding how this function is finally translated to only 0xfffff000-(3 << PAGE_SHIFT)

Let's assume that some kernel function invokes fix_to_virt(FIX_IOAPIC_BASE_0). Because the function is declared as "inline," the C compiler does not generate a call to fix_to_virt( ), but inserts its code in the calling function. Moreover, the check on the index value is never performed at runtime. In fact, FIX_IOAPIC_BASE_0 is a constant equal to 3, so the compiler can cut away the if statement because its condition is false at compile time. Conversely, if the condition is true or the argument of fix_to_virt( ) is not a constant, the compiler issues an error during the linking phase because the symbol _ _this_fixmap_does_not_exist is not defined anywhere. Eventually, the compiler computes 0xfffff000-(3 << PAGE_SHIFT) and replaces the fix_to_virt( ) function call with the constant linear address 0xffffc000.

So, it seems that the writer of the code relies on some assumption that if we have an if statement with comparison between two numbers that are defined in compilation time (lets say FIX_IO_APIC_BASE_0 and _ _end_of_fixed_addresses) and thus the results is knows in compilation time, than the if statement is sure to be optimized and removed from code.

How can the Linux kernel code assume that?

Also, what is the motivation for such code? if the writer want the function to be evaluated to 0xfffff000-(3 << PAGE_SHIFT) why not just write 0xfffff000-(3 << PAGE_SHIFT) instead of a call to this function?

Upvotes: 3

Views: 765

Answers (2)

DvTr
DvTr

Reputation: 347

_ _end_of_fixed_addresses is known at unit compilation time, but not idx: there's the possibility that that function beign called with invalid idx from an external source code. As this_fixmap_does_not_exists symbol doesnt exists, like told in explanation, if a developer attempts to use fix_to_virt with an invalid idx will go to a compiling error. But if he uses a correct one, 'if' statement will be removed by compiler. So, this is in fact not a runtime protection, but a development protection, a technique for translating a possible runtime error to just a compiling one. About the fix result, note that is just by the example. idx could be different of 3, and so result of that function.

Upvotes: 1

Ulrich Eckhardt
Ulrich Eckhardt

Reputation: 17424

There are actually two questions here:

  • How can the Linux kernel code assume that the code is removed from the binary? The simple answer is that the compilation environment (compiler etc) guarantees that. Basically, constant propagation is a simple and well-known compiler optimization and in this case it makes it very easy to detect that the code is unused.
  • Why not just spell out the code? The simple reason is portability and readability. Portability means that this allows you to adjust the function in just a single place for a new platform or CPU. Readability means that the intention is conveyed along with possible documentation for this function, which wouldn't be the case if you just dumped the raw function content in there. It's similar to the rationale for not using "magic numbers" in code.

Upvotes: 1

Related Questions