How kernel determind the low and high memory zone?

I thought Linux fixed highmem zone and low mem zone at the compile time. But, I was wrong. I even found the command line parameter named ‘highmem=’ which can set the highmem size.

Actually, this calculation is done during the initialization and following is the code which actually do the thing.

 895/*
 896 * Determine low and high memory ranges:
 897 */
 898unsigned long __init find_max_low_pfn(void)
 899{
 900        unsigned long max_low_pfn;
 901
 902        max_low_pfn = max_pfn;
 903        if (max_low_pfn > MAXMEM_PFN) {
 904                if (highmem_pages == -1)
 905                        highmem_pages = max_pfn - MAXMEM_PFN;
 906                if (highmem_pages + MAXMEM_PFN < max_pfn)
 907                        max_pfn = MAXMEM_PFN + highmem_pages;
 908                if (highmem_pages + MAXMEM_PFN > max_pfn) {
 909                        printk("only %luMB highmem pages available, ignoring highmem size of %uMB.n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
 910                        highmem_pages = 0;
 911                }
 912                max_low_pfn = MAXMEM_PFN;
 913#ifndef CONFIG_HIGHMEM
 914                /* Maximum memory usable is what is directly addressable */
 915                printk(KERN_WARNING "Warning only %ldMB will be used.n",
 916                                        MAXMEM>>20);
 917                if (max_pfn > MAX_NONPAE_PFN)
 918                        printk(KERN_WARNING "Use a PAE enabled kernel.n");
 919                else
 920                        printk(KERN_WARNING "Use a HIGHMEM enabled kernel.n");
 921                max_pfn = MAXMEM_PFN;
 922#else /* !CONFIG_HIGHMEM */
 923#ifndef CONFIG_X86_PAE
 924                if (max_pfn > MAX_NONPAE_PFN) {
 925                        max_pfn = MAX_NONPAE_PFN;
 926                        printk(KERN_WARNING "Warning only 4GB will be used.n");
 927                        printk(KERN_WARNING "Use a PAE enabled kernel.n");
 928                }
 929#endif /* !CONFIG_X86_PAE */
 930#endif /* !CONFIG_HIGHMEM */
 931        } else {
 932                if (highmem_pages == -1)
 933                        highmem_pages = 0;
 934#ifdef CONFIG_HIGHMEM
 935                if (highmem_pages >= max_pfn) {
 936                        printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
 937                        highmem_pages = 0;
 938                }
 939                if (highmem_pages) {
 940                        if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
 941                                printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.n", pages_to_mb(highmem_pages));
 942                                highmem_pages = 0;
 943                        }
 944                        max_low_pfn -= highmem_pages;
 945                }
 946#else
 947                if (highmem_pages)
 948                        printk(KERN_ERR "ignoring highmem size on non-highmem kernel!n");
 949#endif
 950        }
 951        return max_low_pfn;
 952}

Leave a Comment

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.