Monday, December 20, 2010

Why 32bit Linux only see 3GB memory in a machine with 4GB RAM.

The Symptom:
OS detected  4194304k but only 3105024k is available.

[32bit Linux]$ dmesg | grep -i mem
3200MB HIGHMEM available.
896MB LOWMEM available.
HighMem zone: 819200 pages, LIFO batch:31
ACPI: SRAT (v002 VMWARE MEMPLUG  0x06040000 VMW  0x00000001) @ 0xbfeef3e1
Memory: 3105024k/4194304k available (1584k kernel code, 39372k reserved, 622k data, 168k init, 2228096k highmem)
[32bit Linux]$free 
total       used       free     shared    buffers     cached
Mem:       3108956      73076    3035880          0       8000      37932
-/+ buffers/cache:      27144    3081812
Swap:       779112          0     779112
The Theory: 
hugemem/PAE enabled kernel  is ONLY needed for RAM from 4GB up to 64GB, The generic 32bit Linux Kernel can see 4GB without hugemem/PAE enabled kernel.
The Cause: 
Sometimes, why 32bit Linux can't see all the 4GB ram? The answer is from “physical RAM map” provided by BIOS.
The Analysis:
[32bit Linux]$dmesg | less
Linux version 2.6.16.60-0.21-default (geeko@buildhost) (gcc version 4.1.2 20070115 (SUSE Linux)) #1 Tue May 6 12:41:02 UTC 2008
BIOS-provided physical RAM map:
BIOS-e820: 0000000000000000 - 000000000009f800 (usable)
BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
BIOS-e820: 00000000000ca000 - 00000000000cc000 (reserved)
BIOS-e820: 00000000000dc000 - 00000000000e4000 (reserved)
BIOS-e820: 00000000000e8000 - 0000000000100000 (reserved)
BIOS-e820: 0000000000100000 - 00000000bfee0000 (usable)
BIOS-e820: 00000000bfee0000 - 00000000bfeff000 (ACPI data)
BIOS-e820: 00000000bfeff000 - 00000000bff00000 (ACPI NVS)
BIOS-e820: 00000000bff00000 - 00000000c0000000 (usable)
BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
BIOS-e820: 00000000fec00000 - 00000000fec10000 (reserved)
BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved)
BIOS-e820: 00000000fffe0000 - 0000000100000000 (reserved)
BIOS-e820: 0000000100000000 - 0000000140000000 (usable)
Warning only 4GB will be used.
Use a PAE enabled kernel.
3200MB HIGHMEM available.
896MB LOWMEM available.
The interesting part of  physical RAM map is the last line, and interesting number is  0000000100000000 which is hex value of 4GB. 
Converting them decimal values to be more readable.

[32bit Linux]$ dmesg | awk  --re-interval   --non-decimal-data '/[0-9a-z]{16}/  {  x1=sprintf ("%d", "0x"$2) ; x2=sprintf ("%d", "0x"$4);  printf "%d %s %d %s %d %s\n",  x1/1024/1024, " - ", x2/1024/1024, "=", (x1-x2)/1024/1024,$NF }' 
0  -  0 = -0 (usable)
0  -  0 = -0 (reserved)
0  -  0 = -0 (reserved)
0  -  0 = -0 (reserved)
0  -  1 = -0 (reserved)
1  -  3070 = -3069 (usable)
3070  -  3070 = -0 data)
3070  -  3071 = -0 NVS)
3071  -  3072 = -1 (usable)
3584  -  3840 = -256 (reserved)
4076  -  4076 = -0 (reserved)
4078  -  4078 = -0 (reserved)
4095  -  4096 = -0 (reserved)
4096  -  5120 = -1024 (usable)

It is clear that BIOS has too many reserved parts  in lower address space and push the one trunk of 1GB over 4GB address space.
The Solution:
 1)To release some reserved space and bring all usable spaces below 4GB, you might try to disable some devices in BIOS. It is the best option, but might not be achievable , consult with your hardware vendor.
 2)Reinstall system with 64bit Kernel
 3)Install hugemem/PAE kernel on current 32 Bit system. It is the last option because hugemem/PAE  kernel hurt performance due to the “dynamic rempapping with three-level paging model.

No comments:

Post a Comment