feat: 가상화 문서들 추가
@@ -0,0 +1,32 @@
|
||||
# 게스트의 write() 가 virtqueue 에 실리기까지
|
||||
|
||||
## Alternative text
|
||||
|
||||
게스트 사용자 공간의 PostgreSQL/Keycloak 에서 시작한 write() 가 게스트 커널의 VFS, ext4/XFS, Guest Page Cache, Guest Block Layer, /dev/vda, virtio-blk Frontend 를 거쳐 virtqueue 에 도달하는 위에서 아래로 읽는 흐름도.
|
||||
|
||||
## Long description
|
||||
|
||||
위에서 아래로 읽는다. 맨 위 Guest Userspace 구역에 PostgreSQL / Keycloak 이 있고 write() 가 게스트 커널로 내려간다. Guest Kernel 구역 안에서 VFS 가 먼저 받고, ext4 / XFS 가 파일을 block 공간에 배치하고, Guest Page Cache 가 그 내용을 dirty page 로 받아 두었다가 writeback 으로 Guest Block Layer 에 내려보낸다. Guest Block Layer 는 그것을 WRITE 나 FLUSH 요청으로 바꿔 /dev/vda 에 걸고, virtio-blk Frontend 가 그 요청을 virtqueue 에 게시한다. virtqueue 아래의 VM Boundary 부터는 QEMU 와 호스트 계층이라 이 그림에서 잘랐다. 완료가 같은 virtqueue 로 되돌아오는 역방향은 SSOT 의 다른 절이 대는 사실이라 이 그림에 넣지 않았고 본문 문단이 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **Boundary: Guest Userspace** (boundary): 게스트 사용자 공간. 저장장치를 직접 다루지 않는다. Evidence: L5807–L5809.
|
||||
- **Boundary: Guest Kernel** (boundary): 게스트 커널 공간. VM Boundary 위쪽 계층이 전부 여기 있다. Evidence: L5815–L5833.
|
||||
- **PostgreSQL / Keycloak** (service): 파일 연산을 요청하는 게스트 프로세스. Evidence: L5807–L5809, L5885–L5885, L5811–L5813.
|
||||
- **VFS** (service): 열린 파일이 어느 filesystem 구현에 속하는지 보고 연산을 넘기는 공통 계층. Evidence: L5815–L5817, L5905–L5905.
|
||||
- **ext4 / XFS** (service): 파일과 디렉터리를 block 공간에 배치하는 게스트 filesystem. Evidence: L5819–L5819.
|
||||
- **Guest Page Cache** (store): 게스트 RAM 에 있는 cache. write() 가 성공해도 데이터는 아직 여기까지만 확정된다. Evidence: L5821–L5821.
|
||||
- **Guest Block Layer** (service): 파일 세계의 요청을 block device 세계의 요청으로 바꾸는 계층. Evidence: L5825–L5825.
|
||||
- **/dev/vda** (device): 게스트 Linux 가 하나의 block device 로 인식하는 이름. Evidence: L5829–L5829, L5879–L5879.
|
||||
- **virtio-blk Frontend** (service): 그 가상 block device 를 제어하는 게스트 커널 driver. Evidence: L5831–L5831, L5789–L5789.
|
||||
- **virtqueue** (queue): 요청이 실리는 자리. 바로 아래가 VM Boundary 다. Evidence: L5833–L5835.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **PostgreSQL / Keycloak → VFS:** data. Evidence: L5811–L5813, L5890–L5890.
|
||||
- **VFS → ext4 / XFS:** data. Evidence: L5817–L5819.
|
||||
- **ext4 / XFS → Guest Page Cache:** data. Evidence: L5819–L5821.
|
||||
- **Guest Page Cache → Guest Block Layer:** writeback. Evidence: L5823–L5825.
|
||||
- **Guest Block Layer → /dev/vda:** WRITE / FLUSH. Evidence: L5827–L5829.
|
||||
- **/dev/vda → virtio-blk Frontend:** data. Evidence: L5829–L5831.
|
||||
- **virtio-blk Frontend → virtqueue:** Virtio block request. Evidence: L5831–L5833.
|
||||
@@ -0,0 +1,38 @@
|
||||
# 게스트의 write() 가 virtqueue 에 실리기까지
|
||||
# Question: 게스트 애플리케이션의 write() 는 virtqueue 에 실리기 전에 게스트의 어느 계층을 어떤 순서로 지나는가
|
||||
direction: down
|
||||
g0: "Guest Userspace" {
|
||||
n0: "PostgreSQL / Keycloak" {
|
||||
shape: rectangle
|
||||
}
|
||||
}
|
||||
g1: "Guest Kernel" {
|
||||
n1: "VFS" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "ext4 / XFS" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "Guest Page Cache" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "Guest Block Layer" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "/dev/vda" {
|
||||
shape: rectangle
|
||||
}
|
||||
n6: "virtio-blk Frontend" {
|
||||
shape: rectangle
|
||||
}
|
||||
n7: "virtqueue" {
|
||||
shape: queue
|
||||
}
|
||||
}
|
||||
g0.n0 -> g1.n1
|
||||
g1.n1 -> g1.n2
|
||||
g1.n2 -> g1.n3
|
||||
g1.n3 -> g1.n4: "writeback"
|
||||
g1.n4 -> g1.n5: "WRITE / FLUSH"
|
||||
g1.n5 -> g1.n6
|
||||
g1.n6 -> g1.n7: "Virtio block request"
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="guest-block-io-to-virtqueue" name="게스트의 write() 가 virtqueue 에 실리기까지">
|
||||
<mxGraphModel dx="680" dy="1360" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1360" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="g_guest-userspace" value="Guest Userspace" style="swimlane;html=1;rounded=1;startSize=30;horizontal=1;dashed=1;strokeWidth=1.5;fillColor=#f7f9fb;strokeColor=#66788a;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="40.0" y="35.0" width="241.0" height="160.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="g_guest-kernel" value="Guest Kernel" style="swimlane;html=1;rounded=1;startSize=30;horizontal=1;dashed=1;strokeWidth=1.5;fillColor=#f7f9fb;strokeColor=#66788a;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="47.0" y="219.0" width="227.0" height="1096.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_app" value="PostgreSQL / Keycloak<br/>read / write<br/>fsync / sync" tooltip="파일 연산을 요청하는 게스트 프로세스. | Evidence: L5807-L5809, L5885-L5885, L5811-L5813" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="81.0" width="181.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_vfs" value="VFS" tooltip="열린 파일이 어느 filesystem 구현에 속하는지 보고 연산을 넘기는 공통 계층. | Evidence: L5815-L5817, L5905-L5905" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="85.5" y="265.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_fs" value="ext4 / XFS" tooltip="파일과 디렉터리를 block 공간에 배치하는 게스트 filesystem. | Evidence: L5819-L5819" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="85.5" y="425.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_page-cache" value="Guest Page Cache" tooltip="게스트 RAM 에 있는 cache. write() 가 성공해도 데이터는 아직 여기까지만 확정된다. | Evidence: L5821-L5821" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="85.5" y="585.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_block-layer" value="Guest Block Layer" tooltip="파일 세계의 요청을 block device 세계의 요청으로 바꾸는 계층. | Evidence: L5825-L5825" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="84.0" y="745.0" width="153.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_vda" value="/dev/vda" tooltip="게스트 Linux 가 하나의 block device 로 인식하는 이름. | Evidence: L5829-L5829, L5879-L5879" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="85.5" y="905.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtio-blk" value="virtio-blk Frontend" tooltip="그 가상 block device 를 제어하는 게스트 커널 driver. | Evidence: L5831-L5831, L5789-L5789" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="77.0" y="1065.0" width="167.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtqueue" value="virtqueue" tooltip="요청이 실리는 자리. 바로 아래가 VM Boundary 다. | Evidence: L5833-L5835" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="85.5" y="1225.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_app-to-vfs" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_app" target="n_vfs">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="217.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_vfs-to-fs" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vfs" target="n_fs">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="377.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_fs-to-page-cache" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_fs" target="n_page-cache">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="537.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_page-cache-to-block-layer" value="writeback" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_page-cache" target="n_block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="697.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_block-layer-to-vda" value="WRITE / FLUSH" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_block-layer" target="n_vda">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="857.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_vda-to-virtio-blk" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vda" target="n_virtio-blk">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="1017.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_virtio-blk-to-virtqueue" value="Virtio block request" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtio-blk" target="n_virtqueue">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="184.5" y="1177.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "guest-block-io-to-virtqueue",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "f41eedadcb8a6841cf981bea9e0a9e50a3df836df3cad528b4245a8d42e83915",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "128. 전체 구조",
|
||||
"line": 5804
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"guest-block-io-to-virtqueue.svg",
|
||||
"guest-block-io-to-virtqueue.drawio",
|
||||
"guest-block-io-to-virtqueue.mmd",
|
||||
"guest-block-io-to-virtqueue.d2",
|
||||
"guest-block-io-to-virtqueue.excalidraw",
|
||||
"guest-block-io-to-virtqueue.alt.md"
|
||||
],
|
||||
"lint_issue_count": 5,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
%% 게스트의 write() 가 virtqueue 에 실리기까지
|
||||
%% question: 게스트 애플리케이션의 write() 는 virtqueue 에 실리기 전에 게스트의 어느 계층을 어떤 순서로 지나는가
|
||||
flowchart TB
|
||||
subgraph g_guest_userspace["Guest Userspace"]
|
||||
n0["PostgreSQL / Keycloak"]
|
||||
end
|
||||
subgraph g_guest_kernel["Guest Kernel"]
|
||||
n1["VFS"]
|
||||
n2["ext4 / XFS"]
|
||||
n3["Guest Page Cache"]
|
||||
n4["Guest Block Layer"]
|
||||
n5["/dev/vda"]
|
||||
n6["virtio-blk Frontend"]
|
||||
n7(["virtqueue"])
|
||||
end
|
||||
n0 --> n1
|
||||
n1 --> n2
|
||||
n2 --> n3
|
||||
n3 -->|"writeback"| n4
|
||||
n4 -->|"WRITE / FLUSH"| n5
|
||||
n5 --> n6
|
||||
n6 -->|"Virtio block request"| n7
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="1360" viewBox="0 0 680 1360" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">게스트의 write() 가 virtqueue 에 실리기까지</title>
|
||||
<desc id="diagram-description">위에서 아래로 읽는다. 맨 위 Guest Userspace 구역에 PostgreSQL / Keycloak 이 있고 write() 가 게스트 커널로 내려간다. Guest Kernel 구역 안에서 VFS 가 먼저 받고, ext4 / XFS 가 파일을 block 공간에 배치하고, Guest Page Cache 가 그 내용을 dirty page 로 받아 두었다가 writeback 으로 Guest Block Layer 에 내려보낸다. Guest Block Layer 는 그것을 WRITE 나 FLUSH 요청으로 바꿔 /dev/vda 에 걸고, virtio-blk Frontend 가 그 요청을 virtqueue 에 게시한다. virtqueue 아래의 VM Boundary 부터는 QEMU 와 호스트 계층이라 이 그림에서 잘랐다. 완료가 같은 virtqueue 로 되돌아오는 역방향은 SSOT 의 다른 절이 대는 사실이라 이 그림에 넣지 않았고 본문 문단이 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"guest-block-io-to-virtqueue","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"128. 전체 구조","line":5804}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="680" height="1360" />
|
||||
<rect class="group-box" x="40.0" y="35.0" width="241.0" height="160.0" rx="8" />
|
||||
<rect class="group-label-bg" x="54.0" y="25.0" width="127.0" height="22" />
|
||||
<text class="group-label" x="64.0" y="40.0">Guest Userspace</text>
|
||||
<rect class="group-box" x="47.0" y="219.0" width="227.0" height="1096.0" rx="8" />
|
||||
<rect class="group-label-bg" x="61.0" y="209.0" width="106.0" height="22" />
|
||||
<text class="group-label" x="71.0" y="224.0">Guest Kernel</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,169.0 160.5,217.0 160.5,217.0 160.5,265.0" data-evidence="5811-5813,5890-5890" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,329.0 160.5,377.0 160.5,377.0 160.5,425.0" data-evidence="5817-5819" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,489.0 160.5,537.0 160.5,537.0 160.5,585.0" data-evidence="5819-5821" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,649.0 160.5,697.0 160.5,697.0 160.5,745.0" data-evidence="5823-5825" />
|
||||
<rect class="edge-label-bg" x="145.3" y="683.0" width="78.3" height="22" rx="3" />
|
||||
<text class="edge-label" x="184.5" y="698.0">writeback</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,809.0 160.5,857.0 160.5,857.0 160.5,905.0" data-evidence="5827-5829" />
|
||||
<rect class="edge-label-bg" x="131.9" y="843.0" width="105.1" height="22" rx="3" />
|
||||
<text class="edge-label" x="184.5" y="858.0">WRITE / FLUSH</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,969.0 160.5,1017.0 160.5,1017.0 160.5,1065.0" data-evidence="5829-5831" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="160.5,1129.0 160.5,1177.0 160.5,1177.0 160.5,1225.0" data-evidence="5831-5833" />
|
||||
<rect class="edge-label-bg" x="108.5" y="1163.0" width="152.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="184.5" y="1178.0">Virtio block request</text>
|
||||
<g id="node-app">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="5807-5809,5885-5885,5811-5813" x="70.0" y="81.0" width="181.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="108.0">PostgreSQL / Keycloak</text>
|
||||
<line class="node-detail-divider" x1="84.0" y1="129.0" x2="237.0" y2="129.0" />
|
||||
<text class="node-detail" x="86.0" y="146.0">read / write</text>
|
||||
<text class="node-detail" x="86.0" y="162.0">fsync / sync</text>
|
||||
</g>
|
||||
<g id="node-vfs">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="5815-5817,5905-5905" x="85.5" y="265.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="295.0">VFS</text>
|
||||
</g>
|
||||
<g id="node-fs">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="5819-5819" x="85.5" y="425.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="455.0">ext4 / XFS</text>
|
||||
</g>
|
||||
<g id="node-page-cache">
|
||||
<rect class="node-shape kind-store emphasis-normal role-store" data-evidence="5821-5821" x="85.5" y="585.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="615.0">Guest Page Cache</text>
|
||||
</g>
|
||||
<g id="node-block-layer">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="5825-5825" x="84.0" y="745.0" width="153.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="775.0">Guest Block Layer</text>
|
||||
</g>
|
||||
<g id="node-vda">
|
||||
<rect class="node-shape kind-device emphasis-normal role-service" data-evidence="5829-5829,5879-5879" x="85.5" y="905.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="935.0">/dev/vda</text>
|
||||
</g>
|
||||
<g id="node-virtio-blk">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="5831-5831,5789-5789" x="77.0" y="1065.0" width="167.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="1095.0">virtio-blk Frontend</text>
|
||||
</g>
|
||||
<g id="node-virtqueue">
|
||||
<rect class="node-shape kind-queue emphasis-primary role-queue" data-evidence="5833-5835" x="85.5" y="1225.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="160.5" y="1255.0">virtqueue</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
@@ -0,0 +1,30 @@
|
||||
# Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다
|
||||
|
||||
## Alternative text
|
||||
|
||||
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 가 이 경로를 어떻게 준비하는지는 본문의 문단과 표가 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **Boundary: Guest** (boundary): VM Boundary 안쪽. Guest Userspace 와 Guest Kernel 이 여기 있고 GVA 가 GPA 가 되는 첫 번째 변환이 여기서 끝난다. Evidence: L4034–L4053.
|
||||
- **Boundary: Host RAM** (boundary): 변환이 끝난 주소가 닿는 실제 서버 메모리. Evidence: L4069–L4079.
|
||||
- **Keycloak · PostgreSQL** (actor): Guest 안에서 메모리를 읽는 프로세스. 여기서 GVA 가 출발한다. Evidence: L4034–L4038.
|
||||
- **Guest TLB** (component): 최근 변환 결과를 담아 두는 CPU 안의 캐시. Evidence: L4043–L4045.
|
||||
- **Guest Page Table** (component): GVA 를 GPA 로 바꾸는 첫 번째 변환 표. Evidence: L4048–L4053.
|
||||
- **EPT** (component): VM Boundary 바깥에서 GPA 를 HPA 로 바꾸는 두 번째 변환 표. KVM 과 CPU 가 맡는다. Evidence: L4055–L4067.
|
||||
- **Host Physical Memory** (store): HPA 가 가리키는 실제 서버 메모리. Evidence: L4069–L4072.
|
||||
- **NUMA Node 0** (store): physical page 가 놓일 수 있는 한쪽 NUMA node. Evidence: L4073–L4075.
|
||||
- **NUMA Node 1** (store): physical page 가 놓일 수 있는 다른 쪽 NUMA node. Evidence: L4073–L4075.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **EPT → Host Physical Memory:** HPA. Evidence: L4062–L4071.
|
||||
- **Host Physical Memory → NUMA Node 0:** Physical Page. Evidence: L4071–L4075.
|
||||
- **Host Physical Memory → NUMA Node 1:** Physical Page. Evidence: L4071–L4075.
|
||||
- **Guest Page Table → EPT:** VM Boundary. Evidence: L4053–L4062.
|
||||
- **Keycloak · PostgreSQL → Guest TLB:** GVA. Evidence: L4036–L4043.
|
||||
- **Guest TLB → Guest Page Table:** TLB Miss. Evidence: L4043–L4048.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다
|
||||
# Question: Guest 프로세스가 읽은 주소는 어느 계층을 차례로 지나 어떤 물리 메모리에 닿는가
|
||||
direction: down
|
||||
g0: "Guest" {
|
||||
n0: "Keycloak · PostgreSQL" {
|
||||
shape: person
|
||||
}
|
||||
n1: "Guest TLB" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "Guest Page Table" {
|
||||
shape: rectangle
|
||||
}
|
||||
}
|
||||
g1: "Host RAM" {
|
||||
n4: "Host Physical Memory" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "NUMA Node 0" {
|
||||
shape: rectangle
|
||||
}
|
||||
n6: "NUMA Node 1" {
|
||||
shape: rectangle
|
||||
}
|
||||
}
|
||||
n3: "EPT" {
|
||||
shape: rectangle
|
||||
}
|
||||
g0.n0 -> g0.n1: "GVA"
|
||||
g0.n1 -> g0.n2: "TLB Miss"
|
||||
g0.n2 -> n3: "VM Boundary"
|
||||
n3 -> g1.n4: "HPA"
|
||||
g1.n4 -> g1.n5: "Physical Page"
|
||||
g1.n4 -> g1.n6: "Physical Page"
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="guest-memory-address-translation-path" name="Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다">
|
||||
<mxGraphModel dx="680" dy="1078" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="g_guest" value="Guest" style="swimlane;html=1;rounded=1;startSize=30;horizontal=1;dashed=1;strokeWidth=1.5;fillColor=#f7f9fb;strokeColor=#66788a;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="129.5" y="35.0" width="241.0" height="494.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="g_host-ram" value="Host RAM" style="swimlane;html=1;rounded=1;startSize=30;horizontal=1;dashed=1;strokeWidth=1.5;fillColor=#f7f9fb;strokeColor=#66788a;fontStyle=1;fontSize=13;" vertex="1" parent="1">
|
||||
<mxGeometry x="40.0" y="737.0" width="420.0" height="296.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-process" value="Keycloak · PostgreSQL<br/>Guest Userspace" tooltip="Guest 안에서 메모리를 읽는 프로세스. 여기서 GVA 가 출발한다. | Evidence: L4034-L4038" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="159.5" y="81.0" width="181.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-tlb" value="Guest TLB<br/>Guest Kernel" tooltip="최근 변환 결과를 담아 두는 CPU 안의 캐시. | Evidence: L4043-L4045" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="175.0" y="248.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-page-table" value="Guest Page Table<br/>Guest Kernel<br/>GVA → GPA" tooltip="GVA 를 GPA 로 바꾸는 첫 번째 변환 표. | Evidence: L4048-L4053" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="175.0" y="415.0" width="150.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_ept" value="EPT<br/>KVM / CPU<br/>GPA → HPA" tooltip="VM Boundary 바깥에서 GPA 를 HPA 로 바꾸는 두 번째 변환 표. KVM 과 CPU 가 맡는다. | Evidence: L4055-L4067" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="175.0" y="599.0" width="150.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-physical-memory" value="Host Physical Memory" tooltip="HPA 가 가리키는 실제 서버 메모리. | Evidence: L4069-L4072" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="163.0" y="783.0" width="174.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_numa-node-0" value="NUMA Node 0" tooltip="physical page 가 놓일 수 있는 한쪽 NUMA node. | Evidence: L4073-L4075" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="943.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_numa-node-1" value="NUMA Node 1" tooltip="physical page 가 놓일 수 있는 다른 쪽 NUMA node. | Evidence: L4073-L4075" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="280.0" y="943.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_ept-to-host-memory" value="HPA" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_ept" target="n_host-physical-memory">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="274.0" y="735.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_host-memory-to-node-0" value="Physical Page" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-physical-memory" target="n_numa-node-0">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="193.0" y="867.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_host-memory-to-node-1" value="Physical Page" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-physical-memory" target="n_numa-node-1">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="307.0" y="867.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_page-table-to-ept" value="VM Boundary" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-page-table" target="n_ept">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="274.0" y="551.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_process-to-tlb" value="GVA" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-process" target="n_guest-tlb">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="274.0" y="200.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_tlb-to-page-table" value="TLB Miss" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-tlb" target="n_guest-page-table">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="274.0" y="367.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "guest-memory-address-translation-path",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "9db86cb8c5f81b1c5886877e1efd3ae4d4174d839fb29cffd5f8ae102508f2f3",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "87. 최종 기준 그림",
|
||||
"line": 4029
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"guest-memory-address-translation-path.svg",
|
||||
"guest-memory-address-translation-path.drawio",
|
||||
"guest-memory-address-translation-path.mmd",
|
||||
"guest-memory-address-translation-path.d2",
|
||||
"guest-memory-address-translation-path.excalidraw",
|
||||
"guest-memory-address-translation-path.alt.md"
|
||||
],
|
||||
"lint_issue_count": 0,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
%% Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다
|
||||
%% question: Guest 프로세스가 읽은 주소는 어느 계층을 차례로 지나 어떤 물리 메모리에 닿는가
|
||||
flowchart TB
|
||||
subgraph g_guest["Guest"]
|
||||
n0(["Keycloak · PostgreSQL"])
|
||||
n1["Guest TLB"]
|
||||
n2["Guest Page Table"]
|
||||
end
|
||||
subgraph g_host_ram["Host RAM"]
|
||||
n4["Host Physical Memory"]
|
||||
n5["NUMA Node 0"]
|
||||
n6["NUMA Node 1"]
|
||||
end
|
||||
n3["EPT"]
|
||||
n0 -->|"GVA"| n1
|
||||
n1 -->|"TLB Miss"| n2
|
||||
n2 -->|"VM Boundary"| n3
|
||||
n3 -->|"HPA"| n4
|
||||
n4 -->|"Physical Page"| n5
|
||||
n4 -->|"Physical Page"| n6
|
||||
classDef external stroke-dasharray: 6 4
|
||||
class n0 external
|
||||
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="1078" viewBox="0 0 680 1078" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">Guest 의 메모리 접근 한 번은 이름이 두 번 바뀌며 네 계층을 지난다</title>
|
||||
<desc id="diagram-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 가 이 경로를 어떻게 준비하는지는 본문의 문단과 표가 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"guest-memory-address-translation-path","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"87. 최종 기준 그림","line":4029}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="680" height="1078" />
|
||||
<rect class="group-box" x="129.5" y="35.0" width="241.0" height="494.0" rx="8" />
|
||||
<rect class="group-label-bg" x="143.5" y="25.0" width="90.0" height="22" />
|
||||
<text class="group-label" x="153.5" y="40.0">Guest</text>
|
||||
<rect class="group-box" x="40.0" y="737.0" width="420.0" height="296.0" rx="8" />
|
||||
<rect class="group-label-bg" x="54.0" y="727.0" width="90.0" height="22" />
|
||||
<text class="group-label" x="64.0" y="742.0">Host RAM</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="250.0,687.0 250.0,735.0 250.0,735.0 250.0,783.0" data-evidence="4062-4071" />
|
||||
<rect class="edge-label-bg" x="252.0" y="721.0" width="44.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="274.0" y="736.0">HPA</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="241.0,847.0 241.0,895.0 145.0,895.0 145.0,943.0" data-evidence="4071-4075" />
|
||||
<rect class="edge-label-bg" x="140.4" y="853.0" width="105.1" height="22" rx="3" />
|
||||
<text class="edge-label" x="193.0" y="868.0">Physical Page</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="259.0,847.0 259.0,895.0 355.0,895.0 355.0,943.0" data-evidence="4071-4075" />
|
||||
<rect class="edge-label-bg" x="254.4" y="853.0" width="105.1" height="22" rx="3" />
|
||||
<text class="edge-label" x="307.0" y="868.0">Physical Page</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="250.0,503.0 250.0,551.0 250.0,551.0 250.0,599.0" data-evidence="4053-4062" />
|
||||
<rect class="edge-label-bg" x="228.2" y="537.0" width="91.7" height="22" rx="3" />
|
||||
<text class="edge-label" x="274.0" y="552.0">VM Boundary</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="250.0,152.0 250.0,200.0 250.0,200.0 250.0,248.0" data-evidence="4036-4043" />
|
||||
<rect class="edge-label-bg" x="252.0" y="186.0" width="44.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="274.0" y="201.0">GVA</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="250.0,319.0 250.0,367.0 250.0,367.0 250.0,415.0" data-evidence="4043-4048" />
|
||||
<rect class="edge-label-bg" x="238.2" y="353.0" width="71.6" height="22" rx="3" />
|
||||
<text class="edge-label" x="274.0" y="368.0">TLB Miss</text>
|
||||
<g id="node-guest-process">
|
||||
<rect class="node-shape kind-actor emphasis-normal role-source" data-evidence="4034-4038" x="159.5" y="81.0" width="181.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="250.0" y="108.0">Keycloak · PostgreSQL</text>
|
||||
<line class="node-detail-divider" x1="173.5" y1="129.0" x2="326.5" y2="129.0" />
|
||||
<text class="node-detail" x="175.5" y="146.0">Guest Userspace</text>
|
||||
</g>
|
||||
<g id="node-guest-tlb">
|
||||
<rect class="node-shape kind-component emphasis-normal role-store" data-evidence="4043-4045" x="175.0" y="248.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="250.0" y="275.0">Guest TLB</text>
|
||||
<line class="node-detail-divider" x1="189.0" y1="296.0" x2="311.0" y2="296.0" />
|
||||
<text class="node-detail" x="191.0" y="313.0">Guest Kernel</text>
|
||||
</g>
|
||||
<g id="node-guest-page-table">
|
||||
<rect class="node-shape kind-component emphasis-normal role-service" data-evidence="4048-4053" x="175.0" y="415.0" width="150.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="250.0" y="442.0">Guest Page Table</text>
|
||||
<line class="node-detail-divider" x1="189.0" y1="463.0" x2="311.0" y2="463.0" />
|
||||
<text class="node-detail" x="191.0" y="480.0">Guest Kernel</text>
|
||||
<text class="node-detail" x="191.0" y="496.0">GVA → GPA</text>
|
||||
</g>
|
||||
<g id="node-ept">
|
||||
<rect class="node-shape kind-component emphasis-primary role-service" data-evidence="4055-4067" x="175.0" y="599.0" width="150.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="250.0" y="626.0">EPT</text>
|
||||
<line class="node-detail-divider" x1="189.0" y1="647.0" x2="311.0" y2="647.0" />
|
||||
<text class="node-detail" x="191.0" y="664.0">KVM / CPU</text>
|
||||
<text class="node-detail" x="191.0" y="680.0">GPA → HPA</text>
|
||||
</g>
|
||||
<g id="node-host-physical-memory">
|
||||
<rect class="node-shape kind-store emphasis-normal role-store" data-evidence="4069-4072" x="163.0" y="783.0" width="174.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="250.0" y="813.0">Host Physical Memory</text>
|
||||
</g>
|
||||
<g id="node-numa-node-0">
|
||||
<rect class="node-shape kind-store emphasis-normal role-sink" data-evidence="4073-4075" x="70.0" y="943.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="145.0" y="973.0">NUMA Node 0</text>
|
||||
</g>
|
||||
<g id="node-numa-node-1">
|
||||
<rect class="node-shape kind-store emphasis-normal role-sink" data-evidence="4073-4075" x="280.0" y="943.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="355.0" y="973.0">NUMA Node 1</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,25 @@
|
||||
# vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다
|
||||
|
||||
## Alternative text
|
||||
|
||||
QEMU vCPU Thread, VM1 Memory Backing, Node 0 CPU, Node 0 RAM, Node 1 RAM 다섯 참여자 사이의 순서도. 앞 세 메시지는 pinning 만 한 배치에서 접근이 Node 1 RAM 으로 가는 것을, 뒤 두 메시지는 memory 를 Node 0 에 묶은 배치에서 같은 접근이 Node 0 RAM 으로 가는 것을 보인다.
|
||||
|
||||
## Long description
|
||||
|
||||
참여자는 왼쪽부터 QEMU vCPU Thread, VM1 Memory Backing, Node 0 CPU, Node 0 RAM, Node 1 RAM 다섯이다. 메시지는 위에서 아래로 읽는다. 1번에서 vCPU thread 가 Node 0 CPU 에 pinning 되고, 2번에서 VM1 의 memory backing 이 Node 1 에 놓인다. 그 배치에서 3번의 memory 접근은 Node 1 RAM 으로 가고 이것이 remote access 다. Node 0 과 Node 1 사이에는 interconnect 가 있어 이 접근만 그 구간을 건넌다. 4번과 5번은 그 뒤에 일어나는 다른 사건이 아니라 배치를 고친 구성이다. memory placement 와 binding 까지 Node 0 으로 맞추면 같은 접근이 Node 0 RAM 으로 가고 local access 가 된다. 접근 비용이 실제로 얼마나 차이 나는지, 이 Host 가 몇 개의 node 를 가졌는지는 그림이 말하지 않는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **QEMU vCPU Thread** (process): Guest vCPU 가 Host 에서 갖는 실체. Host scheduler 가 이것을 logical CPU 에 올린다. Evidence: L3315–L3324.
|
||||
- **VM1 Memory Backing** (memory): 그 가상 머신의 Host physical backing page 가 놓이는 자리. Evidence: L3327–L3327, L3352–L3354, L3381–L3382.
|
||||
- **Node 0 CPU** (compute): vCPU thread 가 실행되는 logical CPU. NUMA Node 0 에 속한다. Evidence: L3322–L3330.
|
||||
- **Node 0 RAM** (memory): Node 0 CPU 와 같은 node 의 RAM. Evidence: L3288–L3296, L3373–L3382.
|
||||
- **Node 1 RAM** (memory): 다른 node 의 RAM. Node 0 CPU 가 읽으면 interconnect 를 건넌다. Evidence: L3299–L3306, L3334–L3334.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **QEMU vCPU Thread → Node 0 CPU:** vCPU Pinning. Evidence: L3322–L3324, L3347–L3350.
|
||||
- **VM1 Memory Backing → Node 1 RAM:** Memory Placement. Evidence: L3327–L3327, L3352–L3354.
|
||||
- **Node 0 CPU → Node 1 RAM:** Remote Access. Evidence: L3329–L3339, L3356–L3357.
|
||||
- **VM1 Memory Backing → Node 0 RAM:** Memory Binding. Evidence: L3361–L3366, L3381–L3382.
|
||||
- **Node 0 CPU → Node 0 RAM:** Local Access. Evidence: L3288–L3296, L3373–L3382.
|
||||
@@ -0,0 +1,23 @@
|
||||
# vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다
|
||||
# Question: vCPU pinning 만 한 배치와 memory binding 까지 맞춘 배치에서 같은 memory 접근은 각각 어느 node 의 RAM 에 닿는가
|
||||
direction: right
|
||||
n0: "QEMU vCPU Thread" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "VM1 Memory Backing" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "Node 0 CPU" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "Node 0 RAM" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "Node 1 RAM" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n2: "vCPU Pinning"
|
||||
n1 -> n4: "Memory Placement"
|
||||
n2 -> n4: "Remote Access"
|
||||
n1 -> n3: "Memory Binding"
|
||||
n2 -> n3: "Local Access"
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="numa-vcpu-and-memory-placement" name="vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다">
|
||||
<mxGraphModel dx="1080" dy="480" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1080" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_qemu-vcpu-thread" value="QEMU vCPU Thread<br/>Guest vCPU" tooltip="Guest vCPU 가 Host 에서 갖는 실체. Host scheduler 가 이것을 logical CPU 에 올린다. | Evidence: L3315-L3324" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="45.0" y="35.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_vm-memory-backing" value="VM1 Memory Backing<br/>VM1 RAM" tooltip="그 가상 머신의 Host physical backing page 가 놓이는 자리. | Evidence: L3327-L3327, L3352-L3354, L3381-L3382" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="255.0" y="35.0" width="160.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_node0-cpu" value="Node 0 CPU<br/>Host Logical CPU" tooltip="vCPU thread 가 실행되는 logical CPU. NUMA Node 0 에 속한다. | Evidence: L3322-L3330" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="465.0" y="35.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_node0-ram" value="Node 0 RAM<br/>Local Memory" tooltip="Node 0 CPU 와 같은 node 의 RAM. | Evidence: L3288-L3296, L3373-L3382" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="675.0" y="35.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_node1-ram" value="Node 1 RAM<br/>Remote Memory" tooltip="다른 node 의 RAM. Node 0 CPU 가 읽으면 interconnect 를 건넌다. | Evidence: L3299-L3306, L3334-L3334" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="885.0" y="35.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_vcpu-pinning" value="vCPU Pinning" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu-vcpu-thread" target="n_node0-cpu">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="330.0" y="128.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_backing-on-node1" value="Memory Placement" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vm-memory-backing" target="n_node1-ram">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="647.5" y="190.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_remote-access" value="Remote Access" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_node0-cpu" target="n_node1-ram">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="750.0" y="252.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_memory-binding" value="Memory Binding" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vm-memory-backing" target="n_node0-ram">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="542.5" y="314.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_local-access" value="Local Access" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_node0-cpu" target="n_node0-ram">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="645.0" y="376.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,813 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-vcpu-pinning",
|
||||
"type": "arrow",
|
||||
"x": 120.0,
|
||||
"y": 140.0,
|
||||
"width": 420.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 62242264,
|
||||
"version": 1,
|
||||
"versionNonce": 1499099216,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
420.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu-vcpu-thread",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-node0-cpu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-vcpu-pinning",
|
||||
"type": "text",
|
||||
"x": 282.0,
|
||||
"y": 116.0,
|
||||
"width": 96,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1253222705,
|
||||
"version": 1,
|
||||
"versionNonce": 1692022138,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "vCPU Pinning",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "vCPU Pinning",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-backing-on-node1",
|
||||
"type": "arrow",
|
||||
"x": 335.0,
|
||||
"y": 202.0,
|
||||
"width": 625.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 597976500,
|
||||
"version": 1,
|
||||
"versionNonce": 751236157,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
625.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-vm-memory-backing",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-node1-ram",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-backing-on-node1",
|
||||
"type": "text",
|
||||
"x": 583.5,
|
||||
"y": 178.0,
|
||||
"width": 128,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 190361474,
|
||||
"version": 1,
|
||||
"versionNonce": 659971302,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Memory Placement",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Memory Placement",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-remote-access",
|
||||
"type": "arrow",
|
||||
"x": 540.0,
|
||||
"y": 264.0,
|
||||
"width": 420.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 723638991,
|
||||
"version": 1,
|
||||
"versionNonce": 805387919,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
420.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-node0-cpu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-node1-ram",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-remote-access",
|
||||
"type": "text",
|
||||
"x": 698.0,
|
||||
"y": 240.0,
|
||||
"width": 104,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 849395583,
|
||||
"version": 1,
|
||||
"versionNonce": 207564235,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Remote Access",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Remote Access",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-memory-binding",
|
||||
"type": "arrow",
|
||||
"x": 335.0,
|
||||
"y": 326.0,
|
||||
"width": 415.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 196285201,
|
||||
"version": 1,
|
||||
"versionNonce": 1908442994,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
415.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-vm-memory-backing",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-node0-ram",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-memory-binding",
|
||||
"type": "text",
|
||||
"x": 486.5,
|
||||
"y": 302.0,
|
||||
"width": 112,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 34697980,
|
||||
"version": 1,
|
||||
"versionNonce": 231604789,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Memory Binding",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Memory Binding",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-local-access",
|
||||
"type": "arrow",
|
||||
"x": 540.0,
|
||||
"y": 388.0,
|
||||
"width": 210.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 206481616,
|
||||
"version": 1,
|
||||
"versionNonce": 1350583922,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
210.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-node0-cpu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-node0-ram",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-local-access",
|
||||
"type": "text",
|
||||
"x": 597.0,
|
||||
"y": 364.0,
|
||||
"width": 96,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 34733324,
|
||||
"version": 1,
|
||||
"versionNonce": 425512157,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Local Access",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Local Access",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-qemu-vcpu-thread",
|
||||
"type": "rectangle",
|
||||
"x": 45.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1825553164,
|
||||
"version": 1,
|
||||
"versionNonce": 1401023854,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-qemu-vcpu-thread",
|
||||
"type": "text",
|
||||
"x": 55.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1778333500,
|
||||
"version": 1,
|
||||
"versionNonce": 1378313554,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "QEMU vCPU Thread\nGuest vCPU",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "QEMU vCPU Thread\nGuest vCPU",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-vm-memory-backing",
|
||||
"type": "rectangle",
|
||||
"x": 255.0,
|
||||
"y": 35.0,
|
||||
"width": 160.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1737545018,
|
||||
"version": 1,
|
||||
"versionNonce": 1015012347,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-vm-memory-backing",
|
||||
"type": "text",
|
||||
"x": 265.0,
|
||||
"y": 45.0,
|
||||
"width": 140.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1698958649,
|
||||
"version": 1,
|
||||
"versionNonce": 994477758,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "VM1 Memory Backing\nVM1 RAM",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM1 Memory Backing\nVM1 RAM",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-node0-cpu",
|
||||
"type": "rectangle",
|
||||
"x": 465.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 932582931,
|
||||
"version": 1,
|
||||
"versionNonce": 1817086514,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-node0-cpu",
|
||||
"type": "text",
|
||||
"x": 475.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 191003957,
|
||||
"version": 1,
|
||||
"versionNonce": 1993112408,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Node 0 CPU\nHost Logical CPU",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Node 0 CPU\nHost Logical CPU",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-node0-ram",
|
||||
"type": "rectangle",
|
||||
"x": 675.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 107670886,
|
||||
"version": 1,
|
||||
"versionNonce": 1647932318,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-node0-ram",
|
||||
"type": "text",
|
||||
"x": 685.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1867132934,
|
||||
"version": 1,
|
||||
"versionNonce": 938518424,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Node 0 RAM\nLocal Memory",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Node 0 RAM\nLocal Memory",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-node1-ram",
|
||||
"type": "rectangle",
|
||||
"x": 885.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1430922658,
|
||||
"version": 1,
|
||||
"versionNonce": 633973815,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-node1-ram",
|
||||
"type": "text",
|
||||
"x": 895.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 608261168,
|
||||
"version": 1,
|
||||
"versionNonce": 116561591,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Node 1 RAM\nRemote Memory",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Node 1 RAM\nRemote Memory",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "numa-vcpu-and-memory-placement",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "afeb9cbc8d7063a1945cabb916eadab7d248a252fce57e433355e6c679090bd5",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "75. vCPU와 NUMA의 연결",
|
||||
"line": 3313
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"numa-vcpu-and-memory-placement.svg",
|
||||
"numa-vcpu-and-memory-placement.drawio",
|
||||
"numa-vcpu-and-memory-placement.mmd",
|
||||
"numa-vcpu-and-memory-placement.d2",
|
||||
"numa-vcpu-and-memory-placement.excalidraw",
|
||||
"numa-vcpu-and-memory-placement.alt.md"
|
||||
],
|
||||
"lint_issue_count": 0,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "sequence",
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
%% vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다
|
||||
%% question: vCPU pinning 만 한 배치와 memory binding 까지 맞춘 배치에서 같은 memory 접근은 각각 어느 node 의 RAM 에 닿는가
|
||||
sequenceDiagram
|
||||
participant n0 as QEMU vCPU Thread
|
||||
participant n1 as VM1 Memory Backing
|
||||
participant n2 as Node 0 CPU
|
||||
participant n3 as Node 0 RAM
|
||||
participant n4 as Node 1 RAM
|
||||
n0->>n2: vCPU Pinning
|
||||
n1->>n4: Memory Placement
|
||||
n2->>n4: Remote Access
|
||||
n1->>n3: Memory Binding
|
||||
n2->>n3: Local Access
|
||||
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1080" height="480" viewBox="0 0 1080 480" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">vCPU 를 Node 0 에 묶어도 backing 이 Node 1 에 있으면 접근은 remote 로 남는다</title>
|
||||
<desc id="diagram-description">참여자는 왼쪽부터 QEMU vCPU Thread, VM1 Memory Backing, Node 0 CPU, Node 0 RAM, Node 1 RAM 다섯이다. 메시지는 위에서 아래로 읽는다. 1번에서 vCPU thread 가 Node 0 CPU 에 pinning 되고, 2번에서 VM1 의 memory backing 이 Node 1 에 놓인다. 그 배치에서 3번의 memory 접근은 Node 1 RAM 으로 가고 이것이 remote access 다. Node 0 과 Node 1 사이에는 interconnect 가 있어 이 접근만 그 구간을 건넌다. 4번과 5번은 그 뒤에 일어나는 다른 사건이 아니라 배치를 고친 구성이다. memory placement 와 binding 까지 Node 0 으로 맞추면 같은 접근이 Node 0 RAM 으로 가고 local access 가 된다. 접근 비용이 실제로 얼마나 차이 나는지, 이 Host 가 몇 개의 node 를 가졌는지는 그림이 말하지 않는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"numa-vcpu-and-memory-placement","profile":"sequence"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"75. vCPU와 NUMA의 연결","line":3313}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="1080" height="480" />
|
||||
<rect class="node-shape kind-process emphasis-primary role-participant" data-evidence="3315-3324" x="45.0" y="35.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="120.0" y="62.0">QEMU vCPU Thread</text>
|
||||
<line class="node-detail-divider" x1="59.0" y1="83.0" x2="181.0" y2="83.0" />
|
||||
<text class="node-detail" x="61.0" y="100.0">Guest vCPU</text>
|
||||
<line class="lifeline" x1="120.0" y1="106.0" x2="120.0" y2="450.0" />
|
||||
<rect class="node-shape kind-memory emphasis-normal role-participant" data-evidence="3327-3327,3352-3354,3381-3382" x="255.0" y="35.0" width="160.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="335.0" y="62.0">VM1 Memory Backing</text>
|
||||
<line class="node-detail-divider" x1="269.0" y1="83.0" x2="401.0" y2="83.0" />
|
||||
<text class="node-detail" x="271.0" y="100.0">VM1 RAM</text>
|
||||
<line class="lifeline" x1="335.0" y1="106.0" x2="335.0" y2="450.0" />
|
||||
<rect class="node-shape kind-compute emphasis-primary role-participant" data-evidence="3322-3330" x="465.0" y="35.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="540.0" y="62.0">Node 0 CPU</text>
|
||||
<line class="node-detail-divider" x1="479.0" y1="83.0" x2="601.0" y2="83.0" />
|
||||
<text class="node-detail" x="481.0" y="100.0">Host Logical CPU</text>
|
||||
<line class="lifeline" x1="540.0" y1="106.0" x2="540.0" y2="450.0" />
|
||||
<rect class="node-shape kind-memory emphasis-normal role-participant" data-evidence="3288-3296,3373-3382" x="675.0" y="35.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="750.0" y="62.0">Node 0 RAM</text>
|
||||
<line class="node-detail-divider" x1="689.0" y1="83.0" x2="811.0" y2="83.0" />
|
||||
<text class="node-detail" x="691.0" y="100.0">Local Memory</text>
|
||||
<line class="lifeline" x1="750.0" y1="106.0" x2="750.0" y2="450.0" />
|
||||
<rect class="node-shape kind-memory emphasis-normal role-participant" data-evidence="3299-3306,3334-3334" x="885.0" y="35.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="960.0" y="62.0">Node 1 RAM</text>
|
||||
<line class="node-detail-divider" x1="899.0" y1="83.0" x2="1021.0" y2="83.0" />
|
||||
<text class="node-detail" x="901.0" y="100.0">Remote Memory</text>
|
||||
<line class="lifeline" x1="960.0" y1="106.0" x2="960.0" y2="450.0" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="120.0,140.0 540.0,140.0" data-evidence="3322-3324,3347-3350" />
|
||||
<rect class="edge-label-bg" x="270.8" y="114.0" width="118.5" height="22" rx="3" />
|
||||
<text class="edge-label" x="330.0" y="129.0">1. vCPU Pinning</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="335.0,202.0 960.0,202.0" data-evidence="3327-3327,3352-3354" />
|
||||
<rect class="edge-label-bg" x="574.9" y="176.0" width="145.3" height="22" rx="3" />
|
||||
<text class="edge-label" x="647.5" y="191.0">2. Memory Placement</text>
|
||||
<polyline class="edge kind-read style-dashed emphasis-normal" points="540.0,264.0 960.0,264.0" data-evidence="3329-3339,3356-3357" />
|
||||
<rect class="edge-label-bg" x="687.4" y="238.0" width="125.2" height="22" rx="3" />
|
||||
<text class="edge-label" x="750.0" y="253.0">3. Remote Access</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="335.0,326.0 750.0,326.0" data-evidence="3361-3366,3381-3382" />
|
||||
<rect class="edge-label-bg" x="476.6" y="300.0" width="131.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="542.5" y="315.0">4. Memory Binding</text>
|
||||
<polyline class="edge kind-read style-solid emphasis-normal" points="540.0,388.0 750.0,388.0" data-evidence="3288-3296,3373-3382" />
|
||||
<rect class="edge-label-bg" x="585.8" y="362.0" width="118.5" height="22" rx="3" />
|
||||
<text class="edge-label" x="645.0" y="377.0">5. Local Access</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.4 KiB |
@@ -0,0 +1,43 @@
|
||||
# control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다
|
||||
|
||||
## Alternative text
|
||||
|
||||
위쪽 줄은 virsh, libvirt, QEMU, virtio-net Device Model 로 이어지는 control/setup path 이고 아래쪽 줄은 Physical NIC 에서 TAP 까지 이어지는 data path 다. 두 줄이 vhost-net 과 QEMU virtio backend 에서 만나 virtqueue 를 지나 Guest 로 모이는 구성도.
|
||||
|
||||
## Long description
|
||||
|
||||
왼쪽에서 오른쪽으로 읽는다. 위쪽 줄이 control/setup path 다. virsh 에서 libvirt 와 QEMU 를 지나 virtio-net Device Model 에 닿고, 그 device model 이 virtual NIC 생성과 feature negotiation, virtqueue 설정, vhost-net backend 설정을 맡는다. 아래쪽 줄이 data path 다. Physical NIC 에서 Physical NIC Driver 와 Linux Bridge, TAP 까지 온다. 두 줄은 네 번째 열 다음에서 만난다. device model 은 점선으로 backend 둘을 설정하고, TAP 은 실선으로 그 둘 가운데 실제로 쓰는 쪽에 packet 을 넘긴다. vhost-net 을 쓰면 packet 은 Host Kernel 안에서 처리돼 QEMU 사용자 공간을 지나지 않고, QEMU virtio backend 를 쓰면 같은 packet 이 QEMU 사용자 공간을 지난다. 어느 쪽이든 virtqueue 에서 만나 Guest 로 올라간다. 이 Host 가 둘 중 어느 backend 를 쓰고 있는지는 그림이 말하지 않는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **virsh** (cli): VM/network 관리 CLI. packet datapath 에는 직접 참여하지 않는다. Evidence: L5662–L5662, L5687–L5689.
|
||||
- **libvirt** (service): VM lifecycle 과 NIC/network configuration 을 관리한다. Evidence: L5663–L5663, L5691–L5691.
|
||||
- **QEMU** (process): 실제로 실행되는 프로세스. 이 안에 virtio-net device model 이 있다. Evidence: L5666–L5666, L5693–L5693.
|
||||
- **virtio-net Device Model** (service): control/setup path 가 닿는 자리. 장치를 만들고 backend 를 연결한다. Evidence: L5666–L5666, L5695–L5700.
|
||||
- **Physical NIC** (hardware): 밖에서 온 packet 이 처음 닿는 하드웨어. Evidence: L5706–L5708.
|
||||
- **Physical NIC Driver** (driver): 그 하드웨어를 제어하는 Host kernel driver. Evidence: L5674–L5674, L5710–L5710.
|
||||
- **Linux Bridge /
|
||||
Routing / NAT** (network): L2 software switch 와 L3 routing, 주소 변환이 놓이는 자리. Evidence: L5672–L5673, L5712–L5712.
|
||||
- **TAP** (network): VM 의 Ethernet frame 과 Host Linux networking 을 잇는 접점. Evidence: L5671–L5671, L5714–L5714.
|
||||
- **vhost-net** (kernel): 반복되는 packet datapath 를 Host kernel 에서 처리하는 backend. Evidence: L5669–L5669, L5716–L5716.
|
||||
- **QEMU virtio backend** (process): vhost-net 을 쓰지 않을 때 datapath backend 를 맡는 쪽. Evidence: L5668–L5668, L5742–L5742.
|
||||
- **virtqueue** (queue): Guest 와 Host backend 가 I/O buffer 를 주고받는 descriptor 기반 공유 큐. Evidence: L5667–L5667, L5718–L5718.
|
||||
- **Guest** (service): packet 이 올라가 애플리케이션 socket 에 닿는 쪽. Evidence: L5664–L5665, L5720–L5726.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **Linux Bridge /
|
||||
Routing / NAT → TAP:** Ethernet Frame. Evidence: L5671–L5671, L5712–L5714.
|
||||
- **Physical NIC Driver → Linux Bridge /
|
||||
Routing / NAT:** L2 forwarding. Evidence: L5672–L5672, L5710–L5712.
|
||||
- **libvirt → QEMU:** NIC/network configuration. Evidence: L5663–L5663, L5691–L5693.
|
||||
- **Physical NIC → Physical NIC Driver:** Ethernet Frame. Evidence: L5671–L5671, L5708–L5710.
|
||||
- **QEMU virtio backend → virtqueue:** Data Path. Evidence: L5729–L5729, L5742–L5744.
|
||||
- **QEMU → virtio-net Device Model:** QEMU process. Evidence: L5666–L5666, L5693–L5695.
|
||||
- **virtio-net Device Model → QEMU virtio backend:** control. Evidence: L5668–L5668, L5700–L5700.
|
||||
- **virtio-net Device Model → vhost-net:** vhost-net backend 설정. Evidence: L5700–L5700, L5716–L5716.
|
||||
- **TAP → QEMU virtio backend:** data. Evidence: L5729–L5729, L5740–L5742.
|
||||
- **TAP → vhost-net:** vhost-net 사용. Evidence: L5703–L5703, L5714–L5716.
|
||||
- **vhost-net → virtqueue:** Data Path. Evidence: L5703–L5703, L5716–L5718.
|
||||
- **virsh → libvirt:** Control / Setup. Evidence: L5662–L5663, L5684–L5691.
|
||||
- **virtqueue → Guest:** virtio-net Frontend Driver. Evidence: L5664–L5664, L5718–L5726.
|
||||
@@ -0,0 +1,52 @@
|
||||
# control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다
|
||||
# Question: 설정하는 경로와 packet 이 흐르는 경로는 어디에서 갈라지고, 그 두 갈래 가운데 어느 쪽이 QEMU 사용자 공간을 지나는가
|
||||
direction: down
|
||||
n0: "virsh" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "libvirt" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "QEMU" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "virtio-net Device Model" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "Physical NIC" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "Physical NIC Driver" {
|
||||
shape: rectangle
|
||||
}
|
||||
n6: "Linux Bridge /\nRouting / NAT" {
|
||||
shape: rectangle
|
||||
}
|
||||
n7: "TAP" {
|
||||
shape: rectangle
|
||||
}
|
||||
n8: "vhost-net" {
|
||||
shape: rectangle
|
||||
}
|
||||
n9: "QEMU virtio backend" {
|
||||
shape: rectangle
|
||||
}
|
||||
n10: "virtqueue" {
|
||||
shape: queue
|
||||
}
|
||||
n11: "Guest" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n1: "Control / Setup"
|
||||
n1 -> n2: "NIC/network configuration"
|
||||
n2 -> n3: "QEMU process"
|
||||
n4 -> n5: "Ethernet Frame"
|
||||
n5 -> n6: "L2 forwarding"
|
||||
n6 -> n7: "Ethernet Frame"
|
||||
n3 -> n8: "vhost-net backend 설정"
|
||||
n3 -> n9
|
||||
n7 -> n8: "vhost-net 사용"
|
||||
n7 -> n9
|
||||
n8 -> n10: "Data Path"
|
||||
n9 -> n10: "Data Path"
|
||||
n10 -> n11: "virtio-net Frontend Driver"
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="packet-control-and-data-paths" name="control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다">
|
||||
<mxGraphModel dx="680" dy="1296" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1296" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_virsh" value="virsh<br/>User" tooltip="VM/network 관리 CLI. packet datapath 에는 직접 참여하지 않는다. | Evidence: L5662-L5662, L5687-L5689" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="90.5" y="60.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_physical-nic" value="Physical NIC" tooltip="밖에서 온 packet 이 처음 닿는 하드웨어. | Evidence: L5706-L5708" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="300.5" y="63.5" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_libvirt" value="libvirt" tooltip="VM lifecycle 과 NIC/network configuration 을 관리한다. | Evidence: L5663-L5663, L5691-L5691" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="82.0" y="227.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_physical-nic-driver" value="Physical NIC Driver" tooltip="그 하드웨어를 제어하는 Host kernel driver. | Evidence: L5674-L5674, L5710-L5710" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="292.0" y="227.0" width="167.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu" value="QEMU<br/>Host Userspace" tooltip="실제로 실행되는 프로세스. 이 안에 virtio-net device model 이 있다. | Evidence: L5666-L5666, L5693-L5693" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="90.5" y="388.5" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_linux-bridge" value="Linux Bridge /
|
||||
Routing / NAT" tooltip="L2 software switch 와 L3 routing, 주소 변환이 놓이는 자리. | Evidence: L5672-L5673, L5712-L5712" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="300.5" y="387.0" width="150.0" height="74.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtio-net-device-model" value="virtio-net Device Model<br/>virtual NIC 생성<br/>feature negotiation<br/>virtqueue 설정<br/>vhost-net backend 설정" tooltip="control/setup path 가 닿는 자리. 장치를 만들고 backend 를 연결한다. | Evidence: L5666-L5666, L5695-L5700" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="557.0" width="174.0" height="142.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_tap" value="TAP<br/>Host-side interface" tooltip="VM 의 Ethernet frame 과 Host Linux networking 을 잇는 접점. | Evidence: L5671-L5671, L5714-L5714" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="304.0" y="592.5" width="167.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu-virtio-backend" value="QEMU virtio backend<br/>QEMU Userspace" tooltip="vhost-net 을 쓰지 않을 때 datapath backend 를 맡는 쪽. | Evidence: L5668-L5668, L5742-L5742" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="82.0" y="795.0" width="167.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_vhost-net" value="vhost-net<br/>Host Kernel" tooltip="반복되는 packet datapath 를 Host kernel 에서 처리하는 backend. | Evidence: L5669-L5669, L5716-L5716" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="309.0" y="795.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtqueue" value="virtqueue<br/>shared queue" tooltip="Guest 와 Host backend 가 I/O buffer 를 주고받는 descriptor 기반 공유 큐. | Evidence: L5667-L5667, L5718-L5718" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="195.5" y="962.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest" value="Guest<br/>virtio-net Frontend Driver<br/>Guest TCP/IP Stack<br/>Socket<br/>Keycloak" tooltip="packet 이 올라가 애플리케이션 socket 에 닿는 쪽. | Evidence: L5664-L5665, L5720-L5726" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="162.5" y="1129.0" width="216.0" height="122.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_bridge-to-tap" value="Ethernet Frame" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_linux-bridge" target="n_tap">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="381.5" y="498.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_driver-to-bridge" value="L2 forwarding" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_physical-nic-driver" target="n_linux-bridge">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="399.5" y="339.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_libvirt-to-qemu" value="NIC/network configuration" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_libvirt" target="n_qemu">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="161.2" y="311.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_nic-to-driver" value="Ethernet Frame" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_physical-nic" target="n_physical-nic-driver">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="399.5" y="177.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_qemu-backend-to-virtqueue" value="Data Path" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu-virtio-backend" target="n_virtqueue">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="213.5" y="886.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_qemu-to-device-model" value="QEMU process" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu" target="n_virtio-net-device-model">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="161.2" y="480.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_setup-qemu-backend" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtio-net-device-model" target="n_qemu-virtio-backend">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="152.2" y="719.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_setup-vhost-backend" value="vhost-net backend 설정" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtio-net-device-model" target="n_vhost-net">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="270.5" y="719.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_tap-to-qemu-backend" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_tap" target="n_qemu-virtio-backend">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="276.5" y="701.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_tap-to-vhost" value="vhost-net 사용" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_tap" target="n_vhost-net">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="394.8" y="701.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_vhost-to-virtqueue" value="Data Path" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vhost-net" target="n_virtqueue">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="331.8" y="886.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_virsh-to-libvirt" value="Control / Setup" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virsh" target="n_libvirt">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="161.2" y="151.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_virtqueue-to-guest" value="virtio-net Frontend Driver" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtqueue" target="n_guest">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="294.5" y="1081.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "packet-control-and-data-paths",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "fa2d5e22352fa6cf975665cd431a236deaa4ae88ea0eb8461bb1b3c8b0b03dc6",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "125. 최종 기준 구조",
|
||||
"line": 5682
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"packet-control-and-data-paths.svg",
|
||||
"packet-control-and-data-paths.drawio",
|
||||
"packet-control-and-data-paths.mmd",
|
||||
"packet-control-and-data-paths.d2",
|
||||
"packet-control-and-data-paths.excalidraw",
|
||||
"packet-control-and-data-paths.alt.md"
|
||||
],
|
||||
"lint_issue_count": 4,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
%% control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다
|
||||
%% question: 설정하는 경로와 packet 이 흐르는 경로는 어디에서 갈라지고, 그 두 갈래 가운데 어느 쪽이 QEMU 사용자 공간을 지나는가
|
||||
flowchart TB
|
||||
n0["virsh"]
|
||||
n1["libvirt"]
|
||||
n2["QEMU"]
|
||||
n3["virtio-net Device Model"]
|
||||
n4["Physical NIC"]
|
||||
n5["Physical NIC Driver"]
|
||||
n6["Linux Bridge /<br/>Routing / NAT"]
|
||||
n7["TAP"]
|
||||
n8["vhost-net"]
|
||||
n9["QEMU virtio backend"]
|
||||
n10(["virtqueue"])
|
||||
n11["Guest"]
|
||||
n0 -->|"Control / Setup"| n1
|
||||
n1 -->|"NIC/network configuration"| n2
|
||||
n2 -->|"QEMU process"| n3
|
||||
n4 -->|"Ethernet Frame"| n5
|
||||
n5 -->|"L2 forwarding"| n6
|
||||
n6 -->|"Ethernet Frame"| n7
|
||||
n3 -->|"vhost-net backend 설정"| n8
|
||||
n3 --> n9
|
||||
n7 -->|"vhost-net 사용"| n8
|
||||
n7 --> n9
|
||||
n8 -->|"Data Path"| n10
|
||||
n9 -->|"Data Path"| n10
|
||||
n10 -->|"virtio-net Frontend Driver"| n11
|
||||
@@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="1296" viewBox="0 0 680 1296" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">control/setup path 는 QEMU 를 지나고 data path 는 backend 에 따라 QEMU 를 지나기도 안 지나기도 한다</title>
|
||||
<desc id="diagram-description">왼쪽에서 오른쪽으로 읽는다. 위쪽 줄이 control/setup path 다. virsh 에서 libvirt 와 QEMU 를 지나 virtio-net Device Model 에 닿고, 그 device model 이 virtual NIC 생성과 feature negotiation, virtqueue 설정, vhost-net backend 설정을 맡는다. 아래쪽 줄이 data path 다. Physical NIC 에서 Physical NIC Driver 와 Linux Bridge, TAP 까지 온다. 두 줄은 네 번째 열 다음에서 만난다. device model 은 점선으로 backend 둘을 설정하고, TAP 은 실선으로 그 둘 가운데 실제로 쓰는 쪽에 packet 을 넘긴다. vhost-net 을 쓰면 packet 은 Host Kernel 안에서 처리돼 QEMU 사용자 공간을 지나지 않고, QEMU virtio backend 를 쓰면 같은 packet 이 QEMU 사용자 공간을 지난다. 어느 쪽이든 virtqueue 에서 만나 Guest 로 올라간다. 이 Host 가 둘 중 어느 backend 를 쓰고 있는지는 그림이 말하지 않는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"packet-control-and-data-paths","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"125. 최종 기준 구조","line":5682}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="680" height="1296" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="375.5,461.0 375.5,526.8 387.5,526.8 387.5,592.5" data-evidence="5671-5671,5712-5714" />
|
||||
<rect class="edge-label-bg" x="325.6" y="484.8" width="111.8" height="22" rx="3" />
|
||||
<text class="edge-label" x="381.5" y="499.8">Ethernet Frame</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="375.5,291.0 375.5,339.0 375.5,339.0 375.5,387.0" data-evidence="5672-5672,5710-5712" />
|
||||
<rect class="edge-label-bg" x="346.9" y="325.0" width="105.1" height="22" rx="3" />
|
||||
<text class="edge-label" x="399.5" y="340.0">L2 forwarding</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="157.0,291.0 157.0,339.8 165.5,339.8 165.5,388.5" data-evidence="5663-5663,5691-5693" />
|
||||
<rect class="edge-label-bg" x="68.5" y="297.8" width="185.5" height="22" rx="3" />
|
||||
<text class="edge-label" x="161.2" y="312.8">NIC/network configuration</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="375.5,127.5 375.5,177.2 375.5,177.2 375.5,227.0" data-evidence="5671-5671,5708-5710" />
|
||||
<rect class="edge-label-bg" x="343.6" y="163.2" width="111.8" height="22" rx="3" />
|
||||
<text class="edge-label" x="399.5" y="178.2">Ethernet Frame</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="165.5,866.0 165.5,914.0 261.5,914.0 261.5,962.0" data-evidence="5729-5729,5742-5744" />
|
||||
<rect class="edge-label-bg" x="174.3" y="872.0" width="78.3" height="22" rx="3" />
|
||||
<text class="edge-label" x="213.5" y="887.0">Data Path</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="165.5,459.5 165.5,508.2 157.0,508.2 157.0,557.0" data-evidence="5666-5666,5693-5695" />
|
||||
<rect class="edge-label-bg" x="112.0" y="466.2" width="98.4" height="22" rx="3" />
|
||||
<text class="edge-label" x="161.2" y="481.2">QEMU process</text>
|
||||
<polyline class="edge kind-control style-dashed emphasis-normal" points="148.0,699.0 148.0,747.0 156.5,747.0 156.5,795.0" data-evidence="5668-5668,5700-5700" />
|
||||
<polyline class="edge kind-control style-dashed emphasis-normal" points="166.0,699.0 166.0,747.0 375.0,747.0 375.0,795.0" data-evidence="5700-5700,5716-5716" />
|
||||
<rect class="edge-label-bg" x="194.5" y="705.0" width="152.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="270.5" y="720.0">vhost-net backend 설정</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="378.5,663.5 378.5,729.2 174.5,729.2 174.5,795.0" data-evidence="5729-5729,5740-5742" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="396.5,663.5 396.5,729.2 393.0,729.2 393.0,795.0" data-evidence="5703-5703,5714-5716" />
|
||||
<rect class="edge-label-bg" x="345.6" y="687.2" width="98.4" height="22" rx="3" />
|
||||
<text class="edge-label" x="394.8" y="702.2">vhost-net 사용</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="384.0,866.0 384.0,914.0 279.5,914.0 279.5,962.0" data-evidence="5703-5703,5716-5718" />
|
||||
<rect class="edge-label-bg" x="292.6" y="872.0" width="78.3" height="22" rx="3" />
|
||||
<text class="edge-label" x="331.8" y="887.0">Data Path</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="165.5,131.0 165.5,179.0 157.0,179.0 157.0,227.0" data-evidence="5662-5663,5684-5691" />
|
||||
<rect class="edge-label-bg" x="102.0" y="137.0" width="118.5" height="22" rx="3" />
|
||||
<text class="edge-label" x="161.2" y="152.0">Control / Setup</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="270.5,1033.0 270.5,1081.0 270.5,1081.0 270.5,1129.0" data-evidence="5664-5664,5718-5726" />
|
||||
<rect class="edge-label-bg" x="198.4" y="1067.0" width="192.2" height="22" rx="3" />
|
||||
<text class="edge-label" x="294.5" y="1082.0">virtio-net Frontend Driver</text>
|
||||
<g id="node-virsh">
|
||||
<rect class="node-shape kind-cli emphasis-normal role-actor" data-evidence="5662-5662,5687-5689" x="90.5" y="60.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="165.5" y="87.0">virsh</text>
|
||||
<line class="node-detail-divider" x1="104.5" y1="108.0" x2="226.5" y2="108.0" />
|
||||
<text class="node-detail" x="106.5" y="125.0">User</text>
|
||||
</g>
|
||||
<g id="node-physical-nic">
|
||||
<rect class="node-shape kind-hardware emphasis-normal role-source" data-evidence="5706-5708" x="300.5" y="63.5" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="375.5" y="93.5">Physical NIC</text>
|
||||
</g>
|
||||
<g id="node-libvirt">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="5663-5663,5691-5691" x="82.0" y="227.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="157.0" y="257.0">libvirt</text>
|
||||
</g>
|
||||
<g id="node-physical-nic-driver">
|
||||
<rect class="node-shape kind-driver emphasis-normal role-service" data-evidence="5674-5674,5710-5710" x="292.0" y="227.0" width="167.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="375.5" y="257.0">Physical NIC Driver</text>
|
||||
</g>
|
||||
<g id="node-qemu">
|
||||
<rect class="node-shape kind-process emphasis-normal role-service" data-evidence="5666-5666,5693-5693" x="90.5" y="388.5" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="165.5" y="415.5">QEMU</text>
|
||||
<line class="node-detail-divider" x1="104.5" y1="436.5" x2="226.5" y2="436.5" />
|
||||
<text class="node-detail" x="106.5" y="453.5">Host Userspace</text>
|
||||
</g>
|
||||
<g id="node-linux-bridge">
|
||||
<rect class="node-shape kind-network emphasis-normal role-service" data-evidence="5672-5673,5712-5712" x="300.5" y="387.0" width="150.0" height="74.0" rx="7" />
|
||||
<text class="node-label" x="375.5" y="414.0">Linux Bridge /</text>
|
||||
<text class="node-label" x="375.5" y="432.0">Routing / NAT</text>
|
||||
</g>
|
||||
<g id="node-virtio-net-device-model">
|
||||
<rect class="node-shape kind-service emphasis-primary role-service" data-evidence="5666-5666,5695-5700" x="70.0" y="557.0" width="174.0" height="142.0" rx="7" />
|
||||
<text class="node-label" x="157.0" y="585.0">virtio-net Device</text>
|
||||
<text class="node-label" x="157.0" y="603.0">Model</text>
|
||||
<line class="node-detail-divider" x1="84.0" y1="624.0" x2="230.0" y2="624.0" />
|
||||
<text class="node-detail" x="86.0" y="641.0">virtual NIC 생성</text>
|
||||
<text class="node-detail" x="86.0" y="657.0">feature negotiation</text>
|
||||
<text class="node-detail" x="86.0" y="673.0">virtqueue 설정</text>
|
||||
<text class="node-detail" x="86.0" y="689.0">vhost-net backend 설정</text>
|
||||
</g>
|
||||
<g id="node-tap">
|
||||
<rect class="node-shape kind-network emphasis-normal role-service" data-evidence="5671-5671,5714-5714" x="304.0" y="592.5" width="167.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="387.5" y="619.5">TAP</text>
|
||||
<line class="node-detail-divider" x1="318.0" y1="640.5" x2="457.0" y2="640.5" />
|
||||
<text class="node-detail" x="320.0" y="657.5">Host-side interface</text>
|
||||
</g>
|
||||
<g id="node-qemu-virtio-backend">
|
||||
<rect class="node-shape kind-process emphasis-normal role-service" data-evidence="5668-5668,5742-5742" x="82.0" y="795.0" width="167.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="165.5" y="822.0">QEMU virtio backend</text>
|
||||
<line class="node-detail-divider" x1="96.0" y1="843.0" x2="235.0" y2="843.0" />
|
||||
<text class="node-detail" x="98.0" y="860.0">QEMU Userspace</text>
|
||||
</g>
|
||||
<g id="node-vhost-net">
|
||||
<rect class="node-shape kind-kernel emphasis-normal role-service" data-evidence="5669-5669,5716-5716" x="309.0" y="795.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="384.0" y="822.0">vhost-net</text>
|
||||
<line class="node-detail-divider" x1="323.0" y1="843.0" x2="445.0" y2="843.0" />
|
||||
<text class="node-detail" x="325.0" y="860.0">Host Kernel</text>
|
||||
</g>
|
||||
<g id="node-virtqueue">
|
||||
<rect class="node-shape kind-queue emphasis-normal role-queue" data-evidence="5667-5667,5718-5718" x="195.5" y="962.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="270.5" y="989.0">virtqueue</text>
|
||||
<line class="node-detail-divider" x1="209.5" y1="1010.0" x2="331.5" y2="1010.0" />
|
||||
<text class="node-detail" x="211.5" y="1027.0">shared queue</text>
|
||||
</g>
|
||||
<g id="node-guest">
|
||||
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="5664-5665,5720-5726" x="162.5" y="1129.0" width="216.0" height="122.0" rx="7" />
|
||||
<text class="node-label" x="270.5" y="1156.0">Guest</text>
|
||||
<line class="node-detail-divider" x1="176.5" y1="1177.0" x2="364.5" y2="1177.0" />
|
||||
<text class="node-detail" x="178.5" y="1194.0">virtio-net Frontend Driver</text>
|
||||
<text class="node-detail" x="178.5" y="1210.0">Guest TCP/IP Stack</text>
|
||||
<text class="node-detail" x="178.5" y="1226.0">Socket</text>
|
||||
<text class="node-detail" x="178.5" y="1242.0">Keycloak</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,25 @@
|
||||
# 세 fault 는 변환 사슬의 서로 다른 단계에서 갈라져 나가 서로 다른 계층이 받는다
|
||||
|
||||
## Alternative text
|
||||
|
||||
Guest Page Table 과 EPT, QEMU 의 Guest RAM Backing 에서 각각 fault 가 갈라져 Guest Kernel · KVM · Host Kernel 로 가는 갈래도.
|
||||
|
||||
## Long description
|
||||
|
||||
위에서 아래로 읽는다. 맨 위 왼쪽에 Guest Page Table 이 있고 거기서 갈래가 둘이다. 하나는 Guest Page Fault 로 Guest Kernel 에 빠지고, 다른 하나는 GPA 를 들고 아래 EPT 로 내려간다. EPT 에서도 갈래가 나뉘어 EPT Violation 은 VM Exit 을 거쳐 KVM 으로 간다. 맨 위 오른쪽에는 QEMU 의 Guest RAM Backing 이 따로 있고 그쪽 갈래인 Host Page Fault 는 Host Kernel 로 간다. 받는 자리의 이름이 그대로 계층 이름이다 — Guest Kernel · KVM · Host Kernel. QEMU 갈래가 EPT 갈래와 선으로 이어져 있지 않은 것은 근거 문서가 둘을 잇는 문장을 두지 않았기 때문이다. 다섯 원인이 무엇인지와 두 사건을 항목별로 견주는 것은 본문의 표가 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **Guest Page Table** (component): 첫 번째 translation 단계. 여기서 접근을 완료할 수 없으면 Guest Page Fault 가 난다. Evidence: L2443–L2445, L2484–L2485.
|
||||
- **Guest Kernel** (service): Guest Page Fault 를 받는 계층. Evidence: L2487–L2487, L2493–L2494.
|
||||
- **EPT** (component): 두 번째 translation 단계. Guest translation 이 성공한 뒤 여기서 막히면 EPT Violation 이 난다. Evidence: L2465–L2469, L2484–L2485.
|
||||
- **KVM** (service): EPT Violation 을 VM Exit 뒤에 받는 계층. Evidence: L2471–L2473, L2487–L2487.
|
||||
- **QEMU · Guest RAM Backing** (store): Host 의 일반 userspace 메모리로 관리되는 자리. demand allocation 이나 reclaim, swap 때문에 여기서 fault 가 난다. Evidence: L2504–L2504, L2514–L2519.
|
||||
- **Host Kernel** (service): Host Page Fault 를 받아 필요한 Host page 를 처리하는 계층. Evidence: L2521–L2525.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **EPT → KVM:** EPT Violation · VM Exit. Evidence: L2467–L2473, L2487–L2487.
|
||||
- **Guest Page Table → Guest Kernel:** Guest Page Fault. Evidence: L2484–L2487, L2493–L2494.
|
||||
- **QEMU · Guest RAM Backing → Host Kernel:** Host Page Fault. Evidence: L2517–L2525.
|
||||
- **Guest Page Table → EPT:** GPA. Evidence: L2461–L2467.
|
||||
@@ -0,0 +1,25 @@
|
||||
# 세 fault 는 변환 사슬의 서로 다른 단계에서 갈라져 나가 서로 다른 계층이 받는다
|
||||
# Question: Guest Page Fault · EPT Violation · Host Page Fault 는 각각 어느 단계에서 갈라지고 누가 받는가
|
||||
direction: down
|
||||
n0: "Guest Page Table" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "Guest Kernel" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "EPT" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "KVM" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "QEMU · Guest RAM Backing" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "Host Kernel" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n1: "Guest Page Fault" { style.stroke-dash: 4 }
|
||||
n0 -> n2: "GPA"
|
||||
n2 -> n3: "EPT Violation · VM Exit" { style.stroke-dash: 4 }
|
||||
n4 -> n5: "Host Page Fault" { style.stroke-dash: 4 }
|
||||
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="page-fault-layers-in-a-vm" name="세 fault 는 변환 사슬의 서로 다른 단계에서 갈라져 나가 서로 다른 계층이 받는다">
|
||||
<mxGraphModel dx="685" dy="523" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_guest-page-table" value="Guest Page Table<br/>GVA → GPA" tooltip="첫 번째 translation 단계. 여기서 접근을 완료할 수 없으면 Guest Page Fault 가 난다. | Evidence: L2443-L2445, L2484-L2485" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="166.5" y="70.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu-backing" value="QEMU · Guest RAM Backing<br/>Host Virtual Memory" tooltip="Host 의 일반 userspace 메모리로 관리되는 자리. demand allocation 이나 reclaim, swap 때문에 여기서 fault 가 난다. | Evidence: L2504-L2504, L2514-L2519" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="376.5" y="60.0" width="167.0" height="91.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_ept" value="EPT<br/>GPA → HPA" tooltip="두 번째 translation 단계. Guest translation 이 성공한 뒤 여기서 막히면 EPT Violation 이 난다. | Evidence: L2465-L2469, L2484-L2485" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="247.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-kernel" value="Guest Kernel" tooltip="Guest Page Fault 를 받는 계층. | Evidence: L2487-L2487, L2493-L2494" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="280.0" y="250.5" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-kernel" value="Host Kernel" tooltip="Host Page Fault 를 받아 필요한 Host page 를 처리하는 계층. | Evidence: L2521-L2525" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="490.0" y="250.5" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_kvm" value="KVM" tooltip="EPT Violation 을 VM Exit 뒤에 받는 계층. | Evidence: L2471-L2473, L2487-L2487" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="280.0" y="414.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_ept-violation-branch" value="EPT Violation · VM Exit" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;dashed=1;" edge="1" parent="1" source="n_ept" target="n_kvm">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="250.0" y="338.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_guest-fault-branch" value="Guest Page Fault" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;dashed=1;" edge="1" parent="1" source="n_guest-page-table" target="n_guest-kernel">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="302.8" y="167.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_host-fault-branch" value="Host Page Fault" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;dashed=1;" edge="1" parent="1" source="n_qemu-backing" target="n_host-kernel">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="512.5" y="172.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_translation-continues" value="GPA" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-page-table" target="n_ept">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="188.8" y="166.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,823 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-ept-violation-branch",
|
||||
"type": "arrow",
|
||||
"x": 145.0,
|
||||
"y": 318.0,
|
||||
"width": 210.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1813435601,
|
||||
"version": 1,
|
||||
"versionNonce": 1356316492,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
210.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
210.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-ept",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-kvm",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-ept-violation-branch",
|
||||
"type": "text",
|
||||
"x": 158.0,
|
||||
"y": 326.0,
|
||||
"width": 184,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 126213589,
|
||||
"version": 1,
|
||||
"versionNonce": 1594262405,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "EPT Violation · VM Exit",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "EPT Violation · VM Exit",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-guest-fault-branch",
|
||||
"type": "arrow",
|
||||
"x": 250.5,
|
||||
"y": 141.0,
|
||||
"width": 104.5,
|
||||
"height": 109.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 270453869,
|
||||
"version": 1,
|
||||
"versionNonce": 1761730436,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
54.75
|
||||
],
|
||||
[
|
||||
104.5,
|
||||
54.75
|
||||
],
|
||||
[
|
||||
104.5,
|
||||
109.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-guest-page-table",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-guest-kernel",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-guest-fault-branch",
|
||||
"type": "text",
|
||||
"x": 238.75,
|
||||
"y": 155.75,
|
||||
"width": 128,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 651157700,
|
||||
"version": 1,
|
||||
"versionNonce": 1730090925,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest Page Fault",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest Page Fault",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-host-fault-branch",
|
||||
"type": "arrow",
|
||||
"x": 460.0,
|
||||
"y": 151.0,
|
||||
"width": 105.0,
|
||||
"height": 99.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "dashed",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 361491347,
|
||||
"version": 1,
|
||||
"versionNonce": 164584873,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
49.75
|
||||
],
|
||||
[
|
||||
105.0,
|
||||
49.75
|
||||
],
|
||||
[
|
||||
105.0,
|
||||
99.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu-backing",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-kernel",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-host-fault-branch",
|
||||
"type": "text",
|
||||
"x": 452.5,
|
||||
"y": 160.75,
|
||||
"width": 120,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 392218398,
|
||||
"version": 1,
|
||||
"versionNonce": 343368682,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Host Page Fault",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host Page Fault",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-translation-continues",
|
||||
"type": "arrow",
|
||||
"x": 145.0,
|
||||
"y": 141.0,
|
||||
"width": 87.5,
|
||||
"height": 106.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 468653972,
|
||||
"version": 1,
|
||||
"versionNonce": 27222128,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
87.5,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
87.5,
|
||||
53.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
53.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
106.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-guest-page-table",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-ept",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-translation-continues",
|
||||
"type": "text",
|
||||
"x": 143.75,
|
||||
"y": 154.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1755263566,
|
||||
"version": 1,
|
||||
"versionNonce": 1161066356,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "GPA",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "GPA",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest-page-table",
|
||||
"type": "rectangle",
|
||||
"x": 166.5,
|
||||
"y": 70.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 858382528,
|
||||
"version": 1,
|
||||
"versionNonce": 1649692634,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest-page-table",
|
||||
"type": "text",
|
||||
"x": 176.5,
|
||||
"y": 80.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1187226205,
|
||||
"version": 1,
|
||||
"versionNonce": 1771047591,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest Page Table\nGVA → GPA",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest Page Table\nGVA → GPA",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-qemu-backing",
|
||||
"type": "rectangle",
|
||||
"x": 376.5,
|
||||
"y": 60.0,
|
||||
"width": 167.0,
|
||||
"height": 91.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 245780206,
|
||||
"version": 1,
|
||||
"versionNonce": 1054758503,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-qemu-backing",
|
||||
"type": "text",
|
||||
"x": 386.5,
|
||||
"y": 70.0,
|
||||
"width": 147.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 470938543,
|
||||
"version": 1,
|
||||
"versionNonce": 1389218466,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "QEMU · Guest RAM Backing\nHost Virtual Memory",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "QEMU · Guest RAM Backing\nHost Virtual Memory",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-ept",
|
||||
"type": "rectangle",
|
||||
"x": 70.0,
|
||||
"y": 247.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1508191037,
|
||||
"version": 1,
|
||||
"versionNonce": 1352757918,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-ept",
|
||||
"type": "text",
|
||||
"x": 80.0,
|
||||
"y": 257.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 243376460,
|
||||
"version": 1,
|
||||
"versionNonce": 599206536,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "EPT\nGPA → HPA",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "EPT\nGPA → HPA",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest-kernel",
|
||||
"type": "rectangle",
|
||||
"x": 280.0,
|
||||
"y": 250.5,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1858630489,
|
||||
"version": 1,
|
||||
"versionNonce": 1370487869,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest-kernel",
|
||||
"type": "text",
|
||||
"x": 290.0,
|
||||
"y": 260.5,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 199697629,
|
||||
"version": 1,
|
||||
"versionNonce": 1282544489,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest Kernel",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest Kernel",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-host-kernel",
|
||||
"type": "rectangle",
|
||||
"x": 490.0,
|
||||
"y": 250.5,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 335259087,
|
||||
"version": 1,
|
||||
"versionNonce": 753872004,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-host-kernel",
|
||||
"type": "text",
|
||||
"x": 500.0,
|
||||
"y": 260.5,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 608596992,
|
||||
"version": 1,
|
||||
"versionNonce": 1964329339,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Host Kernel",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host Kernel",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-kvm",
|
||||
"type": "rectangle",
|
||||
"x": 280.0,
|
||||
"y": 414.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1294725949,
|
||||
"version": 1,
|
||||
"versionNonce": 774205501,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-kvm",
|
||||
"type": "text",
|
||||
"x": 290.0,
|
||||
"y": 424.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 820201432,
|
||||
"version": 1,
|
||||
"versionNonce": 242634004,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "KVM",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "KVM",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "page-fault-layers-in-a-vm",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "1db9b8029b08c8d4c61b3f01119f121b394b7d0efb9818cb63793d65b858d667",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "48. Guest Page Fault와 EPT Violation 비교",
|
||||
"line": 2480
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"page-fault-layers-in-a-vm.svg",
|
||||
"page-fault-layers-in-a-vm.drawio",
|
||||
"page-fault-layers-in-a-vm.mmd",
|
||||
"page-fault-layers-in-a-vm.d2",
|
||||
"page-fault-layers-in-a-vm.excalidraw",
|
||||
"page-fault-layers-in-a-vm.alt.md"
|
||||
],
|
||||
"lint_issue_count": 0,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
%% 세 fault 는 변환 사슬의 서로 다른 단계에서 갈라져 나가 서로 다른 계층이 받는다
|
||||
%% question: Guest Page Fault · EPT Violation · Host Page Fault 는 각각 어느 단계에서 갈라지고 누가 받는가
|
||||
flowchart TB
|
||||
n0["Guest Page Table"]
|
||||
n1["Guest Kernel"]
|
||||
n2["EPT"]
|
||||
n3["KVM"]
|
||||
n4["QEMU · Guest RAM Backing"]
|
||||
n5["Host Kernel"]
|
||||
n0 -.->|"Guest Page Fault"| n1
|
||||
n0 -->|"GPA"| n2
|
||||
n2 -.->|"EPT Violation · VM Exit"| n3
|
||||
n4 -.->|"Host Page Fault"| n5
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="685" height="523" viewBox="0 0 685 523" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">세 fault 는 변환 사슬의 서로 다른 단계에서 갈라져 나가 서로 다른 계층이 받는다</title>
|
||||
<desc id="diagram-description">위에서 아래로 읽는다. 맨 위 왼쪽에 Guest Page Table 이 있고 거기서 갈래가 둘이다. 하나는 Guest Page Fault 로 Guest Kernel 에 빠지고, 다른 하나는 GPA 를 들고 아래 EPT 로 내려간다. EPT 에서도 갈래가 나뉘어 EPT Violation 은 VM Exit 을 거쳐 KVM 으로 간다. 맨 위 오른쪽에는 QEMU 의 Guest RAM Backing 이 따로 있고 그쪽 갈래인 Host Page Fault 는 Host Kernel 로 간다. 받는 자리의 이름이 그대로 계층 이름이다 — Guest Kernel · KVM · Host Kernel. QEMU 갈래가 EPT 갈래와 선으로 이어져 있지 않은 것은 근거 문서가 둘을 잇는 문장을 두지 않았기 때문이다. 다섯 원인이 무엇인지와 두 사건을 항목별로 견주는 것은 본문의 표가 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"page-fault-layers-in-a-vm","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"48. Guest Page Fault와 EPT Violation 비교","line":2480}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="685" height="523" />
|
||||
<polyline class="edge kind-event style-solid emphasis-normal semantic-dashed" points="145.0,318.0 145.0,366.0 355.0,366.0 355.0,414.0" data-evidence="2467-2473,2487-2487" />
|
||||
<rect class="edge-label-bg" x="163.9" y="324.0" width="172.1" height="22" rx="3" />
|
||||
<text class="edge-label" x="250.0" y="339.0">EPT Violation · VM Exit</text>
|
||||
<polyline class="edge kind-event style-solid emphasis-normal semantic-dashed" points="250.5,141.0 250.5,195.8 355.0,195.8 355.0,250.5" data-evidence="2484-2487,2493-2494" />
|
||||
<rect class="edge-label-bg" x="240.2" y="153.8" width="125.2" height="22" rx="3" />
|
||||
<text class="edge-label" x="302.8" y="168.8">Guest Page Fault</text>
|
||||
<polyline class="edge kind-event style-solid emphasis-normal semantic-dashed" points="460.0,151.0 460.0,200.8 565.0,200.8 565.0,250.5" data-evidence="2517-2525" />
|
||||
<rect class="edge-label-bg" x="453.2" y="158.8" width="118.5" height="22" rx="3" />
|
||||
<text class="edge-label" x="512.5" y="173.8">Host Page Fault</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="232.5,141.0 232.5,194.0 145.0,194.0 145.0,247.0" data-evidence="2461-2467" />
|
||||
<rect class="edge-label-bg" x="166.8" y="152.0" width="44.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="188.8" y="167.0">GPA</text>
|
||||
<g id="node-guest-page-table">
|
||||
<rect class="node-shape kind-component emphasis-normal role-source" data-evidence="2443-2445,2484-2485" x="166.5" y="70.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="241.5" y="97.0">Guest Page Table</text>
|
||||
<line class="node-detail-divider" x1="180.5" y1="118.0" x2="302.5" y2="118.0" />
|
||||
<text class="node-detail" x="182.5" y="135.0">GVA → GPA</text>
|
||||
</g>
|
||||
<g id="node-qemu-backing">
|
||||
<rect class="node-shape kind-store emphasis-normal role-source" data-evidence="2504-2504,2514-2519" x="376.5" y="60.0" width="167.0" height="91.0" rx="7" />
|
||||
<text class="node-label" x="460.0" y="87.0">QEMU · Guest RAM</text>
|
||||
<text class="node-label" x="460.0" y="105.0">Backing</text>
|
||||
<line class="node-detail-divider" x1="390.5" y1="126.0" x2="529.5" y2="126.0" />
|
||||
<text class="node-detail" x="392.5" y="143.0">Host Virtual Memory</text>
|
||||
</g>
|
||||
<g id="node-ept">
|
||||
<rect class="node-shape kind-component emphasis-primary role-service" data-evidence="2465-2469,2484-2485" x="70.0" y="247.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="145.0" y="274.0">EPT</text>
|
||||
<line class="node-detail-divider" x1="84.0" y1="295.0" x2="206.0" y2="295.0" />
|
||||
<text class="node-detail" x="86.0" y="312.0">GPA → HPA</text>
|
||||
</g>
|
||||
<g id="node-guest-kernel">
|
||||
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="2487-2487,2493-2494" x="280.0" y="250.5" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="355.0" y="280.5">Guest Kernel</text>
|
||||
</g>
|
||||
<g id="node-host-kernel">
|
||||
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="2521-2525" x="490.0" y="250.5" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="565.0" y="280.5">Host Kernel</text>
|
||||
</g>
|
||||
<g id="node-kvm">
|
||||
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="2471-2473,2487-2487" x="280.0" y="414.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="355.0" y="444.0">KVM</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.1 KiB |
@@ -0,0 +1,33 @@
|
||||
# balloon target 은 VM Boundary 를 건너 driver 에 닿고 확보한 page 는 같은 경계를 되건너 온다
|
||||
|
||||
## Alternative text
|
||||
|
||||
virtio-balloon Driver, virtqueue, QEMU virtio-balloon Device, Host Memory Management 네 참여자 사이의 순서도. 앞 세 메시지는 오른쪽에서 왼쪽으로 Guest 안으로 들어가고 뒤 세 메시지는 왼쪽에서 오른쪽으로 Host 로 돌아온다.
|
||||
|
||||
## Long description
|
||||
|
||||
참여자는 왼쪽부터 Guest kernel 의 virtio-balloon Driver, virtqueue, QEMU virtio-balloon Device, Host Memory Management 네 개다. 메시지는 위에서 아래로 읽는다. 1번은 Host Memory Management 가 QEMU 쪽 device 에 balloon target 조정을 보내는 것이고, 2번에서 그 요청이 virtqueue 로 내려가면서 VM Boundary 를 넘고, 3번에서 Guest kernel 의 driver 에 balloon target 이 닿는다. 여기서 방향이 바뀐다. 4번에서 driver 가 확보한 Guest page 를 virtqueue 에 올리고, 5번에서 그것이 다시 VM Boundary 를 넘어 QEMU 쪽 device 로 가고, 6번에서 device 가 Host Memory Management 에 회수 가능 backing 으로 넘긴다. target 을 올릴 때와 내릴 때 Guest 가 쓸 수 있는 memory 가 어느 쪽으로 움직이는지는 본문의 표가 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **virtio-balloon Driver** (driver): Guest kernel 쪽 balloon driver. target 을 받아 Guest page 를 확보한다. Evidence: L3013–L3015, L3046–L3046.
|
||||
- **virtqueue** (queue): Guest 와 QEMU 가 balloon 요청을 주고받는 공유 큐. VM Boundary 바로 안쪽이다. Evidence: L3017–L3017.
|
||||
- **QEMU virtio-balloon
|
||||
Device** (service): Host 쪽 balloon device. 경계를 넘어온 내용을 Host memory management 로 넘긴다. Evidence: L3022–L3022, L3037–L3041.
|
||||
- **Host Memory
|
||||
Management** (service): balloon target 을 정하는 쪽이자 회수 기회가 생기는 자리. Evidence: L3025–L3025, L3034–L3037.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **Host Memory
|
||||
Management → QEMU virtio-balloon
|
||||
Device:** Balloon target 조정. Evidence: L3034–L3041.
|
||||
- **QEMU virtio-balloon
|
||||
Device → virtqueue:** VM Boundary. Evidence: L3017–L3022, L3041–L3046.
|
||||
- **virtqueue → virtio-balloon Driver:** Balloon target. Evidence: L3013–L3017, L3043–L3046.
|
||||
- **virtio-balloon Driver → virtqueue:** Guest pages 확보. Evidence: L3046–L3050.
|
||||
- **virtqueue → QEMU virtio-balloon
|
||||
Device:** VM Boundary. Evidence: L3017–L3025.
|
||||
- **QEMU virtio-balloon
|
||||
Device → Host Memory
|
||||
Management:** 회수 가능 backing. Evidence: L3022–L3028, L3077–L3079.
|
||||
@@ -0,0 +1,21 @@
|
||||
# balloon target 은 VM Boundary 를 건너 driver 에 닿고 확보한 page 는 같은 경계를 되건너 온다
|
||||
# Question: Host 가 balloon target 을 바꾸면 그 요청은 어떤 순서로 어느 경계를 건너 Guest 안의 driver 까지 가고, 확보된 page 는 어떻게 Host 로 돌아오는가
|
||||
direction: right
|
||||
n0: "virtio-balloon Driver" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "virtqueue" {
|
||||
shape: queue
|
||||
}
|
||||
n2: "QEMU virtio-balloon\nDevice" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "Host Memory\nManagement" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3 -> n2: "Balloon target 조정"
|
||||
n2 -> n1: "VM Boundary"
|
||||
n1 -> n0: "Balloon target"
|
||||
n0 -> n1: "Guest pages 확보"
|
||||
n1 -> n2: "VM Boundary"
|
||||
n2 -> n3: "회수 가능 backing"
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="virtio-balloon-inflate-deflate" name="balloon target 은 VM Boundary 를 건너 driver 에 닿고 확보한 page 는 같은 경계를 되건너 온다">
|
||||
<mxGraphModel dx="870" dy="542" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="870" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_balloon-driver" value="virtio-balloon Driver<br/>Guest Kernel" tooltip="Guest kernel 쪽 balloon driver. target 을 받아 Guest page 를 확보한다. | Evidence: L3013-L3015, L3046-L3046" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="45.0" y="35.0" width="181.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtqueue" value="virtqueue" tooltip="Guest 와 QEMU 가 balloon 요청을 주고받는 공유 큐. VM Boundary 바로 안쪽이다. | Evidence: L3017-L3017" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="255.0" y="35.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu-balloon-device" value="QEMU virtio-balloon
|
||||
Device" tooltip="Host 쪽 balloon device. 경계를 넘어온 내용을 Host memory management 로 넘긴다. | Evidence: L3022-L3022, L3037-L3041" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="465.0" y="35.0" width="167.0" height="74.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-memory-management" value="Host Memory
|
||||
Management" tooltip="balloon target 을 정하는 쪽이자 회수 기회가 생기는 자리. | Evidence: L3025-L3025, L3034-L3037" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="675.0" y="35.0" width="150.0" height="74.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_target-adjust" value="Balloon target 조정" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-memory-management" target="n_qemu-balloon-device">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="649.2" y="128.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_target-crosses-in" value="VM Boundary" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu-balloon-device" target="n_virtqueue">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="439.2" y="190.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_target-to-driver" value="Balloon target" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtqueue" target="n_balloon-driver">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="232.8" y="252.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_pages-secured" value="Guest pages 확보" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_balloon-driver" target="n_virtqueue">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="232.8" y="314.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_pages-cross-out" value="VM Boundary" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtqueue" target="n_qemu-balloon-device">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="439.2" y="376.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_reclaimable-backing" value="회수 가능 backing" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu-balloon-device" target="n_host-memory-management">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="649.2" y="438.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,835 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-target-adjust",
|
||||
"type": "arrow",
|
||||
"x": 548.5,
|
||||
"y": 140.0,
|
||||
"width": 201.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 737020640,
|
||||
"version": 1,
|
||||
"versionNonce": 1525160168,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
201.5,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-host-memory-management",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-qemu-balloon-device",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-target-adjust",
|
||||
"type": "text",
|
||||
"x": 581.25,
|
||||
"y": 116.0,
|
||||
"width": 136,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 453083568,
|
||||
"version": 1,
|
||||
"versionNonce": 1469276324,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Balloon target 조정",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Balloon target 조정",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-target-crosses-in",
|
||||
"type": "arrow",
|
||||
"x": 330.0,
|
||||
"y": 202.0,
|
||||
"width": 218.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1982038005,
|
||||
"version": 1,
|
||||
"versionNonce": 61702621,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
218.5,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu-balloon-device",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-virtqueue",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-target-crosses-in",
|
||||
"type": "text",
|
||||
"x": 394.25,
|
||||
"y": 178.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 777212613,
|
||||
"version": 1,
|
||||
"versionNonce": 349365301,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "VM Boundary",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM Boundary",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-target-to-driver",
|
||||
"type": "arrow",
|
||||
"x": 135.5,
|
||||
"y": 264.0,
|
||||
"width": 194.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 135515254,
|
||||
"version": 1,
|
||||
"versionNonce": 613652303,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
194.5,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-virtqueue",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-balloon-driver",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-target-to-driver",
|
||||
"type": "text",
|
||||
"x": 176.75,
|
||||
"y": 240.0,
|
||||
"width": 112,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1817118777,
|
||||
"version": 1,
|
||||
"versionNonce": 19943219,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Balloon target",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Balloon target",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-pages-secured",
|
||||
"type": "arrow",
|
||||
"x": 135.5,
|
||||
"y": 326.0,
|
||||
"width": 194.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 107373777,
|
||||
"version": 1,
|
||||
"versionNonce": 1878244752,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
194.5,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-balloon-driver",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-virtqueue",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-pages-secured",
|
||||
"type": "text",
|
||||
"x": 176.75,
|
||||
"y": 302.0,
|
||||
"width": 112,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 695343754,
|
||||
"version": 1,
|
||||
"versionNonce": 1171214433,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest pages 확보",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest pages 확보",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-pages-cross-out",
|
||||
"type": "arrow",
|
||||
"x": 330.0,
|
||||
"y": 388.0,
|
||||
"width": 218.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1480907426,
|
||||
"version": 1,
|
||||
"versionNonce": 1830405205,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
218.5,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-virtqueue",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-qemu-balloon-device",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-pages-cross-out",
|
||||
"type": "text",
|
||||
"x": 394.25,
|
||||
"y": 364.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 19536809,
|
||||
"version": 1,
|
||||
"versionNonce": 1120594763,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "VM Boundary",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM Boundary",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-reclaimable-backing",
|
||||
"type": "arrow",
|
||||
"x": 548.5,
|
||||
"y": 450.0,
|
||||
"width": 201.5,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 289901807,
|
||||
"version": 1,
|
||||
"versionNonce": 383977982,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
201.5,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu-balloon-device",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-memory-management",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-reclaimable-backing",
|
||||
"type": "text",
|
||||
"x": 597.25,
|
||||
"y": 426.0,
|
||||
"width": 104,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 617340894,
|
||||
"version": 1,
|
||||
"versionNonce": 525555255,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "회수 가능 backing",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "회수 가능 backing",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-balloon-driver",
|
||||
"type": "rectangle",
|
||||
"x": 45.0,
|
||||
"y": 35.0,
|
||||
"width": 181.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1402975843,
|
||||
"version": 1,
|
||||
"versionNonce": 162304747,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-balloon-driver",
|
||||
"type": "text",
|
||||
"x": 55.0,
|
||||
"y": 45.0,
|
||||
"width": 161.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 218037921,
|
||||
"version": 1,
|
||||
"versionNonce": 1781698181,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "virtio-balloon Driver\nGuest Kernel",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "virtio-balloon Driver\nGuest Kernel",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-virtqueue",
|
||||
"type": "rectangle",
|
||||
"x": 255.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#f3f0ff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1427608734,
|
||||
"version": 1,
|
||||
"versionNonce": 104915312,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-virtqueue",
|
||||
"type": "text",
|
||||
"x": 265.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1863917934,
|
||||
"version": 1,
|
||||
"versionNonce": 579283696,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "virtqueue",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "virtqueue",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-qemu-balloon-device",
|
||||
"type": "rectangle",
|
||||
"x": 465.0,
|
||||
"y": 35.0,
|
||||
"width": 167.0,
|
||||
"height": 74.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 823854416,
|
||||
"version": 1,
|
||||
"versionNonce": 1128635888,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-qemu-balloon-device",
|
||||
"type": "text",
|
||||
"x": 475.0,
|
||||
"y": 45.0,
|
||||
"width": 147.0,
|
||||
"height": 54.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 560943017,
|
||||
"version": 1,
|
||||
"versionNonce": 818393145,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "QEMU virtio-balloon\nDevice",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "QEMU virtio-balloon\nDevice",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-host-memory-management",
|
||||
"type": "rectangle",
|
||||
"x": 675.0,
|
||||
"y": 35.0,
|
||||
"width": 150.0,
|
||||
"height": 74.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 765979520,
|
||||
"version": 1,
|
||||
"versionNonce": 934288555,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-host-memory-management",
|
||||
"type": "text",
|
||||
"x": 685.0,
|
||||
"y": 45.0,
|
||||
"width": 130.0,
|
||||
"height": 54.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1363069112,
|
||||
"version": 1,
|
||||
"versionNonce": 234953733,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Host Memory\nManagement",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host Memory\nManagement",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "virtio-balloon-inflate-deflate",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "1a53fd7e3e5cf5b553be00d6c12f47f8493d302f9a79f660d29e1d85490e61de",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "65. virtio-balloon 구조",
|
||||
"line": 3008
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"virtio-balloon-inflate-deflate.svg",
|
||||
"virtio-balloon-inflate-deflate.drawio",
|
||||
"virtio-balloon-inflate-deflate.mmd",
|
||||
"virtio-balloon-inflate-deflate.d2",
|
||||
"virtio-balloon-inflate-deflate.excalidraw",
|
||||
"virtio-balloon-inflate-deflate.alt.md"
|
||||
],
|
||||
"lint_issue_count": 0,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "sequence",
|
||||
"reference_ids": [
|
||||
"payment-approval-sequence"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
%% balloon target 은 VM Boundary 를 건너 driver 에 닿고 확보한 page 는 같은 경계를 되건너 온다
|
||||
%% question: Host 가 balloon target 을 바꾸면 그 요청은 어떤 순서로 어느 경계를 건너 Guest 안의 driver 까지 가고, 확보된 page 는 어떻게 Host 로 돌아오는가
|
||||
sequenceDiagram
|
||||
participant n0 as virtio-balloon Driver
|
||||
participant n1 as virtqueue
|
||||
participant n2 as QEMU virtio-balloon<br/>Device
|
||||
participant n3 as Host Memory<br/>Management
|
||||
n3->>n2: Balloon target 조정
|
||||
n2->>n1: VM Boundary
|
||||
n1->>n0: Balloon target
|
||||
n0->>n1: Guest pages 확보
|
||||
n1->>n2: VM Boundary
|
||||
n2->>n3: 회수 가능 backing
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="870" height="542" viewBox="0 0 870 542" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">balloon target 은 VM Boundary 를 건너 driver 에 닿고 확보한 page 는 같은 경계를 되건너 온다</title>
|
||||
<desc id="diagram-description">참여자는 왼쪽부터 Guest kernel 의 virtio-balloon Driver, virtqueue, QEMU virtio-balloon Device, Host Memory Management 네 개다. 메시지는 위에서 아래로 읽는다. 1번은 Host Memory Management 가 QEMU 쪽 device 에 balloon target 조정을 보내는 것이고, 2번에서 그 요청이 virtqueue 로 내려가면서 VM Boundary 를 넘고, 3번에서 Guest kernel 의 driver 에 balloon target 이 닿는다. 여기서 방향이 바뀐다. 4번에서 driver 가 확보한 Guest page 를 virtqueue 에 올리고, 5번에서 그것이 다시 VM Boundary 를 넘어 QEMU 쪽 device 로 가고, 6번에서 device 가 Host Memory Management 에 회수 가능 backing 으로 넘긴다. target 을 올릴 때와 내릴 때 Guest 가 쓸 수 있는 memory 가 어느 쪽으로 움직이는지는 본문의 표가 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"virtio-balloon-inflate-deflate","profile":"sequence"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"65. virtio-balloon 구조","line":3008}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="870" height="542" />
|
||||
<rect class="node-shape kind-driver emphasis-primary role-participant" data-evidence="3013-3015,3046-3046" x="45.0" y="35.0" width="181.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="135.5" y="62.0">virtio-balloon Driver</text>
|
||||
<line class="node-detail-divider" x1="59.0" y1="83.0" x2="212.0" y2="83.0" />
|
||||
<text class="node-detail" x="61.0" y="100.0">Guest Kernel</text>
|
||||
<line class="lifeline" x1="135.5" y1="106.0" x2="135.5" y2="512.0" />
|
||||
<rect class="node-shape kind-queue emphasis-normal role-participant" data-evidence="3017-3017" x="255.0" y="35.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="330.0" y="65.0">virtqueue</text>
|
||||
<line class="lifeline" x1="330.0" y1="99.0" x2="330.0" y2="512.0" />
|
||||
<rect class="node-shape kind-service emphasis-normal role-participant" data-evidence="3022-3022,3037-3041" x="465.0" y="35.0" width="167.0" height="74.0" rx="7" />
|
||||
<text class="node-label" x="548.5" y="62.0">QEMU virtio-balloon</text>
|
||||
<text class="node-label" x="548.5" y="80.0">Device</text>
|
||||
<line class="lifeline" x1="548.5" y1="109.0" x2="548.5" y2="512.0" />
|
||||
<rect class="node-shape kind-service emphasis-normal role-participant" data-evidence="3025-3025,3034-3037" x="675.0" y="35.0" width="150.0" height="74.0" rx="7" />
|
||||
<text class="node-label" x="750.0" y="62.0">Host Memory</text>
|
||||
<text class="node-label" x="750.0" y="80.0">Management</text>
|
||||
<line class="lifeline" x1="750.0" y1="109.0" x2="750.0" y2="512.0" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="750.0,140.0 548.5,140.0" data-evidence="3034-3041" />
|
||||
<rect class="edge-label-bg" x="573.2" y="114.0" width="152.0" height="22" rx="3" />
|
||||
<text class="edge-label" x="649.2" y="129.0">1. Balloon target 조정</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="548.5,202.0 330.0,202.0" data-evidence="3017-3022,3041-3046" />
|
||||
<rect class="edge-label-bg" x="383.4" y="176.0" width="111.8" height="22" rx="3" />
|
||||
<text class="edge-label" x="439.2" y="191.0">2. VM Boundary</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="330.0,264.0 135.5,264.0" data-evidence="3013-3017,3043-3046" />
|
||||
<rect class="edge-label-bg" x="166.8" y="238.0" width="131.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="232.8" y="253.0">3. Balloon target</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="135.5,326.0 330.0,326.0" data-evidence="3046-3050" />
|
||||
<rect class="edge-label-bg" x="166.8" y="300.0" width="131.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="232.8" y="315.0">4. Guest pages 확보</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="330.0,388.0 548.5,388.0" data-evidence="3017-3025" />
|
||||
<rect class="edge-label-bg" x="383.4" y="362.0" width="111.8" height="22" rx="3" />
|
||||
<text class="edge-label" x="439.2" y="377.0">5. VM Boundary</text>
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="548.5,450.0 750.0,450.0" data-evidence="3022-3028,3077-3079" />
|
||||
<rect class="edge-label-bg" x="586.6" y="424.0" width="125.2" height="22" rx="3" />
|
||||
<text class="edge-label" x="649.2" y="439.0">6. 회수 가능 backing</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,25 @@
|
||||
# VM Exit 은 KVM 에서 끝나기도 하고 QEMU userspace 까지 가기도 한다
|
||||
|
||||
## Alternative text
|
||||
|
||||
Guest 에서 VM Exit 으로 KVM 에 닿은 뒤 커널 처리와 QEMU 처리 두 갈래로 갈라졌다가 VM Entry 로 다시 Guest 실행 재개에 모이는 흐름도.
|
||||
|
||||
## Long description
|
||||
|
||||
왼쪽에서 오른쪽으로 읽는다. 왼쪽 끝에 Guest 가 있고 VM Exit 이 KVM 으로 제어권을 넘긴다. KVM 은 Exit Reason 을 확인해 두 갈래 중 하나를 고른다. 커널 안에서 처리할 수 있는 Exit 은 Kernel 쪽 KVM 커널 처리로 가고, userspace 처리가 필요한 Exit 만 KVM_RUN 이 반환되면서 Userspace 쪽 QEMU 로 간다. QEMU 는 필요한 장치 동작을 처리한 뒤 KVM_RUN 을 다시 호출한다. 두 갈래는 오른쪽 끝에서 다시 만나며 어느 쪽이든 VM Entry 를 지나 Guest 실행 재개로 돌아온다. 무엇이 Exit 을 부르는지와 Exit 이 잦을 때 무엇을 함께 보는지는 본문의 표와 문단이 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **Guest** (service): VM Exit 이 나기 직전까지 실행 중이던 Guest. Evidence: L498–L501.
|
||||
- **KVM** (service): VM Exit 을 받아 Exit Reason 을 확인하고 갈래를 고르는 자리. Evidence: L495–L495, L502–L504.
|
||||
- **KVM 커널 처리** (service): 커널 안에서 끝낼 수 있는 Exit 을 처리하는 갈래. QEMU 까지 올라가지 않는다. Evidence: L508–L510, L531–L531.
|
||||
- **QEMU** (service): userspace 처리가 필요한 Exit 에서만 개입하는 갈래. Evidence: L510–L516, L533–L533.
|
||||
- **Guest 실행 재개** (service): 두 갈래가 다시 만나는 자리. VM Exit 은 VM 종료가 아니라 여기로 돌아온다. Evidence: L521–L524, L529–L529.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **Guest → KVM:** VM Exit. Evidence: L495–L495, L498–L502.
|
||||
- **KVM → KVM 커널 처리:** 커널 처리 가능. Evidence: L504–L510, L531–L531.
|
||||
- **KVM 커널 처리 → Guest 실행 재개:** VM Entry. Evidence: L518–L524, L531–L531.
|
||||
- **KVM → QEMU:** KVM_RUN return. Evidence: L508–L512, L533–L533.
|
||||
- **QEMU → Guest 실행 재개:** VM Entry. Evidence: L514–L524, L533–L533.
|
||||
@@ -0,0 +1,23 @@
|
||||
# VM Exit 은 KVM 에서 끝나기도 하고 QEMU userspace 까지 가기도 한다
|
||||
# Question: VM Exit 이 난 뒤 제어권은 어디까지 올라갔다가 어떻게 Guest 로 돌아오는가
|
||||
direction: right
|
||||
n0: "Guest" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "KVM" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "KVM 커널 처리" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "QEMU" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "Guest 실행 재개" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n1: "VM Exit"
|
||||
n1 -> n2: "커널 처리 가능"
|
||||
n1 -> n3: "KVM_RUN return"
|
||||
n2 -> n4: "VM Entry"
|
||||
n3 -> n4: "VM Entry"
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="vm-exit-handling-cycle" name="VM Exit 은 KVM 에서 끝나기도 하고 QEMU userspace 까지 가기도 한다">
|
||||
<mxGraphModel dx="1195" dy="353" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1195" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_guest" value="Guest" tooltip="VM Exit 이 나기 직전까지 실행 중이던 Guest. | Evidence: L498-L501" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="152.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_kvm" value="KVM<br/>Exit Reason" tooltip="VM Exit 을 받아 Exit Reason 을 확인하고 갈래를 고르는 자리. | Evidence: L495-L495, L502-L504" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="380.0" y="148.5" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_kvm-kernel-handling" value="KVM 커널 처리<br/>Kernel" tooltip="커널 안에서 끝낼 수 있는 Exit 을 처리하는 갈래. QEMU 까지 올라가지 않는다. | Evidence: L508-L510, L531-L531" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="690.0" y="60.0" width="150.0" height="71.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu" value="QEMU<br/>Userspace<br/>device emulation<br/>KVM_RUN 재호출" tooltip="userspace 처리가 필요한 Exit 에서만 개입하는 갈래. | Evidence: L510-L516, L533-L533" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="690.0" y="203.0" width="150.0" height="105.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-resume" value="Guest 실행 재개" tooltip="두 갈래가 다시 만나는 자리. VM Exit 은 VM 종료가 아니라 여기로 돌아온다. | Evidence: L521-L524, L529-L529" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="1000.0" y="152.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_exit-to-kvm" value="VM Exit" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest" target="n_kvm">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="300.0" y="156.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_kernel-branch" value="커널 처리 가능" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_kvm" target="n_kvm-kernel-handling">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="634.0" y="135.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_kernel-reentry" value="VM Entry" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_kvm-kernel-handling" target="n_guest-resume">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="944.0" y="135.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_userspace-branch" value="KVM_RUN return" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_kvm" target="n_qemu">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="634.0" y="224.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_userspace-reentry" value="VM Entry" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu" target="n_guest-resume">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="944.0" y="224.2" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,853 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-exit-to-kvm",
|
||||
"type": "arrow",
|
||||
"x": 220.0,
|
||||
"y": 184.0,
|
||||
"width": 160.0,
|
||||
"height": 0.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 576129632,
|
||||
"version": 1,
|
||||
"versionNonce": 483419770,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
160.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-guest",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-kvm",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-exit-to-kvm",
|
||||
"type": "text",
|
||||
"x": 255.0,
|
||||
"y": 144.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1778979104,
|
||||
"version": 1,
|
||||
"versionNonce": 1759467009,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "VM Exit",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM Exit",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-kernel-branch",
|
||||
"type": "arrow",
|
||||
"x": 530.0,
|
||||
"y": 95.5,
|
||||
"width": 160.0,
|
||||
"height": 79.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 298728286,
|
||||
"version": 1,
|
||||
"versionNonce": 1052103781,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
79.5
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
79.5
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
160.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-kvm",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-kvm-kernel-handling",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-kernel-branch",
|
||||
"type": "text",
|
||||
"x": 589.0,
|
||||
"y": 123.25,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 182098500,
|
||||
"version": 1,
|
||||
"versionNonce": 150063666,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "커널 처리 가능",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "커널 처리 가능",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-kernel-reentry",
|
||||
"type": "arrow",
|
||||
"x": 840.0,
|
||||
"y": 95.5,
|
||||
"width": 160.0,
|
||||
"height": 79.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1851363334,
|
||||
"version": 1,
|
||||
"versionNonce": 126183680,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
79.5
|
||||
],
|
||||
[
|
||||
160.0,
|
||||
79.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-kvm-kernel-handling",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-guest-resume",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-kernel-reentry",
|
||||
"type": "text",
|
||||
"x": 899.0,
|
||||
"y": 123.25,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1185810906,
|
||||
"version": 1,
|
||||
"versionNonce": 1820150380,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "VM Entry",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM Entry",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-userspace-branch",
|
||||
"type": "arrow",
|
||||
"x": 530.0,
|
||||
"y": 193.0,
|
||||
"width": 160.0,
|
||||
"height": 62.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1399118646,
|
||||
"version": 1,
|
||||
"versionNonce": 1254117045,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
62.5
|
||||
],
|
||||
[
|
||||
160.0,
|
||||
62.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-kvm",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-qemu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-userspace-branch",
|
||||
"type": "text",
|
||||
"x": 578.0,
|
||||
"y": 212.25,
|
||||
"width": 112,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1771993102,
|
||||
"version": 1,
|
||||
"versionNonce": 1685196756,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "KVM_RUN return",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "KVM_RUN return",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-userspace-reentry",
|
||||
"type": "arrow",
|
||||
"x": 840.0,
|
||||
"y": 193.0,
|
||||
"width": 160.0,
|
||||
"height": 62.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 633909860,
|
||||
"version": 1,
|
||||
"versionNonce": 1287721817,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
62.5
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
62.5
|
||||
],
|
||||
[
|
||||
80.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
160.0,
|
||||
0.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-guest-resume",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-userspace-reentry",
|
||||
"type": "text",
|
||||
"x": 899.0,
|
||||
"y": 212.25,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 142846947,
|
||||
"version": 1,
|
||||
"versionNonce": 1732717636,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "VM Entry",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM Entry",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest",
|
||||
"type": "rectangle",
|
||||
"x": 70.0,
|
||||
"y": 152.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 746352068,
|
||||
"version": 1,
|
||||
"versionNonce": 1245638436,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest",
|
||||
"type": "text",
|
||||
"x": 80.0,
|
||||
"y": 162.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1592812232,
|
||||
"version": 1,
|
||||
"versionNonce": 724526867,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-kvm",
|
||||
"type": "rectangle",
|
||||
"x": 380.0,
|
||||
"y": 148.5,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1294725949,
|
||||
"version": 1,
|
||||
"versionNonce": 774205501,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-kvm",
|
||||
"type": "text",
|
||||
"x": 390.0,
|
||||
"y": 158.5,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 820201432,
|
||||
"version": 1,
|
||||
"versionNonce": 242634004,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "KVM\nExit Reason",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "KVM\nExit Reason",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-kvm-kernel-handling",
|
||||
"type": "rectangle",
|
||||
"x": 690.0,
|
||||
"y": 60.0,
|
||||
"width": 150.0,
|
||||
"height": 71.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 116878736,
|
||||
"version": 1,
|
||||
"versionNonce": 1278264154,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-kvm-kernel-handling",
|
||||
"type": "text",
|
||||
"x": 700.0,
|
||||
"y": 70.0,
|
||||
"width": 130.0,
|
||||
"height": 51.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 66773704,
|
||||
"version": 1,
|
||||
"versionNonce": 1987847254,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "KVM 커널 처리\nKernel",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "KVM 커널 처리\nKernel",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-qemu",
|
||||
"type": "rectangle",
|
||||
"x": 690.0,
|
||||
"y": 203.0,
|
||||
"width": 150.0,
|
||||
"height": 105.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1265942130,
|
||||
"version": 1,
|
||||
"versionNonce": 447320704,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-qemu",
|
||||
"type": "text",
|
||||
"x": 700.0,
|
||||
"y": 213.0,
|
||||
"width": 130.0,
|
||||
"height": 85.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 82355235,
|
||||
"version": 1,
|
||||
"versionNonce": 463780486,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "QEMU\nUserspace\ndevice emulation\nKVM_RUN 재호출",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "QEMU\nUserspace\ndevice emulation\nKVM_RUN 재호출",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest-resume",
|
||||
"type": "rectangle",
|
||||
"x": 1000.0,
|
||||
"y": 152.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1508197857,
|
||||
"version": 1,
|
||||
"versionNonce": 1661088114,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest-resume",
|
||||
"type": "text",
|
||||
"x": 1010.0,
|
||||
"y": 162.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1489903096,
|
||||
"version": 1,
|
||||
"versionNonce": 1640327916,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest 실행 재개",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest 실행 재개",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "vm-exit-handling-cycle",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "114180c059ff8c4be3e253da16d2d2f0e0fb44a2b87b03fcd2104f4e3fd6fa79",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "9. VM Exit 이후 처리",
|
||||
"line": 493
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"vm-exit-handling-cycle.svg",
|
||||
"vm-exit-handling-cycle.drawio",
|
||||
"vm-exit-handling-cycle.mmd",
|
||||
"vm-exit-handling-cycle.d2",
|
||||
"vm-exit-handling-cycle.excalidraw",
|
||||
"vm-exit-handling-cycle.alt.md"
|
||||
],
|
||||
"lint_issue_count": 0,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
%% VM Exit 은 KVM 에서 끝나기도 하고 QEMU userspace 까지 가기도 한다
|
||||
%% question: VM Exit 이 난 뒤 제어권은 어디까지 올라갔다가 어떻게 Guest 로 돌아오는가
|
||||
flowchart LR
|
||||
n0["Guest"]
|
||||
n1["KVM"]
|
||||
n2["KVM 커널 처리"]
|
||||
n3["QEMU"]
|
||||
n4["Guest 실행 재개"]
|
||||
n0 -->|"VM Exit"| n1
|
||||
n1 -->|"커널 처리 가능"| n2
|
||||
n1 -->|"KVM_RUN return"| n3
|
||||
n2 -->|"VM Entry"| n4
|
||||
n3 -->|"VM Entry"| n4
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1195" height="353" viewBox="0 0 1195 353" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">VM Exit 은 KVM 에서 끝나기도 하고 QEMU userspace 까지 가기도 한다</title>
|
||||
<desc id="diagram-description">왼쪽에서 오른쪽으로 읽는다. 왼쪽 끝에 Guest 가 있고 VM Exit 이 KVM 으로 제어권을 넘긴다. KVM 은 Exit Reason 을 확인해 두 갈래 중 하나를 고른다. 커널 안에서 처리할 수 있는 Exit 은 Kernel 쪽 KVM 커널 처리로 가고, userspace 처리가 필요한 Exit 만 KVM_RUN 이 반환되면서 Userspace 쪽 QEMU 로 간다. QEMU 는 필요한 장치 동작을 처리한 뒤 KVM_RUN 을 다시 호출한다. 두 갈래는 오른쪽 끝에서 다시 만나며 어느 쪽이든 VM Entry 를 지나 Guest 실행 재개로 돌아온다. 무엇이 Exit 을 부르는지와 Exit 이 잦을 때 무엇을 함께 보는지는 본문의 표와 문단이 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"vm-exit-handling-cycle","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"9. VM Exit 이후 처리","line":493}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="1195" height="353" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="220.0,184.0 300.0,184.0 300.0,184.0 380.0,184.0" data-evidence="495-495,498-502" />
|
||||
<rect class="edge-label-bg" x="267.6" y="142.0" width="64.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="300.0" y="157.0">VM Exit</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="530.0,175.0 610.0,175.0 610.0,95.5 690.0,95.5" data-evidence="504-510,531-531" />
|
||||
<rect class="edge-label-bg" x="598.2" y="121.2" width="71.6" height="22" rx="3" />
|
||||
<text class="edge-label" x="634.0" y="136.2">커널 처리 가능</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="840.0,95.5 920.0,95.5 920.0,175.0 1000.0,175.0" data-evidence="518-524,531-531" />
|
||||
<rect class="edge-label-bg" x="908.2" y="121.2" width="71.6" height="22" rx="3" />
|
||||
<text class="edge-label" x="944.0" y="136.2">VM Entry</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="530.0,193.0 610.0,193.0 610.0,255.5 690.0,255.5" data-evidence="508-512,533-533" />
|
||||
<rect class="edge-label-bg" x="578.1" y="210.2" width="111.8" height="22" rx="3" />
|
||||
<text class="edge-label" x="634.0" y="225.2">KVM_RUN return</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="840.0,255.5 920.0,255.5 920.0,193.0 1000.0,193.0" data-evidence="514-524,533-533" />
|
||||
<rect class="edge-label-bg" x="908.2" y="210.2" width="71.6" height="22" rx="3" />
|
||||
<text class="edge-label" x="944.0" y="225.2">VM Entry</text>
|
||||
<g id="node-guest">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="498-501" x="70.0" y="152.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="145.0" y="182.0">Guest</text>
|
||||
</g>
|
||||
<g id="node-kvm">
|
||||
<rect class="node-shape kind-service emphasis-primary role-service" data-evidence="495-495,502-504" x="380.0" y="148.5" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="455.0" y="175.5">KVM</text>
|
||||
<line class="node-detail-divider" x1="394.0" y1="196.5" x2="516.0" y2="196.5" />
|
||||
<text class="node-detail" x="396.0" y="213.5">Exit Reason</text>
|
||||
</g>
|
||||
<g id="node-kvm-kernel-handling">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="508-510,531-531" x="690.0" y="60.0" width="150.0" height="71.0" rx="7" />
|
||||
<text class="node-label" x="765.0" y="87.0">KVM 커널 처리</text>
|
||||
<line class="node-detail-divider" x1="704.0" y1="108.0" x2="826.0" y2="108.0" />
|
||||
<text class="node-detail" x="706.0" y="125.0">Kernel</text>
|
||||
</g>
|
||||
<g id="node-qemu">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="510-516,533-533" x="690.0" y="203.0" width="150.0" height="105.0" rx="7" />
|
||||
<text class="node-label" x="765.0" y="230.0">QEMU</text>
|
||||
<line class="node-detail-divider" x1="704.0" y1="251.0" x2="826.0" y2="251.0" />
|
||||
<text class="node-detail" x="706.0" y="268.0">Userspace</text>
|
||||
<text class="node-detail" x="706.0" y="284.0">device emulation</text>
|
||||
<text class="node-detail" x="706.0" y="300.0">KVM_RUN 재호출</text>
|
||||
</g>
|
||||
<g id="node-guest-resume">
|
||||
<rect class="node-shape kind-service emphasis-normal role-sink" data-evidence="521-524,529-529" x="1000.0" y="152.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="1075.0" y="182.0">Guest 실행 재개</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,26 @@
|
||||
# 가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다
|
||||
|
||||
## Alternative text
|
||||
|
||||
VM1 QEMU, VM2 QEMU, Nginx, Host 기타 네 곳에서 나온 화살표가 하나의 Host Block Layer 로 모이고 거기서 NVMe 로 나가는 수렴 흐름도.
|
||||
|
||||
## Long description
|
||||
|
||||
위쪽에 네 출발점이 나란히 있다. VM1 QEMU 는 WRITE X 와 READ Y, WRITE Z 를 내고 VM2 QEMU 는 READ A 와 WRITE B 를 내며, 그 옆에 호스트의 Nginx 와 다른 프로세스가 있다. 네 갈래가 모두 가운데의 Host Block Layer 하나로 모인다. Host Block Layer 는 그 I/O 가 가상 머신 안에서 시작했는지 호스트 프로세스에서 시작했는지를 본질적으로 구분해 처리하는 계층이 아니라 들어온 것을 모두 Host block request 로 다루고, 그 요청들을 queue 에서 관리해 맨 아래 NVMe 로 dispatch 한다. 여기서 생기는 경쟁이 Storage Contention 이고 CPU 실행 시간을 두고 벌어지는 CPU Contention 과는 다투는 자원이 다르다는 것은 본문 문단이 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **VM1 QEMU** (service): 가상 머신 하나의 QEMU 프로세스. 게스트의 I/O 가 여기서 호스트 파일 I/O 가 된다. Evidence: L7029–L7029, L7041–L7044.
|
||||
- **VM2 QEMU** (service): 다른 가상 머신의 QEMU 프로세스. Evidence: L7031–L7031, L7046–L7048.
|
||||
- **Nginx** (service): 호스트에서 직접 도는 프로세스. Evidence: L7033–L7033.
|
||||
- **Host 기타** (service): 그 밖의 호스트 프로세스. Evidence: L7035–L7038.
|
||||
- **Host Block Layer** (service): 어디서 왔는지 구분하지 않고 모두 Host block request 로 다루는 계층. queue 에서 관리해 device 로 내보낸다. Evidence: L7031–L7031, L7017–L7022, L7054–L7054, L7058–L7060.
|
||||
- **NVMe** (device): 네 갈래가 결국 함께 쓰는 하나의 물리 device. Evidence: L7031–L7031, L7019–L7019, L7066–L7069.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **VM1 QEMU → Host Block Layer:** data. Evidence: L7029–L7031.
|
||||
- **VM2 QEMU → Host Block Layer:** data. Evidence: L7031–L7031.
|
||||
- **Nginx → Host Block Layer:** data. Evidence: L7031–L7033.
|
||||
- **Host 기타 → Host Block Layer:** data. Evidence: L7031–L7035.
|
||||
- **Host Block Layer → NVMe:** dispatch. Evidence: L7031–L7031, L7054–L7054.
|
||||
@@ -0,0 +1,26 @@
|
||||
# 가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다
|
||||
# Question: 서로 다른 곳에서 시작한 I/O 는 어디에서 하나로 모여 device 로 나가는가
|
||||
direction: down
|
||||
n0: "VM1 QEMU" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "VM2 QEMU" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "Nginx" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "Host 기타" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "Host Block Layer" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "NVMe" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n4
|
||||
n1 -> n4
|
||||
n2 -> n4
|
||||
n3 -> n4
|
||||
n4 -> n5: "dispatch"
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="vms-sharing-one-nvme" name="가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다">
|
||||
<mxGraphModel dx="895" dy="580" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="895" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_vm1-qemu" value="VM1 QEMU<br/>WRITE X<br/>READ Y<br/>WRITE Z" tooltip="가상 머신 하나의 QEMU 프로세스. 게스트의 I/O 가 여기서 호스트 파일 I/O 가 된다. | Evidence: L7029-L7029, L7041-L7044" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="60.0" width="150.0" height="105.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_vm2-qemu" value="VM2 QEMU<br/>READ A<br/>WRITE B" tooltip="다른 가상 머신의 QEMU 프로세스. | Evidence: L7031-L7031, L7046-L7048" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="280.0" y="68.5" width="150.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_nginx" value="Nginx" tooltip="호스트에서 직접 도는 프로세스. | Evidence: L7033-L7033" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="490.0" y="80.5" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-other" value="Host 기타" tooltip="그 밖의 호스트 프로세스. | Evidence: L7035-L7038" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="700.0" y="80.5" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-block-layer" value="Host Block Layer<br/>Host block request<br/>blk-mq" tooltip="어디서 왔는지 구분하지 않고 모두 Host block request 로 다루는 계층. queue 에서 관리해 device 로 내보낸다. | Evidence: L7031-L7031, L7017-L7022, L7054-L7054, L7058-L7060" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="380.0" y="261.0" width="160.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_nvme" value="NVMe" tooltip="네 갈래가 결국 함께 쓰는 하나의 물리 device. | Evidence: L7031-L7031, L7019-L7019, L7066-L7069" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;shape=cylinder3;boundedLbl=1;backgroundOutline=1;fillColor=#eef6fb;" vertex="1" parent="1">
|
||||
<mxGeometry x="385.0" y="445.0" width="150.0" height="90.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_vm1-to-block-layer" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vm1-qemu" target="n_host-block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="289.0" y="185.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_vm2-to-block-layer" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_vm2-qemu" target="n_host-block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="403.0" y="180.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_nginx-to-block-layer" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_nginx" target="n_host-block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="517.0" y="174.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_host-other-to-block-layer" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-other" target="n_host-block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="631.0" y="174.8" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_block-layer-to-nvme" value="dispatch" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-block-layer" target="n_nvme">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="484.0" y="397.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,766 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-vm1-to-block-layer",
|
||||
"type": "arrow",
|
||||
"x": 145.0,
|
||||
"y": 165.0,
|
||||
"width": 288.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1225083499,
|
||||
"version": 1,
|
||||
"versionNonce": 1066380271,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
288.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
288.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-vm1-qemu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-vm2-to-block-layer",
|
||||
"type": "arrow",
|
||||
"x": 355.0,
|
||||
"y": 156.5,
|
||||
"width": 96.0,
|
||||
"height": 104.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 948207587,
|
||||
"version": 1,
|
||||
"versionNonce": 1141556592,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
52.25
|
||||
],
|
||||
[
|
||||
96.0,
|
||||
52.25
|
||||
],
|
||||
[
|
||||
96.0,
|
||||
104.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-vm2-qemu",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-nginx-to-block-layer",
|
||||
"type": "arrow",
|
||||
"x": 469.0,
|
||||
"y": 144.5,
|
||||
"width": 96.0,
|
||||
"height": 116.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 414555304,
|
||||
"version": 1,
|
||||
"versionNonce": 162956757,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
96.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
96.0,
|
||||
58.25
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
58.25
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
116.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-nginx",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-host-other-to-block-layer",
|
||||
"type": "arrow",
|
||||
"x": 487.0,
|
||||
"y": 144.5,
|
||||
"width": 288.0,
|
||||
"height": 116.5,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1681052111,
|
||||
"version": 1,
|
||||
"versionNonce": 495490748,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
288.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
288.0,
|
||||
58.25
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
58.25
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
116.5
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-host-other",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-block-layer-to-nvme",
|
||||
"type": "arrow",
|
||||
"x": 460.0,
|
||||
"y": 349.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1129222860,
|
||||
"version": 1,
|
||||
"versionNonce": 1630472271,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-host-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-nvme",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-block-layer-to-nvme",
|
||||
"type": "text",
|
||||
"x": 439.0,
|
||||
"y": 385.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 181877595,
|
||||
"version": 1,
|
||||
"versionNonce": 1808212730,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "dispatch",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "dispatch",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-vm1-qemu",
|
||||
"type": "rectangle",
|
||||
"x": 70.0,
|
||||
"y": 60.0,
|
||||
"width": 150.0,
|
||||
"height": 105.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 845950122,
|
||||
"version": 1,
|
||||
"versionNonce": 605509420,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-vm1-qemu",
|
||||
"type": "text",
|
||||
"x": 80.0,
|
||||
"y": 70.0,
|
||||
"width": 130.0,
|
||||
"height": 85.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1628887011,
|
||||
"version": 1,
|
||||
"versionNonce": 506408877,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "VM1 QEMU\nWRITE X\nREAD Y\nWRITE Z",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM1 QEMU\nWRITE X\nREAD Y\nWRITE Z",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-vm2-qemu",
|
||||
"type": "rectangle",
|
||||
"x": 280.0,
|
||||
"y": 68.5,
|
||||
"width": 150.0,
|
||||
"height": 88.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1622552226,
|
||||
"version": 1,
|
||||
"versionNonce": 1610483505,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-vm2-qemu",
|
||||
"type": "text",
|
||||
"x": 290.0,
|
||||
"y": 78.5,
|
||||
"width": 130.0,
|
||||
"height": 68.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 892438862,
|
||||
"version": 1,
|
||||
"versionNonce": 41324946,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "VM2 QEMU\nREAD A\nWRITE B",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "VM2 QEMU\nREAD A\nWRITE B",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-nginx",
|
||||
"type": "rectangle",
|
||||
"x": 490.0,
|
||||
"y": 80.5,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 721013300,
|
||||
"version": 1,
|
||||
"versionNonce": 1520646945,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-nginx",
|
||||
"type": "text",
|
||||
"x": 500.0,
|
||||
"y": 90.5,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 117243520,
|
||||
"version": 1,
|
||||
"versionNonce": 936748041,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Nginx",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Nginx",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-host-other",
|
||||
"type": "rectangle",
|
||||
"x": 700.0,
|
||||
"y": 80.5,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1719667036,
|
||||
"version": 1,
|
||||
"versionNonce": 1594842564,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-host-other",
|
||||
"type": "text",
|
||||
"x": 710.0,
|
||||
"y": 90.5,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 376776079,
|
||||
"version": 1,
|
||||
"versionNonce": 223147487,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Host 기타",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host 기타",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-host-block-layer",
|
||||
"type": "rectangle",
|
||||
"x": 380.0,
|
||||
"y": 261.0,
|
||||
"width": 160.0,
|
||||
"height": 88.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 923862125,
|
||||
"version": 1,
|
||||
"versionNonce": 1842771359,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-host-block-layer",
|
||||
"type": "text",
|
||||
"x": 390.0,
|
||||
"y": 271.0,
|
||||
"width": 140.0,
|
||||
"height": 68.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 117879901,
|
||||
"version": 1,
|
||||
"versionNonce": 785252073,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Host Block Layer\nHost block request\nblk-mq",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host Block Layer\nHost block request\nblk-mq",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-nvme",
|
||||
"type": "rectangle",
|
||||
"x": 385.0,
|
||||
"y": 445.0,
|
||||
"width": 150.0,
|
||||
"height": 90.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1447108727,
|
||||
"version": 1,
|
||||
"versionNonce": 491109462,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-nvme",
|
||||
"type": "text",
|
||||
"x": 395.0,
|
||||
"y": 455.0,
|
||||
"width": 130.0,
|
||||
"height": 70.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 502338443,
|
||||
"version": 1,
|
||||
"versionNonce": 1220402361,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "NVMe",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "NVMe",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "vms-sharing-one-nvme",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "43a75d5863edb3e1585ebf97e76f7bd9bf773c90836d4f8f91936eb8a557bd28",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "159. 여러 VM이 하나의 NVMe를 공유하면",
|
||||
"line": 7026
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"vms-sharing-one-nvme.svg",
|
||||
"vms-sharing-one-nvme.drawio",
|
||||
"vms-sharing-one-nvme.mmd",
|
||||
"vms-sharing-one-nvme.d2",
|
||||
"vms-sharing-one-nvme.excalidraw",
|
||||
"vms-sharing-one-nvme.alt.md"
|
||||
],
|
||||
"lint_issue_count": 5,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
%% 가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다
|
||||
%% question: 서로 다른 곳에서 시작한 I/O 는 어디에서 하나로 모여 device 로 나가는가
|
||||
flowchart TB
|
||||
n0["VM1 QEMU"]
|
||||
n1["VM2 QEMU"]
|
||||
n2["Nginx"]
|
||||
n3["Host 기타"]
|
||||
n4["Host Block Layer"]
|
||||
n5["NVMe"]
|
||||
n0 --> n4
|
||||
n1 --> n4
|
||||
n2 --> n4
|
||||
n3 --> n4
|
||||
n4 -->|"dispatch"| n5
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="895" height="580" viewBox="0 0 895 580" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">가상 머신 둘과 호스트 프로세스가 하나의 NVMe 로 모인다</title>
|
||||
<desc id="diagram-description">위쪽에 네 출발점이 나란히 있다. VM1 QEMU 는 WRITE X 와 READ Y, WRITE Z 를 내고 VM2 QEMU 는 READ A 와 WRITE B 를 내며, 그 옆에 호스트의 Nginx 와 다른 프로세스가 있다. 네 갈래가 모두 가운데의 Host Block Layer 하나로 모인다. Host Block Layer 는 그 I/O 가 가상 머신 안에서 시작했는지 호스트 프로세스에서 시작했는지를 본질적으로 구분해 처리하는 계층이 아니라 들어온 것을 모두 Host block request 로 다루고, 그 요청들을 queue 에서 관리해 맨 아래 NVMe 로 dispatch 한다. 여기서 생기는 경쟁이 Storage Contention 이고 CPU 실행 시간을 두고 벌어지는 CPU Contention 과는 다투는 자원이 다르다는 것은 본문 문단이 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"vms-sharing-one-nvme","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"159. 여러 VM이 하나의 NVMe를 공유하면","line":7026}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="895" height="580" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="145.0,165.0 145.0,213.0 433.0,213.0 433.0,261.0" data-evidence="7029-7031" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="355.0,156.5 355.0,208.8 451.0,208.8 451.0,261.0" data-evidence="7031-7031" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="565.0,144.5 565.0,202.8 469.0,202.8 469.0,261.0" data-evidence="7031-7033" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="775.0,144.5 775.0,202.8 487.0,202.8 487.0,261.0" data-evidence="7031-7035" />
|
||||
<polyline class="edge kind-data style-solid emphasis-normal" points="460.0,349.0 460.0,397.0 460.0,397.0 460.0,445.0" data-evidence="7031-7031,7054-7054" />
|
||||
<rect class="edge-label-bg" x="448.2" y="383.0" width="71.6" height="22" rx="3" />
|
||||
<text class="edge-label" x="484.0" y="398.0">dispatch</text>
|
||||
<g id="node-vm1-qemu">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="7029-7029,7041-7044" x="70.0" y="60.0" width="150.0" height="105.0" rx="7" />
|
||||
<text class="node-label" x="145.0" y="87.0">VM1 QEMU</text>
|
||||
<line class="node-detail-divider" x1="84.0" y1="108.0" x2="206.0" y2="108.0" />
|
||||
<text class="node-detail" x="86.0" y="125.0">WRITE X</text>
|
||||
<text class="node-detail" x="86.0" y="141.0">READ Y</text>
|
||||
<text class="node-detail" x="86.0" y="157.0">WRITE Z</text>
|
||||
</g>
|
||||
<g id="node-vm2-qemu">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="7031-7031,7046-7048" x="280.0" y="68.5" width="150.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="355.0" y="95.5">VM2 QEMU</text>
|
||||
<line class="node-detail-divider" x1="294.0" y1="116.5" x2="416.0" y2="116.5" />
|
||||
<text class="node-detail" x="296.0" y="133.5">READ A</text>
|
||||
<text class="node-detail" x="296.0" y="149.5">WRITE B</text>
|
||||
</g>
|
||||
<g id="node-nginx">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="7033-7033" x="490.0" y="80.5" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="565.0" y="110.5">Nginx</text>
|
||||
</g>
|
||||
<g id="node-host-other">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="7035-7038" x="700.0" y="80.5" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="775.0" y="110.5">Host 기타</text>
|
||||
</g>
|
||||
<g id="node-host-block-layer">
|
||||
<rect class="node-shape kind-service emphasis-primary role-queue" data-evidence="7031-7031,7017-7022,7054-7054,7058-7060" x="380.0" y="261.0" width="160.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="460.0" y="288.0">Host Block Layer</text>
|
||||
<line class="node-detail-divider" x1="394.0" y1="309.0" x2="526.0" y2="309.0" />
|
||||
<text class="node-detail" x="396.0" y="326.0">Host block request</text>
|
||||
<text class="node-detail" x="396.0" y="342.0">blk-mq</text>
|
||||
</g>
|
||||
<g id="node-nvme">
|
||||
<rect class="node-shape kind-device emphasis-normal role-sink" data-evidence="7031-7031,7019-7019,7066-7069" x="385.0" y="458.0" width="150.0" height="64.0" /><ellipse class="node-shape kind-device emphasis-normal role-sink" cx="460.0" cy="458.0" rx="75.0" ry="13.0" /><path class="storage-bottom" d="M 385.0 522.0 A 75.0 13.0 0 0 0 535.0 522.0" />
|
||||
<text class="node-label" x="460.0" y="488.0">NVMe</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,28 @@
|
||||
# fsync() 의 요구가 물리 storage 까지 내려가는 사슬
|
||||
|
||||
## Alternative text
|
||||
|
||||
PostgreSQL 의 fsync() 가 Guest Filesystem, Guest Block Layer, virtio-blk, QEMU / Backend, Host Storage Stack 을 차례로 지나 Physical Storage 에 닿는 위에서 아래로 읽는 흐름도.
|
||||
|
||||
## Long description
|
||||
|
||||
위에서 아래로 읽는다. 맨 위 PostgreSQL 이 fsync() 를 부르고 그 요구가 Guest Filesystem 으로 내려간다. Guest Block Layer 에서 FLUSH 등의 요청으로 바뀌고, virtio-blk 를 지나 VM 경계를 넘어 QEMU / Backend 로 간다. 거기서 Host Storage Stack 을 지나 맨 아래 Physical Storage 까지 그 의미가 전달되어야 완료가 성립한다. 여섯 번 손이 바뀌는 동안 한 곳이라도 그 의미를 지키지 않으면 게스트가 받은 완료 응답이 거짓이 된다. write() 완료와 writeback 완료, fsync/flush 완료, 전원 장애에도 안전한 durability 가 서로 다르다는 구분은 본문의 코드블록이 맡는다.
|
||||
|
||||
## Elements and evidence
|
||||
|
||||
- **PostgreSQL** (service): 필요한 시점에 fsync() 를 불러 영속성 경계까지 반영을 요청하는 게스트 프로세스. Evidence: L6742–L6742, L6726–L6734.
|
||||
- **Guest Filesystem** (service): fsync() 요구를 처음 받는 게스트 파일시스템. Evidence: L6746–L6746.
|
||||
- **Guest Block Layer** (service): 요구를 FLUSH 등의 block 요청으로 바꾸는 계층. Evidence: L6749–L6751.
|
||||
- **virtio-blk** (service): 그 요청을 VM 경계 너머로 옮기는 게스트 driver. Evidence: L6753–L6753.
|
||||
- **QEMU / Backend** (service): 요청을 받아 호스트 쪽 파일 I/O 나 block I/O 로 잇는 자리. Evidence: L6756–L6756, L6686–L6686.
|
||||
- **Host Storage Stack** (service): 호스트 Page Cache 와 파일시스템, Block Layer 가 놓인 구간. Evidence: L6759–L6759, L6688–L6692.
|
||||
- **Physical Storage** (store): 요구가 여기까지 전달되어야 정전 이후 생존을 말할 수 있다. Evidence: L6762–L6765, L6729–L6729.
|
||||
|
||||
## Relationships
|
||||
|
||||
- **PostgreSQL → Guest Filesystem:** fsync(). Evidence: L6744–L6746.
|
||||
- **Guest Filesystem → Guest Block Layer:** control. Evidence: L6746–L6749.
|
||||
- **Guest Block Layer → virtio-blk:** FLUSH 등. Evidence: L6751–L6753.
|
||||
- **virtio-blk → QEMU / Backend:** control. Evidence: L6753–L6756.
|
||||
- **QEMU / Backend → Host Storage Stack:** control. Evidence: L6756–L6759.
|
||||
- **Host Storage Stack → Physical Storage:** control. Evidence: L6759–L6765.
|
||||
@@ -0,0 +1,30 @@
|
||||
# fsync() 의 요구가 물리 storage 까지 내려가는 사슬
|
||||
# Question: 게스트가 fsync() 를 부르면 그 요구는 어느 계층까지, 몇 번 손이 바뀌어 내려가야 하는가
|
||||
direction: down
|
||||
n0: "PostgreSQL" {
|
||||
shape: rectangle
|
||||
}
|
||||
n1: "Guest Filesystem" {
|
||||
shape: rectangle
|
||||
}
|
||||
n2: "Guest Block Layer" {
|
||||
shape: rectangle
|
||||
}
|
||||
n3: "virtio-blk" {
|
||||
shape: rectangle
|
||||
}
|
||||
n4: "QEMU / Backend" {
|
||||
shape: rectangle
|
||||
}
|
||||
n5: "Host Storage Stack" {
|
||||
shape: rectangle
|
||||
}
|
||||
n6: "Physical Storage" {
|
||||
shape: rectangle
|
||||
}
|
||||
n0 -> n1: "fsync()"
|
||||
n1 -> n2
|
||||
n2 -> n3: "FLUSH 등"
|
||||
n3 -> n4
|
||||
n4 -> n5
|
||||
n5 -> n6
|
||||
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mxfile host="app.diagrams.net" modified="2026-07-23T00:00:00.000Z" agent="techviz-harness" version="24.7.17" type="device">
|
||||
<diagram id="write-completion-boundaries" name="fsync() 의 요구가 물리 storage 까지 내려가는 사슬">
|
||||
<mxGraphModel dx="680" dy="1153" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n_postgresql" value="PostgreSQL<br/>write()<br/>fsync()" tooltip="필요한 시점에 fsync() 를 불러 영속성 경계까지 반영을 요청하는 게스트 프로세스. | Evidence: L6742-L6742, L6726-L6734" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="75.0" y="60.0" width="150.0" height="88.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-filesystem" value="Guest Filesystem" tooltip="fsync() 요구를 처음 받는 게스트 파일시스템. | Evidence: L6746-L6746" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="75.0" y="244.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_guest-block-layer" value="Guest Block Layer" tooltip="요구를 FLUSH 등의 block 요청으로 바꾸는 계층. | Evidence: L6749-L6751" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="73.5" y="404.0" width="153.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_virtio-blk" value="virtio-blk" tooltip="그 요청을 VM 경계 너머로 옮기는 게스트 driver. | Evidence: L6753-L6753" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="75.0" y="564.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_qemu-backend" value="QEMU / Backend" tooltip="요청을 받아 호스트 쪽 파일 I/O 나 block I/O 로 잇는 자리. | Evidence: L6756-L6756, L6686-L6686" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="75.0" y="724.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_host-storage-stack" value="Host Storage Stack" tooltip="호스트 Page Cache 와 파일시스템, Block Layer 가 놓인 구간. | Evidence: L6759-L6759, L6688-L6692" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;" vertex="1" parent="1">
|
||||
<mxGeometry x="70.0" y="884.0" width="160.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="n_physical-storage" value="Physical Storage" tooltip="요구가 여기까지 전달되어야 정전 이후 생존을 말할 수 있다. | Evidence: L6762-L6765, L6729-L6729" style="whiteSpace=wrap;html=1;rounded=1;strokeWidth=2;fontSize=14;fontStyle=1;fillColor=#ffffff;strokeColor=#2d4357;verticalAlign=middle;strokeColor=#2563eb;strokeWidth=2;" vertex="1" parent="1">
|
||||
<mxGeometry x="75.0" y="1044.0" width="150.0" height="64.0" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="e_app-to-guest-fs" value="fsync()" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_postgresql" target="n_guest-filesystem">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="196.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_guest-fs-to-block-layer" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-filesystem" target="n_guest-block-layer">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="356.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_block-layer-to-virtio" value="FLUSH 등" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_guest-block-layer" target="n_virtio-blk">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="516.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_virtio-to-qemu" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_virtio-blk" target="n_qemu-backend">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="676.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_qemu-to-host-stack" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_qemu-backend" target="n_host-storage-stack">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="836.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="e_host-stack-to-physical" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;strokeWidth=2;endArrow=block;endFill=1;" edge="1" parent="1" source="n_host-storage-stack" target="n_physical-storage">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="174.0" y="996.0" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,934 @@
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "techviz-harness",
|
||||
"elements": [
|
||||
{
|
||||
"id": "edge-app-to-guest-fs",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 148.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 812660886,
|
||||
"version": 1,
|
||||
"versionNonce": 98088779,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-postgresql",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-guest-filesystem",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-app-to-guest-fs",
|
||||
"type": "text",
|
||||
"x": 129.0,
|
||||
"y": 184.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 106795923,
|
||||
"version": 1,
|
||||
"versionNonce": 801195523,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "fsync()",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "fsync()",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-guest-fs-to-block-layer",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 308.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1352950235,
|
||||
"version": 1,
|
||||
"versionNonce": 1614356579,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-guest-filesystem",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-guest-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-block-layer-to-virtio",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 468.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 653332640,
|
||||
"version": 1,
|
||||
"versionNonce": 706884381,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-guest-block-layer",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-virtio-blk",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-label-block-layer-to-virtio",
|
||||
"type": "text",
|
||||
"x": 129.0,
|
||||
"y": 504.0,
|
||||
"width": 90,
|
||||
"height": 24,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 352541713,
|
||||
"version": 1,
|
||||
"versionNonce": 1745807882,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 13,
|
||||
"fontFamily": 5,
|
||||
"text": "FLUSH 등",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "FLUSH 등",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "edge-virtio-to-qemu",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 628.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1913137791,
|
||||
"version": 1,
|
||||
"versionNonce": 1422107469,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-virtio-blk",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-qemu-backend",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-qemu-to-host-stack",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 788.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 1785251986,
|
||||
"version": 1,
|
||||
"versionNonce": 1697013013,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-qemu-backend",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-host-storage-stack",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "edge-host-stack-to-physical",
|
||||
"type": "arrow",
|
||||
"x": 150.0,
|
||||
"y": 948.0,
|
||||
"width": 0.0,
|
||||
"height": 96.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": null,
|
||||
"seed": 574245066,
|
||||
"version": 1,
|
||||
"versionNonce": 83280906,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"points": [
|
||||
[
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
48.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
96.0
|
||||
]
|
||||
],
|
||||
"lastCommittedPoint": null,
|
||||
"startBinding": {
|
||||
"elementId": "node-host-storage-stack",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"endBinding": {
|
||||
"elementId": "node-physical-storage",
|
||||
"focus": 0,
|
||||
"gap": 4
|
||||
},
|
||||
"startArrowhead": null,
|
||||
"endArrowhead": "arrow",
|
||||
"elbowed": true
|
||||
},
|
||||
{
|
||||
"id": "node-postgresql",
|
||||
"type": "rectangle",
|
||||
"x": 75.0,
|
||||
"y": 60.0,
|
||||
"width": 150.0,
|
||||
"height": 88.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 51288073,
|
||||
"version": 1,
|
||||
"versionNonce": 91686637,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-postgresql",
|
||||
"type": "text",
|
||||
"x": 85.0,
|
||||
"y": 70.0,
|
||||
"width": 130.0,
|
||||
"height": 68.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 308492034,
|
||||
"version": 1,
|
||||
"versionNonce": 936735075,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "PostgreSQL\nwrite()\nfsync()",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "PostgreSQL\nwrite()\nfsync()",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest-filesystem",
|
||||
"type": "rectangle",
|
||||
"x": 75.0,
|
||||
"y": 244.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1533824948,
|
||||
"version": 1,
|
||||
"versionNonce": 1692132304,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest-filesystem",
|
||||
"type": "text",
|
||||
"x": 85.0,
|
||||
"y": 254.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 21094774,
|
||||
"version": 1,
|
||||
"versionNonce": 893088149,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest Filesystem",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest Filesystem",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-guest-block-layer",
|
||||
"type": "rectangle",
|
||||
"x": 73.5,
|
||||
"y": 404.0,
|
||||
"width": 153.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 197573630,
|
||||
"version": 1,
|
||||
"versionNonce": 1359380081,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-guest-block-layer",
|
||||
"type": "text",
|
||||
"x": 83.5,
|
||||
"y": 414.0,
|
||||
"width": 133.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1437945492,
|
||||
"version": 1,
|
||||
"versionNonce": 1941177307,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Guest Block Layer",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Guest Block Layer",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-virtio-blk",
|
||||
"type": "rectangle",
|
||||
"x": 75.0,
|
||||
"y": 564.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 805183008,
|
||||
"version": 1,
|
||||
"versionNonce": 387189353,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-virtio-blk",
|
||||
"type": "text",
|
||||
"x": 85.0,
|
||||
"y": 574.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1466921391,
|
||||
"version": 1,
|
||||
"versionNonce": 178652417,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "virtio-blk",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "virtio-blk",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-qemu-backend",
|
||||
"type": "rectangle",
|
||||
"x": 75.0,
|
||||
"y": 724.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 88754261,
|
||||
"version": 1,
|
||||
"versionNonce": 960115709,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-qemu-backend",
|
||||
"type": "text",
|
||||
"x": 85.0,
|
||||
"y": 734.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 18150914,
|
||||
"version": 1,
|
||||
"versionNonce": 118285455,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "QEMU / Backend",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "QEMU / Backend",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-host-storage-stack",
|
||||
"type": "rectangle",
|
||||
"x": 70.0,
|
||||
"y": 884.0,
|
||||
"width": 160.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 185667777,
|
||||
"version": 1,
|
||||
"versionNonce": 165868748,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-host-storage-stack",
|
||||
"type": "text",
|
||||
"x": 80.0,
|
||||
"y": 894.0,
|
||||
"width": 140.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1032766674,
|
||||
"version": 1,
|
||||
"versionNonce": 1275711067,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Host Storage Stack",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Host Storage Stack",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
},
|
||||
{
|
||||
"id": "node-physical-storage",
|
||||
"type": "rectangle",
|
||||
"x": 75.0,
|
||||
"y": 1044.0,
|
||||
"width": 150.0,
|
||||
"height": 64.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "#ffffff",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 2,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 748275136,
|
||||
"version": 1,
|
||||
"versionNonce": 1258638582,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false
|
||||
},
|
||||
{
|
||||
"id": "node-label-physical-storage",
|
||||
"type": "text",
|
||||
"x": 85.0,
|
||||
"y": 1054.0,
|
||||
"width": 130.0,
|
||||
"height": 44.0,
|
||||
"angle": 0,
|
||||
"strokeColor": "#1e1e1e",
|
||||
"backgroundColor": "transparent",
|
||||
"fillStyle": "solid",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 0,
|
||||
"opacity": 100,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"index": null,
|
||||
"roundness": {
|
||||
"type": 3
|
||||
},
|
||||
"seed": 1619302994,
|
||||
"version": 1,
|
||||
"versionNonce": 56126538,
|
||||
"isDeleted": false,
|
||||
"boundElements": [],
|
||||
"updated": 0,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"fontSize": 15,
|
||||
"fontFamily": 5,
|
||||
"text": "Physical Storage",
|
||||
"textAlign": "center",
|
||||
"verticalAlign": "middle",
|
||||
"containerId": null,
|
||||
"originalText": "Physical Storage",
|
||||
"autoResize": true,
|
||||
"lineHeight": 1.25
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"gridSize": 10,
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemFontFamily": 5
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": "0.2.0",
|
||||
"spec_id": "write-completion-boundaries",
|
||||
"spec_version": "1.1",
|
||||
"spec_sha256": "c7838bc8393b43c94ed4628db350f0fb26e90fc0d566201e471d49d533963699",
|
||||
"source_context": {
|
||||
"document": "docs/virtualization/final/document.md",
|
||||
"document_sha256": "181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd",
|
||||
"anchor": {
|
||||
"kind": "heading",
|
||||
"value": "150. `fsync()`가 필요한 이유",
|
||||
"line": 6723
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
"write-completion-boundaries.svg",
|
||||
"write-completion-boundaries.drawio",
|
||||
"write-completion-boundaries.mmd",
|
||||
"write-completion-boundaries.d2",
|
||||
"write-completion-boundaries.excalidraw",
|
||||
"write-completion-boundaries.alt.md"
|
||||
],
|
||||
"lint_issue_count": 4,
|
||||
"assumption_count": 0,
|
||||
"assumptions_allowed": false,
|
||||
"composition_profile": "component-flow",
|
||||
"reference_ids": [
|
||||
"payment-event-flow"
|
||||
],
|
||||
"diagram_only": true
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
%% fsync() 의 요구가 물리 storage 까지 내려가는 사슬
|
||||
%% question: 게스트가 fsync() 를 부르면 그 요구는 어느 계층까지, 몇 번 손이 바뀌어 내려가야 하는가
|
||||
flowchart TB
|
||||
n0["PostgreSQL"]
|
||||
n1["Guest Filesystem"]
|
||||
n2["Guest Block Layer"]
|
||||
n3["virtio-blk"]
|
||||
n4["QEMU / Backend"]
|
||||
n5["Host Storage Stack"]
|
||||
n6["Physical Storage"]
|
||||
n0 -->|"fsync()"| n1
|
||||
n1 --> n2
|
||||
n2 -->|"FLUSH 등"| n3
|
||||
n3 --> n4
|
||||
n4 --> n5
|
||||
n5 --> n6
|
||||
@@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="1153" viewBox="0 0 680 1153" role="img" aria-labelledby="diagram-title diagram-description">
|
||||
<title id="diagram-title">fsync() 의 요구가 물리 storage 까지 내려가는 사슬</title>
|
||||
<desc id="diagram-description">위에서 아래로 읽는다. 맨 위 PostgreSQL 이 fsync() 를 부르고 그 요구가 Guest Filesystem 으로 내려간다. Guest Block Layer 에서 FLUSH 등의 요청으로 바뀌고, virtio-blk 를 지나 VM 경계를 넘어 QEMU / Backend 로 간다. 거기서 Host Storage Stack 을 지나 맨 아래 Physical Storage 까지 그 의미가 전달되어야 완료가 성립한다. 여섯 번 손이 바뀌는 동안 한 곳이라도 그 의미를 지키지 않으면 게스트가 받은 완료 응답이 거짓이 된다. write() 완료와 writeback 완료, fsync/flush 완료, 전원 장애에도 안전한 durability 가 서로 다르다는 구분은 본문의 코드블록이 맡는다.</desc>
|
||||
<metadata>{"techviz":{"spec_version":"1.1","id":"write-completion-boundaries","profile":"component-flow"},"source_context":{"document":"docs/virtualization/final/document.md","document_sha256":"181e2b3cc8a45bae81e7e8193d026937c4d586ae4495d3b2c323eb7e6abcfadd","anchor":{"kind":"heading","value":"150. `fsync()`가 필요한 이유","line":6723}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
||||
<defs>
|
||||
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||
<path d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</marker>
|
||||
<style>
|
||||
:root { color-scheme: light; }
|
||||
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
||||
.canvas { fill: #ffffff; }
|
||||
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
||||
.group-label-bg { fill: #ffffff; }
|
||||
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
||||
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
||||
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
||||
.edge.style-dotted { stroke-dasharray: 2 5; }
|
||||
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.edge.emphasis-muted { stroke: #9ca3af; }
|
||||
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
||||
.edge-label-bg { fill: #ffffff; }
|
||||
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
||||
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
||||
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
||||
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
||||
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
||||
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
||||
.node-shape.assumption { stroke-dasharray: 4 4; }
|
||||
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
||||
.controller-led { fill: #4b5563; }
|
||||
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
||||
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
||||
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
||||
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
||||
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
||||
.node-detail { font-size: 11px; fill: #374151; }
|
||||
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
||||
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
||||
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
||||
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
||||
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
||||
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
||||
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
||||
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
||||
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
||||
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
||||
</style>
|
||||
</defs>
|
||||
<rect class="canvas" width="680" height="1153" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,148.0 150.0,196.0 150.0,196.0 150.0,244.0" data-evidence="6744-6746" />
|
||||
<rect class="edge-label-bg" x="141.6" y="182.0" width="64.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="174.0" y="197.0">fsync()</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,308.0 150.0,356.0 150.0,356.0 150.0,404.0" data-evidence="6746-6749" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,468.0 150.0,516.0 150.0,516.0 150.0,564.0" data-evidence="6751-6753" />
|
||||
<rect class="edge-label-bg" x="141.6" y="502.0" width="64.9" height="22" rx="3" />
|
||||
<text class="edge-label" x="174.0" y="517.0">FLUSH 등</text>
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,628.0 150.0,676.0 150.0,676.0 150.0,724.0" data-evidence="6753-6756" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,788.0 150.0,836.0 150.0,836.0 150.0,884.0" data-evidence="6756-6759" />
|
||||
<polyline class="edge kind-control style-solid emphasis-normal" points="150.0,948.0 150.0,996.0 150.0,996.0 150.0,1044.0" data-evidence="6759-6765" />
|
||||
<g id="node-postgresql">
|
||||
<rect class="node-shape kind-service emphasis-normal role-source" data-evidence="6742-6742,6726-6734" x="75.0" y="60.0" width="150.0" height="88.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="87.0">PostgreSQL</text>
|
||||
<line class="node-detail-divider" x1="89.0" y1="108.0" x2="211.0" y2="108.0" />
|
||||
<text class="node-detail" x="91.0" y="125.0">write()</text>
|
||||
<text class="node-detail" x="91.0" y="141.0">fsync()</text>
|
||||
</g>
|
||||
<g id="node-guest-filesystem">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="6746-6746" x="75.0" y="244.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="274.0">Guest Filesystem</text>
|
||||
</g>
|
||||
<g id="node-guest-block-layer">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="6749-6751" x="73.5" y="404.0" width="153.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="434.0">Guest Block Layer</text>
|
||||
</g>
|
||||
<g id="node-virtio-blk">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="6753-6753" x="75.0" y="564.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="594.0">virtio-blk</text>
|
||||
</g>
|
||||
<g id="node-qemu-backend">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="6756-6756,6686-6686" x="75.0" y="724.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="754.0">QEMU / Backend</text>
|
||||
</g>
|
||||
<g id="node-host-storage-stack">
|
||||
<rect class="node-shape kind-service emphasis-normal role-service" data-evidence="6759-6759,6688-6692" x="70.0" y="884.0" width="160.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="914.0">Host Storage Stack</text>
|
||||
</g>
|
||||
<g id="node-physical-storage">
|
||||
<rect class="node-shape kind-store emphasis-primary role-sink" data-evidence="6762-6765,6729-6729" x="75.0" y="1044.0" width="150.0" height="64.0" rx="7" />
|
||||
<text class="node-label" x="150.0" y="1074.0">Physical Storage</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |