Re: A question about function split_mem_range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 25 Mar 2018 22:32:42 +0800, Hao Lee said:

> In arch/x86/mm/init.c, there is a function called split_mem_range[0].
> Its logic is very complicated and I can't figure out what it does. I
> have added some debug statements in this function to print all
> variable, but I still can't understand it. I have also searched it on
> Google and couldn't find any helpful articles. Could someone give me
> some help about what on earth this function does? Many thanks!

Step 0: kernel functions are usually given somewhat descriptive names.
So what can we guess based on the function name?  That it performs some
sort of slicing and dicing of a memory range...

Step 1:  Use what you already know about the function. For example, it's under
arch/x86 - which means it has architecture dependencies. It's marked 'static
__meminit' - which means that (a) there's no direct calls from other files, and
(b) there probably isn't a call through an address pointer (because this code
may get freed and the memory reclaimed after __miminit is done).  And indeed,
'git grep' (or "grep -r') confirms the only other use is also in mm/init.c (and we
see no sign of an &split_mem_range() so it can't be called via pointer passed
elsewhere).

Step 2: look at the call site in init_memory_swapping(), which provides us this
nice block comment:

/*
 * Setup the direct mapping of the physical memory at PAGE_OFFSET.
 * This runs before bootmem is initialized and gets pages directly from
 * the physical memory. To access them they are temporarily mapped.
 */

Step 3: look at the code around the call site:

        memset(mr, 0, sizeof(mr));
        nr_range = split_mem_range(mr, 0, start, end);

        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
                                                   mr[i].page_size_mask);

So  before the call, mr[] is a whole lot of zeros.  After the call, the array
has a series of start/end/mask entries suitable for setting up a temporary
physical mapping.

>From this we can conclude that split_mem_range() is a helper function that
takes a range (for example "starting at the 0M address line and ending at the
512M address line") and returns a list of suitable ranges for mappings, while
applying some rules like "Don't use a hugepage for the first 4M on 32-bit".  So
what comes back is an array that basically says something like "Use a 4K page
at 0, a 4K page at 4K, a 4K at 8/12/... up to "4K at (2M-4))", a 2M hugepage at
2M, 4M... 508M. Or something else suitable for the kernel config (32/64 bit,
etc, look at the #ifdefs to figure out exactly what it does for a given address
location)

 (Actual  start and end are whatever the rest of the kernel decides, I couldn't
be bothered to chase down code that has a pr_debug() to print the numbers out
for anybody who care).

Attachment: pgpDoLmynTFXD.pgp
Description: PGP signature

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@xxxxxxxxxxxxxxxxx
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]

  Powered by Linux