feat: 가상화 문서들 추가

This commit is contained in:
DongHyeonka
2026-09-10 08:54:05 +09:00
parent e9f6a93327
commit 43e1aadef0
695 changed files with 153404 additions and 12754 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,285 @@
{
"version": "1.1",
"id": "guest-memory-address-translation-path",
"title": "Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다",
"question": "Guest 프로세스가 읽은 주소는 어느 계층을 차례로 지나 어떤 물리 메모리에 닿는가",
"type": "data-flow",
"direction": "TB",
"audience": [
"가상 머신에 준 RAM 이 Host RAM 에서 무엇을 뜻하는지 가르려는 사람",
"KVM/QEMU 메모리 경로를 처음 읽는 사람"
],
"summary": "Guest 구역 안에서 GVA 가 Guest TLB 와 Guest Page Table 을 지나 GPA 가 되고, VM Boundary 를 넘은 뒤 EPT 가 GPA 를 HPA 로 바꾸며, 그 HPA 가 Host RAM 의 physical page 와 그 page 가 속한 NUMA node 로 이어진다.",
"alt": "Guest 구역 안에서 Keycloak · PostgreSQL 의 GVA 가 Guest TLB 와 Guest Page Table 을 지나 GPA 가 되고, VM Boundary 를 넘어 EPT 에서 HPA 가 된 뒤 Host RAM 구역의 Host Physical Memory 를 지나 NUMA Node 0 과 NUMA Node 1 로 갈라지는 주소 변환 경로도.",
"long_description": "위에서 아래로 읽는다. 맨 위 Guest 구역 안에 Keycloak · PostgreSQL 이 있고 그 접근은 GVA 로 Guest TLB 에 들어간다. TLB 에 변환이 없으면 TLB Miss 로 Guest Page Table 을 조회하고 거기서 GVA 가 GPA 가 된다. 그 GPA 는 VM Boundary 를 넘어 Guest 구역 밖의 EPT 로 가고 EPT 가 GPA 를 HPA 로 바꾼다. HPA 는 Host RAM 구역의 Host Physical Memory 에 닿고, 그 physical page 는 맨 아래에서 NUMA Node 0 또는 NUMA Node 1 가운데 한쪽에 놓인다. 상자 안 작은 글씨는 그 단계가 어느 계층인지와 무엇을 무엇으로 바꾸는지를 적은 것이다. 어느 단계에서 접근이 완료되지 못할 때 무엇이 일어나는지와 QEMU 가 이 경로를 어떻게 준비하는지는 본문의 문단과 표가 맡는다.",
"source_context": {
"document": "docs/virtualization/final/document.md",
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
"anchor": {
"kind": "heading",
"value": "87. 최종 기준 그림",
"line": 4029
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "이 절이 세우는 것은 한 번의 메모리 접근이 한 방향으로 지나가는 경로와 그 경로가 네 계층으로 나뉜다는 것이다. sequence 는 참여자마다 생명선을 세우고 메시지에 시각 순서를 매기는데 여기서는 참여자끼리 주고받는 메시지가 아니라 주소 하나가 계층을 지나며 이름이 바뀌는 변환 사슬이라 순서를 매길 메시지가 없다. two-zone-pipeline 은 구역이 둘일 때의 문법인데 이 경로는 Guest Userspace · Guest Kernel · KVM/CPU · Host RAM 넷으로 갈리고 Guest Kernel 안쪽에도 TLB Miss 엣지가 있어 구역 안 엣지 라벨이 캔버스 위쪽에 고정된다.",
"focus_node": "ept"
},
"groups": [
{
"id": "guest",
"label": "Guest",
"kind": "boundary",
"description": "VM Boundary 안쪽. Guest Userspace 와 Guest Kernel 이 여기 있고 GVA 가 GPA 가 되는 첫 번째 변환이 여기서 끝난다.",
"evidence": [
{
"start_line": 4034,
"end_line": 4053
}
],
"assumption": false
},
{
"id": "host-ram",
"label": "Host RAM",
"kind": "boundary",
"description": "변환이 끝난 주소가 닿는 실제 서버 메모리.",
"evidence": [
{
"start_line": 4069,
"end_line": 4079
}
],
"assumption": false
}
],
"nodes": [
{
"id": "guest-process",
"label": "Keycloak · PostgreSQL",
"kind": "actor",
"role": "source",
"shape": "box",
"group": "guest",
"description": "Guest 안에서 메모리를 읽는 프로세스. 여기서 GVA 가 출발한다.",
"evidence": [
{
"start_line": 4034,
"end_line": 4038
}
],
"assumption": false,
"details": [
"Guest Userspace"
]
},
{
"id": "guest-tlb",
"label": "Guest TLB",
"kind": "component",
"role": "store",
"shape": "box",
"group": "guest",
"description": "최근 변환 결과를 담아 두는 CPU 안의 캐시.",
"evidence": [
{
"start_line": 4043,
"end_line": 4045
}
],
"assumption": false,
"details": [
"Guest Kernel"
]
},
{
"id": "guest-page-table",
"label": "Guest Page Table",
"kind": "component",
"role": "service",
"shape": "box",
"group": "guest",
"description": "GVA 를 GPA 로 바꾸는 첫 번째 변환 표.",
"evidence": [
{
"start_line": 4048,
"end_line": 4053
}
],
"assumption": false,
"details": [
"Guest Kernel",
"GVA → GPA"
]
},
{
"id": "ept",
"label": "EPT",
"kind": "component",
"role": "service",
"shape": "box",
"emphasis": "primary",
"description": "VM Boundary 바깥에서 GPA 를 HPA 로 바꾸는 두 번째 변환 표. KVM 과 CPU 가 맡는다.",
"evidence": [
{
"start_line": 4055,
"end_line": 4067
}
],
"assumption": false,
"details": [
"KVM / CPU",
"GPA → HPA"
]
},
{
"id": "host-physical-memory",
"label": "Host Physical Memory",
"kind": "store",
"role": "store",
"shape": "box",
"group": "host-ram",
"description": "HPA 가 가리키는 실제 서버 메모리.",
"evidence": [
{
"start_line": 4069,
"end_line": 4072
}
],
"assumption": false
},
{
"id": "numa-node-0",
"label": "NUMA Node 0",
"kind": "store",
"role": "sink",
"shape": "box",
"group": "host-ram",
"description": "physical page 가 놓일 수 있는 한쪽 NUMA node.",
"evidence": [
{
"start_line": 4073,
"end_line": 4075
}
],
"assumption": false
},
{
"id": "numa-node-1",
"label": "NUMA Node 1",
"kind": "store",
"role": "sink",
"shape": "box",
"group": "host-ram",
"description": "physical page 가 놓일 수 있는 다른 쪽 NUMA node.",
"evidence": [
{
"start_line": 4073,
"end_line": 4075
}
],
"assumption": false
}
],
"edges": [
{
"id": "process-to-tlb",
"from": "guest-process",
"to": "guest-tlb",
"label": "GVA",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 4036,
"end_line": 4043
}
],
"assumption": false
},
{
"id": "tlb-to-page-table",
"from": "guest-tlb",
"to": "guest-page-table",
"label": "TLB Miss",
"kind": "control",
"style": "solid",
"evidence": [
{
"start_line": 4043,
"end_line": 4048
}
],
"assumption": false
},
{
"id": "page-table-to-ept",
"from": "guest-page-table",
"to": "ept",
"label": "VM Boundary",
"kind": "control",
"style": "solid",
"evidence": [
{
"start_line": 4053,
"end_line": 4062
}
],
"assumption": false
},
{
"id": "ept-to-host-memory",
"from": "ept",
"to": "host-physical-memory",
"label": "HPA",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 4062,
"end_line": 4071
}
],
"assumption": false
},
{
"id": "host-memory-to-node-0",
"from": "host-physical-memory",
"to": "numa-node-0",
"label": "Physical Page",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 4071,
"end_line": 4075
}
],
"assumption": false
},
{
"id": "host-memory-to-node-1",
"from": "host-physical-memory",
"to": "numa-node-1",
"label": "Physical Page",
"kind": "data",
"style": "solid",
"evidence": [
{
"start_line": 4071,
"end_line": 4075
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "data-flow 로 고른 이유는 이 절이 답하는 물음이 「주소 하나가 어디를 지나 어디에 닿는가」이기 때문이다. LR 로 세우면 캔버스가 1889px 에 종횡비 5.37 이라 문서 폭에서 글자가 읽히지 않아 TB 로 세웠다. Guest Userspace · Guest Kernel · KVM / CPU · Host RAM 넷을 모두 group 으로 두면 group 이름이 그 경계를 넘는 엣지 라벨에 먹혀 「Guest Kerne」·「KVM / CP」로 잘렸다. 그래서 경계는 VM Boundary 를 사이에 둔 Guest 와 Host RAM 둘만 상자로 두고, 나머지 두 계층 이름은 그 자리 노드의 details 로 내렸다. SSOT 가 같은 절에 그린 관리 경로(virsh · libvirt · QEMU · KVM)와 자원 압박 경로는 다른 물음이라 이 그림에 넣지 않았다. §87 이 EPT 옆에 적어 둔 「EPT Violation 가능」과 Guest Page Table 옆의 「Guest #PF 가능」도 뺐다 — 이 기록의 본문은 정상 경로를 세우고, 세 계층의 fault 는 짝이 되는 기록이 맡는다. 마지막 Physical RAM 상자는 Host Physical Memory 와 뜻이 겹쳐 빼고 NUMA node 둘을 끝으로 두었다."
}
}