[커널 18차] 109주차

2023.06.24 23:12

kkr 조회 수:33

numa fault 진행중

 

git : https://github.com/iamroot18/5.10/commit/95e3f7b9dbb6cc641f098a38f10bbe63c627c047

 

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 35cd749a4eeb..73d6c8f8b005 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -273,6 +273,10 @@
 #define PTE_AF            (_AT(pteval_t, 1) << 10)    /* Access Flag */
 #define PTE_NG            (_AT(pteval_t, 1) << 11)    /* nG */
 #define PTE_GP            (_AT(pteval_t, 1) << 50)    /* BTI guarded */
+/*
+ * IAMROOT, 2023.06.24:
+ * - cpu가 관리한다.
+ */
 #define PTE_DBM            (_AT(pteval_t, 1) << 51)    /* Dirty Bit Management */
 #define PTE_CONT        (_AT(pteval_t, 1) << 52)    /* Contiguous range */
 #define PTE_PXN            (_AT(pteval_t, 1) << 53)    /* Privileged XN */
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 64544e167464..23ac7ffdea8f 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -13,6 +13,10 @@
 /*
  * Software defined PTE bits definition.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - PTE_DBM은 hw, PTE_DIRTY은 sw(원래부터 kernel이 관리하는 flag)
+ */
 #define PTE_WRITE        (PTE_DBM)         /* same as DBM (51) */
 #define PTE_DIRTY        (_AT(pteval_t, 1) << 55)
 
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 899ed2b35ead..983efea73003 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -169,6 +169,18 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
     (__boundary - 1 < (end) - 1) ? __boundary : (end);            \
 })
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - dirty flag가 설정되었는지 여부를 알아온다. (write flag == dirty flag)
+ * - DBM (Dirty Bit Management)
+ *   예전에서는 kernel이 어떤 물리페이지에 접근했는지 cpu가 몰랐다.
+ *   하지만 현재는 cpu가 알게 하기위해 fault를 발생하기 위해 mapping을 끊고
+ *   page access의 시도를 알게 한다.
+ *   arm 8.2부터는 DBM이라는 개념을 넣어 access page에(tlb cache) dirty flag에
+ *   hw가 기록한다. 이렇게 함으로써 mapping을 지우지 않아도 접근여부를
+ *   알수있게됬다.
+ *   dirty상태면 메모리에 아직 기록이 안됬다는것을 알수있을것이다.
+ */
 #define pte_hw_dirty(pte)    (pte_write(pte) && !(pte_val(pte) & PTE_RDONLY))
 #define pte_sw_dirty(pte)    (!!(pte_val(pte) & PTE_DIRTY))
 #define pte_dirty(pte)        (pte_sw_dirty(pte) || pte_hw_dirty(pte))
@@ -254,12 +266,17 @@ static inline pte_t pte_mkclean(pte_t pte)
 
 /*
  * IAMROOT, 2022.06.04:
- * - @pte에 PTE_DIRTY bit를 set한다.
+ * - @pte에 PTE_DIRTY bit(sw dirty)를 set한다.
  */
 static inline pte_t pte_mkdirty(pte_t pte)
 {
     pte = set_pte_bit(pte, __pgprot(PTE_DIRTY));
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - wr와 rdonly는 공존이 안된다. wr이 set되있으면
+ *   rdonly는 그냥 한번 지워주는 개념인듯하다.
+ */
     if (pte_write(pte))
         pte = clear_pte_bit(pte, __pgprot(PTE_RDONLY));
 
@@ -965,18 +982,39 @@ static inline pud_t *p4d_pgtable(p4d_t p4d)
 #define pgd_set_fixmap(addr)    ((pgd_t *)set_fixmap_offset(FIX_PGD, addr))
 #define pgd_clear_fixmap()    clear_fixmap(FIX_PGD)
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - 1. @pte가 hw dirty이면 sw dirty set한다.
+ *   2. @pte에서 mask를 제외한 부분 유지하고, @newprot에서 mask에 해당하는
+ *   것만 추가해서 return한다.
+ */
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
     /*
      * Normal and Normal-Tagged are two different memory types and indices
      * in MAIR_EL1. The mask below has to include PTE_ATTRINDX_MASK.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   Normal 및 Normal-Tagged는 MAIR_EL1의 두 가지 메모리 유형 및 
+ *   인덱스입니다. 아래 마스크는 PTE_ATTRINDX_MASK를 포함해야 합니다.
+ */
     const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
                   PTE_PROT_NONE | PTE_VALID | PTE_WRITE | PTE_GP |
                   PTE_ATTRINDX_MASK;
     /* preserve the hardware dirty information */
+/*
+ * IAMROOT, 2023.06.24:
+ * - hw dirty여부를 알아온다 hw dirty라면. sw dirty도 set한다.
+ */
     if (pte_hw_dirty(pte))
         pte = pte_mkdirty(pte);
+/*
+ * IAMROOT, 2023.06.24:
+ * - @pte에서 mask를 뺀것은 그대로 유지하고, @newprot의 mask에 있는것만
+ *   추가한다.
+ */
     pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
     return pte;
 }
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2e77d1b9be74..bc6bf60bc2f0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -591,6 +591,10 @@ struct vm_fault {
                      * the 'address'
                      */
     union {
+/*
+ * IAMROOT, 2023.06.24:
+ * - fault 당시의 pte, pmd entry value
+ */
         pte_t orig_pte;        /* Value of PTE at the time of fault */
         pmd_t orig_pmd;        /* Value of PMD at the time of fault,
                      * used by PMD fault only.
@@ -1632,6 +1636,10 @@ static inline int page_to_nid(const struct page *page)
 #endif
 
 #ifdef CONFIG_NUMA_BALANCING
+/*
+ * IAMROOT, 2023.06.24:
+ * - cpuid 생성
+ */
 static inline int cpu_pid_to_cpupid(int cpu, int pid)
 {
     return ((cpu & LAST__CPU_MASK) << LAST__PID_SHIFT) | (pid & LAST__PID_MASK);
@@ -1652,6 +1660,10 @@ static inline int cpupid_to_nid(int cpupid)
     return cpu_to_node(cpupid_to_cpu(cpupid));
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @cpupid가 아직 unset인지 확인한다.
+ */
 static inline bool cpupid_pid_unset(int cpupid)
 {
     return cpupid_to_pid(cpupid) == (-1 & LAST__PID_MASK);
@@ -1662,11 +1674,19 @@ static inline bool cpupid_cpu_unset(int cpupid)
     return cpupid_to_cpu(cpupid) == (-1 & LAST__CPU_MASK);
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @task_pid 와 cpupid에서 각각 pid를 추출해 비교한다.
+ */
 static inline bool __cpupid_match_pid(pid_t task_pid, int cpupid)
 {
     return (task_pid & LAST__PID_MASK) == cpupid_to_pid(cpupid);
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @task_pid 와 cpupid에서 각각 pid를 추출해 비교한다.
+ */
 #define cpupid_match_pid(task, cpupid) __cpupid_match_pid(task->pid, cpupid)
 /*
  * IAMROOT, 2021.12.11:
@@ -2165,6 +2185,13 @@ extern unsigned long move_page_tables(struct vm_area_struct *vma,
  * for now all the callers are only use one of the flags at the same
  * time.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *  change_protection()에서 사용하는 플래그입니다. 지금은 매개변수처럼
+ *  여러 플래그를 전달할 수 있도록 비트맵으로 만듭니다. 그러나 지금은
+ *  모든 호출자가 동시에 플래그 중 하나만 사용합니다.
+ */
 /* Whether we should allow dirty bit accounting */
 #define  MM_CP_DIRTY_ACCT                  (1UL << 0)
 /* Whether this protection change is for NUMA hints */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index e57daee4042b..02c75c577581 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -340,6 +340,11 @@ struct page {
 #endif /* WANT_PAGE_VIRTUAL */
 
 #ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
+/*
+ * IAMROOT, 2023.06.24:
+ * - page를 마지막으로 썻던 cpu + pid
+ * - 초기값 / reset = -1 & LAST_CPUPID_MASK
+ */
     int _last_cpupid;
 #endif
 } _struct_page_alignment;
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 2df8f7577807..93cec82a9cab 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -149,6 +149,11 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long address)
      pte_index((address)))
 #define pte_unmap(pte) kunmap_atomic((pte))
 #else
+/*
+ * IAMROOT, 2023.06.24:
+ * - 64bit
+ *   address에 해당하는 pte page table entry주소를 가져온다.
+ */
 #define pte_offset_map(dir, address)    pte_offset_kernel((dir), (address))
 #define pte_unmap(pte) ((void)(pte))    /* NOP */
 #endif
@@ -975,6 +980,10 @@ static inline pte_t __ptep_modify_prot_start(struct vm_area_struct *vma,
     return ptep_get_and_clear(vma->vm_mm, addr, ptep);
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - pte entry(@ptep)에 @pte값을 기록한다.
+ */
 static inline void __ptep_modify_prot_commit(struct vm_area_struct *vma,
                          unsigned long addr,
                          pte_t *ptep, pte_t pte)
@@ -1034,6 +1043,13 @@ static inline pte_t ptep_modify_prot_start(struct vm_area_struct *vma,
  * Commit an update to a pte, leaving any hardware-controlled bits in
  * the PTE unmodified.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   PTE에 대한 업데이트를 커밋하고 PTE의 모든 하드웨어 제어 비트를 수정하지
+ *   않은 상태로 둡니다.
+ * - pte entry(@ptep)에 @pte값을 기록한다.
+ */
 static inline void ptep_modify_prot_commit(struct vm_area_struct *vma,
                        unsigned long addr,
                        pte_t *ptep, pte_t old_pte, pte_t pte)
@@ -1115,6 +1131,22 @@ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
  * case, this is required so that preemption is disabled, and in the SMP case,
  * it must synchronize the delayed page table writes properly on other CPUs.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   lazy MMU 일괄 처리를 제공하는 기능입니다. 이렇게 하면 lazy MMU 모드를 
+ *   종료하라는 호출이 발행될 때까지 PTE 업데이트 및 페이지 무효화를 지연할 수 
+ *   있습니다. 일부 아키텍처는 이 작업을 통해 이점을 얻을 수 있으며 이 기간 동안 
+ *   발생하는 PTE 업데이트를 일괄 처리할 수 있는 섀도우 및 dirty mode hypervisor 
+ *   모두에 유용합니다. 이 인터페이스를 사용하려면 코드에서 읽기 위험을 제거해야 
+ *   합니다. 읽기 위험은 페이지 테이블에 대한 실제 쓰기가 아직 발생하지 않았을 수
+ *   있으므로 수정된 후 원시 PTE 포인터를 통한 읽기가 최신 상태임을 보장하지 않기
+ *   때문에 dirty mode hypervisor 사례에서 발생할 수 있습니다. 이 모드는 수정될
+ *   수 있는 모든 페이지 테이블에 대한 페이지 테이블 잠금의 보호 하에서만 들어갈
+ *   수 있고 남을 수 있습니다. UP의 경우 선점을 비활성화하기 위해 필요하며,
+ *   SMP의 경우 다른 CPU에서 지연된 페이지 테이블 쓰기를 적절하게 동기화해야 합니다.
+ * - sparc, x86, powerpc
+ */
 #ifndef __HAVE_ARCH_ENTER_LAZY_MMU_MODE
 #define arch_enter_lazy_mmu_mode()    do {} while (0)
 #define arch_leave_lazy_mmu_mode()    do {} while (0)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 6deed9d32ea3..4f4b4b41d385 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1657,6 +1657,7 @@ struct task_struct {
  * IAMROOT, 2023.06.17:
  * - 계산된 task(thread)기준의 node scan 간격(msec)
  *   실제 scan은 mm->numa_next_scan
+ *   task_numa_work()에서 scan후, task 실행시간의 최대 3%로 제한한다.
  */
     u64                node_stamp;
     u64                last_task_numa_placement;
@@ -1691,6 +1692,19 @@ struct task_struct {
      * during the current scan window. When the scan completes, the counts
      * in faults_memory and faults_cpu decay and these values are copied.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   numa_faults는 4개의 영역으로 분할된 배열입니다.
+ *   faults_memory, faults_cpu, faults_memory_buffer, faults_cpu_buffer 이 정확한 순서대로.
+ *
+ *   faults_memory: 노드당 기준으로 결함의 기하급수적 감쇠 평균. 일정 배치
+ *   결정은 이러한 수를 기반으로 이루어집니다. 값은 PTE 스캔 기간 동안 정적
+ *   상태로 유지됩니다.
+ *   faults_cpu: NUMA 힌트 오류가 발생했을 때 프로세스가 실행 중인 노드를 추적합니다.
+ *   faults_memory_buffer 및 faults_cpu_buffer: 현재 스캔 기간 동안 노드당 오류를 기록합니다.
+ *   스캔이 완료되면 faults_memory 및 faults_cpu의 카운트가 감소하고 이러한 값이 복사됩니다. 
+ */
     unsigned long            *numa_faults;
     unsigned long            total_numa_faults;
 
@@ -1700,6 +1714,15 @@ struct task_struct {
      * period is adapted based on the locality of the faults with different
      * weights depending on whether they were shared or private faults
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   numa_faults_locality는 마지막 스캔 기간 동안 기록된 결함이
+ *   원격/로컬인지 또는 마이그레이션에 실패했는지 추적합니다. 태스크
+ *   스캔 기간은 공유 결함인지 개인 결함인지에 따라 가중치가 다른 결함의
+ *   위치에 따라 조정됩니다. 
+ * - remote / local / fail
+ */
     unsigned long            numa_faults_locality[3];
 
     unsigned long            numa_pages_migrated;
diff --git a/include/linux/sched/numa_balancing.h b/include/linux/sched/numa_balancing.h
index 3988762efe15..59c246d30e87 100644
--- a/include/linux/sched/numa_balancing.h
+++ b/include/linux/sched/numa_balancing.h
@@ -9,6 +9,11 @@
 
 #include <linux/sched.h>
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - TNF(task numa fault)
+ *   TNF_NO_GROUP : rdonly에서는 group화 하지 않는다.(do_numa_page() 참고)
+ */
 #define TNF_MIGRATED    0x01
 #define TNF_NO_GROUP    0x02
 #define TNF_SHARED    0x04
diff --git a/include/uapi/linux/mempolicy.h b/include/uapi/linux/mempolicy.h
index 5428de7f0161..1e53c1d14b8b 100644
--- a/include/uapi/linux/mempolicy.h
+++ b/include/uapi/linux/mempolicy.h
@@ -82,6 +82,10 @@ enum {
  */
 #define MPOL_F_SHARED  (1 << 0)    /* identify shared policies */
 #define MPOL_F_MOF    (1 << 3) /* this policy wants migrate on fault */
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa balaning에서 사용하는 flag
+ */
 #define MPOL_F_MORON    (1 << 4) /* Migrate On protnone Reference On Node */
 
 /*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index fb7a0f5eb579..27ebfeca2818 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1564,12 +1564,24 @@ struct numa_group {
 
     struct rcu_head rcu;
     unsigned long total_faults;
+/*
+ * IAMROOT, 2023.06.24:
+ * - 전체 노드에 대해서 fault cpu를 더해놓은 통계값.
+ */
     unsigned long max_faults_cpu;
     /*
      * Faults_cpu is used to decide whether memory should move
      * towards the CPU. As a consequence, these stats are weighted
      * more by CPU use than by memory faults.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   Faults_cpu는 메모리가 CPU 쪽으로 이동해야 하는지 여부를 결정하는
+ *   데 사용됩니다. 결과적으로 이러한 통계는 메모리 fault보다 CPU 사용에
+ *   더 많은 가중치를 부여합니다.
+ * - numa_faults 참고
+ */
     unsigned long *faults_cpu;
     unsigned long faults[];
 };
@@ -1586,7 +1598,7 @@ static struct numa_group *deref_task_numa_group(struct task_struct *p)
 
 /*
  * IAMROOT, 2023.06.17:
- * - @p의 numa_group을 가져온다.
+ * - @p가 curr인경우에만 @p의 numa_group을 가져온다.
  */
 static struct numa_group *deref_curr_numa_group(struct task_struct *p)
 {
@@ -1616,7 +1628,7 @@ static unsigned int task_nr_scan_windows(struct task_struct *p)
  * IAMROOT, 2023.06.17:
  * - papago
  *   존재하지 않는 빈 페이지로 RSS를 기반으로 하는 계산은 PTE 스캐너에서 
- *   건너뛰고 NUMA 힌트 오류는 상주 페이지를 기반으로 트랩되어야 합니다. 
+ *   건너뛰고 NUMA 힌트 fault는 상주 페이지를 기반으로 트랩되어야 합니다. 
  * - ex) PAGE_SIZE = 12
  *   nr_scan_pages * 2^8 = 256 * 256 = 65536 = 64kb = 2^16
  */
@@ -1833,7 +1845,7 @@ pid_t task_numa_group_id(struct task_struct *p)
 /*
  * IAMROOT, 2023.06.17:
  * - papago
- *   평균 통계, 공유 및 개인, 메모리 및 CPU가 어레이의 전반부를 차지합니다. 
+ *   평균 통계, 공유 및 private, 메모리 및 CPU가 어레이의 전반부를 차지합니다. 
  *   배열의 두 번째 절반은 task_numa_placement에 의해 첫 번째 세트로 
  *   평균화되는 현재 카운터용입니다.
  *   
@@ -1854,6 +1866,10 @@ static inline unsigned long task_faults(struct task_struct *p, int nid)
         p->numa_faults[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @group에 대한 @nid의 전체 memory node fault값(private + shared fault)
+ */
 static inline unsigned long group_faults(struct task_struct *p, int nid)
 {
     struct numa_group *ng = deref_task_numa_group(p);
@@ -1865,6 +1881,10 @@ static inline unsigned long group_faults(struct task_struct *p, int nid)
         ng->faults[task_faults_idx(NUMA_MEM, nid, 1)];
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @group에 대한 @nid의 전체 memory node fault cpu값(private + shared fault)
+ */
 static inline unsigned long group_faults_cpu(struct numa_group *group, int nid)
 {
     return group->faults_cpu[task_faults_idx(NUMA_MEM, nid, 0)] +
@@ -1908,8 +1928,22 @@ static inline unsigned long group_faults_shared(struct numa_group *ng)
  * considered part of a numa group's pseudo-interleaving set. Migrations
  * between these nodes are slowed down, to allow things to settle down.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   최대값의 1/3보다 많은 NUMA 결함을 트리거하는 노드는 numa 그룹의
+ *   의사 인터리빙 세트의 일부로 간주됩니다. 이러한 노드 간의
+ *   마이그레이션은 속도가 느려지므로 문제가 해결됩니다.
+ */
 #define ACTIVE_NODE_FRACTION 3
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - max_faults_cpu의 1/3배 초과로 cpu fault가 많이 일어난경우.
+ *   즉 @ng fault개수에서 @nid의 fault cpu 비중이 많은경우이다.
+ * - 전체 노드대비 비율로 되기때문에 acitve인 node가 있고, inactive인 node가 있을것이다.
+ * - 비율상 active node는 최대 2개.
+ */
 static bool numa_is_active_node(int nid, struct numa_group *ng)
 {
     return group_faults_cpu(ng, nid) * ACTIVE_NODE_FRACTION > ng->max_faults_cpu;
@@ -2025,6 +2059,16 @@ static inline unsigned long group_weight(struct task_struct *p, int nid,
     return 1000 * faults / total_faults;
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @dst_cpu로 numa migrate가 가능한지 확인한다.
+ *   1. scan 횟수가 적은경우 true
+ *   2. 
+ *   3. private fault인경우 true.
+ *   4. dst_nid의 fault cpu이 src_nid fault cpu보다 3배초과인경우 true
+ *   5. fault cpu / falut mem의 비율이  dst가 1.33배이상 많은경우 true.
+ *      아니면 false
+ */
 bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
                 int src_nid, int dst_cpu)
 {
@@ -2041,6 +2085,16 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
      * two full passes of the "multi-stage node selection" test that is
      * executed below.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   첫 번째 fault 또는 private fault가 task lifetime 초기에 즉시 마이그레이션되도록 
+ *   허용합니다. 매직 넘버 4는 아래에서 실행되는 다단계 노드 선택 테스트의
+ *   두 번의 전체 패스를 기다리는 것을 기반으로 합니다.
+ * - 초기에는(numa_scan 횟수 2번이하), 설정이 안됬거나, @p가 last_cpuid로 설정되있다면
+ *   return true.
+ *   
+ */
     if ((p->numa_preferred_nid == NUMA_NO_NODE || p->numa_scan_seq <= 4) &&
         (cpupid_pid_unset(last_cpupid) || cpupid_match_pid(p, last_cpupid)))
         return true;
@@ -2062,15 +2116,42 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
      * This quadric squishes small probabilities, making it less likely we
      * act on an unlikely task<->page relation.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   다단계 노드 선택은 임시 작업<->페이지 관계를 구축하기 위해 주기적
+ *   마이그레이션 fault와 함께 사용됩니다. 2단계 필터를 사용하여 짧거나
+ *   가능성이 없는 관계를 제거합니다.  빈도주의자 확률에 따라
+ *   P(p) ~ n_p / n_t를 사용하여 이 페이지의 총 사용량(n_t)당 특정
+ *   페이지의 작업 사용량(n_p)을 확률과 동일시할 수 있습니다.
+ *
+ *   주기적인 fault은 이 확률을 샘플링하고 이러한 샘플이 완전히 독립적인
+ *   경우 연속으로 두 번 동일한 결과를 얻고 샘플 기간이 사용 패턴에 비해
+ *   충분히 짧은 경우 P(n)^2로 제공됩니다.
+ *
+ *   이 2차 함수는 작은 확률을 찌그러뜨려 우리가 있을 법하지 않은
+ *   작업<->페이지 관계에서 행동할 가능성을 줄입니다.
+ *
+ * - last_cpupid가 설정되있었고, 그게 dst_nid가 아니라면 return false
+ */
     if (!cpupid_pid_unset(last_cpupid) &&
                 cpupid_to_nid(last_cpupid) != dst_nid)
         return false;
 
     /* Always allow migrate on private faults */
+/*
+ * IAMROOT, 2023.06.24:
+ * - @p의 last pid와 @page의 lastpid가 같으면 private fault라고 판단하여
+ *   return true.
+ */
     if (cpupid_match_pid(p, last_cpupid))
         return true;
 
     /* A shared fault, but p->numa_group has not been set up yet. */
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa group이 아직 설정이 안됬으면 그냥 migrate 수행.
+ */
     if (!ng)
         return true;
 
@@ -2078,6 +2159,10 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
      * Destination node is much more heavily used than the source
      * node? Allow migration.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - @ng dst_nid가 src_nid보다 3배초과로 fault cpu 가 많이 발생했으면 옮긴다.
+ */
     if (group_faults_cpu(ng, dst_nid) > group_faults_cpu(ng, src_nid) *
                     ACTIVE_NODE_FRACTION)
         return true;
@@ -2090,6 +2175,18 @@ bool should_numa_migrate_memory(struct task_struct *p, struct page * page,
      * --------------- * - > ---------------
      * faults_mem(dst)   4   faults_mem(src)
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   불필요한 메모리 마이그레이션을 방지하기 위해 3/4 히스테리시스를
+ *   사용하여 각 노드의 CPU 및 메모리 사용에 따라 메모리를 분배합니다.
+ *
+ *   faults_cpu(dst)   3   faults_cpu(src)
+ *   --------------- * - > ---------------
+ *   faults_mem(dst)   4   faults_mem(src)
+ *
+ * - dst의 fault가 src보다 1.33배 이상 많다면 dst로 옮긴다.
+ */
     return group_faults_cpu(ng, dst_nid) * group_faults(p, src_nid) * 3 >
            group_faults_cpu(ng, src_nid) * group_faults(p, dst_nid) * 4;
 }
@@ -3086,6 +3183,12 @@ static inline void put_numa_group(struct numa_group *grp)
         kfree_rcu(grp, rcu);
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @p 요청
+ *   tsk : @cpupid(page)의 cpu에서 동작중인 curr
+ *   cpupid의 pid : @cpupid)를 마지막에 썻던 task
+ */
 static void task_numa_group(struct task_struct *p, int cpupid, int flags,
             int *priv)
 {
@@ -3095,7 +3198,16 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
     int cpu = cpupid_to_cpu(cpupid);
     int i;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - first access시 grp를 만든다. @p의 값을 초기값으로 해서 생성한다.
+ *   ING
+ */
     if (unlikely(!deref_curr_numa_group(p))) {
+/*
+ * IAMROOT, 2023.06.24:
+ * - mem shared, mem priv, cpu shard, cpu priv 이렇게해서 4쌍
+ */
         unsigned int size = sizeof(struct numa_group) +
                     4*nr_node_ids*sizeof(unsigned long);
 
@@ -3109,9 +3221,17 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
         spin_lock_init(&grp->lock);
         grp->gid = p->pid;
         /* Second half of the array tracks nids where faults happen */
+/*
+ * IAMROOT, 2023.06.24:
+ * - faults 뒤에 address를 계산하여 faults_cpu에 넣는것.
+ */
         grp->faults_cpu = grp->faults + NR_NUMA_HINT_FAULT_TYPES *
                         nr_node_ids;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - task것을 초기값으로 가져온다.
+ */
         for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++)
             grp->faults[i] = p->numa_faults[i];
 
@@ -3122,11 +3242,24 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
     }
 
     rcu_read_lock();
+/*
+ * IAMROOT, 2023.06.24:
+ * - cpupid의 cpu에서 동작중인 task를 가져온다.
+ */
     tsk = READ_ONCE(cpu_rq(cpu)->curr);
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - 해당 page를 마지막에 접근했던 task와 page를 사용했던 cpu의 curr와
+ *   동일한지 비교한다.
+ */
     if (!cpupid_match_pid(tsk, cpupid))
         goto no_join;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - tsk(cpupid의 curr)의 ng가 없으면 return.
+ @*/
     grp = rcu_dereference(tsk->numa_group);
     if (!grp)
         goto no_join;
@@ -3139,16 +3272,28 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
      * Only join the other group if its bigger; if we're the bigger group,
      * the other task will join us.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - my_grp -> grp로 옮길려고한다. my_grp이 작은데 괜히 옮길 필욘 없을것이다.
+ */
     if (my_grp->nr_tasks > grp->nr_tasks)
         goto no_join;
 
     /*
      * Tie-break on the grp address.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - 같다면, grp가 address가 큰경우에만 움직인다.
+ */
     if (my_grp->nr_tasks == grp->nr_tasks && my_grp > grp)
         goto no_join;
 
     /* Always join threads in the same process. */
+/*
+ * IAMROOT, 2023.06.24:
+ * - 같은 process면 무조건 join
+ */
     if (tsk->mm == current->mm)
         join = true;
 
@@ -3159,6 +3304,10 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
     /* Update priv based on whether false sharing was detected */
     *priv = !join;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - grp로 get ref한다.
+ */
     if (join && !get_numa_group(grp))
         goto no_join;
 
@@ -3170,6 +3319,10 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
     BUG_ON(irqs_disabled());
     double_lock_irq(&my_grp->lock, &grp->lock);
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - @p(current)에 대한 값들을 my_group -> grp으로 옮긴다.
+ */
     for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) {
         my_grp->faults[i] -= p->numa_faults[i];
         grp->faults[i] += p->numa_faults[i];
@@ -3183,8 +3336,16 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags,
     spin_unlock(&my_grp->lock);
     spin_unlock_irq(&grp->lock);
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - 최종적으로 curr를 grp로 옮긴다.
+ */
     rcu_assign_pointer(p->numa_group, grp);
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - grp로 다 옮겨졌고, my_group은 ref down한다.
+ */
     put_numa_group(my_grp);
     return;
 
@@ -3236,6 +3397,10 @@ void task_numa_free(struct task_struct *p, bool final)
 /*
  * Got a PROT_NONE fault for a page on @node.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * -
+ */
 void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
 {
     struct task_struct *p = current;
@@ -3253,6 +3418,10 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
         return;
 
     /* Allocate buffer to track faults on a per-node basis */
+/*
+ * IAMROOT, 2023.06.24:
+ * - 최초 memory 할당.
+ */
     if (unlikely(!p->numa_faults)) {
         int size = sizeof(*p->numa_faults) *
                NR_NUMA_HINT_FAULT_BUCKETS * nr_node_ids;
@@ -3269,10 +3438,18 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
      * First accesses are treated as private, otherwise consider accesses
      * to be private if the accessing pid has not changed
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - first access는 priv 으로 처리.
+ */
     if (unlikely(last_cpupid == (-1 & LAST_CPUPID_MASK))) {
         priv = 1;
     } else {
         priv = cpupid_match_pid(p, last_cpupid);
+/*
+ * IAMROOT, 2023.06.24:
+ * - shared고, no group요청이 없엇으면 group화 한다.
+ */
         if (!priv && !(flags & TNF_NO_GROUP))
             task_numa_group(p, last_cpupid, flags, &priv);
     }
@@ -3283,6 +3460,19 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
      * actively using should be counted as local. This allows the
      * scan rate to slow down when a workload has settled down.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   워크로드가 여러 NUMA 노드에 걸쳐 있는 경우 워크로드가 적극적으로
+ *   사용하는 노드 세트 내에서 전적으로 발생하는 공유 fault은 로컬로
+ *   계산되어야 합니다. 이렇게 하면 워크로드가 안정되었을 때 스캔
+ *   속도가 느려질 수 있습니다.
+ *
+ * - shared fault가 local로 처리가 되야되는 경우에 대한 처리.
+ *   1. workload가 여러 numa node에 걸쳐있다.
+ *   2. active node가 많다.
+ *   3. 그중에서도 cpu node, mem node 둘다 활성화되있다.
+ */
     ng = deref_curr_numa_group(p);
     if (!priv && !local && ng && ng->active_nodes > 1 &&
                 numa_is_active_node(cpu_node, ng) &&
@@ -3293,6 +3483,14 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags)
      * Retry to migrate task to preferred node periodically, in case it
      * previously failed, or the scheduler moved us.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   이전에 실패했거나 스케줄러가 이동한 경우 주기적으로 작업을 기본
+ *   노드로 마이그레이션을 다시 시도하십시오.
+ * - 실패했을경우 이번에 다시 한번 한다는 개념인듯
+ * - ING
+ */
     if (time_after(jiffies, p->numa_migrate_retry)) {
         task_numa_placement(p);
         numa_migrate_preferred(p);
@@ -3344,6 +3542,13 @@ static void reset_ptenuma_scan(struct task_struct *p)
  * - papago
  *   numa 마이그레이션의 비용이 많이 드는 부분은 task_work 컨텍스트에서 수행됩니다.
  *   task_tick_numa()에서 트리거됩니다.
+ *
+ * - 1. next scan 시간 갱신
+ *   2. 이미 scan 중이라고 판단되면 return
+ *   3. scan 갯수만큼의 pages를 vma를 순회하며 numa fault 시킨다.
+ *   4. scan 완료 next scan offset 갱신
+ * - 이 함수에서 numa fault의해서 mapping해제된 page는 fault 발생시
+ *   handle_pte_fault()에서 do_numa_page()를 통해 수행할것이다.
  */
 static void task_numa_work(struct callback_head *work)
 {
@@ -3448,6 +3653,10 @@ static void task_numa_work(struct callback_head *work)
         start = 0;
         vma = mm->mmap;
     }
+/*
+ * IAMROOT, 2023.06.24:
+ * - vma를 순회하며 pages개수만큼 numa fault 시킨다.
+ */
     for (; vma; vma = vma->vm_next) {
 /*
  * IAMROOT, 2023.06.17:
@@ -3473,7 +3682,7 @@ static void task_numa_work(struct callback_head *work)
  * - papago
  *   여러 프로세스에 의해 매핑된 공유 라이브러리 페이지는 캐시 복제될 것으로 
  *   예상되므로 마이그레이션되지 않습니다. 읽기 전용 파일 지원 매핑 또는 
- *   vdso에서 힌트 결함을 피하십시오. 페이지를 마이그레이션하는 것이 약간의 
+ *   vdso에서 힌트 fault을 피하십시오. 페이지를 마이그레이션하는 것이 약간의 
  *   이점이 있을 것입니다.
  *
  * - library(readonly file)은 안한다. 주석내용확인.
@@ -3489,10 +3698,18 @@ static void task_numa_work(struct callback_head *work)
         if (!vma_is_accessible(vma))
             continue;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - HPAGE_SIZE단위로 ALIGN을 한 범위를 순회하며 numa fault시킨다.
+ */
         do {
             start = max(start, vma->vm_start);
             end = ALIGN(start + (pages << PAGE_SHIFT), HPAGE_SIZE);
             end = min(end, vma->vm_end);
+/*
+ * IAMROOT, 2023.06.24:
+ * - start ~ end까지 PAGE_NONE으로 numa fault식으로 update한다.
+ */
             nr_pte_updates = change_prot_numa(vma, start, end);
 
             /*
@@ -3511,11 +3728,15 @@ static void task_numa_work(struct callback_head *work)
  *   VMA에 사용되지 않았거나 이미 prot_numa PTE로 가득 찬 영역이 
  *   포함된 경우 해당 영역을 더 빨리 건너뛰려면 virtpages까지 
  *   스캔하십시오.
+ * - 남은것을 pages, virtpages에 기록한다.
  */
             if (nr_pte_updates)
                 pages -= (end - start) >> PAGE_SHIFT;
             virtpages -= (end - start) >> PAGE_SHIFT;
-
+/*
+ * IAMROOT, 2023.06.24:
+ * - 범위갱신
+ */
             start = end;
             if (pages <= 0 || virtpages <= 0)
                 goto out;
@@ -3559,6 +3780,7 @@ static void task_numa_work(struct callback_head *work)
  *   확인하십시오.
  *   일반적으로 update_task_scan_period는 스캔 속도를 충분히 늦춥니다. 
  *   오버로드된 시스템에서는 작업별로 오버헤드를 제한해야 합니다.
+ * - ex) numa fault하는 데 1초 걸렸으면, 최소 32초후에 하겠다는 의미.
  */
     if (unlikely(p->se.sum_exec_runtime != runtime)) {
         u64 diff = p->se.sum_exec_runtime - runtime;
@@ -3653,8 +3875,10 @@ void init_numa_balancing(unsigned long clone_flags, struct task_struct *p)
  * IAMROOT, 2023.06.17:
  * - callstack
  *   task_tick_fair() -> task_tick_numa()
+ *
  * - numa scan시간이 됬으면 task work(task_numa_work)를 add한다.
  *   즉 work수행요청.
+ * - numa balance time은 최대 task의 실행시간의 3%로 제한된다.
  */
 static void task_tick_numa(struct rq *rq, struct task_struct *curr)
 {
@@ -8847,7 +9071,7 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, bool
         /*
          * IAMROOT. 2023.06.10:
          * - google-translate
-         * 우리가 바쁘다면 마지막 유휴 기간이 미래를 예측한다는 가정에 결함이
+         * 우리가 바쁘다면 마지막 유휴 기간이 미래를 예측한다는 가정에 fault이
          * 있습니다. 남은 예상 유휴 시간을 에이징합니다.
          *
          * - 틱으로 wake_avg_idle을 반감시킨다.
@@ -16399,7 +16623,8 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued)
 
 /*
  * IAMROOT, 2023.06.17:
- * - numa balance
+ * - numa balance수행한다. 내부에서 numa balance시간이 도래했으면 수행하고 아니면
+ *   아무것도 안할것이다.
  */
     if (static_branch_unlikely(&sched_numa_balancing))
         task_tick_numa(rq, curr);
diff --git a/mm/memory.c b/mm/memory.c
index 865f113e9be8..62dcf6270c5d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4797,6 +4797,14 @@ static vm_fault_t do_fault(struct vm_fault *vmf)
     return ret;
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - local이면 이전이랑 같은 node에서 fault됬다는 의미이다.
+ *   TNF_FAULT_LOCAL를 표시한다.
+ *
+ * - @return NUMA_NO_NODE : 이전 node유지
+ *           != NUMA_NO_NODE : 추천 migrate node.
+ */
 int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
               unsigned long addr, int page_nid, int *flags)
 {
@@ -4811,6 +4819,11 @@ int numa_migrate_prep(struct page *page, struct vm_area_struct *vma,
     return mpol_misplaced(page, vma, addr);
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa fault(task_numa_work() 참고)
+ * - 
+ */
 static vm_fault_t do_numa_page(struct vm_fault *vmf)
 {
     struct vm_area_struct *vma = vmf->vma;
@@ -4827,7 +4840,18 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
      * validation through pte_unmap_same(). It's of NUMA type but
      * the pfn may be screwed if the read is non atomic.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   이때 pte는 pte_unmap_same()을 통한 유효성 검사 없이는 안전하게 
+ *   사용할 수 없습니다. NUMA 유형이지만 읽기가 원자적이지 않으면 
+ *   pfn이 망가질 수 있습니다.
+ */
     vmf->ptl = pte_lockptr(vma->vm_mm, vmf->pmd);
+/*
+ * IAMROOT, 2023.06.24:
+ * - lock을 걸어서 확인.
+ */
     spin_lock(vmf->ptl);
     if (unlikely(!pte_same(*vmf->pte, vmf->orig_pte))) {
         pte_unmap_unlock(vmf->pte, vmf->ptl);
@@ -4836,6 +4860,11 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
 
     /* Get the normal PTE  */
     old_pte = ptep_get(vmf->pte);
+/*
+ * IAMROOT, 2023.06.24:
+ * - fault를 시켜놨던 page다. 다시 정상으로 만들어주기 위해 원래의 prot로
+ *   원복을 시켜준다.
+ */
     pte = pte_modify(old_pte, vma->vm_page_prot);
 
     page = vm_normal_page(vma, vmf->address, pte);
@@ -4854,6 +4883,17 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
      * pte_dirty has unpredictable behaviour between PTE scan updates,
      * background writeback, dirty balancing and application behaviour.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   일반적으로 RO 페이지에서 그룹화하지 마십시오. RO 페이지는 공유 캐시 
+ *   상태에 있을 수 있으므로 어쨌든 많이 손상되지 않아야 합니다. 
+ *   이는 매핑이 쓰기 가능하지만 프로세스가 매핑에 쓰지 않지만 보호 
+ *   업데이트 중에 pte_write가 지워지고 pte_dirty가 PTE 스캔 업데이트, 
+ *   백그라운드 쓰기 저장, 더티 밸런싱 및 애플리케이션 동작 간에 예측할
+ *   수 없는 동작을 하는 경우를 놓치고 있습니다.
+ * - readonly page에서는 group하지 말라는것.
+ */
     if (!was_writable)
         flags |= TNF_NO_GROUP;
 
@@ -4861,13 +4901,28 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
      * Flag if the page is shared between multiple address spaces. This
      * is later used when determining whether to group tasks together
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   페이지가 여러 주소 공간 간에 공유되는 경우 플래그를 지정합니다.
+ *   이것은 나중에 작업을 함께 그룹화할지 여부를 결정할 때 사용됩니다. 
+ * - user가 여러명이다. shared page라는것을 표시한다.
+ */
     if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED))
         flags |= TNF_SHARED;
 
     last_cpupid = page_cpupid_last(page);
     page_nid = page_to_nid(page);
+/*
+ * IAMROOT, 2023.06.24:
+ * - mpol 및 fault count를 비교하여 추천 nid를 알아온다.
+ */
     target_nid = numa_migrate_prep(page, vma, vmf->address, page_nid,
             &flags);
+/*
+ * IAMROOT, 2023.06.24:
+ * - 이전 node 유지면 별거 안한다.
+ */
     if (target_nid == NUMA_NO_NODE) {
         put_page(page);
         goto out_map;
@@ -4876,12 +4931,24 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
 
     /* Migrate to the requested node */
     if (migrate_misplaced_page(page, vma, target_nid)) {
+/*
+ * IAMROOT, 2023.06.24:
+ * - migrate가 전부 성공
+ */
         page_nid = target_nid;
         flags |= TNF_MIGRATED;
     } else {
+/*
+ * IAMROOT, 2023.06.24:
+ * - migrate 실패(전부 실패 or 일부만 성공)
+ */
         flags |= TNF_MIGRATE_FAIL;
         vmf->pte = pte_offset_map(vmf->pmd, vmf->address);
         spin_lock(vmf->ptl);
+/*
+ * IAMROOT, 2023.06.24:
+ * - fault당시 pte와 현재 pte를 비교해서 변경이 생겼으면 out.
+ */
         if (unlikely(!pte_same(*vmf->pte, vmf->orig_pte))) {
             pte_unmap_unlock(vmf->pte, vmf->ptl);
             goto out;
@@ -4890,9 +4957,19 @@ static vm_fault_t do_numa_page(struct vm_fault *vmf)
     }
 
 out:
+/*
+ * IAMROOT, 2023.06.24:
+ * - 1. 
+ * - migrate를 성공했다면 page_nid는 target_nid,
+ *   아니라면 원래 자신의 nid를 가리킨다.
+ */
     if (page_nid != NUMA_NO_NODE)
         task_numa_fault(last_cpupid, page_nid, 1, flags);
     return 0;
+/*
+ * IAMROOT, 2023.06.24:
+ * - 아무것도 안하고 나가는겨ㅓㅇ우
+ */
 out_map:
     /*
      * Make it present again, depending on how arch implements
@@ -5056,13 +5133,23 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
 /*
  * IAMROOT, 2022.06.04:
  * - vmf->pte가 있지만 present가 안된. 즉 invalid. swap 상태라는의미.
+ * - 즉 mapping이 없는 상태.
  */
     if (!pte_present(vmf->orig_pte))
         return do_swap_page(vmf);
 
 /*
  * IAMROOT, 2022.06.04:
+ * - fault는 일반적으로 mapping이 없다. 하지만 이 이후는 mapping이 있어도
+ *   fault가 발생한 page들이다. 여기에 대한 case를 진행한다.
+ *   대표적으로 2개의 case가 있다.
+ *   1. numa fault
+ *   2. write protect
+ *
+ * - numa fault(task_numa_work() 참고)
  * - numa_balancing으로 fault가 발생한지 확인한다.
+ *   numa fault시 PTE_PROT_NONE으로 설정했었다. 그렇기 때문에 prot none인지
+ *   확인하는것이다.
  */
     if (pte_protnone(vmf->orig_pte) && vma_is_accessible(vmf->vma))
         return do_numa_page(vmf);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index aeccfb8b90b9..8b3941c2d946 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -649,7 +649,7 @@ static int queue_pages_hugetlb(pte_t *pte, unsigned long hmask,
  *
  *   이것은 NUMA fault가 PROT_NONE을 사용하여 처리된다고 가정합니다. 
  *   아키텍처가 다른 선택을 하면 코어에 추가 변경이 필요합니다.
- * - 
+ * - @addr ~ @end까지 numa fault방법(MM_CP_PROT_NUMA)으로 PAGE_NONE를 적용한다.
  */
 unsigned long change_prot_numa(struct vm_area_struct *vma,
             unsigned long addr, unsigned long end)
@@ -1951,7 +1951,7 @@ unsigned int mempolicy_slab_node(void)
  */
 /*
  * IAMROOT, 2022.05.14:
- * - @p에 따라 node를 선택한다.
+ * - @pol에 따라 node를 선택한다.
  */
 static unsigned offset_il_node(struct mempolicy *pol, unsigned long n)
 {
@@ -2563,6 +2563,30 @@ static void sp_free(struct sp_node *n)
  * Return: NUMA_NO_NODE if the page is in a node that is valid for this
  * policy, or a suitable node ID to allocate a replacement page from.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   mpol_misplaced - 현재 페이지 노드가 정책에서 유효한지 확인합니다.
+ *
+ *   @page: 확인할 페이지.
+ *   @vma: 페이지가 매핑된 vm 영역.
+ *   @addr: 페이지가 매핑된 가상 주소.
+ *
+ *   vma,addr에 대한 현재 정책 노드 ID를 조회하고 페이지의 노드 ID와 
+ *   비교합니다. 정책 결정은 alloc_page_vma()를 모방합니다.
+ *   vma 및 결함 주소를 알고 있는 결함 경로에서 호출됩니다. 
+ *
+ *   Return: 페이지가 이 정책에 유효한 노드에 있는 경우 NUMA_NO_NODE
+ *   또는 교체 페이지를 할당하는 데 적합한 노드 ID입니다.
+ *
+ * - return NUMA_NO_NODE : @vma의 mpol 정책에 유효한 상황. 이전 nid유지
+ *          특정 node    : @vma의 mpol에 적당한 node 번호.
+ * - mpol에 따른 node 번호를 가져온다.
+ * - 아래의 상황에따라 node를 선택한다.
+ *   1. 이전 node 유지(return NUMA_NO_NODE)
+ *   2. 특수한 상황 this node로 강제설정(MPOL_F_MORON이 있고, mpol, fault count비교등)
+ *   3. mpol에 따라 새로 선택한 node.
+ */
 int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long addr)
 {
     struct mempolicy *pol;
@@ -2575,9 +2599,26 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
     int ret = NUMA_NO_NODE;
 
     pol = get_vma_policy(vma, addr);
+/*
+ * IAMROOT, 2023.06.24:
+ * - MOF면 못옮긴다. 즉 그냥 써야된다. 그런 의미에서 현재 node가 유효하다는
+ *   의미로 return NUMA_NO_NODE.
+ */
     if (!(pol->flags & MPOL_F_MOF))
         goto out;
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - MPOL_F_MORON이 설정되있을경우(즉 thisnid로 강제설정 및 fault count 비교)
+ *   MPOL_INTERLEAVE     -> MPOL_F_MORON
+ *   MPOL_PREFERRED      -> 1. curnid가 pol에 소속 O -> curnid선택
+ *                          2. MPOL_F_MORON
+ *   MPOL_LOCAL          -> MPOL_F_MORON
+ *   MPOL_BIND           -> 1. thisnid가 pol에 소속 O -> MPOL_F_MORON
+ *                          2. NUMA_NO_NODE
+ *   MPOL_PREFERRED_MANY -> 1. curnid가 pol에 소속 O-> NUMA_NO_NODE
+ *                          2. MPOL_F_MORON
+ */
     switch (pol->mode) {
     case MPOL_INTERLEAVE:
         pgoff = vma->vm_pgoff;
@@ -2624,6 +2665,10 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
     }
 
     /* Migrate the page towards the node whose CPU is referencing it */
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa policy였을경우 위 MPOL에 상관없이 thisnid로 교체한다.
+ */
     if (pol->flags & MPOL_F_MORON) {
         polnid = thisnid;
 
@@ -2631,6 +2676,10 @@ int mpol_misplaced(struct page *page, struct vm_area_struct *vma, unsigned long
             goto out;
     }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - 그전에 있었던 node와 새로 구한 node가 일치지 않은 경우만 return값 갱신
+ */
     if (curnid != polnid)
         ret = polnid;
 out:
diff --git a/mm/migrate.c b/mm/migrate.c
index 11fc031394b8..7d49fc0e1666 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -2385,6 +2385,15 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
  * Returns true if this is a safe migration target node for misplaced NUMA
  * pages. Currently it only checks the watermarks which crude
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   잘못 배치된 NUMA 페이지에 대한 안전한 마이그레이션 대상 노드인 경우 
+ *   true를 반환합니다. 현재는 조잡한 워터마크만 확인합니다. 
+ *
+ * - @nr_migrate_pages만큼 migrate할 page가 있는지 확인한다. 있다면
+ *   return true.
+ */
 static bool migrate_balanced_pgdat(struct pglist_data *pgdat,
                    unsigned long nr_migrate_pages)
 {
@@ -2407,6 +2416,12 @@ static bool migrate_balanced_pgdat(struct pglist_data *pgdat,
     return false;
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - migrate_misplaced_page() 참고
+ * - @nid에서만 할당. movable(user용 memory) page할당. reclaim 및 retry
+ *   할필요없음등의 조건을 사용하여 할당을 받아온다.
+ */
 static struct page *alloc_misplaced_dst_page(struct page *page,
                        unsigned long data)
 {
@@ -2422,6 +2437,10 @@ static struct page *alloc_misplaced_dst_page(struct page *page,
     return newpage;
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - PASS
+ */
 static struct page *alloc_misplaced_dst_page_thp(struct page *page,
                          unsigned long data)
 {
@@ -2439,6 +2458,13 @@ static struct page *alloc_misplaced_dst_page_thp(struct page *page,
     return newpage;
 }
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - lru list에서 @page를 isolate한다.
+ *
+ * - return 0 : isolate 실패
+ *          1 : isolate성공.
+ */
 static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
 {
     int page_lru;
@@ -2466,6 +2492,12 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
      * caller's reference can be safely dropped without the page
      * disappearing underneath us during migration.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   페이지를 분리하면 다른 참조가 있으므로 마이그레이션 중에 페이지가
+ *   사라지지 않고 호출자의 참조를 안전하게 삭제할 수 있습니다.
+ */
     put_page(page);
     return 1;
 }
@@ -2475,6 +2507,15 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page)
  * node. Caller is expected to have an elevated reference count on
  * the page that will be dropped by this function before returning.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   잘못 배치된 페이지를 지정된 대상 노드로 마이그레이션하려고 
+ *   시도합니다. 호출자는 반환하기 전에 이 함수에 의해 삭제될 
+ *   페이지에서 높은 참조 횟수를 가질 것으로 예상됩니다.
+ *
+ * - lru page에서 isolate후 @node로 migrate한다.
+ */
 int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
                int node)
 {
@@ -2491,6 +2532,13 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
      * be either base page or THP.  And it must be head page if it is
      * THP.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   PTE 매핑된 THP 또는 HugeTLB 페이지는 여기에 도달할 수 없으므로
+ *   페이지는 기본 페이지 또는 THP일 수 있습니다. 그리고 THP라면 반드시
+ *   헤드페이지여야 합니다.
+ */ 
     compound = PageTransHuge(page);
 
     if (compound)
@@ -2502,6 +2550,13 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
      * Don't migrate file pages that are mapped in multiple processes
      * with execute permissions as they are probably shared libraries.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   실행 권한이 있는 여러 프로세스에서 매핑된 파일 페이지는 아마도 
+ *   공유 라이브러리일 수 있으므로 마이그레이션하지 마십시오.
+ * - 실행가능한 공유라이브러리는 옮기지 않는다.
+ */
     if (page_mapcount(page) != 1 && page_is_file_lru(page) &&
         (vma->vm_flags & VM_EXEC))
         goto out;
@@ -2510,6 +2565,14 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
      * Also do not migrate dirty pages as not all filesystems can move
      * dirty pages in MIGRATE_ASYNC mode which is a waste of cycles.
      */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   또한 모든 파일 시스템이 순환 낭비인 MIGRATE_ASYNC 모드에서
+ *   더티 페이지를 이동할 수 있는 것은 아니므로 더티 페이지를
+ *   마이그레이션하지 마십시오.
+ * - 쓰기 기록중인 file page는 옮기지 않는다.
+ */
     if (page_is_file_lru(page) && PageDirty(page))
         goto out;
 
@@ -2520,6 +2583,11 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
     list_add(&page->lru, &migratepages);
     nr_remaining = migrate_pages(&migratepages, *new, NULL, node,
                      MIGRATE_ASYNC, MR_NUMA_MISPLACED, NULL);
+/*
+ * IAMROOT, 2023.06.24:
+ * - migrate 못한것들은 원래 있던 lru로 복귀 시킨다.
+ *   일부만 성공했을경우 실패로 간주한다.
+ */
     if (nr_remaining) {
         if (!list_empty(&migratepages)) {
             list_del(&page->lru);
diff --git a/mm/mmzone.c b/mm/mmzone.c
index 6685914eef24..ff33ba41d5a3 100644
--- a/mm/mmzone.c
+++ b/mm/mmzone.c
@@ -95,6 +95,10 @@ void lruvec_init(struct lruvec *lruvec)
 }
 
 #if defined(CONFIG_NUMA_BALANCING) && !defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS)
+/*
+ * IAMROOT, 2023.06.24:
+ * - @cpupid로 교체하면서 oldcpuid를 가져온다.
+ */
 int page_cpupid_xchg_last(struct page *page, int cpupid)
 {
     unsigned long old_flags, flags;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 82d0b941c8ea..9eebd7c11665 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -40,6 +40,10 @@
  * - numa fault page 전환인 경우(change_prot_numa() 확인)
  *   @cp_flags  MM_CP_PROT_NUMA.
  *   @newprot PAGE_NONE
+ *   @addr부터 @end까지에 대해 다음을 처리한다.
+ *   1. old를 가져오면서 0 clear를 한다.(modify중 잠깐)
+ *   2. hw dirty가 발생했을경우 sw dirty를 기록해준다.
+ *   3. @newprot(PTE_PROT_NONE)를 설정해준다.(기존 oldpte중에 일부 bit는 가져온다.)
  */
 static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
         unsigned long addr, unsigned long end, pgprot_t newprot,
@@ -94,6 +98,13 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
     flush_tlb_batched_pending(vma->vm_mm);
     arch_enter_lazy_mmu_mode();
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa fault인 경우
+ *  1. old를 가져오면서 0 clear를 한다.
+ *  2. hw dirty가 발생했을경우 sw dirty를 기록해준다.
+ *  3. @newprot(PTE_PROT_NONE)중 pte_modity()의 mask에 해당하는 부분들을 old에서 update한다.
+ */
     do {
         oldpte = *pte;
 /*
@@ -177,14 +188,29 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
 
 /*
  * IAMROOT, 2023.06.17:
- * - old를 가져오면서 0clear를 한다.
- * - ING
+ * - old를 가져오면서 0 clear를 한다.
  */
             oldpte = ptep_modify_prot_start(vma, addr, pte);
+/*
+ * IAMROOT, 2023.06.24:
+ * - mask (PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | 
+ *   PTE_PROT_NONE | PTE_VALID | PTE_WRITE | PTE_GP |
+ *   PTE_ATTRINDX_MASK)에서 @newprot에 포함된것들을 oldpte에
+ *   추가해서 가져온다. 그리고 oldpte가 hw dirty라면 sw dirty를
+ *   추가한다.
+ */
             ptent = pte_modify(oldpte, newprot);
+/*
+ * IAMROOT, 2023.06.24:
+ * - numa fault면서 hw dirty였으면 rdonly를 지우는 개념으로 해준다.
+ */
             if (preserve_write)
                 ptent = pte_mk_savedwrite(ptent);
 
+/*
+ * IAMROOT, 2023.06.24:
+ * - uffd pass
+ */
             if (uffd_wp) {
                 ptent = pte_wrprotect(ptent);
                 ptent = pte_mkuffd_wp(ptent);
@@ -199,11 +225,19 @@ static unsigned long change_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
             }
 
             /* Avoid taking write faults for known dirty pages */
+/*
+ * IAMROOT, 2023.06.24:
+ * - dirty account pass
+ */
             if (dirty_accountable && pte_dirty(ptent) &&
                     (pte_soft_dirty(ptent) ||
                      !(vma->vm_flags & VM_SOFTDIRTY))) {
                 ptent = pte_mkwrite(ptent);
             }
+/*
+ * IAMROOT, 2023.06.24:
+ * - pte에 ptent를 최종적으로 기록한다.
+ */
             ptep_modify_prot_commit(vma, addr, pte, oldpte, ptent);
             pages++;
         } else if (is_swap_pte(oldpte)) {
@@ -288,7 +322,7 @@ static inline int pmd_none_or_clear_bad_unless_trans_huge(pmd_t *pmd)
 
 /*
  * IAMROOT, 2023.06.17:
- * - 
+ * - pte를 순회한다.
  */
 static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
         pud_t *pud, unsigned long addr, unsigned long end,
@@ -372,7 +406,7 @@ static inline unsigned long change_pmd_range(struct vm_area_struct *vma,
 
 /*
  * IAMROOT, 2023.06.17:
- * - 
+ * - pmd를 순회한다.
  */
 static inline unsigned long change_pud_range(struct vm_area_struct *vma,
         p4d_t *p4d, unsigned long addr, unsigned long end,
@@ -396,7 +430,7 @@ static inline unsigned long change_pud_range(struct vm_area_struct *vma,
 
 /*
  * IAMROOT, 2023.06.17:
- * - 
+ * - pud를 순회한다
  */
 static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
         pgd_t *pgd, unsigned long addr, unsigned long end,
@@ -420,7 +454,7 @@ static inline unsigned long change_p4d_range(struct vm_area_struct *vma,
 
 /*
  * IAMROOT, 2023.06.17:
- * - 
+ * - p4d를 순회한다.
  */
 static unsigned long change_protection_range(struct vm_area_struct *vma,
         unsigned long addr, unsigned long end, pgprot_t newprot,
@@ -454,7 +488,7 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
 
 /*
  * IAMROOT, 2023.06.17:
- * - 
+ * - @start ~ @end까지 @newprot를 적용한다.
  */
 unsigned long change_protection(struct vm_area_struct *vma, unsigned long start,
                unsigned long end, pgprot_t newprot,
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 20265b0a24bb..7e370330f2e3 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2617,6 +2617,34 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
  * (2) the lru_lock must not be held.
  * (3) interrupts must be enabled.
  */
+/*
+ * IAMROOT, 2023.06.24:
+ * - papago
+ *   isolate_lru_page - LRU 목록에서 페이지를 분리하려고 시도합니다.
+ *   @page: LRU 목록에서 격리할 페이지
+ *
+ *   LRU 목록에서 @page를 분리하고 PageLRU를 지우고 페이지가 있던
+ *   LRU 목록에 해당하는 vmstat 통계를 조정합니다.
+ *
+ *   페이지가 LRU 목록에서 제거된 경우 0을 반환합니다.
+ *   페이지가 LRU 목록에 없으면 -EBUSY를 반환합니다.
+ *
+ *   반환된 페이지는 PageLRU()가 지워집니다. 활성 목록에서 찾은 경우
+ *   PageActive가 설정됩니다. 제거할 수 없는 목록에서 찾은 경우
+ *   PageUnevictable 비트가 설정됩니다. 해당 플래그는 페이지를
+ *   이동하기 전에 호출자가 지워야 할 수 있습니다.
+ *
+ *   페이지가 발견된 목록에 해당하는 vmstat 통계가 감소합니다.
+ *
+ *   제한:
+ *   (1) 페이지에서 높은 refcount로 호출해야 합니다. 이것은
+ *   isolate_lru_pages(안정적인 참조 없이 호출됨)와 근본적인 차이점입니다.
+ *   (2) lru_lock을 보유하지 않아야 합니다.
+ *   (3) 인터럽트를 활성화해야 합니다.
+ * - lru list에서 page를 분리한다.
+ *
+ *   return 0 : lru page에서 삭제 성공.
+ */
 int isolate_lru_page(struct page *page)
 {
     int ret = -EBUSY;
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 627
228 [커널 20차] 20주차 [2] 이민찬 2023.09.17 182
227 [커널 20차] 19주차 이민찬 2023.09.10 103
226 [커널 20차] 18주차 이민찬 2023.09.03 85
225 [커널 20차] 17주차 이민찬 2023.08.27 129
224 [커널 20차] 16주차 이민찬 2023.08.20 132
223 [커널 19차] 64 주차 Min 2023.08.19 91
222 [커널 20차] 15주차 이민찬 2023.08.13 126
221 [커널 19차] 63 주차 Min 2023.08.12 60
220 [커널 19차] 62 주차 Min 2023.08.05 79
219 [커널 20차] 13주차 이민찬 2023.07.30 106
218 [커널 19차] 61 주차 Min 2023.07.30 45
217 [커널 20차] 12주차 이민찬 2023.07.22 87
216 [커널 19차] 59 ~ 60 주차 Min 2023.07.22 37
215 [커널 18차] 113주차 kkr 2023.07.22 78
214 [커널20차] 11주차 이경재 2023.07.15 86
213 [커널20차] 10주차 이경재 2023.07.09 90
212 [커널20차] 9주차 이경재 2023.07.02 85
211 [커널 19차] 58 주차 Min 2023.07.01 41
210 [커널 19차] 56 ~ 57 주차 Min 2023.06.25 40
» [커널 18차] 109주차 kkr 2023.06.24 33
XE Login