[커널 18차] 65주차

2022.08.20 22:22

kkr 조회 수:28

timer 진행중

git : https://github.com/iamroot18/5.10/commit/db6e14048fc71d57f64c1633fb884ee502f91ffc

 

diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index 88d20f04c64a..ae651007eca4 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -149,6 +149,18 @@ u32 arch_timer_reg_read_cp15(int access, enum arch_timer_reg reg)
     BUG();
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - CNTFRQ_EL0, Counter-timer Frequency register를 읽는다.
+ *   (arch timer에 사용한 주파수.)
+ * - Bits [63:32]
+ *   Reserved, RES0.
+ *
+ * - Bits [31:0]
+ *   Clock frequency. Indicates the system counter clock frequency, in Hz.
+ *   The reset behavior of this field is:
+ *   On a Warm reset, this field resets to an architecturally UNKNOWN value. 
+ */
 static inline u32 arch_timer_get_cntfrq(void)
 {
     return read_sysreg(cntfrq_el0);
@@ -175,6 +187,10 @@ static __always_inline u64 __arch_counter_get_cntpct_stable(void)
     return cnt;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - read cntpct_el0
+ */
 static __always_inline u64 __arch_counter_get_cntpct(void)
 {
     u64 cnt;
@@ -195,6 +211,13 @@ static __always_inline u64 __arch_counter_get_cntvct_stable(void)
     return cnt;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - CNTVCT_EL0, Counter-timer Virtual Count register
+ *   Holds the 64-bit virtual count value. The virtual count value is equal to the physical count
+ *   value minus the virtual offset visible in CNTVOFF_EL2.
+ * - read cntvct_el0
+ */
 static __always_inline u64 __arch_counter_get_cntvct(void)
 {
     u64 cnt;
diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h
index 49814ce8d2c6..45420232e35f 100644
--- a/arch/arm64/include/asm/barrier.h
+++ b/arch/arm64/include/asm/barrier.h
@@ -88,6 +88,58 @@ static inline unsigned long array_index_mask_nospec(unsigned long idx,
  *
  * https://lore.kernel.org/r/alpine.DEB.2.21.1902081950260.1662@nanos.tec.linutronix.de/
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * - papago
+ *   카운터 읽기가 후속 메모리 배리어에 의한 순서를 위해 메모리 읽기와 동일하게 처리되는지
+ *   확인하십시오.
+ *
+ *   이 광기는 추측성 시스템 레지스터 읽기, 비순차적 메모리 액세스, 시퀀스 잠금 및
+ *   Thomas Gleixner로 인해 발생했습니다. 
+ * - eor %0, %1, %1 => 같은값 xor을 하면 결국 0.
+ *   add x0, sp, %0 => sp + 0 = sp
+ *   ldr xzr, [%0]  => xzr에 sp가 가리키는 data를 load. 아무 일 안함.
+ *
+ * - git blame
+ *   arm64: vdso: Avoid ISB after reading from cntvct_el0.
+ *
+ *   We can avoid the expensive ISB instruction after reading the counter in the vDSO gettime
+ *   functions by creating a fake address hazard against a dummy stack read, just like we do
+ *   inside the kernel.
+ *
+ * - papgo
+ *   arm64: vdso: cntvct_el0에서 읽은 후에는 ISB를 피하십시오.
+ *
+ *   커널 내부에서처럼 더미 스택 읽기에 대해 가짜 주소 위험을 생성하여 vDSO gettime 함수의
+ *   카운터를 읽은 후 값비싼 ISB 명령을 피할 수 있다.
+ *
+ * - git blame2
+ *   arm64: arch_timer: Ensure counter register reads occur with seqlock held.
+ *
+ *   When executing clock_gettime(), either in the vDSO or via a system call, we need to ensure
+ *   that the read of the counter register occurs within the seqlock reader critical section.
+ *   This ensures that updates to the clocksource parameters (e.g. the multiplier) are consistent
+ *   with the counter value and therefore avoids the situation where time appears to go backwards
+ *   across multiple reads.
+ *
+ *   Extend the vDSO logic so that the seqlock critical section covers the read of the counter
+ *   register as well as accesses to the data page. Since reads of the counter system registers
+ *   are not ordered by memory barrier instructions, introduce dependency ordering from the counter
+ *   read to a subsequent memory access so that the seqlock memory barriers apply to the counter
+ *   access in both the vDSO and the system call paths.
+ *
+ * - papago
+ *   arm64: arch_timer: 카운터 레지스터 읽기가 시퀀스를 누른 상태에서 수행되는지 확인합니다.
+ *
+ *   vDSO에서 또는 시스템 호출을 통해 clock_gettime()을 실행할 때는 카운터 레지스터 읽기가 seqlock
+ *   Reader critical 섹션 내에서 수행되도록 해야 합니다. 이렇게 하면 클럭 소스 매개 변수(예: 승수)에
+ *   대한 업데이트가 카운터 값과 일치하므로 여러 판독에서 시간이 거꾸로 가는 상황을 피할 수 있다.
+ *
+ *   seqlock 중요 섹션이 카운터 레지스터 읽기와 데이터 페이지 액세스를 포함하도록 vDSO 논리를
+ *   확장합니다. 카운터 시스템 레지스터 읽기는 메모리 장벽 지침에 따라 정렬되지 않으므로 카운터
+ *   읽기부터 후속 메모리 액세스까지 종속성 순서를 도입하여 seqlock 메모리 장벽이 vDSO 및 시스템
+ *   호출 경로 모두에서 카운터 액세스에 적용되도록 합니다.  
+ */
 #define arch_counter_enforce_ordering(val) do {                \
     u64 tmp, _val = (val);                        \
                                     \
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index be6d741d404c..41815b33fdb5 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -66,6 +66,15 @@ struct arch_timer {
 static u32 arch_timer_rate __ro_after_init;
 static int arch_timer_ppi[ARCH_TIMER_MAX_TIMER_PPI] __ro_after_init;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - dts에는 다음과 같이 있다.
+ *    interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, // Physical Secure
+ *             <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, // Physical Non-Secure
+ *             <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, // Virtual
+ *             <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; // Hypervisor
+ *
+ */
 static const char *arch_timer_ppi_names[ARCH_TIMER_MAX_TIMER_PPI] = {
     [ARCH_TIMER_PHYS_SECURE_PPI]    = "sec-phys",
     [ARCH_TIMER_PHYS_NONSECURE_PPI]    = "phys",
@@ -76,9 +85,25 @@ static const char *arch_timer_ppi_names[ARCH_TIMER_MAX_TIMER_PPI] = {
 
 static struct clock_event_device __percpu *arch_timer_evt;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - kernel에서 사용할 timer.
+ */
 static enum arch_timer_ppi_nr arch_timer_uses_ppi __ro_after_init = ARCH_TIMER_VIRT_PPI;
+
+/*
+ * IAMROOT, 2022.08.20:
+ * - clock을 끄는 기능의 지원여부. 절전등에서 사용한다.
+ *   core가 정지.
+ */
 static bool arch_timer_c3stop __ro_after_init;
 static bool arch_timer_mem_use_virtual __ro_after_init;
+
+/*
+ * IAMROOT, 2022.08.20:
+ * - dts prop : arm,no-tick-in-suspend
+ *   절전시 interrupt on/off 여부.
+ */
 static bool arch_counter_suspend_stop __ro_after_init;
 #ifdef CONFIG_GENERIC_GETTIMEOFDAY
 static enum vdso_clock_mode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
@@ -166,6 +191,10 @@ static notrace u64 arch_counter_get_cntpct_stable(void)
     return __arch_counter_get_cntpct_stable();
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - read cntpct
+ */
 static notrace u64 arch_counter_get_cntpct(void)
 {
     return __arch_counter_get_cntpct();
@@ -176,6 +205,10 @@ static notrace u64 arch_counter_get_cntvct_stable(void)
     return __arch_counter_get_cntvct_stable();
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - read cntvct
+ */
 static notrace u64 arch_counter_get_cntvct(void)
 {
     return __arch_counter_get_cntvct();
@@ -200,6 +233,10 @@ static u64 arch_counter_read_cc(const struct cyclecounter *cc)
     return arch_timer_read_counter();
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - !arch_counter_suspend_stop => flags CLOCK_SOURCE_SUSPEND_NONSTOP 추가
+ */
 static struct clocksource clocksource_counter = {
     .name    = "arch_sys_counter",
     .id    = CSID_ARM_ARCH_COUNTER,
@@ -391,6 +428,12 @@ static u32 notrace sun50i_a64_read_cntv_tval_el0(void)
 }
 #endif
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - Out of Line Counter.
+ *   하드웨어 이상으로 counter값이 순간적으로 튀는등 이상하게 변동되는경우가 있는데,
+ *   그것에 대한 방어코드.
+ */
 #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
 DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround);
 EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
@@ -592,6 +635,11 @@ void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa
     }
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - ool일 발생할수있는 arch일 경우 거기에 대한 방어처리를 한다.
+ *   ool_workarounds 참고.
+ */
 static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type type,
                         void *arg)
 {
@@ -879,6 +927,12 @@ static void arch_counter_set_user_access(void)
     arch_timer_set_cntkctl(cntkctl);
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - kernel이 현재 쓰는 timer가 ARCH_TIMER_PHYS_SECURE_PPI인데
+ *   ARCH_TIMER_PHYS_NONSECURE_PPI가 설정되잇으면 true.
+ * - system이 secure상태인데 none-secure도 있으면 none-secure도 설정하기 위함.
+ */
 static bool arch_timer_has_nonsecure_ppi(void)
 {
     return (arch_timer_uses_ppi == ARCH_TIMER_PHYS_SECURE_PPI &&
@@ -921,6 +975,10 @@ static int arch_timer_starting_cpu(unsigned int cpu)
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - timer 유효성검사.
+ */
 static int validate_timer_rate(void)
 {
     if (!arch_timer_rate)
@@ -937,6 +995,12 @@ static int validate_timer_rate(void)
  * rate was probed first, and don't verify that others match. If the first node
  * probed has a clock-frequency property, this overrides the HW register.
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * - 이미 설정되있으면 return.
+ *   clock-frequency prop에 없으면 @rate를, 존재한다면 dts를 우선해서 사용한다.
+ * - 즉 dts에 있으면 dts, 아니면 bootloader에서 읽은걸 asrch_timer_rate로 사용한다.
+ */
 static void __init arch_timer_of_configure_rate(u32 rate, struct device_node *np)
 {
     /* Who has more than one independent system counter? */
@@ -951,6 +1015,15 @@ static void __init arch_timer_of_configure_rate(u32 rate, struct device_node *np
         pr_warn("frequency not available\n");
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - pc ubuntu(guest os)
+ *   arch_timer: cp15 timer(s) running at 62.50MHz (virt).
+ * - rpi4
+ *   arch_timer: cp15 timer(s) running at 54.00MHz (phys).
+ * - rpi4(guest os)
+ *   arch_timer: cp15 timer(s) running at 54.00MHz (virt).
+ */
 static void __init arch_timer_banner(unsigned type)
 {
     pr_info("%s%s%s timer(s) running at %lu.%02luMHz (%s%s%s).\n",
@@ -1004,11 +1077,25 @@ struct arch_timer_kvm_info *arch_timer_get_kvm_info(void)
     return &arch_timer_kvm_info;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * @type arch_timers_present
+ */
 static void __init arch_counter_register(unsigned type)
 {
     u64 start_count;
 
     /* Register the CP15 based counter if we have one */
+/*
+ * IAMROOT, 2022.08.20:
+ * - wa(workaround) 는 고려안함.
+ *
+ * 1. type 에 CP15 존재
+ *  - arm64, !hyp                     = arch_counter_get_cntvct
+ *  - ppi = virt_ppi                  = arch_counter_get_cntvct
+ *  - 그외(arm64가 아니거나 hyp mode) = arch_counter_get_cntpct
+ * 2. type 에 CP15 없음(MEM이라는뜻). = arch_counter_get_cntvct_mem
+ */
     if (type & ARCH_TIMER_TYPE_CP15) {
         u64 (*rd)(void);
 
@@ -1033,6 +1120,11 @@ static void __init arch_counter_register(unsigned type)
 
     if (!arch_counter_suspend_stop)
         clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
+
+/*
+ * IAMROOT, 2022.08.20:
+ * - 
+ */
     start_count = arch_timer_read_counter();
     clocksource_register_hz(&clocksource_counter, arch_timer_rate);
     cyclecounter.mult = clocksource_counter.mult;
@@ -1087,6 +1179,10 @@ static struct notifier_block arch_timer_cpu_pm_notifier = {
     .notifier_call = arch_timer_cpu_pm_notify,
 };
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - notifier 등록
+ */
 static int __init arch_timer_cpu_pm_init(void)
 {
     return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier);
@@ -1108,6 +1204,11 @@ static void __init arch_timer_cpu_pm_deinit(void)
 }
 #endif
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - arch_timer_evt를 생성한다.
+ * - kernel timer의 percpu irq를 등록한다.
+ */
 static int __init arch_timer_register(void)
 {
     int err;
@@ -1120,6 +1221,16 @@ static int __init arch_timer_register(void)
     }
 
     ppi = arch_timer_ppi[arch_timer_uses_ppi];
+
+/*
+ * IAMROOT, 2022.08.20:
+ * - cpu마다 있는 irq에 대해 irq를 등록한다.
+ * -
+ *  ARCH_TIMER_VIRT_PPI : guest os용
+ *  ARCH_TIMER_PHYS_NONSECURE_PPI : EL1에서 동작하는 linux kernel 용.
+ *  ARCH_TIMER_PHYS_SECURE_PPI    :
+ *  ARCH_TIMER_HYP_PPI : EL2에서 동작하는 linux kernel 용.
+ */
     switch (arch_timer_uses_ppi) {
     case ARCH_TIMER_VIRT_PPI:
         err = request_percpu_irq(ppi, arch_timer_handler_virt,
@@ -1127,6 +1238,15 @@ static int __init arch_timer_register(void)
         break;
     case ARCH_TIMER_PHYS_SECURE_PPI:
     case ARCH_TIMER_PHYS_NONSECURE_PPI:
+/*
+ * IAMROOT, 2022.08.20:
+ * - kernel이 none-secure
+ *   arch_timer_evt등록.
+ * - kernel이 ARCH_TIMER_PHYS_SECURE_PPI 이면서 ARCH_TIMER_PHYS_NONSECURE_PPI가 없는상태.
+ *   arch_timer_evt등록.
+ * - kernel이 ARCH_TIMER_PHYS_SECURE_PPI 이면서 ARCH_TIMER_PHYS_NONSECURE_PPI가 있는 상태.
+ *   arch_timer_evt, arch_timer_handler_phys등록.
+ */
         err = request_percpu_irq(ppi, arch_timer_handler_phys,
                      "arch_timer", arch_timer_evt);
         if (!err && arch_timer_has_nonsecure_ppi()) {
@@ -1156,6 +1276,10 @@ static int __init arch_timer_register(void)
         goto out_unreg_notify;
 
     /* Register and immediately configure the timer on the boot CPU */
+/*
+ * IAMROOT, 2022.08.20:
+ * - CPUHP_AP_ARM_ARCH_TIMER_STARTING로 on / off일때 각각의 callback 함수를 등록.
+ */
     err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
                 "clockevents/arm/arch_timer:starting",
                 arch_timer_starting_cpu, arch_timer_dying_cpu);
@@ -1217,12 +1341,20 @@ static const struct of_device_id arch_timer_mem_of_match[] __initconst = {
     {},
 };
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - CP15가 설정되있다면 MEM을, MEM이 설정되있다면 CP15를 확인하여 probing.
+ */
 static bool __init arch_timer_needs_of_probing(void)
 {
     struct device_node *dn;
     bool needs_probing = false;
     unsigned int mask = ARCH_TIMER_TYPE_CP15 | ARCH_TIMER_TYPE_MEM;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - CP15, MEM둘중 하나만 초기화 하기 위한것.
+ */
     /* We have two timers, and both device-tree nodes are probed. */
     if ((arch_timers_present & mask) == mask)
         return false;
@@ -1231,6 +1363,16 @@ static bool __init arch_timer_needs_of_probing(void)
      * Only one type of timer is probed,
      * check if we have another type of timer node in device-tree.
      */
+/*
+ * IAMROOT, 2022.08.20:
+ * - ARCH_TIMER_TYPE_CP15 지원.
+ *   arm,armv7-timer-mem
+ *
+ * - ARCH_TIMER_TYPE_MEM 지원.
+ *   arm,armv7-timer, arm,armv7-timer
+ *
+ * 나머지 한개에 대해서 probing을 요구.
+ */
     if (arch_timers_present & ARCH_TIMER_TYPE_CP15)
         dn = of_find_matching_node(NULL, arch_timer_mem_of_match);
     else
@@ -1269,6 +1411,13 @@ static int __init arch_timer_common_init(void)
  *
  * Return: a suitable PPI type for the current system.
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * 1. hyp mode : ARCH_TIMER_HYP_PPI
+ * 2. hyp mode disable. 이고 ARCH_TIMER_VIRT_PPI존재. : ARCH_TIMER_VIRT_PPI
+ * 3. arm64 : ARCH_TIMER_PHYS_NONSECURE_PPI
+ * 4. 그외 ARCH_TIMER_PHYS_SECURE_PPI
+ */
 static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
 {
     if (is_kernel_in_hyp_mode())
@@ -1283,6 +1432,12 @@ static enum arch_timer_ppi_nr __init arch_timer_select_ppi(void)
     return ARCH_TIMER_PHYS_SECURE_PPI;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - ARCH_TIMER_VIRT_PPI에 해당하는 irq를 arch_timer_kvm_info.virtual_irq에 넣는다.
+ *   현재 kernel이 hyp mode면 ARCH_TIMER_PHYS_NONSECURE_PPI에 해당하는 irq를
+ *   arch_timer_kvm_info.physical_irq에 넣는다.
+ */
 static void __init arch_timer_populate_kvm_info(void)
 {
     arch_timer_kvm_info.virtual_irq = arch_timer_ppi[ARCH_TIMER_VIRT_PPI];
@@ -1290,12 +1445,20 @@ static void __init arch_timer_populate_kvm_info(void)
         arch_timer_kvm_info.physical_irq = arch_timer_ppi[ARCH_TIMER_PHYS_NONSECURE_PPI];
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - ARCH_TIMER_TYPE_CP15 방식의 초기화 방법.
+ */
 static int __init arch_timer_of_init(struct device_node *np)
 {
     int i, irq, ret;
     u32 rate;
     bool has_names;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - ARCH_TIMER_TYPE_CP15의 방식으로의 설정이 중복되서 호출됬는지 확인한다.
+ */
     if (arch_timers_present & ARCH_TIMER_TYPE_CP15) {
         pr_warn("multiple nodes in dt, skipping\n");
         return 0;
@@ -1305,6 +1468,22 @@ static int __init arch_timer_of_init(struct device_node *np)
 
     has_names = of_property_read_bool(np, "interrupt-names");
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - interrupt-names에 name이 있다면 name을 기준으로, 아니면 순서대로 irq 번호를 찾는다.
+ *   여기 찾는건 virq(virutal irq).
+ *
+ * - ex) interrupt-names 사용처 예제. dts/apple/t8103.dtsi
+ *   timer {
+ *    compatible = "arm,armv8-timer";
+ *    interrupt-parent = <&aic>;
+ *    interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt";
+ *    interrupts = <AIC_FIQ AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ *    <AIC_FIQ AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>,
+ *    <AIC_FIQ AIC_TMR_HV_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ *    <AIC_FIQ AIC_TMR_HV_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ *   };
+ */
     for (i = ARCH_TIMER_PHYS_SECURE_PPI; i < ARCH_TIMER_MAX_TIMER_PPI; i++) {
         if (has_names)
             irq = of_irq_get_byname(np, arch_timer_ppi_names[i]);
@@ -1316,9 +1495,18 @@ static int __init arch_timer_of_init(struct device_node *np)
 
     arch_timer_populate_kvm_info();
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - arch timer hz를 cntfrq에서 읽어온다. 그 이후에 dts에 timer clock값이 존재하면, dts우선,
+ *   아니면 cntfrq에서 읽어온(bootloader가 세팅해준)값을 사용한다.
+ */
     rate = arch_timer_get_cntfrq();
     arch_timer_of_configure_rate(rate, np);
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - always-on이 존재하면 arch_timer_c3stop을 disable.
+ */
     arch_timer_c3stop = !of_property_read_bool(np, "always-on");
 
     /* Check for globally applicable workarounds */
@@ -1328,6 +1516,10 @@ static int __init arch_timer_of_init(struct device_node *np)
      * If we cannot rely on firmware initializing the timer registers then
      * we should use the physical timers instead.
      */
+/*
+ * IAMROOT, 2022.08.20:
+ * - 현재 kernel이 사용할 timer의 종류를 구한다.
+ */
     if (IS_ENABLED(CONFIG_ARM) &&
         of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
         arch_timer_uses_ppi = ARCH_TIMER_PHYS_SECURE_PPI;
@@ -1340,6 +1532,10 @@ static int __init arch_timer_of_init(struct device_node *np)
     }
 
     /* On some systems, the counter stops ticking when in suspend. */
+/*
+ * IAMROOT, 2022.08.20:
+ * - 절전시 interrupt on/off여부를 dts에서 prop를 통해 읽어온다.
+ */
     arch_counter_suspend_stop = of_property_read_bool(np,
                              "arm,no-tick-in-suspend");
 
@@ -1347,9 +1543,18 @@ static int __init arch_timer_of_init(struct device_node *np)
     if (ret)
         return ret;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - CP15가 위에서 설정되었고, MEM이 아직 설정안된상태에서 MEM이 dts에 있으면 return true로
+ *   probe해야되는 상태. MEM probe에서 arch_timer_common_init을 호출할것이다.
+ */
     if (arch_timer_needs_of_probing())
         return 0;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - MEM을 probe할 필요없거나 둘다 초기화됬으면 arch_timer_common_init()을 호출한다.
+ */
     return arch_timer_common_init();
 }
 TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
@@ -1464,6 +1669,41 @@ arch_timer_mem_frame_register(struct arch_timer_mem_frame *frame)
     return 0;
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - memory mapped 방식의 timer.
+ *   ioremap으로 vmap으로 mapping하며 해당 memory를 register로 사용하는 방법.
+ *
+ * ex) dts에서 사용한 예. cp15방식의 timer와 동시에 사용하는것이 보인다.
+ *     (qcom/ipq6018.dtsi)
+ *
+ * timer {
+ *    compatible = "arm,armv8-timer";
+ *    interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ *             <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ *             <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ *             <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ * };
+ *
+ * timer@b120000 {
+ *    #address-cells = <2>;
+ *    #size-cells = <2>;
+ *    ranges;
+ *    compatible = "arm,armv7-timer-mem";
+ *    reg = <0x0 0x0b120000 0x0 0x1000>; 
+ *    clock-frequency = <19200000>;
+ *
+ *    frame@b120000 {
+ *        frame-number = <0>;
+ *        interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ *                 <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ *        reg = <0x0 0x0b121000 0x0 0x1000>,
+ *              <0x0 0x0b122000 0x0 0x1000>;
+ *      };
+ *      ....
+ * }
+ *
+ */
 static int __init arch_timer_mem_of_init(struct device_node *np)
 {
     struct arch_timer_mem *timer_mem;
diff --git a/drivers/clocksource/bcm_kona_timer.c b/drivers/clocksource/bcm_kona_timer.c
index a50ab5c2154f..f7b32d7f4a26 100644
--- a/drivers/clocksource/bcm_kona_timer.c
+++ b/drivers/clocksource/bcm_kona_timer.c
@@ -41,6 +41,10 @@ struct kona_bcm_timers {
 
 static struct kona_bcm_timers timers;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - dts나 bootloader에서 읽어온 arch timer hz. dts가 우선된다.
+ */
 static u32 arch_timer_rate;
 
 /*
diff --git a/drivers/clocksource/timer-probe.c b/drivers/clocksource/timer-probe.c
index b7860bc0db4b..07c5cb275004 100644
--- a/drivers/clocksource/timer-probe.c
+++ b/drivers/clocksource/timer-probe.c
@@ -8,11 +8,20 @@
 #include <linux/of.h>
 #include <linux/clocksource.h>
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - compile time에 등록된 timer들.
+ *   ex) TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+ */
 extern struct of_device_id __timer_of_table[];
 
 static const struct of_device_id __timer_of_table_sentinel
     __used __section("__timer_of_table_end");
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - 
+ */
 void __init timer_probe(void)
 {
     struct device_node *np;
@@ -21,6 +30,25 @@ void __init timer_probe(void)
     unsigned timers = 0;
     int ret;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - compile time에 __timer_of_table에 등록된 driver들을 순회하며 dts와
+ *   매칭하며 ok된것들에 대해서 init함수를 호출한다
+ *   ex) TIMER_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
+ *   로 등록됬으면 arch_timer_of_init을 호출한다.
+ *
+ * ex) dts 예제
+ *
+ * timer {
+ *    compatible = "arm,armv8-timer";
+ *    interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, // Physical Secure
+ *             <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, // Physical Non-Secure
+ *             <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, // Virtual
+ *             <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; // Hypervisor
+ *    interrupt-parent = <&gic>;
+ *    arm,no-tick-in-suspend;
+ * };
+ */
     for_each_matching_node_and_match(np, __timer_of_table, &match) {
         if (!of_device_is_available(np))
             continue;
@@ -38,6 +66,10 @@ void __init timer_probe(void)
         timers++;
     }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - acpi 호출.
+ */
     timers += acpi_probe_device_table(timer);
 
     if (!timers)
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 352e14b007e7..c9b3303c23aa 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -384,6 +384,10 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource);
  * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
  * of any other failure.
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * - @index에 해당하는 irq번호를 가져온다.
+ */
 int of_irq_get(struct device_node *dev, int index)
 {
     int rc;
diff --git a/include/clocksource/arm_arch_timer.h b/include/clocksource/arm_arch_timer.h
index 73c7139c866f..300020ab4dca 100644
--- a/include/clocksource/arm_arch_timer.h
+++ b/include/clocksource/arm_arch_timer.h
@@ -27,6 +27,12 @@ enum arch_timer_reg {
     ARCH_TIMER_REG_TVAL,
 };
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - PPI : private peri irq. cpu당 개별 irq 지원.
+ * - ARCH_TIMER_PHYS_SECURE_PPI
+ *   arm의 경우 arm,cpu-registers-not-fw-configured prop가 있으면 사용한다.
+ */
 enum arch_timer_ppi_nr {
     ARCH_TIMER_PHYS_SECURE_PPI,
     ARCH_TIMER_PHYS_NONSECURE_PPI,
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 1d42d4b17327..2b8c839c6768 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -241,6 +241,10 @@ static inline int __clocksource_register(struct clocksource *cs)
     return __clocksource_register_scale(cs, 1, 0);
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - 
+ */
 static inline int clocksource_register_hz(struct clocksource *cs, u32 hz)
 {
     return __clocksource_register_scale(cs, 1, hz);
@@ -261,6 +265,10 @@ static inline void __clocksource_update_freq_khz(struct clocksource *cs, u32 khz
     __clocksource_update_freq_scale(cs, 1000, khz);
 }
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - arm은 없음.
+ */
 #ifdef CONFIG_ARCH_CLOCKSOURCE_INIT
 extern void clocksource_arch_init(struct clocksource *cs);
 #else
@@ -279,6 +287,10 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
 
 extern int clocksource_i8253_init(void);
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - __timer_of_table에 등록된다.
+ */
 #define TIMER_OF_DECLARE(name, compat, fn) \
     OF_DECLARE_1_RET(timer, name, compat, fn)
 
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index b8a14d2fb5ba..d7082bc17fc4 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -43,16 +43,49 @@
  * reduce the conversion accuracy by choosing smaller mult and shift
  * factors.
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * ex) from = 19200000, to = 10^9, maxsec = 600
+ * - sftacc 계산
+ *   600 * 19200000 = 0x2_AEA5_4000 => shift32 => 0x2
+ *   두번 loop를 돌면 sftacc = 30가 된다.
+ */
 void
 clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
 {
     u64 tmp;
+/*
+ * IAMROOT, 2022.08.20:
+ * - 정확도는 최대 32bit.
+ */
     u32 sft, sftacc= 32;
 
     /*
      * Calculate the shift factor which is limiting the conversion
      * range:
      */
+/*
+ * IAMROOT, 2022.08.20:
+ * 63..      55                                                      0
+ * | unusable |            counter                                   |
+ *
+ * |          |            empty            | sec(최대600) | freq    |
+ *
+ * 여기선 정확도용으로 사용할 bit를 계산한다.
+ *
+ * | 정확도용                 |               sec(최대600) | freq     |
+ *                            ^
+ *                            이 부분일거같은 bit를 찾는것.
+ *
+ * | 정확도용                 |               sec(최대600) | freq     |
+ * <----------- sftacc ------> <------- maxsec * from ---------------->
+ *                                       ^  
+ * ex) from = 19200000, to = 10^9, maxsec = 600, sftacc = 30
+ *
+ * | 정확도용                 |               sec(최대600) | freq     |
+ * <----------- sftacc ------> <------- maxsec * from ---------------->
+ *              30 bits       ^  34bit
+ */
     tmp = ((u64)maxsec * from) >> 32;
     while (tmp) {
         tmp >>=1;
@@ -63,6 +96,24 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 maxsec)
      * Find the conversion shift/mult pair which has the best
      * accuracy and fits the maxsec conversion range:
      */
+/*
+ * IAMROOT, 2022.08.20:
+ * - from * mult >> shift = to의 개념에서 mult, shift값을 구한다.
+ *   tmp = (to << sft + from / 2) / from
+ *
+ * - sftacc 내에서 처리될수있는 mult, shift값을 계산한다.
+ * - from / 2는 나머지를 고려해서, do_div(mult, from)를 할때 정확성을 조금 올리는것. 
+ * - from으로 위애서 sftacc(정확도)를 구하고, sftacc내의 범위에서 to값의 최종 정확도를 shift
+ *   한값이 들어오는지 계산하여 mult, sft값을 구한다.
+ *
+ * ex) from = 19200000, to = 10^9, maxsec = 600, sftacc = 30
+ * sft = 24이면
+ * tmp = 1000000000 << 24 = 16777216000000000
+ * tmp += 9600000
+ * tmp = do_div(16777216000000000,  19200000) = 873813333 = 0x3415_5555
+ * tmp >> sftasce = 0x3415_5555 >> 30 == 0
+ * mult = 0x3415_5555, shift = 24가 된다.
+ */
     for (sft = 32; sft > 0; sft--) {
         tmp = (u64) to << sft;
         tmp += from / 2;
@@ -1046,7 +1097,24 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
          * clocksource with mask >= 40-bit and f >= 4GHz. That maps to
          * ~ 0.06ppm granularity for NTP.
          */
+
+/*
+ * IAMROOT, 2022.08.20:
+ * - papago
+ *   둘러싸기 전에 실행할 수 있는 최대 시간(초)을 계산합니다. 마스크가 32비트보다 큰 클록
+ *   소스의 경우 좋은 변환 정밀도를 갖기 위해 최대 절전 시간을 제한해야 합니다. 10분은 여전히
+ *   적당한 양입니다. 그 결과 마스크 >= 40비트 및 f >= 4GHz인 클록 소스에 대해 시프트 값이 24가
+ *   됩니다. 이는 NTP의 경우 ~ 0.06ppm 단위로 매핑됩니다.
+ */
         sec = cs->mask;
+/*
+ * IAMROOT, 2022.08.20:
+ * - sec = sec / freq / scale
+ * ex) cs->mask = CLOCKSOURCE_MASK(56), freq = 19200000, scale = 1
+ * sec = 0xff_ffff_ffff_ffff / 19200000 = 3752999689 => clamp => 600
+ *
+ * clamp로 10분을 한계로 두고 정확도를 높이는 개념.
+ */
         do_div(sec, freq);
         do_div(sec, scale);
         if (!sec)
@@ -1054,6 +1122,12 @@ void __clocksource_update_freq_scale(struct clocksource *cs, u32 scale, u32 freq
         else if (sec > 600 && cs->mask > UINT_MAX)
             sec = 600;
 
+/*
+ * IAMROOT, 2022.08.20:
+ * - sec * scale시간을 한계로 freq -> NSEC_PER_SEC / scale이 되기 위한 mult, shift를 계산한다.
+ * ex) clocksource_counter에서 mask = CLOCKSOURCE_MASK(56)
+ * ex) cs->mask = CLOCKSOURCE_MASK(56), freq = 19200000, scale = 1, sec = 600
+ */
         clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
                        NSEC_PER_SEC / scale, sec * scale);
     }
@@ -1115,6 +1189,10 @@ EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale);
  * This *SHOULD NOT* be called directly! Please use the
  * clocksource_register_hz() or clocksource_register_khz helper functions.
  */
+/*
+ * IAMROOT, 2022.08.20:
+ * - scale * freq = 실제 freq
+ */
 int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
     unsigned long flags;
@@ -1123,6 +1201,11 @@ int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 
     if (WARN_ON_ONCE((unsigned int)cs->id >= CSID_MAX))
         cs->id = CSID_GENERIC;
+
+/*
+ * IAMROOT, 2022.08.20:
+ * ex) VDSO_CLOCKMODE_NONE, VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT
+ */
     if (cs->vdso_clock_mode < 0 ||
         cs->vdso_clock_mode >= VDSO_CLOCKMODE_MAX) {
         pr_warn("clocksource %s registered with invalid VDSO mode %d. Disabling VDSO support.\n",
 

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 626
147 [커널 18차] 66주차 kkr 2022.08.27 76
146 [커널 17차] 101~102주차 ㅇㅇㅇ 2022.08.21 47
» [커널 18차] 65주차 kkr 2022.08.20 28
144 [커널 18차] 64주차 kkr 2022.08.13 75
143 [커널 17차] 100주차 [1] ㅇㅇㅇ 2022.08.06 100
142 [커널 18차] 63주차 kkr 2022.08.06 102
141 [커널 17차] 99주차 ㅇㅇㅇ 2022.07.31 35
140 [커널 18차] 62주차 kkr 2022.07.30 26
139 [커널 17차] 97~98주차 ㅇㅇㅇ 2022.07.24 52
138 [커널 18차] 61주차 kkr 2022.07.23 113
137 [커널 18차] 60주차 kkr 2022.07.16 129
136 [커널 17차] 95~96주차 ㅇㅇㅇ 2022.07.10 105
135 [커널 18차] 59주차 kkr 2022.07.09 126
134 [커널 19차] 8주차 kanlee 2022.07.02 160
133 [커널 19차] 7주차 kanlee 2022.07.02 95
132 [커널 19차] 6주차 kanlee 2022.07.02 42
131 [커널 19차] 5주차 kanlee 2022.07.02 38
130 [커널 19차] 4주차 kanlee 2022.07.02 106
129 [커널 18차] 57주차 kkr 2022.06.25 129
128 [커널 17차] 94주차 ㅇㅇㅇ 2022.06.19 80
XE Login