How kernel determind the low and high memory zone?

2009 March 24
by admin

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * Determine low and high memory ranges:
 */
unsigned long __init find_max_low_pfn(void)
{
        unsigned long max_low_pfn;
 
        max_low_pfn = max_pfn;
        if (max_low_pfn > MAXMEM_PFN) {
                if (highmem_pages == -1)
                        highmem_pages = max_pfn - MAXMEM_PFN;
                if (highmem_pages + MAXMEM_PFN < max_pfn)
                        max_pfn = MAXMEM_PFN + highmem_pages;
                if (highmem_pages + MAXMEM_PFN > max_pfn) {
                        printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));
                        highmem_pages = 0;
                }
                max_low_pfn = MAXMEM_PFN;
#ifndef CONFIG_HIGHMEM
                /* Maximum memory usable is what is directly addressable */
                printk(KERN_WARNING "Warning only %ldMB will be used.\n",
                                        MAXMEM>>20);
                if (max_pfn > MAX_NONPAE_PFN)
                        printk(KERN_WARNING "Use a PAE enabled kernel.\n");
                else
                        printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
                max_pfn = MAXMEM_PFN;
#else /* !CONFIG_HIGHMEM */
#ifndef CONFIG_X86_PAE
                if (max_pfn > MAX_NONPAE_PFN) {
                        max_pfn = MAX_NONPAE_PFN;
                        printk(KERN_WARNING "Warning only 4GB will be used.\n");
                        printk(KERN_WARNING "Use a PAE enabled kernel.\n");
                }
#endif /* !CONFIG_X86_PAE */
#endif /* !CONFIG_HIGHMEM */
        } else {
                if (highmem_pages == -1)
                        highmem_pages = 0;
#ifdef CONFIG_HIGHMEM
                if (highmem_pages >= max_pfn) {
                        printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));
                        highmem_pages = 0;
                }
                if (highmem_pages) {
                        if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){
                                printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));
                                highmem_pages = 0;
                        }
                        max_low_pfn -= highmem_pages;
                }
#else
                if (highmem_pages)
                        printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");
#endif
        }
        return max_low_pfn;
}
No comments yet

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS

Easy AdSense by Unreal