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