CMA (Contiguous Memory Allocator)

๊ฐœ์š” (Overview)

CMA๋Š” ์ปค๋„ ๋ถ€ํŒ… ์ดˆ๊ธฐ์— ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์—ฐ์†๋œ ์˜์—ญ์„ ์˜ˆ์•ฝํ•˜๊ณ , ๋Ÿฐํƒ€์ž„์— ํ•ด๋‹น ์˜์—ญ์˜ ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹น/ํ•ด์ œํ•˜๋Š” ์„œ๋ธŒ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ DMA, ๋””์Šคํ”Œ๋ ˆ์ด ํ”„๋ ˆ์ž„๋ฒ„ํผ, GPU, ๋น„๋””์˜ค ๋””์ฝ”๋” ๊ฐ™์€ ์žฅ์น˜์—์„œ ํ•˜๋“œ์›จ์–ด ์ œ์•ฝ์œผ๋กœ ์ธํ•ด ์—ฐ์† ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. CMA ์˜์—ญ์€ ํ‰์†Œ์—๋Š” Buddy Allocator์— ๋ฐ˜ํ™˜๋˜์–ด ์ผ๋ฐ˜ ๋ฉ”๋ชจ๋ฆฌ๋กœ ํ™œ์šฉ๋˜์ง€๋งŒ, ์žฅ์น˜๊ฐ€ ํ• ๋‹น์„ ์š”์ฒญํ•˜๋ฉด ํ•ด๋‹น ์˜์—ญ์˜ ์‚ฌ์šฉ์ž ํŽ˜์ด์ง€๋ฅผ ์žฌ๋ฐฐ์น˜(migrating)ํ•˜์—ฌ ์—ฐ์† ๋ธ”๋ก์„ ํ™•๋ณดํ•ฉ๋‹ˆ๋‹ค.

Linux 7.0์—์„œ CMA๋Š” ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€(multi-range) ์ง€์›์„ ํ†ตํ•ด ํ•˜๋‚˜์˜ CMA ์˜์—ญ์ด ์ตœ๋Œ€ 8๊ฐœ์˜ ๋ถˆ์—ฐ์† ๋ฌผ๋ฆฌ ๋ฒ”์œ„๋กœ ๊ตฌ์„ฑ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ํ™€(memory hole)์ด ์žˆ๋Š” ์‹œ์Šคํ…œ์—์„œ ๋‹จ์ผ ์—ฐ์† ์˜์—ญ ํ™•๋ณด๊ฐ€ ์–ด๋ ค์šด ๊ฒฝ์šฐ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์†Œ์Šค ํŒŒ์ผ:
mm/cma.c                    โ† ํ•ต์‹ฌ ๊ตฌํ˜„ (ํ• ๋‹น/ํ•ด์ œ/์ดˆ๊ธฐํ™”)
mm/cma.h                    โ† ๋‚ด๋ถ€ ๊ตฌ์กฐ์ฒด (cma, cma_memrange)
include/linux/cma.h         โ† ์™ธ๋ถ€ API ํ—ค๋”
include/trace/events/cma.h  โ† tracepoint ์ •์˜
CMA ํ˜ธ์ถœ ํ๋ฆ„
CMA ์ž๋ฃŒ๊ตฌ์กฐ ๊ด€๊ณ„๋„

๋น ๋ฅธ ์ ๊ฒ€ ๋ช…๋ น

# CMA ์˜์—ญ ์ „์ฒด ํ˜„ํ™ฉ ํ™•์ธ (์ด๋ฆ„, ํฌ๊ธฐ, ์‚ฌ์šฉ๋Ÿ‰)
cat /proc/meminfo | grep Cma

# CMA ์˜์—ญ๋ณ„ ์ƒ์„ธ ์ •๋ณด
cat /sys/kernel/debug/cma/cma-0/used_cma  # ์‚ฌ์šฉ ์ค‘์ธ ํŽ˜์ด์ง€ ์ˆ˜
cat /sys/kernel/debug/cma/cma-0/count     # ์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

# Buddy Allocator์—์„œ CMA ํŽ˜์ด์ง€ ๋ธ”๋ก ๋ถ„ํฌ ํ™•์ธ
cat /proc/buddyinfo | grep MIGRATE_CMA

# CMA ์˜์—ญ์˜ pageblock ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํƒ€์ž… ํ™•์ธ
cat /proc/pagetypeinfo | grep CMA

# CMA ํ• ๋‹น/ํ•ด์ œ tracepoint ํ™•์ธ
sudo perf stat -e cma:cma_alloc_start,cma:cma_alloc_finish,cma:cma_release -- sleep 5

# CMA ์˜์—ญ ๋””๋ฒ„๊ทธ ์ •๋ณด (CONFIG_CMA_DEBUGFS)
sudo ls /sys/kernel/debug/cma/

# dmesg์—์„œ CMA ์ดˆ๊ธฐํ™” ๋ฉ”์‹œ์ง€ ํ™•์ธ
dmesg | grep -i "cma"

ํ•ต์‹ฌ ์ž๋ฃŒ๊ตฌ์กฐ

struct cma โ€” CMA ์˜์—ญ ๊ด€๋ฆฌ์ž (`mm/cma.h:39-65`)

struct cma {
unsigned long   count;            // ์ด ํŽ˜์ด์ง€ ์ˆ˜
unsigned long   available_count;  // ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€ ์ˆ˜
unsigned int order_per_bit;       // ๋น„ํŠธ๋งต 1๋น„ํŠธ๋‹น ํŽ˜์ด์ง€ ์ˆ˜ (2^order)
spinlock_t      lock;             // ๋น„ํŠธ๋งต ๋™์‹œ์„ฑ ์ œ์–ด
struct mutex    alloc_mutex;      // ํ• ๋‹น ์‹œ ์ง๋ ฌํ™”
char name[CMA_MAX_NAME];         // ์˜์—ญ ์ด๋ฆ„ ("cma0", "linux,contiguous-region")
int nranges;                      // ์‹ค์ œ ๋ ˆ์ธ์ง€ ์ˆ˜ (1~8)
struct cma_memrange ranges[CMA_MAX_RANGES]; // ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ๋ฐฐ์—ด
unsigned long flags;              // CMA_ACTIVATED ๋“ฑ ํ”Œ๋ž˜๊ทธ
int nid;                          // NUMA ๋…ธ๋“œ ID
};

์„ค๋ช…: count๋Š” ์ „์ฒด ์˜์—ญ ํฌ๊ธฐ(ํŽ˜์ด์ง€ ์ˆ˜), available_count๋Š” ํ˜„์žฌ Buddy์— ๋ฐ˜ํ™˜๋˜์–ด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€ ์ˆ˜์ž…๋‹ˆ๋‹ค. order_per_bit์€ ๋น„ํŠธ๋งต ํ•ด์ƒ๋„๋ฅผ ๊ฒฐ์ •ํ•˜๋ฉฐ, ๋ณดํ†ต 0์ด๋ฉด ๋น„ํŠธ๋งต 1๋น„ํŠธ = 1ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค. nranges๋Š” ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ์ง€์›์œผ๋กœ, ํ•˜๋‚˜์˜ CMA ์˜์—ญ์ด ์—ฌ๋Ÿฌ ๋ถˆ์—ฐ์† ๋ฌผ๋ฆฌ ๋ฒ”์œ„๋ฅผ ๊ฐ€์งˆ ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

struct cma_memrange โ€” ๊ฐœ๋ณ„ ๋ฌผ๋ฆฌ ๋ฒ”์œ„ (`mm/cma.h:26-36`)

struct cma_memrange {
unsigned long base_pfn;    // ๋ฒ”์œ„ ์‹œ์ž‘ PFN
unsigned long count;       // ๋ฒ”์œ„ ๋‚ด ํŽ˜์ด์ง€ ์ˆ˜
union {
unsigned long early_pfn;  // cma_reserve_early()์—์„œ ์‚ฌ์šฉ
unsigned long *bitmap;    // ํ™œ์„ฑํ™” ํ›„ ํ• ๋‹น ๋น„ํŠธ๋งต
};
};

์„ค๋ช…: early_pfn์€ ๋ถ€ํŒ… ์ดˆ๊ธฐ cma_reserve_early() ํ˜ธ์ถœ ์‹œ ์•„์ง ๋น„ํŠธ๋งต์ด ํ• ๋‹น๋˜๊ธฐ ์ „์— ์˜ˆ์•ฝ๋œ PFN์„ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค. bitmap์€ cma_activate_area() ์ดํ›„ ํ• ๋‹น ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋น„ํŠธ๋งต์—์„œ 1๋น„ํŠธ = ํ•ด๋‹น ํŽ˜์ด์ง€๊ฐ€ CMA ํ• ๋‹น๋จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

cma_flags โ€” ์ƒํƒœ ํ”Œ๋ž˜๊ทธ (`mm/cma.h:67-72`)

enum cma_flags {
CMA_RESERVE_PAGES_ON_ERROR,  // ์ดˆ๊ธฐํ™” ์‹คํŒจ ์‹œ ํŽ˜์ด์ง€ ๋ฐ˜ํ™˜ ์•ˆ ํ•จ
CMA_ZONES_VALID,             // ์กด ๊ฒ€์ฆ ํ†ต๊ณผ
CMA_ZONES_INVALID,           // ์กด ๊ฒ€์ฆ ์‹คํŒจ (cross-zone)
CMA_ACTIVATED,               // cma_activate_area ์™„๋ฃŒ
};

์„ค๋ช…: CMA_ACTIVATED๋Š” cma_reserve_early()๊ฐ€ ๋™์ž‘ํ•˜๋Š” ์กฐ๊ฑด์ž…๋‹ˆ๋‹ค โ€” ์ด ๋น„ํŠธ๊ฐ€ ์„ค์ •๋˜๋ฉด ์ดˆ๊ธฐ ํ• ๋‹น์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. CMA_ZONES_VALID/INVALID๋Š” CMA ์˜์—ญ์ด ๋‹จ์ผ ์กด์— ์†ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•œ ๊ฒฐ๊ณผ๋ฅผ ์บ์‹ฑํ•ฉ๋‹ˆ๋‹ค.

struct cma_init_memrange โ€” ์ดˆ๊ธฐํ™” ์ž‘์—… ๊ตฌ์กฐ์ฒด (`mm/cma.c:311-315`)

struct cma_init_memrange {
phys_addr_t base;
phys_addr_t size;
struct list_head list;
};

์„ค๋ช…: cma_declare_contiguous_multi()์—์„œ ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ํ›„๋ณด๋ฅผ ์ •๋ ฌํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๋Š” ์ž„์‹œ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ์ตœ๋Œ€ CMA_MAX_RANGES(8๊ฐœ)๊นŒ์ง€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ํ•จ์ˆ˜

1. `cma_declare_contiguous_nid()` โ€” CMA ์˜์—ญ ์˜ˆ์•ฝ (`mm/cma.c:733-751`)

int __init cma_declare_contiguous_nid(phys_addr_t base,
phys_addr_t size, phys_addr_t limit,
phys_addr_t alignment, unsigned int order_per_bit,
bool fixed, const char *name, struct cma **res_cma,
int nid)

์—ญํ• : ๋ถ€ํŒ… ์ดˆ๊ธฐ์— memblock์—์„œ CMA ์˜์—ญ์„ ์˜ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค. base=0์ด๋ฉด ์ž„์˜ ์œ„์น˜, fixed=true๋ฉด ์ •ํ™•ํ•œ ์ฃผ์†Œ์— ์˜ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง:

1. __cma_declare_contiguous_nid() ํ˜ธ์ถœ (๋‚ด๋ถ€ ๊ตฌํ˜„)

2. fixed=true โ†’ cma_fixed_reserve(): ์ง€์ • ์œ„์น˜์—์„œ ์ง์ ‘ ์˜ˆ์•ฝ ์‹œ๋„

3. fixed=false โ†’ cma_alloc_mem(): 64๋น„ํŠธ ์‹œ์Šคํ…œ์—์„œ๋Š” 4GB ์œ„์ชฝ๋ถ€ํ„ฐ bottom-up ํƒ์ƒ‰, HIGHMEM ์ฒ˜๋ฆฌ

4. cma_init_reserved_mem(): struct cma ์ดˆ๊ธฐํ™”

2. `cma_alloc()` / `cma_alloc_frozen()` โ€” ํŽ˜์ด์ง€ ํ• ๋‹น (`mm/cma.c:943-953, 918-924`)

struct page *cma_alloc(struct cma *cma, unsigned long count,
unsigned int align, bool no_warn)

struct page *cma_alloc_frozen(struct cma *cma, unsigned long count,
unsigned int align, bool no_warn)

์—ญํ• : CMA ์˜์—ญ์—์„œ ์—ฐ์† ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. cma_alloc()์€ refcount ์„ค์ •๊นŒ์ง€, cma_alloc_frozen()์€ refcount ์—†์ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง (cma_range_alloc ๋‚ด๋ถ€, mm/cma.c:780-858):

1. bitmap_find_next_zero_area_off(): ๋น„ํŠธ๋งต์—์„œ ์—ฐ์† ๋นˆ ์˜์—ญ ํƒ์ƒ‰

2. page_range_contiguous(): ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์—ฐ์†์ธ์ง€ ์žฌ๊ฒ€์ฆ

3. bitmap_set(): ํ•ด๋‹น ์˜์—ญ์„ "์‚ฌ์šฉ ์ค‘"์œผ๋กœ ํ‘œ์‹œ

4. alloc_contig_frozen_range(): Buddy์—์„œ ์‹ค์ œ ํŽ˜์ด์ง€๋ฅผ ๋™๊ฒฐ(freeze)ํ•˜๊ณ  ํ• ๋‹น

5. ํ• ๋‹น ์‹คํŒจ ์‹œ cma_clear_bitmap()์œผ๋กœ ๋˜๋Œ๋ฆฌ๊ณ  -EBUSY ์‹œ ์žฌ์‹œ๋„

3. `cma_release()` โ€” ํŽ˜์ด์ง€ ํ•ด์ œ (`mm/cma.c:1012-1032`)

bool cma_release(struct cma *cma, const struct page *pages,
unsigned long count)

์—ญํ• : cma_alloc()์œผ๋กœ ํ• ๋‹น๋œ ํŽ˜์ด์ง€๋ฅผ ํ•ด์ œํ•˜๊ณ  Buddy์— ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง:

1. find_cma_memrange(): ํ•ด๋‹น ํŽ˜์ด์ง€๊ฐ€ ์–ด๋А ๋ ˆ์ธ์ง€์— ์†ํ•˜๋Š”์ง€ ํƒ์ƒ‰

2. put_page_testzero(): ๋ชจ๋“  ํŽ˜์ด์ง€์˜ refcount๋ฅผ 0์œผ๋กœ ๊ฐ์†Œ

3. __cma_release_frozen(): free_contig_frozen_range()๋กœ Buddy ๋ฐ˜ํ™˜ + cma_clear_bitmap()

4. `cma_activate_area()` โ€” ์ดˆ๊ธฐํ™” ์™„๋ฃŒ (`mm/cma.c:140-200`)

static void __init cma_activate_area(struct cma *cma)

์—ญํ• : ๋ถ€ํŒ… ์‹œ core_initcall์—์„œ ํ˜ธ์ถœ๋˜์–ด ๋น„ํŠธ๋งต ํ• ๋‹น, ์กด ๊ฒ€์ฆ, init_cma_reserved_pageblock() ํ˜ธ์ถœ๋กœ pageblock์„ CMA ์ „์šฉ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง:

1. ๊ฐ ๋ ˆ์ธ์ง€๋ณ„ bitmap_zalloc()์œผ๋กœ ๋น„ํŠธ๋งต ํ• ๋‹น

2. cma_validate_zones(): CMA ์˜์—ญ์ด ๋‹จ์ผ ์กด์— ์†ํ•˜๋Š”์ง€ ๊ฒ€์ฆ

3. early_pfn์ด base_pfn๊ณผ ๋‹ค๋ฅด๋ฉด โ†’ ์ฐจ์ด๋ถ„(์ด๋ฏธ ์˜ˆ์•ฝ๋œ ๋ถ€๋ถ„)์„ ๋น„ํŠธ๋งต์—์„œ "์‚ฌ์šฉ ์ค‘"์œผ๋กœ ํ‘œ์‹œ

4. ์‹คํŒจ ์‹œ cleanup: ๋น„ํŠธ๋งต ํ•ด์ œ + Buddy์— ํŽ˜์ด์ง€ ๋ฐ˜ํ™˜

5. `cma_declare_contiguous_multi()` โ€” ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ์˜ˆ์•ฝ (`mm/cma.c:528-711`)

int __init cma_declare_contiguous_multi(phys_addr_t total_size,
phys_addr_t align, unsigned int order_per_bit,
const char *name, struct cma **res_cma, int nid)

์—ญํ• : ๋‹จ์ผ ์—ฐ์† ์˜์—ญ ํ™•๋ณด์— ์‹คํŒจํ•˜๋ฉด 4GB ์œ„์ชฝ ํฐ ๋ฉ”๋ชจ๋ฆฌ ๋ธ”๋ก๋“ค์„ ์ˆ˜์ง‘ํ•˜์—ฌ ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ CMA๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๊ธฐ ๋กœ์ง:

1. ๋จผ์ € __cma_declare_contiguous_nid()๋กœ ๋‹จ์ผ ๋ ˆ์ธ์ง€ ์‹œ๋„

2. -ENOSPC ์™ธ ์‹คํŒจ โ†’ ์ข…๋ฃŒ

3. for_each_free_mem_range()๋กœ 4GB ์œ„ ๋นˆ ๋ฒ”์œ„ ์ˆ˜์ง‘

4. ํฌ๊ธฐ์ˆœ ์ •๋ ฌ ํ›„ CMA_MAX_RANGES๊ฐœ ์„ ํƒ

5. ์ฃผ์†Œ์ˆœ ์žฌ์ •๋ ฌ โ†’ ์ˆœ์ฐจ์ ์œผ๋กœ memblock_reserve() + cmr ์ดˆ๊ธฐํ™”


ํ˜ธ์ถœ ํ๋ฆ„

CMA ์˜์—ญ ์ดˆ๊ธฐํ™” ํ๋ฆ„

firmware/reserved-memory
โ”‚
โ–ผ
cma_declare_contiguous_nid()          โ† arch ์ฝ”๋“œ์—์„œ ํ˜ธ์ถœ
โ”‚
โ”œโ”€โ”€ __cma_declare_contiguous_nid()
โ”‚      โ”œโ”€โ”€ cma_fixed_reserve()  ๋˜๋Š” cma_alloc_mem()
โ”‚      โ”‚      โ””โ”€โ”€ memblock_alloc_range_nid()
โ”‚      โ””โ”€โ”€ cma_init_reserved_mem()
โ”‚             โ””โ”€โ”€ cma_new_area()
โ”‚
โ–ผ  (core_initcall)
cma_init_reserved_areas()
โ”‚
โ””โ”€โ”€ cma_activate_area()         โ† ๋น„ํŠธ๋งต + ์กด ๊ฒ€์ฆ
โ”œโ”€โ”€ bitmap_zalloc()
โ”œโ”€โ”€ cma_validate_zones()
โ”œโ”€โ”€ init_cma_reserved_pageblock()
โ””โ”€โ”€ set_bit(CMA_ACTIVATED)

CMA ํ• ๋‹น/ํ•ด์ œ ํ๋ฆ„

์žฅ์น˜ ๋“œ๋ผ์ด๋ฒ„ (DMA, GPU, etc.)
โ”‚
โ–ผ
cma_alloc(cma, count, align, no_warn)
โ”‚
โ”œโ”€โ”€ cma_alloc_frozen()
โ”‚      โ””โ”€โ”€ __cma_alloc_frozen()
โ”‚             โ””โ”€โ”€ cma_range_alloc()         โ† ๋ ˆ์ธ์ง€๋ณ„ ๋ฐ˜๋ณต
โ”‚                    โ”œโ”€โ”€ bitmap_find_next_zero_area_off()
โ”‚                    โ”œโ”€โ”€ page_range_contiguous()
โ”‚                    โ”œโ”€โ”€ bitmap_set()
โ”‚                    โ””โ”€โ”€ alloc_contig_frozen_range()  โ† Buddy์—์„œ ๋™๊ฒฐ
โ”‚                           โ””โ”€โ”€ isolate_migratepages_block() ๋“ฑ
โ”‚
โ–ผ ์‚ฌ์šฉ ์™„๋ฃŒ
cma_release(cma, pages, count)
โ”‚
โ”œโ”€โ”€ find_cma_memrange()
โ”œโ”€โ”€ put_page_testzero() x count
โ””โ”€โ”€ __cma_release_frozen()
โ”œโ”€โ”€ free_contig_frozen_range()   โ† Buddy์— ๋ฐ˜ํ™˜
โ””โ”€โ”€ cma_clear_bitmap()

์กฐ๊ฑด๋ณ„ ๋น„๊ต

CMA ์˜์—ญ ์œ ํ˜• ๋น„๊ต

๊ตฌ๋ถ„๋‹จ์ผ ๋ ˆ์ธ์ง€๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€
**์ดˆ๊ธฐํ™” ํ•จ์ˆ˜**`cma_declare_contiguous_nid()``cma_declare_contiguous_multi()`
**๋ ˆ์ธ์ง€ ์ˆ˜**12~8 (`CMA_MAX_RANGES`)
**์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค**๋ฉ”๋ชจ๋ฆฌ ํ™€ ์—†๋Š” ์‹œ์Šคํ…œ4GB ์œ„ large block ๋ถ„์‚ฐ ์‹œ
**๋น„ํŠธ๋งต**๋ ˆ์ธ์ง€๋‹น 1๊ฐœ๋ ˆ์ธ์ง€๋ณ„ ๋…๋ฆฝ ๋น„ํŠธ๋งต
**ํ• ๋‹น ํƒ์ƒ‰**๋‹จ์ผ ๋น„ํŠธ๋งต ์ˆœํšŒ๋ ˆ์ธ์ง€ ์ˆœ์„œ๋Œ€๋กœ ํƒ์ƒ‰
**๋Œ€ํ‘œ ์‚ฌ์šฉ์ฒ˜**๊ธฐ๋ณธ DMA ์˜์—ญhugetlb CMA, ๋Œ€์šฉ๋Ÿ‰ ๋””์Šคํ”Œ๋ ˆ์ด

ํ• ๋‹น ๊ฒฝ๋กœ ๋น„๊ต

๊ฒฝ๋กœํ•จ์ˆ˜ํŠน์ง•
**์ผ๋ฐ˜ ํ• ๋‹น**`cma_alloc()`refcount ์„ค์ •, ๋“œ๋ผ์ด๋ฒ„์šฉ
**Frozen ํ• ๋‹น**`cma_alloc_frozen()`refcount ์—†์ด ๋ฐ˜ํ™˜
**Frozen Compound**`cma_alloc_frozen_compound()``__GFP_COMP` ํฌํ•จ, huge page์šฉ
**์ดˆ๊ธฐ ํ• ๋‹น**`cma_reserve_early()`๋ถ€ํŒ… ์ดˆ๊ธฐ, ๋น„ํŠธ๋งต ์—†์Œ, ๋‹จ์ผ ์Šค๋ ˆ๋“œ

์ดˆ๊ธฐํ™” ์‹œ์  ๋น„๊ต

๋‹จ๊ณ„ํ•จ์ˆ˜์‹œ์ 
**๋ฉ”๋ชจ๋ฆฌ ์˜ˆ์•ฝ**`cma_declare_contiguous_nid()`arch ์ดˆ๊ธฐํ™” (memblock ํ™œ์„ฑํ™” ํ›„)
**๋น„ํŠธ๋งต/๊ฒ€์ฆ**`cma_activate_area()``core_initcall` (slab ํ™œ์„ฑํ™” ํ›„)
**์ดˆ๊ธฐ ํ• ๋‹น**`cma_reserve_early()``CMA_ACTIVATED` ์ด์ „

๊ด€๋ จ ๋ฌธ์„œ

  • 00-overview.html โ€” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ์ „์ฒด ๊ฐœ์š”
  • 01-page_alloc.html โ€” Buddy Allocator (CMA์˜ ํ•˜์œ„ ํ• ๋‹น์ž)
  • 04-memblock.html โ€” Memblock ํ• ๋‹น์ž (๋ถ€ํŒ… ์ดˆ๊ธฐ CMA ์˜ˆ์•ฝ ๊ธฐ๋ฐ˜)
  • 11-compaction.html โ€” Memory Compaction (CMA ํ• ๋‹น ์‹œ ํŽ˜์ด์ง€ ์žฌ๋ฐฐ์น˜)
  • 13-numa.html โ€” NUMA (CMA์˜ nid ์„ค์ •)
  • 20-migrate.html โ€” ํŽ˜์ด์ง€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ (CMA์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜)
  • 22-memory_hotplug.html โ€” ๋ฉ”๋ชจ๋ฆฌ ํ•ซํ”Œ๋Ÿฌ๊ทธ

  • DMA API๋ฅผ ํ†ตํ•œ CMA ์‚ฌ์šฉ

    ๋Œ€๋ถ€๋ถ„์˜ ๋“œ๋ผ์ด๋ฒ„๋Š” cma_alloc()์„ ์ง์ ‘ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  DMA API๋ฅผ ํ†ตํ•ด ๊ฐ„์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    /* ๋“œ๋ผ์ด๋ฒ„์—์„œ DMA ๋ฒ„ํผ ํ• ๋‹น โ€” CMA๋ฅผ ํ†ตํ•ด ์ž๋™ ์—ฐ์† ํ™•๋ณด */
    void *vaddr = dma_alloc_coherent(dev, size, &dma_handle, GFP_KERNEL);
    /* ๋ฐ˜ํ™˜ ์‹œ */
    dma_free_coherent(dev, size, vaddr, dma_handle);

    dma_alloc_coherent()๋Š” CONFIG_DMA_CMA๊ฐ€ ํ™œ์„ฑํ™”๋˜๋ฉด ๋‚ด๋ถ€์ ์œผ๋กœ CMA ์˜์—ญ์—์„œ ์—ฐ์† ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋“œ๋ผ์ด๋ฒ„ ๊ฐœ๋ฐœ์ž๋Š” CMA ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ์•Œ ํ•„์š” ์—†์ด DMA API๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.


    ๋ถ€ํŠธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ CMA ์˜์—ญ ์„ค์ •

    ์ปค๋„ ๋ถ€ํŠธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ CMA ์˜์—ญ ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    # ๊ธฐ๋ณธ CMA ์˜์—ญ 256MB ์„ค์ •
    cma=256M
    
    # ํŠน์ • ๋ฌผ๋ฆฌ ์ฃผ์†Œ ๋ฒ”์œ„์— 256MB CMA ์„ค์ •
    cma=256M@0-4G
    
    # Device Tree์—์„œ CMA ์„ค์ • (์ž„๋ฒ ๋””๋“œ)
    # reserved-memory {
    #     linux,cma {
    #         compatible = "shared-dma-pool";
    #         reusable;
    #         size = <0x10000000>;  /* 256MB */
    #     };
    # };

    CMA vs HugeTLB ๋น„๊ต

    ๊ตฌ๋ถ„CMAHugeTLB
    **ํ‰์‹œ ํ™œ์šฉ**movable ํŽ˜์ด์ง€๊ฐ€ ์ผ๋ฐ˜ ๋ฉ”๋ชจ๋ฆฌ๋กœ ์‚ฌ์šฉ (๋‚ญ๋น„ ์—†์Œ)์˜ˆ์•ฝ ์ฆ‰์‹œ ์ „์šฉ (์ผ๋ฐ˜ ์‚ฌ์šฉ ๋ถˆ๊ฐ€)
    **์œ ์—ฐ์„ฑ**๋†’์Œ โ€” ํ•„์š” ์‹œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์œผ๋กœ ํ™•๋ณด๋‚ฎ์Œ โ€” ๋ฏธ๋ฆฌ ํ™•๋ณด๋œ ๊ฒƒ๋งŒ ์‚ฌ์šฉ
    **์‹คํŒจ ์›์ธ**unmovable ํŽ˜์ด์ง€ ์นจํˆฌ, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํƒ€์ž„์•„์›ƒ์˜ˆ์•ฝ ๋ถ€์กฑ ์‹œ ์ฆ‰์‹œ ์‹คํŒจ
    **์ ํ•ฉํ•œ ์šฉ๋„**DMA, ๋””์Šคํ”Œ๋ ˆ์ด ํ”„๋ ˆ์ž„๋ฒ„ํผ, GPU๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ๋Œ€์šฉ๋Ÿ‰ ์บ์‹œ
    **์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ**`cma=256M``hugepagesz=2M hugepages=128`

    CMA ์‹คํŒจ ์›์ธ๊ณผ ๋Œ€์‘

    CMA ํ• ๋‹น์ด ์‹คํŒจํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ์›์ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

    1. unmovable ํŽ˜์ด์ง€ ์นจํˆฌ: slab ํ• ๋‹น์ž, ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋“ฑ unmovable ํŽ˜์ด์ง€๊ฐ€ CMA ์˜์—ญ์— ์œ„์น˜ํ•˜๋ฉด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์ „์— MIGRATE_CMA ํƒ€์ž…์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

    2. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํƒ€์ž„์•„์›ƒ: ๋Œ€๋Ÿ‰์˜ movable ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•ด์•ผ ํ•  ๋•Œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    3. ๋ฌผ๋ฆฌ์  ์—ฐ์†์„ฑ ๋ถ€์กฑ: ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ๊ตฌ์„ฑ ์‹œ์—๋„ ๊ฐ ๋ ˆ์ธ์ง€ ๋‚ด๋ถ€์—์„œ ์—ฐ์† ์˜์—ญ์„ ํ™•๋ณดํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    # CMA ์˜์—ญ์— unmovable ํŽ˜์ด์ง€ ์นจํˆฌ ํ™•์ธ
    cat /proc/pagetypeinfo | grep -A2 "MIGRATE_CMA"
    # CMA ์‹คํŒจ ์‹œ dmesg ํ™•์ธ
    dmesg | grep -i "cma"

    ์ฐธ๊ณ : minzkn.com๊ณผ์˜ ์ฐจ์ด

    minzkn.com ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š” ํŽ˜์ด์ง€์˜ "ํŠน์ˆ˜ ๋ฉ”๋ชจ๋ฆฌ" ์„น์…˜์—์„œ CMA๋ฅผ ๊ฐ„๋žตํžˆ ๋‹ค๋ฃน๋‹ˆ๋‹ค. minzkn์€ CMA๋ฅผ "DMA ๋””๋ฐ”์ด์Šค๋ฅผ ์œ„ํ•œ ๋Œ€์šฉ๋Ÿ‰ ์—ฐ์† ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น"์œผ๋กœ ์„ค๋ช…ํ•˜๋ฉฐ, ๋‹ค์Œ ํ•ต์‹ฌ ํฌ์ธํŠธ๋ฅผ ๊ฐ•์กฐํ•ฉ๋‹ˆ๋‹ค:

  • CMA ์˜์—ญ์€ ํ‰์‹œ์— movable ํŽ˜์ด์ง€๋กœ ํ™œ์šฉ๋˜์–ด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๊ฐ€ ์—†์Œ
  • dma_alloc_coherent()๋ฅผ ํ†ตํ•œ ์ž๋™ ์—ฐ๊ฒฐ
  • IOMMU ์—†๋Š” ๋””๋ฐ”์ด์Šค์˜ scatter-gather ๋ถˆ๊ฐ€ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ•„์ˆ˜
  • CMA๋Š” HugeTLB์™€ ๋‹ฌ๋ฆฌ ํ‰์‹œ ์ผ๋ฐ˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅ (์œ ์—ฐ์„ฑ)
  • ์šฐ๋ฆฌ ๋ฌธ์„œ๋Š” ์ด๋ณด๋‹ค ๋” ์ƒ์„ธํ•˜๊ฒŒ ๋ฉ€ํ‹ฐ ๋ ˆ์ธ์ง€ ์ง€์›, ํ• ๋‹น/ํ•ด์ œ ๋‚ด๋ถ€ ํ๋ฆ„, ์กด ๊ฒ€์ฆ ๋กœ์ง, cma_reserve_early ์ดˆ๊ธฐ ํ• ๋‹น ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๋ถ„์„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.