[커널 18차] 54주차
2022.06.04 22:16
git : https://github.com/iamroot18/5.10/commit/24e45c907359ac476d61210dc26d32493bd9b030
diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
index e3e28f7daf62..b244001b9c4e 100644
--- a/arch/arm64/include/asm/mman.h
+++ b/arch/arm64/include/asm/mman.h
@@ -35,6 +35,10 @@ static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
}
#define arch_calc_vm_flag_bits(flags) arch_calc_vm_flag_bits(flags)
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vm_flags에 더 추가할 arch prot flags가 있으면 추가한다.
+ */
static inline pgprot_t arch_vm_get_page_prot(unsigned long vm_flags)
{
pteval_t prot = 0;
@@ -74,6 +78,10 @@ static inline bool arch_validate_prot(unsigned long prot,
}
#define arch_validate_prot(prot, addr) arch_validate_prot(prot, addr)
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vm_flags validate 검사.
+ */
static inline bool arch_validate_flags(unsigned long vm_flags)
{
if (!system_supports_mte())
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 70e69efd6c6c..1fc7fb41d3a0 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -257,6 +257,10 @@
/*
* Level 3 descriptor (PTE).
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - hardware mapping이 되있는지 확인.
+ */
#define PTE_VALID (_AT(pteval_t, 1) << 0)
#define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0)
#define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 8dc627583876..d1cf47554d58 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -15,8 +15,18 @@
*/
#define PTE_WRITE (PTE_DBM) /* same as DBM (51) */
#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - TODO
+ * 특수하게 관리한다. (zero page등)
+ */
#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
#define PTE_DEVMAP (_AT(pteval_t, 1) << 57)
+/*
+ * IAMROOT, 2022.06.04:
+ * - PTE_PROT_NONE : numa fault인지 여부.
+ */
#define PTE_PROT_NONE (_AT(pteval_t, 1) << 58) /* only when !PTE_VALID */
/*
@@ -84,6 +94,12 @@ extern bool arm64_use_ng_mappings;
__val; \
})
+/*
+ * IAMROOT, 2022.06.04:
+ * - PTE_PXN : kernel 공간에서 실행 불가
+ * PTE_UXN : user 공간에서 실행 불가.
+ * PTE_NG : not global. 다른 cpu core에서도 mapping을 사용안하겠다는것.
+ */
#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
/* shared+writable pages are clean by default, hence PTE_RDONLY|PTE_WRITE */
#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 40ff1acb6d27..841f99e0849a 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -81,6 +81,10 @@
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page.
+ */
extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
#define ZERO_PAGE(vaddr) phys_to_page(__pa_symbol(empty_zero_page))
@@ -123,6 +127,10 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
/*
* The following only work if pte_present(). Undefined behaviour otherwise.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - hardware mapping이나 numa fault가 되있으면 mapping이 됬다는것을 의미한다.
+ */
#define pte_present(pte) (!!(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)))
#define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
#define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
@@ -215,6 +223,10 @@ static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot)
return pmd;
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - @pte에 PTE_WRITE를 set한다.
+ */
static inline pte_t pte_mkwrite(pte_t pte)
{
pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -230,6 +242,10 @@ static inline pte_t pte_mkclean(pte_t pte)
return pte;
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - @pte에 PTE_DIRTY bit를 set한다.
+ */
static inline pte_t pte_mkdirty(pte_t pte)
{
pte = set_pte_bit(pte, __pgprot(PTE_DIRTY));
@@ -259,6 +275,11 @@ static inline pte_t pte_mkold(pte_t pte)
return clear_pte_bit(pte, __pgprot(PTE_AF));
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - ARM8.0까지는 software적으로 af flag를 설정해줘야되고, 8.1은 hardware
+ * 적으로 해준다.
+ */
static inline pte_t pte_mkyoung(pte_t pte)
{
return set_pte_bit(pte, __pgprot(PTE_AF));
@@ -474,6 +495,10 @@ static inline pgprot_t mk_pmd_sect_prot(pgprot_t prot)
/*
* See the comment in include/linux/pgtable.h
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - numa balancing으로 인해서 fault가 발생한 상태.
+ */
static inline int pte_protnone(pte_t pte)
{
return (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) == PTE_PROT_NONE;
@@ -1190,11 +1215,24 @@ static inline bool arch_wants_old_prefaulted_pte(void)
}
#define arch_wants_old_prefaulted_pte arch_wants_old_prefaulted_pte
+/*
+ * IAMROOT, 2022.06.04:
+ * - system등에 따라 @prot 변경 여부를 반영한다.
+ */
static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
{
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - Enhanced Privileged Access Never
+ */
if (cpus_have_const_cap(ARM64_HAS_EPAN))
return prot;
+/*
+ * IAMROOT, 2022.06.04:
+ * - PAGE_EXECONLY -> PAGE_READONLY_EXEC로 변경.
+ */
if (pgprot_val(prot) != pgprot_val(PAGE_EXECONLY))
return prot;
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c
index 31c4bb332c05..1dbd51918b25 100644
--- a/arch/arm64/kernel/sys.c
+++ b/arch/arm64/kernel/sys.c
@@ -54,6 +54,10 @@
*
* read, write 권한이 있는 vma라는것을 알수있다.
* malloc을 호출하면 항상 위와같은 prot, flag를 사용한다.
+ *
+ * - 최종적으로 vma가 새로 생길시 다음과 같은 flag로 완성된다.
+ * VmFlags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE |
+ * VM_MAYEXEC | VM_ACCOUNT | VM_SOFTDIRTY
*/
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index c1eb47753650..d67c4b9403c2 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -51,6 +51,10 @@ void copy_highpage(struct page *to, struct page *from)
}
EXPORT_SYMBOL(copy_highpage);
+/*
+ * IAMROOT, 2022.06.04:
+ * - from을 to로 복사후 PG_dcache_clean bit clear
+ */
void copy_user_highpage(struct page *to, struct page *from,
unsigned long vaddr, struct vm_area_struct *vma)
{
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index f095016edcbf..d1c152666a43 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -194,6 +194,11 @@ static void show_pte(unsigned long addr)
*
* Returns whether or not the PTE actually changed.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - af flag를 set한다. ARM8.1의 경우 자동 기록이 되므로 pte_same을통해서
+ * skip된다.
+ */
int ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep,
pte_t entry, int dirty)
@@ -201,6 +206,10 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
pteval_t old_pteval, pteval;
pte_t pte = READ_ONCE(*ptep);
+/*
+ * IAMROOT, 2022.06.04:
+ * - hardware에서 af를 기록했을수도있다. 같으면 skip.
+ */
if (pte_same(pte, entry))
return 0;
@@ -220,6 +229,11 @@ int ptep_set_access_flags(struct vm_area_struct *vma,
pteval ^= PTE_RDONLY;
pteval |= pte_val(entry);
pteval ^= PTE_RDONLY;
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - atomic 기록.
+ */
pteval = cmpxchg_relaxed(&pte_val(*ptep), old_pteval, pteval);
} while (pteval != old_pteval);
@@ -919,6 +933,11 @@ NOKPROBE_SYMBOL(do_debug_exception);
/*
* Used during anonymous page fault handling.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - anon page의 write fault으로 인해 0으로 초기화된 사용자 메모리를
+ * 할당한다.
+ */
struct page *alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,
unsigned long vaddr)
{
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
index 2aaf950b906c..fa4d8275a97d 100644
--- a/arch/arm64/mm/flush.c
+++ b/arch/arm64/mm/flush.c
@@ -66,6 +66,10 @@ EXPORT_SYMBOL_GPL(__sync_icache_dcache);
* it as dirty for later flushing when mapped in user space (if executable,
* see __sync_icache_dcache).
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - PG_dcache_clean bit을 clear한다.
+ */
void flush_dcache_page(struct page *page)
{
if (test_bit(PG_dcache_clean, &page->flags))
diff --git a/include/linux/highmem-internal.h b/include/linux/highmem-internal.h
index da3723c960c7..42001f186d17 100644
--- a/include/linux/highmem-internal.h
+++ b/include/linux/highmem-internal.h
@@ -88,6 +88,10 @@ static inline void __kunmap_local(void *vaddr)
kunmap_local_indexed(vaddr);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * return page_address(page);
+ */
static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
{
if (IS_ENABLED(CONFIG_PREEMPT_RT))
@@ -99,6 +103,14 @@ static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
return __kmap_local_page_prot(page, prot);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * 32bit에서는 kmap공간을 이용해서 highmem영역을 mapping하고 접근하지만
+ * 64bit에서는 이미 linear mapping이 전부 되있기때문에 별도의 mapping을
+ * 하지 않고 즉시 접근할수있다.
+ *
+ * return page_address(page);
+ */
static inline void *kmap_atomic(struct page *page)
{
return kmap_atomic_prot(page, kmap_prot);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index de268e6571e4..480d688db1a9 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -139,6 +139,15 @@ extern int mmap_rnd_compat_bits __read_mostly;
* s390 does this to prevent multiplexing of hardware bits
* related to the physical page in case of virtualization.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - papgo
+ * 읽기 오류에 대해 0 페이지 매핑을 설정하는 일반적인 메모리 관리
+ * 코드를 방지합니다.
+ * 이 매크로는 <asm/pgtable> 내에 정의되어야 합니다.
+ * s390은 가상화 시 물리적 페이지와 관련된 하드웨어 비트의 다중화를
+ * 방지하기 위해 이를 수행한다.
+ */
#ifndef mm_forbids_zeropage
#define mm_forbids_zeropage(X) (0)
#endif
@@ -685,6 +694,10 @@ struct vm_operations_struct {
unsigned long addr);
};
+/*
+ * IAMROOT, 2022.06.04:
+ * - 기본초기화.
+ */
static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
{
static const struct vm_operations_struct dummy_vm_ops = {};
@@ -695,6 +708,11 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)
INIT_LIST_HEAD(&vma->anon_vma_chain);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - anon일경우 ops를 null로 한다. 최초 init일때는 dummy_vm_ops와 연결되
+ * 있었을것이다.
+ */
static inline void vma_set_anonymous(struct vm_area_struct *vma)
{
vma->vm_ops = NULL;
@@ -2413,6 +2431,10 @@ static inline void pgtable_pte_page_dtor(struct page *page)
dec_lruvec_page_state(page, NR_PAGETABLE);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - @pmd page에서 ptl을 spinlock 걸면서 pte를 return한다.
+ */
#define pte_offset_map_lock(mm, pmd, address, ptlp) \
({ \
spinlock_t *__ptl = pte_lockptr(mm, pmd); \
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index eea1188203d3..1cfae2931135 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -106,6 +106,8 @@ struct page {
* IAMROOT, 2022.02.05:
* - pcpu에서 사용하는 경우 : 해당 struct page에 대항하는 struct pcpu_chunk가 set된다.
* - buddy에서 사용하는경우 : migratetype
+ * - anon으로 사용하는 경우 : page가 속한 vma내에서의
+ * pgoff(__page_set_anon_rmap() 참고)
*/
pgoff_t index; /* Our offset within mapping. */
/**
@@ -416,6 +418,15 @@ struct vm_userfaultfd_ctx {};
* space that has a special rule for the page-fault handlers (ie a shared
* library, the executable area etc).
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * ex) vm_start = 0x1000, len = 4k라면
+ * vm_end(vm_start + len) = 0x2000
+ * -----+
+ * vma |
+ * -----+ vm_start = 0x1000
+ */
struct vm_area_struct {
/* The first cache line has the info for VMA tree walking. */
@@ -485,6 +496,11 @@ struct vm_area_struct {
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
/* Function pointers to deal with this struct. */
+/*
+ * IAMROOT, 2022.06.04:
+ * - 최초 초기화시 dummy로 연결되있다.(vma_init() 참고)
+ * - anon일 경우 null(vma_set_anonymous() 참고)
+ */
const struct vm_operations_struct *vm_ops;
/* Information about our backing store: */
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 94a095d02e03..6396174c24aa 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -119,6 +119,23 @@ static inline bool mm_is_oom_victim(struct mm_struct *mm)
*
* Return 0 when the PF is safe VM_FAULT_SIGBUS otherwise.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - papgo
+ * 지정된 mm의 페이지 결함이 여전히 신뢰할 수 있는지 확인합니다.
+ * 만약 oom reaper가 mm에 설정된 MMF_UNSTABLE 플래그에 의해 반영되는
+ * 주소 공간을 수집하기 시작했다면 이것은 더 이상 사실이 아니다. 이 때
+ * !shared 매핑은 내용을 잃어버리고 메모리 손상을 일으킬 수 있습니다
+ * (원래 내용 대신 0페이지).
+ *
+ * 사용자는 !shared 매핑에 대한 페이지 테이블 항목을 설정하기 전에
+ * 적절한 페이지 테이블 잠금 아래에서 이 항목을 호출해야 합니다.
+ *
+ * 그렇지 않으면 PF가 안전한 VM_FAULT_SIGBUS일 때 0을 반환한다.
+ *
+ * - oom 진행중인 @mm인 경우 MMF_UNSTABLE이 set되있을것이다.
+ * (__oom_reap_task_mm() 참고)
+ */
static inline vm_fault_t check_stable_address_space(struct mm_struct *mm)
{
if (unlikely(test_bit(MMF_UNSTABLE, &mm->flags)))
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 101ed57cc72f..1c26570de016 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -579,6 +579,12 @@ PAGEFLAG(XenRemapped, xen_remapped, PF_NO_COMPOUND)
PAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
__CLEARPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
__SETPAGEFLAG(Reserved, reserved, PF_NO_COMPOUND)
+/*
+ * IAMROOT, 2022.06.04:
+ * - anon page들은 일반적으로 만들어질때 SwapBacked가 set된다.
+ * (page_add_new_anon_rmap() 참고)
+ * clean anon일 경우 flag가 제거된다.
+ */
PAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL)
__CLEARPAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL)
__SETPAGEFLAG(SwapBacked, swapbacked, PF_NO_TAIL)
@@ -794,6 +800,10 @@ static inline int PageUptodate(struct page *page)
return ret;
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - 최근에 page를 갱신했다는 flag.
+ */
static __always_inline void __SetPageUptodate(struct page *page)
{
VM_BUG_ON_PAGE(PageTail(page), page);
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index b03012e0b632..8420f9d0c78e 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -524,6 +524,19 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
* To be differentiate with macro pte_mkyoung, this macro is used on platforms
* where software maintains page access bit.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * -papago
+ * 일부 아키텍처에서는 메모리 페이지에 액세스할 때 하드웨어가 페이지
+ * 액세스 비트를 설정하지 않으며, 소프트웨어가 이 비트를 설정하는 것이
+ * 책임입니다. 페이지 액세스 비트를 추적하기 위해 추가적인 페이지 폴트
+ * 패널티를 발생시킨다. 페이지 최적화를 위해 액세스 비트는 이러한
+ * 아치의 모든 페이지 오류 흐름 중에 설정할 수 있습니다.
+ * macro pte_mkyoung과 차별화하기 위해, 이 매크로는 소프트웨어가 페이지
+ * 액세스 비트를 유지하는 플랫폼에서 사용된다.
+ *
+ * - mips에서만 사용
+ */
#ifndef pte_sw_mkyoung
static inline pte_t pte_sw_mkyoung(pte_t pte)
{
@@ -1030,6 +1043,10 @@ static inline void ptep_modify_prot_commit(struct vm_area_struct *vma,
#ifdef CONFIG_MMU
#ifndef pgprot_modify
#define pgprot_modify pgprot_modify
+/*
+ * IAMROOT, 2022.06.04:
+ * - @oldprot의 cache속성대로 @newprot에 cache속성을 대입한다.
+ */
static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
{
if (pgprot_val(oldprot) == pgprot_val(pgprot_noncached(oldprot)))
@@ -1239,6 +1256,10 @@ static inline int is_zero_pfn(unsigned long pfn)
return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page pfn을 가져온다.
+ */
#define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr))
#else
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index e79cc927b0f9..e2c87be3ef66 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -27,6 +27,10 @@
* pointing to this anon_vma once its vma list is empty.
*/
struct anon_vma {
+/*
+ * IAMROOT, 2022.06.04:
+ * - 최초생성시 root는 자기자신.
+ */
struct anon_vma *root; /* Root of this anon_vma tree */
struct rw_semaphore rwsem; /* W: modification, R: walking the list */
/*
@@ -44,8 +48,16 @@ struct anon_vma {
* This counter is used for making decision about reusing anon_vma
* instead of forking new one. See comments in function anon_vma_clone.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - 최초 할당시 1로 시작한ㄷ.(anon_vma_alloc() 참고)
+ */
unsigned degree;
+/*
+ * IAMROOT, 2022.06.04:
+ * - 최초 할당시 parent는 자기자신.
+ */
struct anon_vma *parent; /* Parent of this anon_vma */
/*
@@ -192,6 +204,11 @@ void unlink_anon_vmas(struct vm_area_struct *);
int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vma가 av이면 prepare가 필요없다.
+ * reuse가능한 av를 찾거나 av를 할당하고 vma에 연결한다.
+ */
static inline int anon_vma_prepare(struct vm_area_struct *vma)
{
if (likely(vma->anon_vma))
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index ac0394087f7d..5ef47fa24296 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -95,6 +95,10 @@ static inline void force_uaccess_end(mm_segment_t oldfs)
* as usual) and both source and destination can trigger faults.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - user영역(@from)을 kernel영역(@to)에 복사한다.
+ */
static __always_inline __must_check unsigned long
__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
{
diff --git a/kernel/fork.c b/kernel/fork.c
index 69364b5dfe7a..fb567db57b97 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -342,6 +342,10 @@ static struct kmem_cache *vm_area_cachep;
/* SLAB cache for mm_struct structures (tsk->mm) */
static struct kmem_cache *mm_cachep;
+/*
+ * IAMROOT, 2022.06.04:
+ * - @mm에 추가할 vma를 하나 생성한다.
+ */
struct vm_area_struct *vm_area_alloc(struct mm_struct *mm)
{
struct vm_area_struct *vma;
diff --git a/mm/highmem.c b/mm/highmem.c
index 74df99a370e7..d69452f31634 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -536,6 +536,10 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot)
}
EXPORT_SYMBOL_GPL(__kmap_local_pfn_prot);
+/*
+ * IAMROOT, 2022.06.04:
+ * - arm64경우 highmem이 없으므로 page_address(page)로 바로 직행할것이다.
+ */
void *__kmap_local_page_prot(struct page *page, pgprot_t prot)
{
void *kmap;
diff --git a/mm/memory.c b/mm/memory.c
index 362aee2c067e..7d1250c81605 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -607,18 +607,73 @@ static void print_bad_pte(struct vm_area_struct *vma, unsigned long addr,
* PFNMAP mappings in order to support COWable mappings.
*
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - papgo
+ * vm_normal_page - 이 함수는 a pte와 연결된 "struct page"를 가져옵니다.
+ *
+ * "special" 매핑은 "struct page"와 연관되는 것을 원하지 않습니다
+ * (struct page가 존재하지 않거나 존재하지만 터치하기를 원하지 않습니다).
+ * 이 경우 NULL이 반환됩니다. "일반" 매핑에는 struct page가 있습니다.
+ *
+ * 두 가지 광범위한 사례가 있습니다. 첫째로, 아키텍처는 a pte_special()
+ * pte 비트를 정의할 수 있는데, 이 경우 이 함수는 사소하다. 둘째로,
+ * 아키텍처는 예비 pte 비트를 갖지 않을 수 있으며, 이는 아래에서 설명되는
+ * 더 복잡한 체계를 필요로 한다.
+ *
+ * 원시 VM_PFNMAP 매핑(즉, COWed가 아닌 매핑)은 항상 특수 매핑으로
+ * 간주됩니다(기본 및 유효한 "struct page"가 있더라도).
+ * VM_PFNMAP의 COWed 페이지는 항상 정상입니다.
+ *
+ * VM_PFNMAP 매핑 내에서 COWed 페이지를 인식하는 방법은
+ * "remap_pfn_range()"에서 설정한 규칙을 통해 다음과 같이 인식합니다.
+ * vma는 VM_PFNMAP 비트를 설정하고 vm_pgoff는 매핑된 첫 번째 PFN을
+ * 가리킵니다.
+ * 따라서 모든 특수 매핑은 항상 규
+ * pfn_of_page == vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT)
+ * 를 준수합니다. 일반 매핑의 경우 이는 false입니다.
+ *
+ * 이렇게 하면 이러한 매핑이 가상 주소에서 PFN으로 선형 변환되는 것으로
+ * 제한됩니다. 이 제한을 피하기 위해 vma가 COW 매핑이 아닌 한 임의 매핑을
+ * 허용한다. 이 경우 모든 pte가 특별하다는 것을 안다(COWed가 될 수 없기
+ * 때문이다).
+ *
+ * 임의 특수 매핑의 COW를 지원하기 위해 VM_MIXEDMAP이 있습니다.
+ *
+ * VM_MIXEDMAP 매핑도 마찬가지로 "struct page" 백업이 있든 없든 메모리를
+ * 포함할 수 있지만, 차이점은 struct page가 있는 _all_ 페이지
+ * (즉, pfn_valid가 true인 페이지)가 리카운트되고 VM에서 일반 페이지로
+ * 간주된다는 점입니다. 단점은 페이지 카운트가 재설정된다는 것이다
+ * (이것은 더 느릴 수 있고 일부 PFNMAP 사용자에게는 옵션이 아닐 수 있다).
+ * 장점은 COWable 매핑을 지원하기 위해 PFNMAP 매핑의 엄격한 선형성
+ * 규칙을 따를 필요가 없다는 것이다.
+ */
+/*
+ * IAMROOT, 2022.06.04:
+ * - special이 아닌 경우 pfn을 return 한다.
+ * - zero page인 경우 NULL을 retun 한다.
+ * - 나머지는 생략
+ */
struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) {
+/*
+ * IAMROOT, 2022.06.04:
+ * - special이 없으면 check_pfn으로 이동.
+ */
if (likely(!pte_special(pte)))
goto check_pfn;
if (vma->vm_ops && vma->vm_ops->find_special_page)
return vma->vm_ops->find_special_page(vma, addr);
if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
return NULL;
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page mapping이면 여기서 걸릴것.
+ */
if (is_zero_pfn(pfn))
return NULL;
if (pte_devmap(pte))
@@ -645,6 +700,11 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
}
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - CONFIG_ARCH_HAS_PTE_SPECIAL이 없으면, 여기서 zero page mapping일 경우
+ * 걸릴것이다.
+ */
if (is_zero_pfn(pfn))
return NULL;
@@ -2794,6 +2854,10 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
struct mm_struct *mm = vma->vm_mm;
unsigned long addr = vmf->address;
+/*
+ * IAMROOT, 2022.06.04:
+ * - @src가 존재할경우 @dst로 복사하고 끝낸다.
+ */
if (likely(src)) {
copy_user_highpage(dst, src, addr, vma);
return true;
@@ -2805,6 +2869,10 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
* just copying from the original user address. If that
* fails, we just zero-fill it. Live with it.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - src가 지정되지 않았으면 user address를 dst로 복사한다.
+ */
kaddr = kmap_atomic(dst);
uaddr = (void __user *)(addr & PAGE_MASK);
@@ -3024,10 +3092,19 @@ static inline void wp_page_reuse(struct vm_fault *vmf)
* held to the old page, as well as updating the rmap.
* - In any case, unlock the PTL and drop the reference we took to the old page.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - write fault(2차 fault) 발생시 user page(new page)를 할당하고 copy를
+ * 한다.
+ */
static vm_fault_t wp_page_copy(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct mm_struct *mm = vma->vm_mm;
+/*
+ * IAMROOT, 2022.06.04:
+ * - do_wp_page()에서 호출시 zero page일 경우 vmf->page는 NULL.
+ */
struct page *old_page = vmf->page;
struct page *new_page = NULL;
pte_t entry;
@@ -3037,6 +3114,11 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
if (unlikely(anon_vma_prepare(vma)))
goto oom;
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page에 mapping됬엇을 경우 zero로 memset하여 할당되고 아니면
+ * 그냥 할당.
+ */
if (is_zero_pfn(pte_pfn(vmf->orig_pte))) {
new_page = alloc_zeroed_user_highpage_movable(vma,
vmf->address);
@@ -3283,6 +3365,10 @@ static vm_fault_t wp_page_shared(struct vm_fault *vmf)
* but allow concurrent faults), with pte both mapped and locked.
* We return with mmap_lock still held, but pte unmapped and unlocked.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - do write protect page
+ */
static vm_fault_t do_wp_page(struct vm_fault *vmf)
__releases(vmf->ptl)
{
@@ -3301,6 +3387,10 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
mm_tlb_flush_pending(vmf->vma->vm_mm)))
flush_tlb_page(vmf->vma, vmf->address);
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page에 mapping되있었을 경우 NULL.
+ */
vmf->page = vm_normal_page(vma, vmf->address, vmf->orig_pte);
if (!vmf->page) {
/*
@@ -3310,6 +3400,11 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
* We should not cow pages in a shared writeable mapping.
* Just mark the pages writable and/or call ops->pfn_mkwrite.
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - shared일경우 wp_pfn_shared(), 아닐경우 wp_page_copy로 간다.
+ */
if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
(VM_WRITE|VM_SHARED))
return wp_pfn_shared(vmf);
@@ -3758,6 +3853,11 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
/*
* IAMROOT, 2022.05.21:
* - anon page fault시 이 함수로 진입하게 될것이다.
+ * 1. write fault가 아닐 경우(read fault)
+ * zero page에 mapping된다.
+ *
+ * 2. write fault일 경우.
+ * 사용자 memory에 할당해주고, rmap에 등록한다.
*/
static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
{
@@ -3780,6 +3880,10 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
*
* Here we only have mmap_read_lock(mm).
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vmf->pmd가 0이면 pte 할당을 한다.
+ */
if (pte_alloc(vma->vm_mm, vmf->pmd))
return VM_FAULT_OOM;
@@ -3788,12 +3892,30 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
return 0;
/* Use the zero-page for reads */
+/*
+ * IAMROOT, 2022.06.04:
+ * - read시 fault.
+ */
if (!(vmf->flags & FAULT_FLAG_WRITE) &&
!mm_forbids_zeropage(vma->vm_mm)) {
+/*
+ * IAMROOT, 2022.06.04:
+ * - zero page의 pte entry를 구해온다.
+ */
entry = pte_mkspecial(pfn_pte(my_zero_pfn(vmf->address),
vma->vm_page_prot));
+/*
+ * IAMROOT, 2022.06.04:
+ * - pmd ptl에 spinlock을 걸면서 해당 lcok을 vmf->pfl에 넣고, pte를
+ * 가져온다.
+ */
vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
vmf->address, &vmf->ptl);
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - mapping이 되있다면 update_mmu_tlb만 하고 unlock으로 이동한다.
+ */
if (!pte_none(*vmf->pte)) {
update_mmu_tlb(vma, vmf->address, vmf->pte);
goto unlock;
@@ -3802,6 +3924,10 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
if (ret)
goto unlock;
/* Deliver the page fault to userland, check inside PT lock */
+/*
+ * IAMROOT, 2022.06.04:
+ * - userfaultfd인지 확인.
+ */
if (userfaultfd_missing(vma)) {
pte_unmap_unlock(vmf->pte, vmf->ptl);
return handle_userfault(vmf, VM_UFFD_MISSING);
@@ -3809,6 +3935,10 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
goto setpte;
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - 이쪽으로 왔다는것은 write fault상태일 것이다.
+ */
/* Allocate our own private page. */
if (unlikely(anon_vma_prepare(vma)))
goto oom;
@@ -3828,6 +3958,11 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
__SetPageUptodate(page);
entry = mk_pte(page, vma->vm_page_prot);
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - mips를 제외하곤 entry 변동이 없다.
+ */
entry = pte_sw_mkyoung(entry);
if (vma->vm_flags & VM_WRITE)
entry = pte_mkwrite(pte_mkdirty(entry));
@@ -3852,8 +3987,18 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
page_add_new_anon_rmap(page, vma, vmf->address, false);
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - file이든 anon이든 inactive부터 시작한다.
+ */
lru_cache_add_inactive_or_unevictable(page, vma);
setpte:
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - entry가 실제 pte에 mapping.
+ */
set_pte_at(vma->vm_mm, vmf->address, vmf->pte, entry);
/* No need to invalidate - it was non-present before */
@@ -4608,6 +4753,11 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
}
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - 마지막 pte에서 fault가 발생햇을때.
+ * 첫 fault가 발생한 상황으로, pte가 null인, 즉 mapping이 안된상황이다.
+ */
if (!vmf->pte) {
if (vma_is_anonymous(vmf->vma))
return do_anonymous_page(vmf);
@@ -4615,15 +4765,27 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
return do_fault(vmf);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - vmf->pte가 있지만 present가 안된. 즉 invalid. swap 상태라는의미.
+ */
if (!pte_present(vmf->orig_pte))
return do_swap_page(vmf);
+/*
+ * IAMROOT, 2022.06.04:
+ * - numa_balancing으로 fault가 발생한지 확인한다.
+ */
if (pte_protnone(vmf->orig_pte) && vma_is_accessible(vmf->vma))
return do_numa_page(vmf);
vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd);
spin_lock(vmf->ptl);
entry = vmf->orig_pte;
+/*
+ * IAMROOT, 2022.06.04:
+ * - 같지 않으면 tlb update 요청.
+ */
if (unlikely(!pte_same(*vmf->pte, entry))) {
update_mmu_tlb(vmf->vma, vmf->address, vmf->pte);
goto unlock;
@@ -4633,6 +4795,11 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
return do_wp_page(vmf);
entry = pte_mkdirty(entry);
}
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - af flag set.
+ */
entry = pte_mkyoung(entry);
if (ptep_set_access_flags(vmf->vma, vmf->address, vmf->pte, entry,
vmf->flags & FAULT_FLAG_WRITE)) {
diff --git a/mm/mmap.c b/mm/mmap.c
index 935d13fa677f..4cf34b594c4c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -100,6 +100,12 @@ static void unmap_region(struct mm_struct *mm,
* w: (no) no
* x: (yes) yes
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - vm_flags의 flags들을 arch prot flag로 변환할때 사용한다.
+ * 작명 : __[Private/Shared][exec, write, read]
+ */
pgprot_t protection_map[16] __ro_after_init = {
__P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
@@ -112,6 +118,10 @@ static inline pgprot_t arch_filter_pgprot(pgprot_t prot)
}
#endif
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vm_flags를 arch prot flag로 변환한다.
+ */
pgprot_t vm_get_page_prot(unsigned long vm_flags)
{
pgprot_t ret = __pgprot(pgprot_val(protection_map[vm_flags &
@@ -122,18 +132,31 @@ pgprot_t vm_get_page_prot(unsigned long vm_flags)
}
EXPORT_SYMBOL(vm_get_page_prot);
+/*
+ * IAMROOT, 2022.06.04:
+ * - @oldprot의 cache속성을 return값에 적용한다.
+ */
static pgprot_t vm_pgprot_modify(pgprot_t oldprot, unsigned long vm_flags)
{
return pgprot_modify(oldprot, vm_get_page_prot(vm_flags));
}
/* Update vma->vm_page_prot to reflect vma->vm_flags. */
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vma에 page prot를 설정한다.
+ */
void vma_set_page_prot(struct vm_area_struct *vma)
{
unsigned long vm_flags = vma->vm_flags;
pgprot_t vm_page_prot;
vm_page_prot = vm_pgprot_modify(vma->vm_page_prot, vm_flags);
+/*
+ * IAMROOT, 2022.06.04:
+ * - write가능한 shared memory에 tracking이 필요한경우 shared flag를
+ * 제외한다.
+ */
if (vma_wants_writenotify(vma, vm_page_prot)) {
vm_flags &= ~VM_SHARED;
vm_page_prot = vm_pgprot_modify(vm_page_prot, vm_flags);
@@ -750,6 +773,10 @@ static void __vma_link_file(struct vm_area_struct *vma)
}
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - @prev와 @vma를 연결하고 rb tree에 vma를 추가한다.
+ */
static void
__vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
struct vm_area_struct *prev, struct rb_node **rb_link,
@@ -759,6 +786,10 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
__vma_link_rb(mm, vma, rb_link, rb_parent);
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vma를 link하고 @mm에 map_count를 증가시킨다.
+ */
static void vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
struct vm_area_struct *prev, struct rb_node **rb_link,
struct rb_node *rb_parent)
@@ -830,6 +861,10 @@ static __always_inline void __vma_unlink(struct mm_struct *mm,
*
* - @insert는 vma_adjust()에서만 사용한다.
* @expand는 vma_merge()에서만 사용한다.
+ *
+ * - vma에 대해 변경(추가 및 확장)이 일어 날시 vma에 관련된 자료구조들을
+ * 갱신한다. 실제 삭제해야될 vma를 삭제하고, vma의 범위를 새로 고치며,
+ * avc를 새로 정렬한다.
*/
int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
@@ -1199,6 +1234,10 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
* we must remove another next too. It would clutter
* up the code too much to do both in one go.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * remove_next의 값에 따라 next를 정한다.
+ */
if (remove_next != 3) {
/*
* If "next" was removed and vma->vm_end was
@@ -1220,6 +1259,12 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
*/
next = vma;
}
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - remove_next 2의 경우 remove_next 1의 방법으로 한번 더 삭제해야된다
+ * (2개통합)
+ */
if (remove_next == 2) {
remove_next = 1;
end = next->vm_end;
@@ -1442,6 +1487,10 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
* parameter) may establish ptes with the wrong permissions of NNNN
* instead of the right permissions of XXXX.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - @addr ~ @end의 범위의 vma를 하나의 기준 vma로 merge를 진행한다.
+ */
struct vm_area_struct *vma_merge(struct mm_struct *mm,
struct vm_area_struct *prev, unsigned long addr,
unsigned long end, unsigned long vm_flags,
@@ -1607,6 +1656,33 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
* driver is doing some kind of reference counting. But that doesn't
* really matter for the anon_vma sharing case.
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - papgo
+ * anon_vma를 공유할 가치가 있는지 여부를 빠르게 확인할 수 있는 대략적인
+ * 호환성 검사입니다.
+ *
+ * vm_file이 동일해야 하며 플래그는 mprotect가 변경할 수 있는 항목에서만
+ * 다를 수 있습니다.
+ *
+ * NOTE! anon_vma를 공유한다는 사실이 두 vma를 병합할 수 있다는 것을
+ * 의미하지는 않습니다. 예를 들어, vm_ops->close() 함수가 있으면
+ * 드라이버가 어떤 종류의 참조 카운트를 수행 중임을 나타내기 때문에 vma
+ * 병합을 거부합니다. 그러나 anon_vma 공유 사례의 경우에는 문제가 되지
+ * 않습니다.
+ *
+ * - @a와 @b를 통합할수있는지 확인한다.
+ * - @a가 before, @b가 after.
+ * 1. a->vm_end = b->vm_stgart
+ * vma끼리 연속되있는지.
+ * 2. mpol_equal(...)
+ * memory policy가 같은지 확인
+ * 3. vm_file, vm_flags
+ * file과 vm_flags가 같은지.
+ * 4. b->vm_pgoff == a->vm_pgoff + ...
+ * a(before vma)와 b의 pg가 연속되있는지.
+ */
static int anon_vma_compatible(struct vm_area_struct *a, struct vm_area_struct *b)
{
return a->vm_end == b->vm_start &&
@@ -1638,6 +1714,29 @@ static int anon_vma_compatible(struct vm_area_struct *a, struct vm_area_struct *
* and with the same memory policies). That's all stable, even with just
* a read lock on the mm_sem.
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - papago
+ * 'old'의 anon_vma를 다시 사용할 수 있는지 확인하기 위해 몇 가지
+ * 기본적인 건전성 검사를 수행합니다. 'a'/'b' vma는 VM 순서로 되어
+ * 있습니다. 이 중 하나는 '이전'과 같고, 다른 하나는 anon_vma를
+ * 공유하려는 새 VM입니다.
+ *
+ * NOTE! 읽기 위해 mm_sem이 보류된 상태에서 실행되므로, 'old'의
+ * anon_vma가 병합하려는 다른 페이지 오류로 인해 동시에 설정될 수
+ * 있습니다. 하지만 괜찮습니다: 설정 중이면 자동으로 병합에 사용할 수
+ * 있는 singleton이 되므로 이 모든 것을 낙관적으로 수행할 수 있습니다.
+ * 그러나 포인터를 다시 로드하지 않도록 하기 위해 READ_ONES()를
+ * 수행합니다.
+ *
+ * IOW(in other word): anon_vma_chain에 대한 "list_is_vma()" 테스트는
+ * 'follow anon_vma' 사례에 대해서만 문제가 됩니다(즉, 포크를 통과했기
+ * 때문에 "복잡한" anon_vma를 반환하는 것을 방지하고자 합니다.
+ *
+ * 또한 두 vma가 호환되는지(인접적이고 동일한 메모리 정책과) 확인합니다.
+ * mm_sem에 읽기 잠금만 있어도 안정적입니다.
+ */
static struct anon_vma *reusable_anon_vma(struct vm_area_struct *old, struct vm_area_struct *a, struct vm_area_struct *b)
{
if (anon_vma_compatible(a, b)) {
@@ -1657,6 +1756,13 @@ static struct anon_vma *reusable_anon_vma(struct vm_area_struct *old, struct vm_
* anon_vmas being allocated, preventing vma merge in subsequent
* mprotect.
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - next가 있으면 next를 기준으로, prev가 있으면 prev를 기준으로 merge가
+ * 가능한지 확인한다.
+ * 가능하면 기존 vma의 av를 재사용한다.
+ */
struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma)
{
struct anon_vma *anon_vma = NULL;
@@ -1750,6 +1856,12 @@ static inline bool file_mmap_ok(struct file *file, struct inode *inode,
/*
* The caller must write-lock current->mm->mmap_lock.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - user malloc호출시 flag
+ * prot = PROT_READ|PROT_WRITE
+ * flags = MAP_PRIVATE|MAP_ANONYMOUS
+ */
unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff,
@@ -1819,6 +1931,11 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
/*
* IAMROOT, 2022.05.21:
* - prot, flags를 vm_flags로 변환하여 추가한다.
+ *
+ * - user malloc호출시 flag
+ * @prot = PROT_READ|PROT_WRITE
+ * @flags = MAP_PRIVATE|MAP_ANONYMOUS
+ * vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC
*/
vm_flags = calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) |
mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
@@ -1943,6 +2060,10 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
* IAMROOT, 2022.05.21:
* - user에서 호출한 malloc인 경우 if문 해당사항이 없어(file이 아닌경우)
* vm_mmap_pgoff를 바로 호출할것이다.
+ *
+ * - user malloc호출시 flag
+ * prot = PROT_READ|PROT_WRITE
+ * flags = MAP_PRIVATE|MAP_ANONYMOUS
*/
unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags,
@@ -2029,6 +2150,20 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg)
* to the private version (using protection_map[] without the
* VM_SHARED bit).
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - write event에 대해 tracking을 하기 위해 확인한다.
+ * (shared memory)
+ *
+ * -- write notify를 하는 상황.
+ * 반드시 VM_WRITE|VM_SHARED가 둘다 존재해야된다.
+ *
+ * 1. vm_ops에 page_mkwrite or pfn_mkwrite가 존재한다.
+ * (이하는 @vm_page_prot와 vma의 cache속성이 같아야됨.)
+ * 2. soft_dirty기능이 있는 상태에서 VM_SOFTDIRTY가 없는 상황
+ * 3. VM_FPNMAP이 없으면서 writeback을 할수잇는 상황.
+ *
+ */
int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
{
vm_flags_t vm_flags = vma->vm_flags;
@@ -2077,6 +2212,11 @@ static inline int accountable_mapping(struct file *file, vm_flags_t vm_flags)
return (vm_flags & (VM_NORESERVE | VM_SHARED | VM_WRITE)) == VM_WRITE;
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - user malloc호출시 flag
+ * @vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC
+ */
unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, vm_flags_t vm_flags, unsigned long pgoff,
struct list_head *uf)
@@ -2112,6 +2252,13 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
/*
* Private writable mapping: check memory availability
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - user malloc호출시 flag
+ * @vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE |
+ * VM_MAYEXEC | VM_ACCOUNT
+ * shared memory가 아닌 write가 가능한 memory인 경우 VM_ACCOUNT가 추가된다.
+ */
if (accountable_mapping(file, vm_flags)) {
charged = len >> PAGE_SHIFT;
if (security_vm_enough_memory_mm(mm, charged))
@@ -2132,6 +2279,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
* specific mapper. the address has already been validated, but
* not unmapped, but the maps are removed from the list.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - merge가 안되는 경우이므로 vma를 새로 만든다.
+ */
vma = vm_area_alloc(mm);
if (!vma) {
error = -ENOMEM;
@@ -2234,6 +2385,13 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
* then new mapped in-place (which must be aimed as
* a completely new data area).
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - user malloc호출시 flag
+ * @vm_flags = VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE |
+ * VM_MAYEXEC | VM_ACCOUNT | VM_SOFTDIRTY
+ * 최종적으로 vma가 새로 생길시 위와 같은 flag로 완성된다.
+ */
vma->vm_flags |= VM_SOFTDIRTY;
vma_set_page_prot(vma);
diff --git a/mm/rmap.c b/mm/rmap.c
index 3b8e975f2960..0fdd51ca6763 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -83,6 +83,10 @@
static struct kmem_cache *anon_vma_cachep;
static struct kmem_cache *anon_vma_chain_cachep;
+/*
+ * IAMROOT, 2022.06.04:
+ * - av를 생성한다.
+ */
static inline struct anon_vma *anon_vma_alloc(void)
{
struct anon_vma *anon_vma;
@@ -198,6 +202,14 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
*
* This must be called with the mmap_lock held for reading.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - av를 만든다.
+ * 만들어진 av와 @vma를 연결하기 위해 avc를 하나 생성해서
+ * rb tree에 넣는다.
+ * 만약 merge가능한 av가 있다면 merge를 하고 그게 아니면 새로운 av를
+ * 생성한다.
+ */
int __anon_vma_prepare(struct vm_area_struct *vma)
{
struct mm_struct *mm = vma->vm_mm;
@@ -213,6 +225,10 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
anon_vma = find_mergeable_anon_vma(vma);
allocated = NULL;
if (!anon_vma) {
+/*
+ * IAMROOT, 2022.06.04:
+ * - merge가 가능한 av가 없으면 할당을 시도한다.
+ */
anon_vma = anon_vma_alloc();
if (unlikely(!anon_vma))
goto out_enomem_free_avc;
@@ -222,6 +238,10 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
anon_vma_lock_write(anon_vma);
/* page_table_lock to protect against threads */
spin_lock(&mm->page_table_lock);
+/*
+ * IAMROOT, 2022.06.04:
+ * - @vma에 연결되있던 av가 없으면 현재 생성되었거나 reuse하는 av로 넣는다.
+ */
if (likely(!vma->anon_vma)) {
vma->anon_vma = anon_vma;
anon_vma_chain_link(vma, avc, anon_vma);
@@ -370,6 +390,14 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
* the corresponding VMA in the parent process is attached to.
* Returns 0 on success, non-zero on failure.
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * @vma : @pvma로부터 복사된 새로만들어진 child vma
+ * @pvma : parent vma
+ *
+ * - dup_mmap()에서 부모의 전체 vma수만큼 호출된다.
+ */
int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
{
struct anon_vma_chain *avc;
@@ -510,6 +538,10 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
}
}
+/*
+ * IAMROOT, 2022.06.04:
+ * - 생성자.
+ */
static void anon_vma_ctor(void *data)
{
struct anon_vma *anon_vma = data;
@@ -1185,6 +1217,12 @@ void page_move_anon_rmap(struct page *page, struct vm_area_struct *vma)
* @address: User virtual address of the mapping
* @exclusive: the page is exclusively owned by the current process
*/
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - @page->mapping에 anon_vma + PAGE_MAPPING_ANON을 set하고,
+ * @page->index에 @page가속한 @vma에서의 pgoff를 set한다.
+ */
static void __page_set_anon_rmap(struct page *page,
struct vm_area_struct *vma, unsigned long address, int exclusive)
{
@@ -1192,6 +1230,10 @@ static void __page_set_anon_rmap(struct page *page,
BUG_ON(!anon_vma);
+/*
+ * IAMROOT, 2022.06.04:
+ * - 이미 되있으면 return.
+ */
if (PageAnon(page))
return;
@@ -1320,12 +1362,20 @@ void do_page_add_anon_rmap(struct page *page,
* This means the inc-and-test can be bypassed.
* Page does not have to be locked.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - @page가 anon_vma를 가리키게 만든다.
+ */
void page_add_new_anon_rmap(struct page *page,
struct vm_area_struct *vma, unsigned long address, bool compound)
{
int nr = compound ? thp_nr_pages(page) : 1;
VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma);
+/*
+ * IAMROOT, 2022.06.04:
+ * - anon page는 SetPageSwapBacked이 set된다.
+ */
__SetPageSwapBacked(page);
if (compound) {
VM_BUG_ON_PAGE(!PageTransHuge(page), page);
@@ -1339,6 +1389,10 @@ void page_add_new_anon_rmap(struct page *page,
/* Anon THP always mapped first with PMD */
VM_BUG_ON_PAGE(PageTransCompound(page), page);
/* increment count (starts at -1) */
+/*
+ * IAMROOT, 2022.06.04:
+ * - page->_mapcount의 초기값은 -1. 사용시 0으로 set.
+ */
atomic_set(&page->_mapcount, 0);
}
__mod_lruvec_page_state(page, NR_ANON_MAPPED, nr);
diff --git a/mm/swap.c b/mm/swap.c
index 9b7261fa3629..c6154b714d81 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -547,6 +547,12 @@ EXPORT_SYMBOL(lru_cache_add);
* Place @page on the inactive or unevictable LRU list, depending on its
* evictability.
*/
+/*
+ * IAMROOT, 2022.06.04:
+ * - 처음 생성된 page는 file이든 anon이든 inactive부터 시작한다.
+ * 원래는 active부터 시작햇는데 refault distance계산때문에 이렇게
+ * 변경됬다.
+ */
void lru_cache_add_inactive_or_unevictable(struct page *page,
struct vm_area_struct *vma)
{
diff --git a/mm/util.c b/mm/util.c
index aa2a8e7dc3ec..6e01fdf9e8d6 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -507,6 +507,13 @@ int account_locked_vm(struct mm_struct *mm, unsigned long pages, bool inc)
}
EXPORT_SYMBOL_GPL(account_locked_vm);
+
+/*
+ * IAMROOT, 2022.06.04:
+ * - user malloc호출시 flag
+ * prot = PROT_READ|PROT_WRITE
+ * flags = MAP_PRIVATE|MAP_ANONYMOUS
+ */
unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long pgoff)
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 629 |
247 | 커널 스터디 공개 노트 링크 [1] | 박동하 | 2016.05.20 | 233115 |
246 | [커널 17차] 41주차 | ㅇㅇㅇ | 2021.06.13 | 36551 |
245 | [커널 17차] 56주차 | ㅇㅇㅇ | 2021.10.03 | 27526 |
244 | [커널 18차] 1주차 | V4bel | 2021.05.29 | 3599 |
243 | [커널 17차 6조] 2주차 | 김정근 | 2020.08.31 | 2175 |
242 | [커널 17차 2조] 4주차 | wellbeing | 2020.09.12 | 1518 |
241 | 커널 스터디 13차 D조 스터디 로그 링크입니다. | 목태양 | 2016.05.15 | 1226 |
240 | 해킹&보안 1차 A팀 스터디로그 링크 | 수비니겨 | 2016.05.19 | 1185 |
239 | [커널 16차 B조] 1주차 [1] | kdy0252 | 2019.05.25 | 1084 |
238 | [커널 17차 A조] 20주차 | 주영 | 2021.01.11 | 1019 |
237 | [커널 20차] 24주차 | 이민찬 | 2023.10.22 | 792 |
236 | [커널 17차 2조] 5주차 | wellbeing | 2020.09.19 | 739 |
235 | [커널 17차 8조] 1주차 [3] | JSYoo5B | 2020.08.22 | 716 |
234 | [커널 19차] 0주차 - 오리엔테이션 | 리턴 | 2022.05.07 | 601 |
233 | [커널 17차] 26주차 | 주영 | 2021.03.01 | 540 |
232 | [커널 19차] 37 주차 | Min | 2023.02.04 | 479 |
231 | [커널 19차] 1주차 | 리턴 | 2022.05.16 | 456 |
230 | [커널 17차] 32주차 | ㅇㅇㅇ | 2021.04.11 | 443 |
229 | [커널 17차 A조] 12주차 | 주영 | 2020.11.16 | 410 |
.