forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 645e752c5a84baeb21015cdc85fc05b7d16312c8
kernel/Documentation/translations/ko_KR/memory-barriers.txt
....@@ -24,7 +24,7 @@
2424 =========================
2525
2626 저자: David Howells <dhowells@redhat.com>
27
- Paul E. McKenney <paulmck@linux.vnet.ibm.com>
27
+ Paul E. McKenney <paulmck@linux.ibm.com>
2828 Will Deacon <will.deacon@arm.com>
2929 Peter Zijlstra <peterz@infradead.org>
3030
....@@ -91,7 +91,6 @@
9191
9292 - 컴파일러 배리어.
9393 - CPU 메모리 배리어.
94
- - MMIO 쓰기 배리어.
9594
9695 (*) 암묵적 커널 메모리 배리어.
9796
....@@ -103,7 +102,6 @@
103102 (*) CPU 간 ACQUIRING 배리어의 효과.
104103
105104 - Acquire vs 메모리 액세스.
106
- - Acquire vs I/O 액세스.
107105
108106 (*) 메모리 배리어가 필요한 곳
109107
....@@ -493,10 +491,8 @@
493491 이 타입의 오퍼레이션은 단방향의 투과성 배리어처럼 동작합니다. ACQUIRE
494492 오퍼레이션 뒤의 모든 메모리 오퍼레이션들이 ACQUIRE 오퍼레이션 후에
495493 일어난 것으로 시스템의 나머지 컴포넌트들에 보이게 될 것이 보장됩니다.
496
- LOCK 오퍼레이션과 smp_load_acquire(), smp_cond_acquire() 오퍼레이션도
497
- ACQUIRE 오퍼레이션에 포함됩니다. smp_cond_acquire() 오퍼레이션은 컨트롤
498
- 의존성과 smp_rmb() 를 사용해서 ACQUIRE 의 의미적 요구사항(semantic)을
499
- 충족시킵니다.
494
+ LOCK 오퍼레이션과 smp_load_acquire(), smp_cond_load_acquire() 오퍼레이션도
495
+ ACQUIRE 오퍼레이션에 포함됩니다.
500496
501497 ACQUIRE 오퍼레이션 앞의 메모리 오퍼레이션들은 ACQUIRE 오퍼레이션 완료 후에
502498 수행된 것처럼 보일 수 있습니다.
....@@ -517,14 +513,13 @@
517513 완료되기 전에 행해진 것처럼 보일 수 있습니다.
518514
519515 ACQUIRE 와 RELEASE 오퍼레이션의 사용은 일반적으로 다른 메모리 배리어의
520
- 필요성을 없앱니다 (하지만 "MMIO 쓰기 배리어" 서브섹션에서 설명되는 예외를
521
- 알아두세요). 또한, RELEASE+ACQUIRE 조합은 범용 메모리 배리어처럼 동작할
522
- 것을 보장하지 -않습니다-. 하지만, 어떤 변수에 대한 RELEASE 오퍼레이션을
523
- 앞서는 메모리 액세스들의 수행 결과는 이 RELEASE 오퍼레이션을 뒤이어 같은
524
- 변수에 대해 수행된 ACQUIRE 오퍼레이션을 뒤따르는 메모리 액세스에는 보여질
525
- 것이 보장됩니다. 다르게 말하자면, 주어진 변수의 크리티컬 섹션에서는, 해당
526
- 변수에 대한 앞의 크리티컬 섹션에서의 모든 액세스들이 완료되었을 것을
527
- 보장합니다.
516
+ 필요성을 없앱니다. 또한, RELEASE+ACQUIRE 조합은 범용 메모리 배리어처럼
517
+ 동작할 것을 보장하지 -않습니다-. 하지만, 어떤 변수에 대한 RELEASE
518
+ 오퍼레이션을 앞서는 메모리 액세스들의 수행 결과는 이 RELEASE 오퍼레이션을
519
+ 뒤이어 같은 변수에 대해 수행된 ACQUIRE 오퍼레이션을 뒤따르는 메모리
520
+ 액세스에는 보여질 것이 보장됩니다. 다르게 말하자면, 주어진 변수의
521
+ 크리티컬 섹션에서는, 해당 변수에 대한 앞의 크리티컬 섹션에서의 모든
522
+ 액세스들이 완료되었을 것을 보장합니다.
528523
529524 즉, ACQUIRE 는 최소한의 "취득" 동작처럼, 그리고 RELEASE 는 최소한의 "공개"
530525 처럼 동작한다는 의미입니다.
....@@ -571,15 +566,15 @@
571566
572567 [*] 버스 마스터링 DMA 와 일관성에 대해서는 다음을 참고하시기 바랍니다:
573568
574
- Documentation/PCI/pci.txt
575
- Documentation/DMA-API-HOWTO.txt
576
- Documentation/DMA-API.txt
569
+ Documentation/driver-api/pci/pci.rst
570
+ Documentation/core-api/dma-api-howto.rst
571
+ Documentation/core-api/dma-api.rst
577572
578573
579574 데이터 의존성 배리어 (역사적)
580575 -----------------------------
581576
582
-리눅스 커널 v4.15 기준으로, smp_read_barrier_depends() 가 READ_ONCE() 에
577
+리눅스 커널 v4.15 기준으로, smp_mb() 가 DEC Alpha 용 READ_ONCE() 코드에
583578 추가되었는데, 이는 이 섹션에 주의를 기울여야 하는 사람들은 DEC Alpha 아키텍쳐
584579 전용 코드를 만드는 사람들과 READ_ONCE() 자체를 만드는 사람들 뿐임을 의미합니다.
585580 그런 분들을 위해, 그리고 역사에 관심 있는 분들을 위해, 여기 데이터 의존성
....@@ -643,7 +638,7 @@
643638 리눅스 커널이 지원하는 CPU 들은 (1) 쓰기가 정말로 일어날지, (2) 쓰기가 어디에
644639 이루어질지, 그리고 (3) 쓰여질 값을 확실히 알기 전까지는 쓰기를 수행하지 않기
645640 때문입니다. 하지만 "컨트롤 의존성" 섹션과
646
-Documentation/RCU/rcu_dereference.txt 파일을 주의 깊게 읽어 주시기 바랍니다:
641
+Documentation/RCU/rcu_dereference.rst 파일을 주의 깊게 읽어 주시기 바랍니다:
647642 컴파일러는 매우 창의적인 많은 방법으로 종속성을 깰 수 있습니다.
648643
649644 CPU 1 CPU 2
....@@ -1503,8 +1498,6 @@
15031498
15041499 (*) CPU 메모리 배리어.
15051500
1506
- (*) MMIO 쓰기 배리어.
1507
-
15081501
15091502 컴파일러 배리어
15101503 ---------------
....@@ -1844,12 +1837,15 @@
18441837 (*) smp_mb__before_atomic();
18451838 (*) smp_mb__after_atomic();
18461839
1847
- 이것들은 값을 리턴하지 않는 (더하기, 빼기, 증가, 감소와 같은) 어토믹
1848
- 함수들을 위한, 특히 그것들이 레퍼런스 카운팅에 사용될 때를 위한
1849
- 함수들입니다. 이 함수들은 메모리 배리어를 내포하고 있지는 않습니다.
1840
+ 이것들은 메모리 배리어를 내포하지 않는 어토믹 RMW 함수를 사용하지만 코드에
1841
+ 메모리 배리어가 필요한 경우를 위한 것들입니다. 메모리 배리어를 내포하지
1842
+ 않는 어토믹 RMW 함수들의 예로는 더하기, 빼기, (실패한) 조건적
1843
+ 오퍼레이션들, _relaxed 함수들이 있으며, atomic_read 나 atomic_set 은 이에
1844
+ 해당되지 않습니다. 메모리 배리어가 필요해지는 흔한 예로는 어토믹
1845
+ 오퍼레이션을 사용해 레퍼런스 카운트를 수정하는 경우를 들 수 있습니다.
18501846
1851
- 이것들은 값을 리턴하지 않으며 어토믹한 (set_bit 과 clear_bit 같은) 비트
1852
- 연산에도 사용될 수 있습니다.
1847
+ 이것들은 또한 (set_bit 과 clear_bit 같은) 메모리 배리어를 내포하지 않는
1848
+ 어토믹 RMW bitop 함수들을 위해서도 사용될 수 있습니다.
18531849
18541850 한 예로, 객체 하나를 무효한 것으로 표시하고 그 객체의 레퍼런스 카운트를
18551851 감소시키는 다음 코드를 보세요:
....@@ -1906,23 +1902,21 @@
19061902
19071903 writel_relaxed() 와 같은 완화된 I/O 접근자들에 대한 자세한 내용을 위해서는
19081904 "커널 I/O 배리어의 효과" 섹션을, consistent memory 에 대한 자세한 내용을
1909
- 위해선 Documentation/DMA-API.txt 문서를 참고하세요.
1905
+ 위해선 Documentation/core-api/dma-api.rst 문서를 참고하세요.
19101906
1907
+ (*) pmem_wmb();
19111908
1912
-MMIO 쓰기 배리어
1913
-----------------
1909
+ 이것은 persistent memory 를 위한 것으로, persistent 저장소에 가해진 변경
1910
+ 사항이 플랫폼 연속성 도메인에 도달했을 것을 보장하기 위한 것입니다.
19141911
1915
-리눅스 커널은 또한 memory-mapped I/O 쓰기를 위한 특별한 배리어도 가지고
1916
-있습니다:
1912
+ 예를 들어, 임시적이지 않은 pmem 영역으로의 쓰기 후, 우리는 쓰기가 플랫폼
1913
+ 연속성 도메인에 도달했을 것을 보장하기 위해 pmem_wmb() 를 사용합니다.
1914
+ 이는 쓰기가 뒤따르는 instruction 들이 유발하는 어떠한 데이터 액세스나
1915
+ 데이터 전송의 시작 전에 persistent 저장소를 업데이트 했을 것을 보장합니다.
1916
+ 이는 wmb() 에 의해 이뤄지는 순서 규칙을 포함합니다.
19171917
1918
- mmiowb();
1919
-
1920
-이것은 mandatory 쓰기 배리어의 변종으로, 완화된 순서 규칙의 I/O 영역에으로의
1921
-쓰기가 부분적으로 순서를 맞추도록 해줍니다. 이 함수는 CPU->하드웨어 사이를
1922
-넘어서 실제 하드웨어에까지 일부 수준의 영향을 끼칩니다.
1923
-
1924
-더 많은 정보를 위해선 "Acquire vs I/O 액세스" 서브섹션을 참고하세요.
1925
-
1918
+ Persistent memory 에서의 로드를 위해선 현재의 읽기 메모리 배리어로도 읽기
1919
+ 순서를 보장하는데 충분합니다.
19261920
19271921 =========================
19281922 암묵적 커널 메모리 배리어
....@@ -2146,33 +2140,40 @@
21462140 event_indicated = 1;
21472141 wake_up_process(event_daemon);
21482142
2149
-wake_up() 류에 의해 쓰기 메모리 배리어가 내포됩니다. 만약 그것들이 뭔가를
2150
-깨운다면요. 이 배리어는 태스크 상태가 지워지기 전에 수행되므로, 이벤트를
2151
-알리기 위한 STORE 와 태스크 상태를 TASK_RUNNING 으로 설정하는 STORE 사이에
2152
-위치하게 됩니다.
2143
+wake_up() 이 무언가를 깨우게 되면, 이 함수는 범용 메모리 배리어를 수행합니다.
2144
+이 함수가 아무것도 깨우지 않는다면 메모리 배리어는 수행될 수도, 수행되지 않을
2145
+수도 있습니다; 이 경우에 메모리 배리어를 수행할 거라 오해해선 안됩니다. 이
2146
+배리어는 태스크 상태가 접근되기 전에 수행되는데, 자세히 말하면 이 이벤트를
2147
+알리기 위한 STORE 와 TASK_RUNNING 으로 상태를 쓰는 STORE 사이에 수행됩니다:
21532148
2154
- CPU 1 CPU 2
2149
+ CPU 1 (Sleeper) CPU 2 (Waker)
21552150 =============================== ===============================
21562151 set_current_state(); STORE event_indicated
21572152 smp_store_mb(); wake_up();
2158
- STORE current->state <쓰기 배리어>
2159
- <범용 배리어> STORE current->state
2160
- LOAD event_indicated
2153
+ STORE current->state ...
2154
+ <범용 배리어> <범용 배리어>
2155
+ LOAD event_indicated if ((LOAD task->state) & TASK_NORMAL)
2156
+ STORE task->state
21612157
2162
-한번더 말합니다만, 이 쓰기 메모리 배리어는 이 코드가 정말로 뭔가를 깨울 때에만
2163
-실행됩니다. 이걸 설명하기 위해, X 와 Y 는 모두 0 으로 초기화 되어 있다는 가정
2164
-하에 아래의 이벤트 시퀀스를 생각해 봅시다:
2158
+여기서 "task" 는 깨어나지는 쓰레드이고 CPU 1 의 "current" 와 같습니다.
2159
+
2160
+반복하지만, wake_up() 이 무언가를 정말 깨운다면 범용 메모리 배리어가 수행될
2161
+것이 보장되지만, 그렇지 않다면 그런 보장이 없습니다. 이걸 이해하기 위해, X 와
2162
+Y 는 모두 0 으로 초기화 되어 있다는 가정 하에 아래의 이벤트 시퀀스를 생각해
2163
+봅시다:
21652164
21662165 CPU 1 CPU 2
21672166 =============================== ===============================
2168
- X = 1; STORE event_indicated
2167
+ X = 1; Y = 1;
21692168 smp_mb(); wake_up();
2170
- Y = 1; wait_event(wq, Y == 1);
2171
- wake_up(); load from Y sees 1, no memory barrier
2172
- load from X might see 0
2169
+ LOAD Y LOAD X
21732170
2174
-위 예제에서의 경우와 달리 깨우기가 정말로 행해졌다면, CPU 2 의 X 로드는 1 을
2175
-본다고 보장될 수 있을 겁니다.
2171
+정말로 깨우기가 행해졌다면, 두 로드 중 (최소한) 하나는 1 을 보게 됩니다.
2172
+반면에, 실제 깨우기가 행해지지 않았다면, 두 로드 모두 0을 볼 수도 있습니다.
2173
+
2174
+wake_up_process() 는 항상 범용 메모리 배리어를 수행합니다. 이 배리어 역시
2175
+태스크 상태가 접근되기 전에 수행됩니다. 특히, 앞의 예제 코드에서 wake_up() 이
2176
+wake_up_process() 로 대체된다면 두 로드 중 하나는 1을 볼 것이 보장됩니다.
21762177
21772178 사용 가능한 깨우기류 함수들로 다음과 같은 것들이 있습니다:
21782179
....@@ -2192,6 +2193,8 @@
21922193 wake_up_poll();
21932194 wake_up_process();
21942195
2196
+메모리 순서규칙 관점에서, 이 함수들은 모두 wake_up() 과 같거나 보다 강한 순서
2197
+보장을 제공합니다.
21952198
21962199 [!] 잠재우는 코드와 깨우는 코드에 내포되는 메모리 배리어들은 깨우기 전에
21972200 이루어진 스토어를 잠재우는 코드가 set_current_state() 를 호출한 후에 행하는
....@@ -2274,73 +2277,6 @@
22742277 *A, *B or *C following RELEASE M
22752278 *F, *G or *H preceding ACQUIRE Q
22762279 *E, *F or *G following RELEASE Q
2277
-
2278
-
2279
-
2280
-ACQUIRE VS I/O 액세스
2281
-----------------------
2282
-
2283
-특정한 (특히 NUMA 가 관련된) 환경 하에서 두개의 CPU 에서 동일한 스핀락으로
2284
-보호되는 두개의 크리티컬 섹션 안의 I/O 액세스는 PCI 브릿지에 겹쳐진 I/O
2285
-액세스로 보일 수 있는데, PCI 브릿지는 캐시 일관성 프로토콜과 합을 맞춰야 할
2286
-의무가 없으므로, 필요한 읽기 메모리 배리어가 요청되지 않기 때문입니다.
2287
-
2288
-예를 들어서:
2289
-
2290
- CPU 1 CPU 2
2291
- =============================== ===============================
2292
- spin_lock(Q)
2293
- writel(0, ADDR)
2294
- writel(1, DATA);
2295
- spin_unlock(Q);
2296
- spin_lock(Q);
2297
- writel(4, ADDR);
2298
- writel(5, DATA);
2299
- spin_unlock(Q);
2300
-
2301
-는 PCI 브릿지에 다음과 같이 보일 수 있습니다:
2302
-
2303
- STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
2304
-
2305
-이렇게 되면 하드웨어의 오동작을 일으킬 수 있습니다.
2306
-
2307
-
2308
-이런 경우엔 잡아둔 스핀락을 내려놓기 전에 mmiowb() 를 수행해야 하는데, 예를
2309
-들면 다음과 같습니다:
2310
-
2311
- CPU 1 CPU 2
2312
- =============================== ===============================
2313
- spin_lock(Q)
2314
- writel(0, ADDR)
2315
- writel(1, DATA);
2316
- mmiowb();
2317
- spin_unlock(Q);
2318
- spin_lock(Q);
2319
- writel(4, ADDR);
2320
- writel(5, DATA);
2321
- mmiowb();
2322
- spin_unlock(Q);
2323
-
2324
-이 코드는 CPU 1 에서 요청된 두개의 스토어가 PCI 브릿지에 CPU 2 에서 요청된
2325
-스토어들보다 먼저 보여짐을 보장합니다.
2326
-
2327
-
2328
-또한, 같은 디바이스에서 스토어를 이어 로드가 수행되면 이 로드는 로드가 수행되기
2329
-전에 스토어가 완료되기를 강제하므로 mmiowb() 의 필요가 없어집니다:
2330
-
2331
- CPU 1 CPU 2
2332
- =============================== ===============================
2333
- spin_lock(Q)
2334
- writel(0, ADDR)
2335
- a = readl(DATA);
2336
- spin_unlock(Q);
2337
- spin_lock(Q);
2338
- writel(4, ADDR);
2339
- b = readl(DATA);
2340
- spin_unlock(Q);
2341
-
2342
-
2343
-더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하세요.
23442280
23452281
23462282 =========================
....@@ -2487,14 +2423,9 @@
24872423 리눅스 커널 내부에서, I/O 는 어떻게 액세스들을 적절히 순차적이게 만들 수 있는지
24882424 알고 있는, - inb() 나 writel() 과 같은 - 적절한 액세스 루틴을 통해 이루어져야만
24892425 합니다. 이것들은 대부분의 경우에는 명시적 메모리 배리어 와 함께 사용될 필요가
2490
-없습니다만, 다음의 두가지 상황에서는 명시적 메모리 배리어가 필요할 수 있습니다:
2491
-
2492
- (1) 일부 시스템에서 I/O 스토어는 모든 CPU 에 일관되게 순서 맞춰지지 않는데,
2493
- 따라서 _모든_ 일반적인 드라이버들에 락이 사용되어야만 하고 이 크리티컬
2494
- 섹션을 빠져나오기 전에 mmiowb() 가 꼭 호출되어야 합니다.
2495
-
2496
- (2) 만약 액세스 함수들이 완화된 메모리 액세스 속성을 갖는 I/O 메모리 윈도우를
2497
- 사용한다면, 순서를 강제하기 위해선 _mandatory_ 메모리 배리어가 필요합니다.
2426
+없습니다만, 완화된 메모리 액세스 속성으로 I/O 메모리 윈도우로의 참조를 위해
2427
+액세스 함수가 사용된다면 순서를 강제하기 위해 _mandatory_ 메모리 배리어가
2428
+필요합니다.
24982429
24992430 더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하십시오.
25002431
....@@ -2538,10 +2469,9 @@
25382469 인터럽트 내에서 일어난 액세스와 섞일 수 있다고 - 그리고 그 반대도 - 가정해야만
25392470 합니다.
25402471
2541
-그런 영역 안에서 일어나는 I/O 액세스들은 엄격한 순서 규칙의 I/O 레지스터에
2542
-묵시적 I/O 배리어를 형성하는 동기적 (synchronous) 로드 오퍼레이션을 포함하기
2543
-때문에 일반적으로는 이런게 문제가 되지 않습니다. 만약 이걸로는 충분치 않다면
2544
-mmiowb() 가 명시적으로 사용될 필요가 있습니다.
2472
+그런 영역 안에서 일어나는 I/O 액세스는 묵시적 I/O 배리어를 형성하는, 엄격한
2473
+순서 규칙의 I/O 레지스터로의 로드 오퍼레이션을 포함하기 때문에 일반적으로는
2474
+문제가 되지 않습니다.
25452475
25462476
25472477 하나의 인터럽트 루틴과 별도의 CPU 에서 수행중이며 서로 통신을 하는 두 루틴
....@@ -2553,67 +2483,102 @@
25532483 커널 I/O 배리어의 효과
25542484 ======================
25552485
2556
-I/O 메모리에 액세스할 때, 드라이버는 적절한 액세스 함수를 사용해야 합니다:
2557
-
2558
- (*) inX(), outX():
2559
-
2560
- 이것들은 메모리 공간보다는 I/O 공간에 이야기를 하려는 의도로
2561
- 만들어졌습니다만, 그건 기본적으로 CPU 마다 다른 컨셉입니다. i386 과
2562
- x86_64 프로세서들은 특별한 I/O 공간 액세스 사이클과 명령어를 실제로 가지고
2563
- 있지만, 다른 많은 CPU 들에는 그런 컨셉이 존재하지 않습니다.
2564
-
2565
- 다른 것들 중에서도 PCI 버스가 I/O 공간 컨셉을 정의하는데, 이는 - i386 과
2566
- x86_64 같은 CPU 에서 - CPU 의 I/O 공간 컨셉으로 쉽게 매치됩니다. 하지만,
2567
- 대체할 I/O 공간이 없는 CPU 에서는 CPU 의 메모리 맵의 가상 I/O 공간으로
2568
- 매핑될 수도 있습니다.
2569
-
2570
- 이 공간으로의 액세스는 (i386 등에서는) 완전하게 동기화 됩니다만, 중간의
2571
- (PCI 호스트 브리지와 같은) 브리지들은 이를 완전히 보장하진 않을수도
2572
- 있습니다.
2573
-
2574
- 이것들의 상호간의 순서는 완전하게 보장됩니다.
2575
-
2576
- 다른 타입의 메모리 오퍼레이션, I/O 오퍼레이션에 대한 순서는 완전하게
2577
- 보장되지는 않습니다.
2486
+I/O 액세스를 통한 주변장치와의 통신은 아키텍쳐와 기기에 매우 종속적입니다.
2487
+따라서, 본질적으로 이식성이 없는 드라이버는 가능한 가장 적은 오버헤드로
2488
+동기화를 하기 위해 각자의 타겟 시스템의 특정 동작에 의존할 겁니다. 다양한
2489
+아키텍쳐와 버스 구현에 이식성을 가지려 하는 드라이버를 위해, 커널은 다양한
2490
+정도의 순서 보장을 제공하는 일련의 액세스 함수를 제공합니다.
25782491
25792492 (*) readX(), writeX():
25802493
2581
- 이것들이 수행 요청되는 CPU 에서 서로에게 완전히 순서가 맞춰지고 독립적으로
2582
- 수행되는지에 대한 보장 여부는 이들이 액세스 하는 메모리 윈도우에 정의된
2583
- 특성에 의해 결정됩니다. 예를 들어, 최신의 i386 아키텍쳐 머신에서는 MTRR
2584
- 레지스터로 이 특성이 조정됩니다.
2494
+ readX() 와 writeX() MMIO 액세스 함수는 접근되는 주변장치로의 포인터를
2495
+ __iomem * 패러미터로 받습니다. 디폴트 I/O 기능으로 매핑되는 포인터
2496
+ (예: ioremap() 으로 반환되는 것) 의 순서 보장은 다음과 같습니다:
25852497
2586
- 일반적으로는, 프리페치 (prefetch) 가능한 디바이스를 액세스 하는게
2587
- 아니라면, 이것들은 완전히 순서가 맞춰지고 결합되지 않게 보장될 겁니다.
2498
+ 1. 같은 주변장치로의 모든 readX() 와 writeX() 액세스는 각자에 대해
2499
+ 순서지어집니다. 이는 같은 CPU 쓰레드에 의한 특정 디바이스로의 MMIO
2500
+ 레지스터 액세스가 프로그램 순서대로 도착할 것을 보장합니다.
25882501
2589
- 하지만, (PCI 브리지와 같은) 중간의 하드웨어는 자신이 원한다면 집행을
2590
- 연기시킬 수 있습니다; 스토어 명령을 실제로 하드웨어로 내려보내기(flush)
2591
- 위해서는 같은 위치로부터 로드를 하는 방법이 있습니다만[*], PCI 의 경우는
2592
- 같은 디바이스나 환경 구성 영역에서의 로드만으로도 충분할 겁니다.
2502
+ 2. 한 스핀락을 잡은 CPU 쓰레드에 의한 writeX() 는 같은 스핀락을 나중에
2503
+ 잡은 다른 CPU 쓰레드에 의해 같은 주변장치를 향해 호출된 writeX()
2504
+ 앞으로 순서지어집니다. 이는 스핀락을 잡은 채 특정 디바이스를 향해
2505
+ 호출된 MMIO 레지스터 쓰기는 해당 락의 획득에 일관적인 순서로 도달할
2506
+ 것을 보장합니다.
25932507
2594
- [*] 주의! 쓰여진 것과 같은 위치로부터의 로드를 시도하는 것은 오동작을
2595
- 일으킬 수도 있습니다 - 예로 16650 Rx/Tx 시리얼 레지스터를 생각해
2596
- 보세요.
2508
+ 3. 특정 주변장치를 향한 특정 CPU 쓰레드의 writeX() 는 먼저 해당
2509
+ 쓰레드로 전파되는, 또는 해당 쓰레드에 의해 요청된 모든 앞선 메모리
2510
+ 쓰기가 완료되기 전까지 먼저 기다립니다. 이는 dma_alloc_coherent()
2511
+ 를 통해 할당된 전송용 DMA 버퍼로의 해당 CPU 의 쓰기가 이 CPU 가 이
2512
+ 전송을 시작시키기 위해 MMIO 컨트롤 레지스터에 쓰기를 할 때 DMA
2513
+ 엔진에 보여질 것을 보장합니다.
25972514
2598
- 프리페치 가능한 I/O 메모리가 사용되면, 스토어 명령들이 순서를 지키도록
2599
- 하기 위해 mmiowb() 배리어가 필요할 수 있습니다.
2515
+ 4. 특정 CPU 쓰레드에 의한 주변장치로의 readX() 는 같은 쓰레드에 의한
2516
+ 모든 뒤따르는 메모리 읽기가 시작되기 전에 완료됩니다. 이는
2517
+ dma_alloc_coherent() 를 통해 할당된 수신용 DMA 버퍼로부터의 CPU 의
2518
+ 읽기는 이 DMA 수신의 완료를 표시하는 DMA 엔진의 MMIO 상태 레지스터
2519
+ 읽기 후에는 오염된 데이터를 읽지 않을 것을 보장합니다.
26002520
2601
- PCI 트랜잭션 사이의 상호작용에 대해 더 많은 정보를 위해선 PCI 명세서를
2602
- 참고하시기 바랍니다.
2521
+ 5. CPU 에 의한 주변장치로의 readX() 는 모든 뒤따르는 delay() 루프가
2522
+ 수행을 시작하기 전에 완료됩니다. 이는 CPU 의 특정
2523
+ 주변장치로의 두개의 MMIO 레지스터 쓰기가 행해지는데 첫번째 쓰기가
2524
+ readX() 를 통해 곧바로 읽어졌고 이어 두번째 writeX() 전에 udelay(1)
2525
+ 이 호출되었다면 이 두개의 쓰기는 최소 1us 의 간격을 두고 행해질 것을
2526
+ 보장합니다:
2527
+
2528
+ writel(42, DEVICE_REGISTER_0); // 디바이스에 도착함...
2529
+ readl(DEVICE_REGISTER_0);
2530
+ udelay(1);
2531
+ writel(42, DEVICE_REGISTER_1); // ...이것보다 최소 1us 전에.
2532
+
2533
+ 디폴트가 아닌 기능을 통해 얻어지는 __iomem 포인터 (예: ioremap_wc() 를
2534
+ 통해 리턴되는 것) 의 순서 속성은 실제 아키텍쳐에 의존적이어서 이런
2535
+ 종류의 매핑으로의 액세스는 앞서 설명된 보장사항에 의존할 수 없습니다.
26032536
26042537 (*) readX_relaxed(), writeX_relaxed()
26052538
2606
- 이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서 보장을
2607
- 제공합니다. 구체적으로, 이것들은 일반적 메모리 액세스 (예: DMA 버퍼) 에도
2608
- LOCK 이나 UNLOCK 오퍼레이션들에도 순서를 보장하지 않습니다. LOCK 이나
2609
- UNLOCK 오퍼레이션들에 맞춰지는 순서가 필요하다면, mmiowb() 배리어가 사용될
2610
- 수 있습니다. 같은 주변 장치에의 완화된 액세스끼리는 순서가 지켜짐을 알아
2611
- 두시기 바랍니다.
2539
+ 이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서
2540
+ 보장을 제공합니다. 구체적으로, 이것들은 일반적 메모리 액세스나 delay()
2541
+ 루프 (예:앞의 2-5 항목) 에 대해 순서를 보장하지 않습니다만 디폴트 I/O
2542
+ 기능으로 매핑된 __iomem 포인터에 대해 동작할 때, 같은 CPU 쓰레드에 의한
2543
+ 같은 주변장치로의 액세스에는 순서가 맞춰질 것이 보장됩니다.
2544
+
2545
+ (*) readsX(), writesX():
2546
+
2547
+ readsX() 와 writesX() MMIO 액세스 함수는 DMA 를 수행하는데 적절치 않은,
2548
+ 주변장치 내의 메모리 매핑된 레지스터 기반 FIFO 로의 액세스를 위해
2549
+ 설계되었습니다. 따라서, 이 기능들은 앞서 설명된 readX_relaxed() 와
2550
+ writeX_relaxed() 의 순서 보장만을 제공합니다.
2551
+
2552
+ (*) inX(), outX():
2553
+
2554
+ inX() 와 outX() 액세스 함수는 일부 아키텍쳐 (특히 x86) 에서는 특수한
2555
+ 명령어를 필요로 하며 포트에 매핑되는, 과거의 유산인 I/O 주변장치로의
2556
+ 접근을 위해 만들어졌습니다.
2557
+
2558
+ 많은 CPU 아키텍쳐가 결국은 이런 주변장치를 내부의 가상 메모리 매핑을
2559
+ 통해 접근하기 때문에, inX() 와 outX() 가 제공하는 이식성 있는 순서
2560
+ 보장은 디폴트 I/O 기능을 통한 매핑을 접근할 때의 readX() 와 writeX() 에
2561
+ 의해 제공되는 것과 각각 동일합니다.
2562
+
2563
+ 디바이스 드라이버는 outX() 가 리턴하기 전에 해당 I/O 주변장치로부터의
2564
+ 완료 응답을 기다리는 쓰기 트랜잭션을 만들어 낸다고 기대할 수도
2565
+ 있습니다. 이는 모든 아키텍쳐에서 보장되지는 않고, 따라서 이식성 있는
2566
+ 순서 규칙의 일부분이 아닙니다.
2567
+
2568
+ (*) insX(), outsX():
2569
+
2570
+ 앞에서와 같이, insX() 와 outsX() 액세스 함수는 디폴트 I/O 기능을 통한
2571
+ 매핑을 접근할 때 각각 readX() 와 writeX() 와 같은 순서 보장을
2572
+ 제공합니다.
26122573
26132574 (*) ioreadX(), iowriteX()
26142575
2615
- 이것들은 inX()/outX() 나 readX()/writeX() 처럼 실제로 수행하는 액세스의
2616
- 종류에 따라 적절하게 수행될 것입니다.
2576
+ 이것들은 inX()/outX() 나 readX()/writeX() 처럼 실제로 수행하는 액세스의
2577
+ 종류에 따라 적절하게 수행될 것입니다.
2578
+
2579
+String 액세스 함수 (insX(), outsX(), readsX() 그리고 writesX()) 의 예외를
2580
+제외하고는, 앞의 모든 것이 아랫단의 주변장치가 little-endian 이라 가정하며,
2581
+따라서 big-endian 아키텍쳐에서는 byte-swapping 오퍼레이션을 수행합니다.
26172582
26182583
26192584 ===================================
....@@ -2705,144 +2670,6 @@
27052670 여부는 디바이스가 액세스 되는 메모리 윈도우의 특성에 의해 결정될 수도 있고, CPU
27062671 가 가지고 있을 수 있는 특수한 디바이스 통신 인스트럭션의 사용에 의해서 결정될
27072672 수도 있습니다.
2708
-
2709
-
2710
-캐시 일관성
2711
------------
2712
-
2713
-하지만 삶은 앞에서 이야기한 것처럼 단순하지 않습니다: 캐시들은 일관적일 것으로
2714
-기대되지만, 그 일관성이 순서에도 적용될 거라는 보장은 없습니다. 한 CPU 에서
2715
-만들어진 변경 사항은 최종적으로는 시스템의 모든 CPU 에게 보여지게 되지만, 다른
2716
-CPU 들에게도 같은 순서로 보이게 될 거라는 보장은 없다는 뜻입니다.
2717
-
2718
-
2719
-두개의 CPU (1 & 2) 가 달려 있고, 각 CPU 에 두개의 데이터 캐시(CPU 1 은 A/B 를,
2720
-CPU 2 는 C/D 를 갖습니다)가 병렬로 연결되어 있는 시스템을 다룬다고 생각해
2721
-봅시다:
2722
-
2723
- :
2724
- : +--------+
2725
- : +---------+ | |
2726
- +--------+ : +--->| Cache A |<------->| |
2727
- | | : | +---------+ | |
2728
- | CPU 1 |<---+ | |
2729
- | | : | +---------+ | |
2730
- +--------+ : +--->| Cache B |<------->| |
2731
- : +---------+ | |
2732
- : | Memory |
2733
- : +---------+ | System |
2734
- +--------+ : +--->| Cache C |<------->| |
2735
- | | : | +---------+ | |
2736
- | CPU 2 |<---+ | |
2737
- | | : | +---------+ | |
2738
- +--------+ : +--->| Cache D |<------->| |
2739
- : +---------+ | |
2740
- : +--------+
2741
- :
2742
-
2743
-이 시스템이 다음과 같은 특성을 갖는다 생각해 봅시다:
2744
-
2745
- (*) 홀수번 캐시라인은 캐시 A, 캐시 C 또는 메모리에 위치할 수 있음;
2746
-
2747
- (*) 짝수번 캐시라인은 캐시 B, 캐시 D 또는 메모리에 위치할 수 있음;
2748
-
2749
- (*) CPU 코어가 한개의 캐시에 접근하는 동안, 다른 캐시는 - 더티 캐시라인을
2750
- 메모리에 내리거나 추측성 로드를 하거나 하기 위해 - 시스템의 다른 부분에
2751
- 액세스 하기 위해 버스를 사용할 수 있음;
2752
-
2753
- (*) 각 캐시는 시스템의 나머지 부분들과 일관성을 맞추기 위해 해당 캐시에
2754
- 적용되어야 할 오퍼레이션들의 큐를 가짐;
2755
-
2756
- (*) 이 일관성 큐는 캐시에 이미 존재하는 라인에 가해지는 평범한 로드에 의해서는
2757
- 비워지지 않는데, 큐의 오퍼레이션들이 이 로드의 결과에 영향을 끼칠 수 있다
2758
- 할지라도 그러함.
2759
-
2760
-이제, 첫번째 CPU 에서 두개의 쓰기 오퍼레이션을 만드는데, 해당 CPU 의 캐시에
2761
-요청된 순서로 오퍼레이션이 도달됨을 보장하기 위해 두 오퍼레이션 사이에 쓰기
2762
-배리어를 사용하는 상황을 상상해 봅시다:
2763
-
2764
- CPU 1 CPU 2 COMMENT
2765
- =============== =============== =======================================
2766
- u == 0, v == 1 and p == &u, q == &u
2767
- v = 2;
2768
- smp_wmb(); v 의 변경이 p 의 변경 전에 보일 것을
2769
- 분명히 함
2770
- <A:modify v=2> v 는 이제 캐시 A 에 독점적으로 존재함
2771
- p = &v;
2772
- <B:modify p=&v> p 는 이제 캐시 B 에 독점적으로 존재함
2773
-
2774
-여기서의 쓰기 메모리 배리어는 CPU 1 의 캐시가 올바른 순서로 업데이트 된 것으로
2775
-시스템의 다른 CPU 들이 인지하게 만듭니다. 하지만, 이제 두번째 CPU 가 그 값들을
2776
-읽으려 하는 상황을 생각해 봅시다:
2777
-
2778
- CPU 1 CPU 2 COMMENT
2779
- =============== =============== =======================================
2780
- ...
2781
- q = p;
2782
- x = *q;
2783
-
2784
-위의 두개의 읽기 오퍼레이션은 예상된 순서로 일어나지 못할 수 있는데, 두번째 CPU
2785
-의 한 캐시에 다른 캐시 이벤트가 발생해 v 를 담고 있는 캐시라인의 해당 캐시에의
2786
-업데이트가 지연되는 사이, p 를 담고 있는 캐시라인은 두번째 CPU 의 다른 캐시에
2787
-업데이트 되어버렸을 수 있기 때문입니다.
2788
-
2789
- CPU 1 CPU 2 COMMENT
2790
- =============== =============== =======================================
2791
- u == 0, v == 1 and p == &u, q == &u
2792
- v = 2;
2793
- smp_wmb();
2794
- <A:modify v=2> <C:busy>
2795
- <C:queue v=2>
2796
- p = &v; q = p;
2797
- <D:request p>
2798
- <B:modify p=&v> <D:commit p=&v>
2799
- <D:read p>
2800
- x = *q;
2801
- <C:read *q> 캐시에 업데이트 되기 전의 v 를 읽음
2802
- <C:unbusy>
2803
- <C:commit v=2>
2804
-
2805
-기본적으로, 두개의 캐시라인 모두 CPU 2 에 최종적으로는 업데이트 될 것이지만,
2806
-별도의 개입 없이는, 업데이트의 순서가 CPU 1 에서 만들어진 순서와 동일할
2807
-것이라는 보장이 없습니다.
2808
-
2809
-
2810
-여기에 개입하기 위해선, 데이터 의존성 배리어나 읽기 배리어를 로드 오퍼레이션들
2811
-사이에 넣어야 합니다 (v4.15 부터는 READ_ONCE() 매크로에 의해 무조건적으로
2812
-그렇게 됩니다). 이렇게 함으로써 캐시가 다음 요청을 처리하기 전에 일관성 큐를
2813
-처리하도록 강제하게 됩니다.
2814
-
2815
- CPU 1 CPU 2 COMMENT
2816
- =============== =============== =======================================
2817
- u == 0, v == 1 and p == &u, q == &u
2818
- v = 2;
2819
- smp_wmb();
2820
- <A:modify v=2> <C:busy>
2821
- <C:queue v=2>
2822
- p = &v; q = p;
2823
- <D:request p>
2824
- <B:modify p=&v> <D:commit p=&v>
2825
- <D:read p>
2826
- smp_read_barrier_depends()
2827
- <C:unbusy>
2828
- <C:commit v=2>
2829
- x = *q;
2830
- <C:read *q> 캐시에 업데이트 된 v 를 읽음
2831
-
2832
-
2833
-이런 부류의 문제는 DEC Alpha 계열 프로세서들에서 발견될 수 있는데, 이들은
2834
-데이터 버스를 좀 더 잘 사용해 성능을 개선할 수 있는, 분할된 캐시를 가지고 있기
2835
-때문입니다. 대부분의 CPU 는 하나의 읽기 오퍼레이션의 메모리 액세스가 다른 읽기
2836
-오퍼레이션에 의존적이라면 데이터 의존성 배리어를 내포시킵니다만, 모두가 그런건
2837
-아니기 때문에 이점에 의존해선 안됩니다.
2838
-
2839
-다른 CPU 들도 분할된 캐시를 가지고 있을 수 있지만, 그런 CPU 들은 평범한 메모리
2840
-액세스를 위해서도 이 분할된 캐시들 사이의 조정을 해야만 합니다. Alpha 는 가장
2841
-약한 메모리 순서 시맨틱 (semantic) 을 선택함으로써 메모리 배리어가 명시적으로
2842
-사용되지 않았을 때에는 그런 조정이 필요하지 않게 했으며, 이는 Alpha 가 당시에
2843
-더 높은 CPU 클락 속도를 가질 수 있게 했습니다. 하지만, (다시 말하건대, v4.15
2844
-이후부터는) Alpha 아키텍쳐 전용 코드와 READ_ONCE() 매크로 내부에서를 제외하고는
2845
-smp_read_barrier_depends() 가 사용되지 않아야 함을 알아두시기 바랍니다.
28462673
28472674
28482675 캐시 일관성 VS DMA
....@@ -3005,10 +2832,8 @@
30052832 데이터의 발견을 올바른 순서로 일어나게 하기 때문입니다.
30062833
30072834 리눅스 커널의 메모리 배리어 모델은 Alpha 에 기초해서 정의되었습니다만, v4.15
3008
-부터는 리눅스 커널이 READ_ONCE() 내에 smp_read_barrier_depends() 를 추가해서
3009
-Alpha 의 메모리 모델로의 영향력이 크게 줄어들긴 했습니다.
3010
-
3011
-위의 "캐시 일관성" 서브섹션을 참고하세요.
2835
+부터는 Alpha 용 READ_ONCE() 코드 내에 smp_mb() 가 추가되어서 메모리 모델로의
2836
+Alpha 의 영향력이 크게 줄어들었습니다.
30122837
30132838
30142839 가상 머신 게스트