Colors of Ray+Hue'

System Memory

Linux Kernel2016. 8. 13. 10:44

original source: http://egloos.zum.com/studyfoss/v/5020843


[Linux] x86 시스템 메모리 맵 설정


시스템 부팅 시에 수행하는 가장 중요한 일 중 하나는 시스템에서 사용할 수 있는 메모리의 크기와 위치를 파악하여 이를 적절히 설정하는 것이다. ARM이나 MIPS와 같은 임베디드에서 주로 사용되는 코어들은 하드웨어 구성이 표준적으로 정해질 수 없으므로 이러한 작업은 보통 컴파일 시 특정 하드웨어에 정해진 설정을 그대로 사용하거나 부트로더에서 명령행 옵션으로 설정을 넘겨주어야 한다.

하지만 x86/PC 환경에서는 이러한 작업을 위한 표준적인 BIOS 서비스를 제공한다. 그 중 가장 대표적으로 사용되는 것이 이른바 'e820' 방식이라고 하는 BIOS 인터럽트 15번을 이용하는 방법이다. (실행 시 AX 레지스터에 16진수 e820이 들어있어야 하기 때문에 붙여진 이름이다.) 이에 대한 설명은 Ralf Brown's Interrupt List에 다음과 같이 나와있다.

INT 15 - newer BIOSes - GET SYSTEM MEMORY MAP
    AX = E820h
    EAX = 0000E820h
    EDX = 534D4150h ('SMAP')
    EBX = continuation value or 00000000h to start at beginning of map
    ECX = size of buffer for result, in bytes (should be >= 20 bytes)
    ES:DI -> buffer for result (see #00581)
Return: CF clear if successful
        EAX = 534D4150h ('SMAP')
        ES:DI buffer filled
        EBX = next offset from which to copy or 00000000h if all done
        ECX = actual length returned in bytes
    CF set on error
        AH = error code (86h) (see #00496 at INT 15/AH=80h)
Notes:    originally introduced with the Phoenix BIOS v4.0, this function is
      now supported by most newer BIOSes, since various versions of Windows
      call it to find out about the system memory
    a maximum of 20 bytes will be transferred at one time, even if ECX is
      higher; some BIOSes (e.g. Award Modular BIOS v4.50PG) ignore the
      value of ECX on entry, and always copy 20 bytes
    some BIOSes expect the high word of EAX to be clear on entry, i.e.
      EAX=0000E820h
    if this function is not supported, an application should fall back
      to AX=E802h, AX=E801h, and then AH=88h
    the BIOS is permitted to return a nonzero continuation value in EBX
      and indicate that the end of the list has already been reached by
      returning with CF set on the next iteration
    this function will return base memory and ISA/PCI memory contiguous
      with base memory as normal memory ranges; it will indicate
      chipset-defined address holes which are not in use and motherboard
      memory-mapped devices, and all occurrences of the system BIOS as
      reserved; standard PC address ranges will not be reported
SeeAlso: AH=C7h,AX=E801h"Phoenix",AX=E881h,MEM xxxxh:xxx0h"ACPI"
 
Format of Phoenix BIOS system memory map address range descriptor:
Offset    Size    Description    (Table 00580)
 00h    QWORD    base address
 08h    QWORD    length in bytes
 10h    DWORD    type of address range (see #00581)
 
(Table 00581)
Values for System Memory Map address type:
 01h    memory, available to OS
 02h    reserved, not available (e.g. system ROM, memory-mapped device)
 03h    ACPI Reclaim Memory (usable by OS after reading ACPI tables)
 04h    ACPI NVS Memory (OS is required to save this memory between NVS
      sessions)
 other    not defined yet -- treat as Reserved
SeeAlso: #00580


이 방식을 통해 메모리 맵 정보를 구성하는 코드는 (setup 프로그램에 포함되는) arch/x86/boot/memory.c 파일의 detect_memory_e820 함수이다. e820 방식을 통해 얻은 메모리 맵 정보는 부트로더 혹은 setup 프로그램을 통해 boot_params내에 포함되어 커널로 전달된다. 커널은 해당 e820 맵 정보를 모두 검사하여 중복된 정보가 있는지 확인하고 이를 순서대로 정리한다. (sanitize_e820_map) 이 후 이 정보를 통대로 max_pfn, max_low_pfn 등의 변수를 설정하고 init_memory_mapping 함수를 호출하여 커널 영역의 페이지 테이블을 초기화한다. e820 방식으로 얻은 메모리 정보 및 커널이 수정한 메모리 정보는 dmesg 명령을 통해 확인할 수 있으며 /sys/firmware/memmap 디렉토리에서도 확인할 수 있다.

현재 이 글을 작성 중인 머신에서의 dmesg 출력은 다음과 같다.

[    0.000000] BIOS-provided physical RAM map:
[    0.000000]  BIOS-e820: 0000000000000000 - 000000000009f800 (usable)
[    0.000000]  BIOS-e820: 000000000009f800 - 00000000000a0000 (reserved)
[    0.000000]  BIOS-e820: 00000000000dc000 - 0000000000100000 (reserved)
[    0.000000]  BIOS-e820: 0000000000100000 - 000000007f6e0000 (usable)
[    0.000000]  BIOS-e820: 000000007f6e0000 - 000000007f700000 (ACPI NVS)
[    0.000000]  BIOS-e820: 000000007f700000 - 0000000080000000 (reserved)
[    0.000000]  BIOS-e820: 00000000e0000000 - 00000000f0000000 (reserved)
...

sysfs의 정보는 다음과 같다.

namhyung@NHK-XNOTE:/sys/firmware/memmap/0$ cat start end type 
0x0
0x9f7ff
System RAM


'Linux Kernel' 카테고리의 다른 글

malloc 소개  (0) 2016.08.18
posix_fallocate  (0) 2016.08.16
Radix Tree  (0) 2016.08.12
Linear VS Physical Address  (0) 2016.08.10
Block I/O Operation  (0) 2016.08.06