MMU Gather (TLB ํ”Œ๋Ÿฌ์‹œ ์ตœ์ ํ™”)

๊ฐœ์š” (Overview)

MMU Gather๋Š” Linux ์ปค๋„์ด ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์—์„œ ์—”ํŠธ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ TLB(Translation Lookaside Buffer) ํ”Œ๋Ÿฌ์‹œ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฐ์น˜(batching) ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์—์„œ PTE, PMD ๊ฐ™์€ ์—”ํŠธ๋ฆฌ๋ฅผ ํ•˜๋‚˜์”ฉ ์ œ๊ฑฐํ•  ๋•Œ๋งˆ๋‹ค ์ฆ‰์‹œ TLB ํ”Œ๋Ÿฌ์‹œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด SMP ํ™˜๊ฒฝ์—์„œ IPI(Inter-Processor Interrupt) ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋„ˆ๋ฌด ์ปค์ง€๋ฏ€๋กœ, ์—ฌ๋Ÿฌ ์ œ๊ฑฐ ์ž‘์—…์„ ๋ชจ์•„์„œ ํ•œ ๋ฒˆ์— ํ”Œ๋Ÿฌ์‹œํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค.

mm/mmu_gather.c๋Š” struct mmu_gather ๊ตฌ์กฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ์ œ๊ฑฐ๋œ ํŽ˜์ด์ง€/ํ…Œ์ด๋ธ”์„ ๋ฐฐ์น˜๋กœ ์ˆ˜์ง‘ํ•œ ๋’ค, ์ตœ์ข…์ ์œผ๋กœ TLB ํ”Œ๋Ÿฌ์‹œ์™€ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•ต์‹ฌ ๋ฃจํ‹ด์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์•„ํ‚คํ…์ฒ˜๋ณ„๋กœ flush_tlb_mm(), flush_tlb_range() ๊ฐ™์€ ์ €์ˆ˜์ค€ ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๋ฉฐ, asm-generic/tlb.h์—์„œ ๊ณตํ†ต ์ธ๋ผ์ธ ํ•จ์ˆ˜๋“ค์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

TLB shootdown์€ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์„ ์ •๋ฆฌํ•˜๋Š” ์ˆœ๊ฐ„๋ฟ ์•„๋‹ˆ๋ผ mprotect(), munmap(), MADV_DONTNEED, COW, NUMA balancing์ฒ˜๋Ÿผ PTE ์˜๋ฏธ๊ฐ€ ๋ฐ”๋€Œ๋Š” ์ˆœ๊ฐ„์—๋„ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์„œ๋Š” tlb_gather_mmu()๋กœ ๋ณ€๊ฒฝ์„ ๋ชจ์€ ๋’ค tlb_flush_mmu_tlbonly() ๋˜๋Š” tlb_flush_mmu()์—์„œ invalidate์™€ free๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๋Š” ํ๋ฆ„์„ ๊ฐ™์ด ๋ด…๋‹ˆ๋‹ค.

์†Œ์Šค ํŒŒ์ผ ๊ฒฝ๋กœ:
โ”œโ”€โ”€ mm/mmu_gather.c                          โ† MMU gather ํ•ต์‹ฌ ๋กœ์ง (536์ค„)
โ”œโ”€โ”€ include/asm-generic/tlb.h                โ† struct mmu_gather ์ •์˜ (L321-392), ์ธ๋ผ์ธ ํ•จ์ˆ˜
โ”œโ”€โ”€ include/linux/mm_types.h                 โ† encode_page/decode_page (L238-279)
โ”œโ”€โ”€ include/linux/mm_types.h:1578-1582       โ† tlb_gather_mmu/finish ์„ ์–ธ
โ”œโ”€โ”€ arch/Kconfig:508-530                     โ† MMU_GATHER_* ์˜ต์…˜ ์ •์˜
โ”œโ”€โ”€ arch/x86/Kconfig:285-286                 โ† x86: RCU_TABLE_FREE, MERGE_VMAS
โ”œโ”€โ”€ arch/arm64/Kconfig:251                   โ† ARM64: RCU_TABLE_FREE
โ””โ”€โ”€ arch/s390/Kconfig:265-267                โ† s390: MERGE_VMAS, NO_GATHER, RCU_TABLE_FREE
MMU Gather ๊ตฌ์กฐ์™€ ํ๋ฆ„

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

# MMU_GATHER ๊ด€๋ จ ์ปค๋„ ์„ค์ • ํ™•์ธ
zcat /proc/config.gz 2>/dev/null | grep -E "CONFIG_MMU_GATHER" || grep -E "CONFIG_MMU_GATHER" /boot/config-$(uname -r) 2>/dev/null

# RCU ํ…Œ์ด๋ธ” ํ•ด์ œ ์ง€์› ์—ฌ๋ถ€ ํ™•์ธ
zcat /proc/config.gz 2>/dev/null | grep CONFIG_MMU_GATHER_RCU_TABLE_FREE || grep CONFIG_MMU_GATHER_RCU_TABLE_FREE /boot/config-$(uname -r) 2>/dev/null

# TLB ํ”Œ๋Ÿฌ์‹œ ๊ด€๋ จ ์ปค๋„ ํ†ต๊ณ„ ํ™•์ธ
cat /proc/vmstat | grep -E "tlb_flush|pgfault|pgmajfault"

# ํ˜„์žฌ ์‹œ์Šคํ…œ์˜ ํŽ˜์ด์ง€ ํฌ๊ธฐ ํ™•์ธ
getconf PAGESIZE

# ์ปค๋„ ๋นŒ๋“œ ์‹œ MMU_GATHER ๋ชจ๋“ˆ ํฌํ•จ ์—ฌ๋ถ€ ํ™•์ธ
cat /lib/modules/$(uname -r)/build/.config 2>/dev/null | grep CONFIG_MMU_GATHER

# TLB ๊ด€๋ จ ์ปค๋„ ๋กœ๊ทธ ํ™•์ธ
dmesg | grep -iE "tlb|flush|gather" | tail -10

# NUMA ์‹œ์Šคํ…œ์—์„œ์˜ TLB ํ”Œ๋Ÿฌ์‹œ ํ†ต๊ณ„
cat /proc/interrupts | grep -i "TLB" 2>/dev/null || echo "TLB ์ธํ„ฐ๋ŸฝํŠธ ์ •๋ณด ์—†์Œ"

# ์•„ํ‚คํ…์ฒ˜๋ณ„ MMU_GATHER ์„ ํƒ ์˜ต์…˜ ํ™•์ธ
grep -r "select MMU_GATHER" arch/*/Kconfig 2>/dev/null

# ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ
cat /proc/meminfo | grep -E "PageTables|KernelStack"

# ์ปค๋„ ์†Œ์Šค์—์„œ์˜ MMU gather ๊ด€๋ จ ํ•จ์ˆ˜ ๋ชฉ๋ก ํ™•์ธ
grep -rn "tlb_gather_mmu\|tlb_finish_mmu\|tlb_remove_page\|tlb_remove_table" mm/mmu_gather.c

# TLB miss ๊ด€์ฐฐ
perf stat -e dTLB-load-misses,dTLB-store-misses,iTLB-load-misses -a -- sleep 5

# ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ minor/major fault ํ™•์ธ
ps -o pid,minflt,majflt -p $$

# ํŽ˜์ด์ง€ ํดํŠธ ๋ฐ reclaim ์••๋ ฅ ํ™•์ธ
cat /proc/vmstat | grep -E "pgfault|pgmajfault|allocstall|tlb"
cat /proc/pressure/memory

# ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋คํ”„(ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ)
cat /sys/kernel/debug/kernel_page_tables 2>/dev/null | head -40

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

1. `struct mmu_gather` (include/asm-generic/tlb.h:321)

TLB ํ”Œ๋Ÿฌ์‹œ ๋ฐฐ์น˜์˜ ํ•ต์‹ฌ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ์Šคํƒ์— ํ• ๋‹น๋˜๋ฉฐ, ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์ œ๊ฑฐ ์ž‘์—…์„ ์ˆ˜์ง‘ํ•˜๊ณ  ๋ฒ”์œ„๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

// include/asm-generic/tlb.h:321-392
struct mmu_gather {
struct mm_struct    *mm;        // ๋Œ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„

struct mmu_table_batch *batch;  // ํ…Œ์ด๋ธ” ๋ฐฐ์น˜ (CONFIG_MMU_GATHER_TABLE_FREE)

unsigned long       start;      // ํ”Œ๋Ÿฌ์‹œ ๋Œ€์ƒ ๋ฒ”์œ„ ์‹œ์ž‘
unsigned long       end;        // ํ”Œ๋Ÿฌ์‹œ ๋Œ€์ƒ ๋ฒ”์œ„ ๋

unsigned int        fullmm : 1;           // ์ „์ฒด mm ์ œ๊ฑฐ ์—ฌ๋ถ€ (exit/execve)
unsigned int        need_flush_all : 1;   // ์ „์ฒด flush ํ•„์š” ์—ฌ๋ถ€
unsigned int        freed_tables : 1;     // ํŽ˜์ด์ง€ ๋””๋ ‰ํ† ๋ฆฌ ์ œ๊ฑฐ๋จ
unsigned int        delayed_rmap : 1;     // ์ง€์—ฐ๋œ rmap ์ œ๊ฑฐ ๋ณด์œ  ์—ฌ๋ถ€

unsigned int        cleared_ptes : 1;     // PTE ๋ ˆ๋ฒจ ์ œ๊ฑฐ ๊ธฐ๋ก
unsigned int        cleared_pmds : 1;     // PMD ๋ ˆ๋ฒจ ์ œ๊ฑฐ ๊ธฐ๋ก
unsigned int        cleared_puds : 1;     // PUD ๋ ˆ๋ฒจ ์ œ๊ฑฐ ๊ธฐ๋ก
unsigned int        cleared_p4ds : 1;     // P4D ๋ ˆ๋ฒจ ์ œ๊ฑฐ ๊ธฐ๋ก

unsigned int        vma_exec : 1;         // VM_EXEC ํ”Œ๋ž˜๊ทธ ์ถ”์ 
unsigned int        vma_huge : 1;         // VM_HUGETLB ํ”Œ๋ž˜๊ทธ ์ถ”์ 
unsigned int        vma_pfn  : 1;         // VM_PFNMAP/VM_MIXEDMAP ์ถ”์ 

unsigned int        unshared_tables : 1;  // ๊ณต์œ  ํ•ด์ œ๋œ ํ…Œ์ด๋ธ” ์กด์žฌ
unsigned int        fully_unshared_tables : 1; // ์™„์ „ํžˆ ํ•ด์ œ๋œ ํ…Œ์ด๋ธ”

unsigned int        batch_count;           // ํ˜„์žฌ ๋ฐฐ์น˜ ์ˆ˜

struct mmu_gather_batch *active;   // ํ˜„์žฌ ํ™œ์„ฑ ๋ฐฐ์น˜
struct mmu_gather_batch local;     // ์Šคํƒ ํ• ๋‹น ๋กœ์ปฌ ๋ฐฐ์น˜
struct page         *__pages[MMU_GATHER_BUNDLE]; // ๋กœ์ปฌ ํŽ˜์ด์ง€ ๋ฐฐ์—ด

unsigned int page_size;            // ํ˜„์žฌ ํŽ˜์ด์ง€ ํฌ๊ธฐ (CONFIG_MMU_GATHER_PAGE_SIZE)
};

ํ•„๋“œ ์„ค๋ช…:

  • start, end: TLB ํ”Œ๋Ÿฌ์‹œ๊ฐ€ ํ•„์š”ํ•œ ์ฃผ์†Œ ๋ฒ”์œ„. __tlb_adjust_range()๋กœ ๊ฐฑ์‹ ๋จ.
  • fullmm: exit(), execve()์ฒ˜๋Ÿผ ์ „์ฒด ์ฃผ์†Œ ๊ณต๊ฐ„์„ ์ œ๊ฑฐํ•  ๋•Œ true. ๋ฒ”์œ„ ์ถ”์ ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์ „์ฒด flush ์ˆ˜ํ–‰.
  • freed_tables, cleared_ptes/pmds/puds/p4ds: ์–ด๋–ค ๋ ˆ๋ฒจ์˜ ์—”ํŠธ๋ฆฌ๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ๊ธฐ๋ก. tlb_flush_mmu_tlbonly()์—์„œ flush ํ•„์š” ์—ฌ๋ถ€ ๊ฒฐ์ •.
  • delayed_rmap: SMP์—์„œ rmap ์ œ๊ฑฐ๋ฅผ TLB flush ํ›„๋กœ ๋ฏธ๋ฃธ. tlb_flush_rmaps()์—์„œ ์ฒ˜๋ฆฌ.
  • active: ํ˜„์žฌ ์ฑ„์šฐ๊ณ  ์žˆ๋Š” ๋ฐฐ์น˜. local์—์„œ ์‹œ์ž‘ํ•˜์—ฌ ํ•„์š” ์‹œ ์ƒˆ ๋ฐฐ์น˜ ํ• ๋‹น.
  • batch_count: ํ• ๋‹น๋œ ๋ฐฐ์น˜ ์ˆ˜. MAX_GATHER_BATCH_COUNT(โ‰ˆ10K ํŽ˜์ด์ง€/๋ฐฐ์น˜ ํฌ๊ธฐ)๋กœ ์ œํ•œํ•˜์—ฌ soft lockup ๋ฐฉ์ง€.
  • 2. `struct mmu_gather_batch` (include/asm-generic/tlb.h:272)

    ์ธ์ฝ”๋”ฉ๋œ ํŽ˜์ด์ง€ ํฌ์ธํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋‹จ์ผ linked list ๋…ธ๋“œ์ž…๋‹ˆ๋‹ค.

    // include/asm-generic/tlb.h:272-277
    struct mmu_gather_batch {
    struct mmu_gather_batch *next;   // ๋‹ค์Œ ๋ฐฐ์น˜ (linked list)
    unsigned int        nr;          // ํ˜„์žฌ ์ €์žฅ๋œ ์—”ํŠธ๋ฆฌ ์ˆ˜
    unsigned int        max;         // ์ตœ๋Œ€ ์—”ํŠธ๋ฆฌ ์ˆ˜
    struct encoded_page *encoded_pages[];  // ์ธ์ฝ”๋”ฉ๋œ ํŽ˜์ด์ง€ ๋ฐฐ์—ด (flexible array)
    };

    ์„ค๋ช…:

  • encoded_pages[]: ํŽ˜์ด์ง€ ํฌ์ธํ„ฐ์— ํ”Œ๋ž˜๊ทธ๋ฅผ ๋น„ํŠธ ๋งˆ์Šคํ‚นํ•˜์—ฌ ์ €์žฅ. ํ•˜์œ„ 2๋น„ํŠธ๋Š” ENCODED_PAGE_BIT_DELAY_RMAP(bit 1)๊ณผ ENCODED_PAGE_BIT_NR_PAGES_NEXT(bit 2)๋กœ ์‚ฌ์šฉ.
  • MAX_GATHER_BATCH: (PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *). 4KB ํŽ˜์ด์ง€ ๊ธฐ์ค€ ์•ฝ 512 ์—”ํŠธ๋ฆฌ.
  • local: ์Šคํƒ์— ์ง์ ‘ ํ• ๋‹น๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฐฐ์น˜. ์ถ”๊ฐ€ ๋ฐฐ์น˜๋Š” __get_free_page(GFP_NOWAIT)๋กœ ๋™์  ํ• ๋‹น.
  • 3. `struct mmu_table_batch` (include/asm-generic/tlb.h:205)

    ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋””๋ ‰ํ† ๋ฆฌ ํ•ด์ œ๋ฅผ ์œ„ํ•œ ๋ฐฐ์น˜ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. CONFIG_MMU_GATHER_RCU_TABLE_FREE ํ™œ์„ฑํ™” ์‹œ RCU grace period ํ›„ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

    // include/asm-generic/tlb.h:205-211
    struct mmu_table_batch {
    struct rcu_head     rcu;         // RCU ํ•ด์ œ ํ—ค๋“œ (CONFIG_MMU_GATHER_RCU_TABLE_FREE)
    unsigned int        nr;          // ํ˜„์žฌ ์ €์žฅ๋œ ํ…Œ์ด๋ธ” ์ˆ˜
    void                *tables[];   // ํ…Œ์ด๋ธ” ํฌ์ธํ„ฐ ๋ฐฐ์—ด (flexible array)
    };

    ์„ค๋ช…:

  • MAX_TABLE_BATCH: (PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *).
  • RCU ํ…Œ์ด๋ธ” ํ•ด์ œ๋Š” ์†Œํ”„ํŠธ์›จ์–ด ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์›Œ์ปค(gup_fast ๋“ฑ)์™€์˜ ๋™๊ธฐํ™”์— ์‚ฌ์šฉ๋จ. IRQ ๋น„ํ™œ์„ฑํ™” ๊ตฌ๊ฐ„์—์„œ ์›Œ์ปค๊ฐ€ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์„ ์ฝ์œผ๋ฏ€๋กœ, ํ•ด์ œ ์ „์— RCU grace period๋ฅผ ๋Œ€๊ธฐํ•ด์•ผ ํ•จ.
  • 4. `struct encoded_page` (include/linux/mm_types.h:238)

    ํŽ˜์ด์ง€ ํฌ์ธํ„ฐ์— ํ”Œ๋ž˜๊ทธ๋ฅผ ๋น„ํŠธ ๋งˆ์Šคํ‚นํ•˜์—ฌ ์ €์žฅํ•˜๋Š” ์ธ์ฝ”๋”ฉ ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค.

    // include/linux/mm_types.h:238-279
    struct encoded_page;
    
    #define ENCODED_PAGE_BITS           3ul      // ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋น„ํŠธ ์ˆ˜
    #define ENCODED_PAGE_BIT_DELAY_RMAP 1ul      // TLB flush ํ›„ rmap ์ œ๊ฑฐ ์ง€์—ฐ
    #define ENCODED_PAGE_BIT_NR_PAGES_NEXT 2ul   // ๋‹ค์Œ ์—”ํŠธ๋ฆฌ๊ฐ€ nr_pages ๊ฐ’
    
    // ์ธ์ฝ”๋”ฉ: ํŽ˜์ด์ง€ ํฌ์ธํ„ฐ ํ•˜์œ„ ๋น„ํŠธ์— ํ”Œ๋ž˜๊ทธ ์ถ”๊ฐ€
    static __always_inline struct encoded_page *encode_page(struct page *page, unsigned long flags)
    {
    BUILD_BUG_ON(flags > ENCODED_PAGE_BITS);
    return (struct encoded_page *)(flags | (unsigned long)page);
    }
    
    // ๋””์ฝ”๋”ฉ: ํ•˜์œ„ ๋น„ํŠธ ์ œ๊ฑฐํ•˜์—ฌ ์‹ค์ œ ํŽ˜์ด์ง€ ํฌ์ธํ„ฐ ๋ณต์›
    static inline struct page *encoded_page_ptr(struct encoded_page *page)
    {
    return (struct page *)(~ENCODED_PAGE_BITS & (unsigned long)page);
    }
    // include/linux/mm_types.h:260-268
    static inline unsigned long encoded_page_flags(struct encoded_page *page)
    {
    return ENCODED_PAGE_BITS & (unsigned long)page;
    }

    ์„ค๋ช…:

  • ENCODED_PAGE_BIT_DELAY_RMAP (bit 1): SMP ํ™˜๊ฒฝ์—์„œ rmap ์ œ๊ฑฐ๋ฅผ TLB flush ์ดํ›„๋กœ ๋ฏธ๋ฃธ. folio_remove_rmap_ptes() ํ˜ธ์ถœ์ด ์ง€์—ฐ๋จ.
  • ENCODED_PAGE_BIT_NR_PAGES_NEXT (bit 2): ์—ฐ์†๋œ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€(folio)๋ฅผ ํ•˜๋‚˜์˜ ๋ฐฐ์น˜ ์—”ํŠธ๋ฆฌ๋กœ ํ‘œํ˜„. ๋‹ค์Œ ์—”ํŠธ๋ฆฌ์— ์‹ค์ œ ํŽ˜์ด์ง€ ์ˆ˜๊ฐ€ ์ธ์ฝ”๋”ฉ๋จ.
  • 5. `encode_page` / `encode_nr_pages` (include/linux/mm_types.h:254-279)

    ํŽ˜์ด์ง€ ์ธ์ฝ”๋”ฉ/๋””์ฝ”๋”ฉ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

    // include/linux/mm_types.h:270-278
    // ํŽ˜์ด์ง€ ์ˆ˜ ์ธ์ฝ”๋”ฉ: ์ƒ์œ„ ๋น„ํŠธ์— ํŽ˜์ด์ง€ ์ˆ˜ ์ €์žฅ
    static __always_inline struct encoded_page *encode_nr_pages(unsigned long nr)
    {
    VM_WARN_ON_ONCE((nr << 2) >> 2 != nr);  // 30๋น„ํŠธ ์ดˆ๊ณผ ๊ฒ€์ฆ
    return (struct encoded_page *)(nr << 2);
    }
    
    // ์ธ์ฝ”๋”ฉ๋œ ํŽ˜์ด์ง€ ์ˆ˜ ๋””์ฝ”๋”ฉ
    static __always_inline unsigned long encoded_nr_pages(struct encoded_page *page)
    {
    return ((unsigned long)page) >> 2;
    }

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

    1. `tlb_gather_mmu()` โ€” ์ดˆ๊ธฐํ™”

    // mm/mmu_gather.c:443-446
    void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm)
    {
    __tlb_gather_mmu(tlb, mm, false);  // fullmm = false
    }
  • ์—ญํ• : ์Šคํƒ์— ํ• ๋‹น๋œ mmu_gather ๊ตฌ์กฐ์ฒด๋ฅผ ์ดˆ๊ธฐํ™”. ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์ œ๊ฑฐ ์ž‘์—… ์‹œ์ž‘ ์ „์— ํ˜ธ์ถœ.
  • ๋™์ž‘: __tlb_gather_mmu()์—์„œ mm ์—ฐ๊ฒฐ, ๋ฐฐ์น˜ ์ดˆ๊ธฐํ™”(local ์‚ฌ์šฉ), ๋ฒ”์œ„ ์ดˆ๊ธฐํ™”(__tlb_reset_range()), inc_tlb_flush_pending() ํ˜ธ์ถœ.
  • ๋ณ€ํ˜•:
  • - tlb_gather_mmu_fullmm(): fullmm=true. ์ „์ฒด ์ฃผ์†Œ ๊ณต๊ฐ„ ์ œ๊ฑฐ(exit/execve) ์‹œ ์‚ฌ์šฉ.

    - tlb_gather_mmu_vma(): ๋‹จ์ผ VMA ๋Œ€์ƒ. tlb_update_vma_flags()์™€ HugeTLB ํŽ˜์ด์ง€ ํฌ๊ธฐ ์„ค์ • ํฌํ•จ.

    2. `__tlb_remove_folio_pages()` โ€” ํŽ˜์ด์ง€ ์ œ๊ฑฐ ๊ธฐ๋ก

    // mm/mmu_gather.c:207-212
    bool __tlb_remove_folio_pages(struct mmu_gather *tlb, struct page *page,
    unsigned int nr_pages, bool delay_rmap)
    {
    return __tlb_remove_folio_pages_size(tlb, page, nr_pages, delay_rmap,
    PAGE_SIZE);
    }
  • ์—ญํ• : ์ œ๊ฑฐ๋œ ํŽ˜์ด์ง€๋ฅผ ๋ฐฐ์น˜์— ์ธ์ฝ”๋”ฉํ•˜์—ฌ ์ €์žฅ. ๋ฐฐ์น˜๊ฐ€ ๊ฐ€๋“ ์ฐจ๋ฉด tlb_flush_mmu()๋ฅผ ์œ ๋ฐœ.
  • ๋ถ„๊ธฐ ๋กœ์ง:
  • - nr_pages == 1: ๋‹จ์ผ ํŽ˜์ด์ง€ โ†’ encode_page(page, flags)๋กœ ์ €์žฅ.

    - nr_pages > 1: folio โ†’ ENCODED_PAGE_BIT_NR_PAGES_NEXT ์„ค์ • ํ›„ ๋‹ค์Œ ์—”ํŠธ๋ฆฌ์— encode_nr_pages(nr_pages) ์ €์žฅ.

    - batch->nr >= batch->max - 1: ๋ฐฐ์น˜ ๊ฐ€๋“ ์ฐธ โ†’ tlb_next_batch()๋กœ ์ƒˆ ๋ฐฐ์น˜ ํ• ๋‹น ์‹คํŒจ ์‹œ true ๋ฐ˜ํ™˜ โ†’ ํ˜ธ์ถœ๋ถ€์—์„œ flush ์œ ๋ฐœ.

  • ๋ฐ˜ํ™˜๊ฐ’: true = ์ฆ‰์‹œ flush ํ•„์š”, false = ๊ณ„์† ๋ฐฐ์น˜ ๊ฐ€๋Šฅ.
  • 3. `tlb_flush_mmu()` โ€” TLB ํ”Œ๋Ÿฌ์‹œ ์‹คํ–‰

    // mm/mmu_gather.c:402-406
    void tlb_flush_mmu(struct mmu_gather *tlb)
    {
    tlb_flush_mmu_tlbonly(tlb);   // ์•„ํ‚คํ…์ฒ˜๋ณ„ TLB flush
    tlb_flush_mmu_free(tlb);       // ํ…Œ์ด๋ธ” ๋ฐ ํŽ˜์ด์ง€ ํ•ด์ œ
    }
  • ์—ญํ• : tlb_remove_page() ๋“ฑ์—์„œ ๋ฐฐ์น˜๊ฐ€ ๊ฐ€๋“ ์ฐผ์„ ๋•Œ ํ˜ธ์ถœ. ์‹ค์ œ TLB flush์™€ ๋ฆฌ์†Œ์Šค ํ•ด์ œ๋ฅผ ์ˆ˜ํ–‰.
  • ๋™์ž‘:
  • 1. tlb_flush_mmu_tlbonly(): freed_tables ๋˜๋Š” cleared_* ํ”Œ๋ž˜๊ทธ๊ฐ€ ์„ค์ •๋œ ๊ฒฝ์šฐ์—๋งŒ tlb_flush() ํ˜ธ์ถœ. flush ํ›„ __tlb_reset_range()๋กœ ๋ฒ”์œ„ ๋ฆฌ์…‹.

    2. tlb_flush_mmu_free(): tlb_table_flush()๋กœ ํ…Œ์ด๋ธ” ๋ฐฐ์น˜ ํ•ด์ œ + tlb_batch_pages_flush()๋กœ ํŽ˜์ด์ง€ ๋ฐฐ์น˜ ํ•ด์ œ.

    4. `tlb_finish_mmu()` โ€” ์ตœ์ข… ์ •๋ฆฌ

    // mm/mmu_gather.c:496-536
    void tlb_finish_mmu(struct mmu_gather *tlb)
  • ์—ญํ• : ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์ œ๊ฑฐ ์ž‘์—… ์™„๋ฃŒ ํ›„ ํ˜ธ์ถœ. ์ค‘์ฒฉ flush ์ฒ˜๋ฆฌ, ์ตœ์ข… flush, ๋ฐฐ์น˜ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ.
  • ๋™์ž‘:
  • 1. mm_tlb_flush_nested() ํ™•์ธ: ๋ณ‘๋ ฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ฒ”์œ„์— PTE ๋ณ€๊ฒฝ ์‹œ ๊ฐ•์ œ ์ „์ฒด flush (fullmm=1, __tlb_reset_range(), freed_tables=1).

    2. tlb_flush_mmu(): ์ตœ์ข… flush ์‹คํ–‰.

    3. tlb_batch_list_free(): ๋™์  ํ• ๋‹น๋œ ๋ฐฐ์น˜ ํŽ˜์ด์ง€ ํ•ด์ œ.

    4. dec_tlb_flush_pending(): ๋Œ€๊ธฐ ์นด์šดํŠธ ๊ฐ์†Œ.

    ๋ณด์กฐ ๊ฒฝ๋กœ

    // include/asm-generic/tlb.h:495-507
    static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
    {
    if (!(tlb->freed_tables || tlb->cleared_ptes || tlb->cleared_pmds ||
    tlb->cleared_puds || tlb->cleared_p4ds || tlb->unshared_tables))
    return;
    
    tlb_flush(tlb);
    __tlb_reset_range(tlb);
    }
  • tlb_flush_mmu_tlbonly()๋Š” freed_tables, cleared_*, unshared_tables๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ invalidateํ•˜๊ณ  ๋ฒ”์œ„๋ฅผ ๋ฆฌ์…‹ํ•ฉ๋‹ˆ๋‹ค.
  • tlb_remove_tlb_entry()๋Š” mm/memory.c:1695-1705์—์„œ ptep_get_and_clear_full() ๋’ค์— ํ˜ธ์ถœ๋˜์–ด PTE ์ œ๊ฑฐ ๋ฒ”์œ„๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
  • tlb_free_vmas()๋Š” VM_PFNMAP / VM_MIXEDMAP์ด ์„ž์ธ ๋ฒ”์œ„์—์„œ VMA๋ฅผ unlinkํ•˜๊ธฐ ์ „์— TLB flush๋ฅผ ์•ž๋‹น๊น๋‹ˆ๋‹ค.
  • 5. `tlb_remove_table()` โ€” ํ…Œ์ด๋ธ” ๋ฐฐ์น˜

    // mm/mmu_gather.c:363-380
    void tlb_remove_table(struct mmu_gather *tlb, void *table)
  • ์—ญํ• : ์ œ๊ฑฐ๋œ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋””๋ ‰ํ† ๋ฆฌ(PGD, P4D ๋“ฑ)๋ฅผ ๋ฐฐ์น˜์— ์ €์žฅ. CONFIG_MMU_GATHER_TABLE_FREE ํ™œ์„ฑํ™” ์‹œ ์‚ฌ์šฉ.
  • ๋™์ž‘:
  • 1. ๋ฐฐ์น˜ ํ• ๋‹น: __get_free_page(GFP_NOWAIT)๋กœ ์ƒˆ ๋ฐฐ์น˜ ํ• ๋‹น ์‹คํŒจ ์‹œ ์ฆ‰์‹œ tlb_table_invalidate() + ๋‹จ์ผ ํ•ด์ œ.

    2. ๋ฐฐ์น˜ ์ถ”๊ฐ€: batch->tables[batch->nr++] = table.

    3. ๋ฐฐ์น˜ ๊ฐ€๋“ ์ฐธ: tlb_table_flush()๋กœ ์ฆ‰์‹œ flush.

    6. `tlb_flush_rmaps()` โ€” ์ง€์—ฐ rmap ์ œ๊ฑฐ

    // mm/mmu_gather.c:84-93
    void tlb_flush_rmaps(struct mmu_gather *tlb, struct vm_area_struct *vma)
  • ์—ญํ• : SMP์—์„œ delayed_rmap์ด ์„ค์ •๋œ ๊ฒฝ์šฐ, TLB flush ์™„๋ฃŒ ํ›„ rmap ์ œ๊ฑฐ๋ฅผ ์ˆ˜ํ–‰.
  • ๋™์ž‘: tlb->local๊ณผ tlb->active ๋ฐฐ์น˜์˜ ๋ชจ๋“  ์—”ํŠธ๋ฆฌ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ENCODED_PAGE_BIT_DELAY_RMAP์ด ์„ค์ •๋œ ํŽ˜์ด์ง€์— ๋Œ€ํ•ด folio_remove_rmap_ptes() ํ˜ธ์ถœ.
  • 7. `tlb_next_batch()` โ€” ์ƒˆ ๋ฐฐ์น˜ ํ• ๋‹น

    // mm/mmu_gather.c:20-50
    static bool tlb_next_batch(struct mmu_gather *tlb)
  • ์—ญํ• : ํ˜„์žฌ ๋ฐฐ์น˜๊ฐ€ ๊ฐ€๋“ ์ฐผ์„ ๋•Œ ๋‹ค์Œ ๋ฐฐ์น˜๋ฅผ ํ• ๋‹นํ•˜๊ฑฐ๋‚˜ ์ด๋™.
  • ๋ถ„๊ธฐ:
  • - tlb->delayed_rmap && tlb->active != &tlb->local: ์ง€์—ฐ rmap ๋ณด์œ  ์‹œ ์ƒˆ ๋ฐฐ์น˜ ์‹œ์ž‘ ๋ถˆ๊ฐ€ (๊ธฐ์กด ๋ฐฐ์น˜์—์„œ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•จ).

    - batch->next: ์ด๋ฏธ ํ• ๋‹น๋œ ๋‹ค์Œ ๋ฐฐ์น˜๊ฐ€ ์žˆ์œผ๋ฉด ์ด๋™.

    - batch_count == MAX_GATHER_BATCH_COUNT: ๋ฐฐ์น˜ ์ˆ˜ ์ œํ•œ ๋„๋‹ฌ โ†’ ํ• ๋‹น ๊ฑฐ๋ถ€ (soft lockup ๋ฐฉ์ง€).

    - __get_free_page(GFP_NOWAIT) ์‹คํŒจ: ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ์‹œ ํ• ๋‹น ๊ฑฐ๋ถ€.


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

    ์‚ฌ์šฉ์ž: munmap() / exit() / madvise(MADV_DONTNEED)
    โ”‚
    โ–ผ
    tlb_gather_mmu(tlb, mm)  โ† ์ดˆ๊ธฐํ™” (์Šคํƒ ํ• ๋‹น, ๋ฐฐ์น˜ ์ดˆ๊ธฐํ™”)
    โ”‚
    โ–ผ
    tlb_start_vma(tlb, vma)  โ† ์บ์‹œ ํ”Œ๋Ÿฌ์‹œ, VMA ํ”Œ๋ž˜๊ทธ ๊ธฐ๋ก
    โ”‚
    โ–ผ (VMA ์ˆœํšŒํ•˜๋ฉฐ)
    zap_pte_range(tlb, vma, pmd, addr, end)
    โ”‚
    โ”œโ”€โ”€ tlb_remove_tlb_entry(tlb, ptep, addr)
    โ”‚     โ””โ”€โ”€ tlb_flush_pte_range(tlb, addr, PAGE_SIZE)  โ† ๋ฒ”์œ„ ๊ฐฑ์‹ 
    โ”‚
    โ””โ”€โ”€ __tlb_remove_folio_pages(tlb, page, nr_pages, delay_rmap)
    โ””โ”€โ”€ __tlb_remove_folio_pages_size()
    โ””โ”€โ”€ ๋ฐฐ์น˜์— ์ธ์ฝ”๋”ฉ๋œ ํŽ˜์ด์ง€ ์ €์žฅ
    โ””โ”€โ”€ ๋ฐฐ์น˜ ๊ฐ€๋“ ์ฐธ โ†’ tlb_flush_mmu() ์œ ๋ฐœ
    โ”‚
    โ–ผ
    tlb_end_vma(tlb, vma)  โ† VMA ๊ฒฝ๊ณ„์—์„œ ํ”Œ๋Ÿฌ์‹œ (MERGE_VMAS ๋ฏธํ™œ์„ฑํ™” ์‹œ)
    โ”‚
    โ–ผ
    tlb_finish_mmu(tlb)  โ† ์ตœ์ข… ์ •๋ฆฌ
    โ”œโ”€โ”€ mm_tlb_flush_nested() ํ™•์ธ โ†’ ๋ณ‘๋ ฌ flush ํ•„์š” ์‹œ fullmm ๊ฐ•์ œ
    โ”œโ”€โ”€ tlb_flush_mmu()
    โ”‚     โ”œโ”€โ”€ tlb_flush_mmu_tlbonly() โ†’ flush_tlb_mm() ๋˜๋Š” flush_tlb_range()
    โ”‚     โ””โ”€โ”€ tlb_flush_mmu_free()
    โ”‚           โ”œโ”€โ”€ tlb_table_flush() โ†’ RCU/์ง์ ‘ ํ…Œ์ด๋ธ” ํ•ด์ œ
    โ”‚           โ””โ”€โ”€ tlb_batch_pages_flush() โ†’ free_pages_and_swap_cache()
    โ””โ”€โ”€ tlb_batch_list_free() โ†’ ๋™์  ๋ฐฐ์น˜ ํ•ด์ œ

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

    MMU_GATHER_* ์ปค๋„ ์˜ต์…˜ ๋น„๊ต

    ์˜ต์…˜์„ค๋ช…ํ™œ์„ฑํ™” ์•„ํ‚คํ…์ฒ˜
    `MMU_GATHER_TABLE_FREE`ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋ฐฐ์น˜๋กœ ํ•ด์ œx86, ARM64, RISC-V, PowerPC, s390 ๋“ฑ ๋Œ€๋ถ€๋ถ„
    `MMU_GATHER_RCU_TABLE_FREE`RCU grace period ํ›„ ํ…Œ์ด๋ธ” ํ•ด์ œ. ์†Œํ”„ํŠธ์›จ์–ด ์›Œ์ปค(gup_fast) ๋™๊ธฐํ™”x86(SMP), ARM64(SMP), RISC-V(SMP), s390, PowerPC
    `MMU_GATHER_NO_RANGE`๋ฒ”์œ„ ๊ธฐ๋ฐ˜ ํ”Œ๋Ÿฌ์‹œ ์—†์ด ์ „์ฒด mm ํ”Œ๋Ÿฌ์‹œ๋งŒ ์‚ฌ์šฉnios2, m68k, microblaze, OpenRISC
    `MMU_GATHER_MERGE_VMAS`VMA ๊ฒฝ๊ณ„์—์„œ ํ”Œ๋Ÿฌ์‹œ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋ฒ”์œ„ ๋ณ‘ํ•ฉx86, PowerPC, s390, SPARC, LoongArch
    `MMU_GATHER_NO_FLUSH_CACHE``flush_cache_range()` ํ˜ธ์ถœ ์•ˆ ํ•จs390, SPARC
    `MMU_GATHER_NO_GATHER`ํŽ˜์ด์ง€ ๋ฐฐ์น˜ ์—†์ด ์ฆ‰์‹œ ํ•ด์ œ. ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์ž์ฒด flush ์ง€์› ์‹œs390
    `MMU_GATHER_PAGE_SIZE`ํŽ˜์ด์ง€ ํฌ๊ธฐ ๋ณ€๊ฒฝ ๊ฐ์ง€ ( HugeTLB)PowerPC

    ์•„ํ‚คํ…์ฒ˜๋ณ„ TLB flush ๋ฐฉ์‹ ๋น„๊ต

    ์•„ํ‚คํ…์ฒ˜flush ๋ฐฉ์‹ํŠน์ง•
    x86_64`flush_tlb_mm()`, `flush_tlb_range()`INVLPG ๋ช…๋ น์–ด ์‚ฌ์šฉ. ์ „์ฒด flush ์‹œ CR3 ์žฌ๋กœ๋“œ. MERGE_VMAS๋กœ ๋ฒ”์œ„ ์ตœ์ ํ™”.
    ARM64`tlbi vmalle1is`, `tlbi vae1is`HW ์ง€์› cross-CPU ๋™๊ธฐํ™”. fullmm ์‚ฌ์šฉ ์‹œ IPI ์ŠคํŒธ ๋ฐฉ์ง€.
    s390๋™๊ธฐ์‹ ์›๊ฒฉ flushNO_GATHER๋กœ ์ฆ‰์‹œ ํ•ด์ œ. ์†Œํ”„ํŠธ์›จ์–ด ์›Œ์ปค ๋ถˆํ•„์š”.
    RISC-V`sfence.vma`SMP ์‹œ RCU_TABLE_FREE๋กœ IPI ๋น„ํ™œ์„ฑํ™” ๊ตฌ๊ฐ„ ๋™๊ธฐํ™”.

    ๋ฐฐ์น˜ ๋™์ž‘ ๋น„๊ต

    ์ƒํ™ฉ๋™์ž‘์„ค๋ช…
    ๋‹จ์ผ ํŽ˜์ด์ง€ ์ œ๊ฑฐ`encode_page(page, 0)` โ†’ `batch->encoded_pages[nr++]`ํ”Œ๋ž˜๊ทธ ์—†์ด ๋‹จ์ˆœ ์ €์žฅ
    folio ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€`encode_page(page, NR_PAGES_NEXT)` + `encode_nr_pages(nr)`์—ฐ์† 2์—”ํŠธ๋ฆฌ ์‚ฌ์šฉ
    SMP rmap ์ง€์—ฐ`tlb_delay_rmap(tlb)` โ†’ `ENCODED_PAGE_BIT_DELAY_RMAP` ์„ค์ •flush ํ›„ rmap ์ œ๊ฑฐ
    ๋ฐฐ์น˜ ๊ฐ€๋“ ์ฐธ`tlb_next_batch()` โ†’ ์ƒˆ ๋ฐฐ์น˜ ํ• ๋‹น ๋˜๋Š” flush ์œ ๋ฐœ`MAX_GATHER_BATCH_COUNT` ์ œํ•œ
    ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ`__get_free_page(GFP_NOWAIT)` ์‹คํŒจ โ†’ ๊ธฐ์กด ๋ฐฐ์น˜์—์„œ flush์ง„ํ–‰ ๋ณด์žฅ

    ๋Œ€ํ‘œ VMA ๊ฒฝ๋กœ ๋น„๊ต

    ๊ฒฝ๋กœ์ง„์ž… ํ•จ์ˆ˜mmu_gather ์‚ฌ์šฉํ•ต์‹ฌ ํ๋ฆ„
    `munmap()``unmap_region()``tlb_gather_mmu()` โ†’ `tlb_finish_mmu()``unmap_vmas()` โ†’ `free_pgtables()` โ†’ page table tear-down
    `mprotect()``do_mprotect_pkey()``tlb_gather_mmu()` โ†’ `mprotect_fixup()` โ†’ `tlb_finish_mmu()``change_protection()` โ†’ `walk_page_range()` โ†’ PTE ๊ถŒํ•œ ๊ฐฑ์‹ 
    `MADV_COLD` / `MADV_PAGEOUT``madvise_cold()` / `madvise_pageout()``tlb_gather_mmu()` โ†’ `tlb_start_vma()` / `tlb_end_vma()` โ†’ `tlb_finish_mmu()`LRU ์ ‘๊ทผ ๋น„ํŠธ ์ •๋ฆฌ ํ›„ TLB invalidate
    `MADV_FREE``madvise_free_single_vma()``tlb_start_vma()` / `tlb_end_vma()``clear_young_dirty_ptes()` + `tlb_remove_tlb_entries()`
    NUMA balancing`change_prot_numa()``tlb_gather_mmu()` โ†’ `tlb_finish_mmu()`PROT_NONE ๋งˆํ‚น ํ›„ `change_protection()`
    exec stack relocation`relocate_vma_down()``tlb_gather_mmu()` โ†’ `free_pgd_range()` โ†’ `tlb_finish_mmu()`์ƒˆ ์œ„์น˜๋กœ ์ด๋™ ํ›„ ์ƒ์œ„ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์ •๋ฆฌ

    ์•„ํ‚คํ…์ฒ˜๋ณ„ invalidate ๋ฐฉ์‹

    ์•„ํ‚คํ…์ฒ˜๋Œ€ํ‘œ primitive๋™๊ธฐ ๋ฒ”์œ„๋น„๊ณ 
    x86_64`invlpg`, `flush_tlb_mm()`, `flush_tlb_range()`local + IPI shootdownPCID๊ฐ€ ์žˆ์œผ๋ฉด ํƒœ๊ทธ ์ „ํ™˜์œผ๋กœ ๋น„์šฉ์„ ์ค„์ž„
    ARM64`TLBI ...`, `dsb ish`, `isb`inner-shareable broadcastASID ๊ธฐ๋ฐ˜์œผ๋กœ range/fullmm ๊ตฌ๋ถ„
    RISC-V`sfence.vma`per-hart ๋˜๋Š” IPI ๋™๊ธฐํ™”ASID ์ธ์ž๊ฐ€ ์žˆ์œผ๋ฉด ๋ฒ”์œ„ ์ถ•์†Œ ๊ฐ€๋Šฅ
    s390synchronous remote flush๋™๊ธฐ์‹ CPU sync`MMU_GATHER_NO_GATHER`์™€ ํ•จ๊ป˜ ์“ฐ์ด๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ

    ๊ด€๋ จ ๋ฌธ์„œ

  • 00 โ€” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ ๊ฐœ์š”
  • 03 โ€” VMA / mmap
  • 36 โ€” mprotect
  • 38 โ€” Page Table Walk
  • 05 โ€” ํŽ˜์ด์ง€ ํšŒ์ˆ˜
  • 20 โ€” Migration
  • 39 โ€” vmpressure
  • 33 โ€” GUP (Get User Pages)
  • 43 โ€” HugeTLB
  • 64 โ€” MMU ์—†๋Š” ์‹œ์Šคํ…œ