Record-replay는 interrupt, race, 자료 값에 따라 crash가 나고 developer가 같은 실행을 만들 수 없을 때 유용합니다. Recorder가 nondeterministic input을 모두 capture하고 나중에 같은 sequence를 inject하면 반복 debugging과 reverse analysis가 가능합니다. Whole-machine system은 virtual machine 전체를 boundary로 둡니다. Complete하지만 failure가 guest kernel에 있어도 application 및 I/O activity를 기록합니다.
현재 datacenter workload에서는 비용이 커집니다. Multicore replay는 race를 deterministic하게 만들기 위해 execution을 serialize하므로 overhead가 core count를 넘을 수 있습니다. I/O-intensive software는 큰 trace를 만듭니다. Kernel-bypass framework에서는 mismatch가 더 뚜렷합니다. Application thread가 device와 직접 자료를 주고받아 guest kernel에 들어가지 않아도 whole-VM replay는 traffic을 capture하고 order합니다[1].
KRR은 replay unit을 VM에서 kernel execution slice로 바꿉니다. Recording 중 user space는 실행되지만 kernel로 넘어가는 value와 event만 trace에 들어갑니다. Replay는 user-side boundary를 emulate해 kernel behavior를 reconstruct합니다. 더 빠른 recorder를 얻는 대신 external state가 kernel에 영향을 주는 모든 경로를 식별해야 completeness를 유지할 수 있습니다.
두 boundary를 보는 split recorder
Guest kernel은 user space와 hardware에서 input을 받습니다. 한 layer가 둘을 효율적으로 볼 수 없습니다. Hypervisor는 interrupt와 emulated-device activity를 intercept할 수 있지만 system-call buffer마다 introspection하면 expensive exit가 생깁니다. Guest instrumentation은 copy와 shared-memory read를 자연스럽게 보지만 모든 hardware timing을 독립적으로 control할 수 없습니다.
KRR은 책임을 나눕니다. In-guest recorder는 system call, copied user buffer, shared queue, nondeterministic instruction, kernel scheduling을 capture합니다. In-hypervisor recorder는 interrupt, I/O read, emulation에 보이는 device DMA를 capture합니다. Event는 하나의 total order로 들어가 replay가 같은 kernel point에서 각 input을 inject합니다.
User-memory capture는 hardened kernel API를 활용합니다. Linux는 untrusted read를 copy_from_user, get_user 같은 function으로 보냅니다. KRR은 copy 뒤 destination kernel byte를 기록해 user memory를 두 번 읽으며 생기는 time-of-check/time-of-use race를 피합니다. io_uring에는 shared submission queue와 entry를 읽는 kernel path를 instrument합니다. User execution이 page-table accessed 및 dirty bit를 바꾸고 kernel replacement decision에 영향을 줄 수 있어 이 값도 기록합니다.

Hardware event에는 timing signature가 필요합니다. KRR은 kernel-mode performance 계수기 하나를 reserve하고 interrupt 또는 DMA event가 도착했을 때 executed kernel instruction 수를 기록합니다. Replay는 corresponding count에서 event를 inject합니다. CPUID masking으로 계수기를 guest available set에서 숨기고 다른 계수기는 ordinary kernel use에 남깁니다.
설계에는 architecture-specific point가 많습니다. Counter behavior, interrupt state, repeating instruction, page fault, device emulation을 정확히 model해야 합니다. KRR porting은 kernel probe를 recompile하는 일이 아니라 processor 및 virtual-device model마다 timing과 state contract를 검증하는 일입니다.
Kernel execution만 serialize하는 이유
Kernel에는 benign 및 intentional 자료 race가 있어 synchronization order만 기록하는 것으로 부족합니다. KRR은 virtual CPU 사이의 kernel execution을 serialize하고 어느 thread가 다음에 들어오는지 기록합니다. User-space thread는 kernel 밖에 있을 때 병렬로 계속 실행할 수 있습니다. Complete VM을 single-core로 만들지 않고 deterministic kernel schedule을 얻습니다.
Polling application에 특히 유리합니다. SPDK 또는 DPDK thread는 system call 없이 passthrough device와 bulk 자료를 주고받을 수 있습니다. Whole-VM serialization은 polling core를 멈추고 다른 thread가 이를 기다리게 해 slowdown을 키웁니다. KRR은 kernel을 bypass한 자료를 기록하지 않고 user thread를 실행하게 하며 Linux에 들어오는 작은 control path만 기록합니다.
Serialization은 timing을 바꿔 bug를 가릴 수 있습니다. KRR은 single core에서 context switch와 interrupt로 생길 concurrency를 model합니다. Separate core에서 simultaneous kernel execution이 꼭 필요한 failure, 일부 weak-memory interaction, 좁은 병렬 window는 재현할 수 없습니다. Recorder는 diagnostic coverage tool이지 모든 field failure의 reproduction guarantee가 아닙니다.
Deterministic replay에 포함되는 initial state
Replay가 다른 kernel state에서 시작하면 input과 order만으로 부족합니다. KRR은 recording 중 VM snapshot을 저장하고 뒤의 trace segment와 state를 연결합니다. Replay는 boot부터 전체 execution을 해석하지 않고 intermediate snapshot에서 시작할 수 있습니다. Long trace의 turnaround를 줄이고 reconstruct할 state 범위를 제한합니다.
Snapshot은 storage와 privacy 책임도 만듭니다. Trace entry에는 kernel로 copy된 application 자료, network payload, file block, credential, memory mapping이 들어갈 수 있습니다. KRR은 whole-VM recording보다 exposure를 줄이지만 남은 slice도 sensitive합니다. 운영 collection에는 encryption, access control, retention limit, tenant consent, original incident와 연결한 deletion이 필요합니다.
Trace completeness는 bug replay와 별도로 test해야 합니다. Deterministic workload를 실행하고 kernel output 및 state hash를 비교하며 input class를 의도적으로 exercise할 수 있습니다. 새 shared-memory API나 passthrough driver가 hook 없이 boundary를 넘을 수 있습니다. Kernel upgrade는 build test뿐 아니라 interface audit를 trigger해야 합니다.
8-core workload에서 확인한 scaling 차이
8-core VM의 RocksDB와 Linux kernel compilation은 KRR recording에서 기본 실행 대비 1.52배에서 2.79배 느려졌습니다. Traditional whole-VM recorder는 같은 class의 workload를 8.97배에서 29.94배 느리게 했습니다. KRR overhead도 kernel activity와 core count가 늘면 올라가며 원문은 1개에서 8개 virtual CPU를 practical range로 봅니다.
Kernel bypass는 denominator를 바꿉니다. 2-core RocksDB-SPDK에서 KRR operation slowdown은 1.17배에서 1.27배였고 whole-VM replay는 reported workload에서 29.36배에서 64.51배였습니다. Relevant case에서 SPDK는 system call을 77%에서 94%, user-to-kernel 자료 copy를 94%에서 99% 없애 KRR event volume을 직접 줄였습니다.
4-core VM의 Redis over DPDK는 GET throughput 0.26%, SET throughput 1.14%를 평균적으로 잃었습니다. P99 latency change는 5.19% improvement부터 11.27% slowdown까지여서 run-to-run variance와 workload detail을 함께 봐야 합니다. Bulk 자료 path는 recorded kernel slice 밖에 있었습니다.
Nginx-DPDK는 반대 case를 보였습니다. Small 1KB 및 4KB file은 work 대부분을 kernel file read에 써 slowdown이 46%를 넘고 core가 늘수록 악화됐습니다. 16KB와 64KB에서는 network transfer가 지배해 overhead가 약 2%, 5%로 줄었습니다. “Kernel bypass” 자체가 recorder cost를 결정하지 않습니다. Request time과 input byte 중 kernel boundary를 통과하는 fraction이 중요합니다.
Bug reproduction의 범위
저자는 Syzbot에서 Linux 6.1 bug 12개, high-impact CVE 5개를 골라 총 17개를 시험했습니다. Syzbot case 중 6개는 nondeterministic이었습니다. KRR은 nondeterministic bug 하나를 제외하고 모두 record 및 reproduce해 전체 16개를 성공했습니다. 여러 Linux 버전의 concurrency fault와 security-relevant failure가 포함됩니다.
Selection 조건을 봐야 합니다. Syzbot population에는 reproducer program이 이미 있었고 CVE 5개는 이전 연구에서 다룬 high-severity issue에서 골랐습니다. Experiment는 mechanism breadth를 보여 주지만 arbitrary field crash의 success rate가 아닙니다. Deployment에는 trigger strategy, trace budget, unknown failure 이전 interval을 capture할 방법이 필요합니다.
Recording은 찾으려는 event를 perturb할 수도 있습니다. Instrumentation과 serialization이 timing을 바꿉니다. Software-only recorder가 모든 race probability를 보존한다고 약속할 수 없습니다. Crash dump, hardware trace, sanitizer, schedule-independent detector와 KRR을 함께 써야 합니다. Failure가 boundary 안에서 capture된 뒤에는 deterministic replay가 expensive offline analysis를 가능하게 한다는 점이 강점입니다.
Device와 scale이 정하는 deployment envelope
KRR은 DMA와 timing을 보기 위해 hypervisor emulation에 의존합니다. Kernel과 interaction하면서 emulation 밖에 있는 passthrough device 및 SR-IOV path는 현재 지원하지 않습니다. Guest recorder를 driver interface까지 확장할 수 있지만 driver마다 새 completeness surface가 생깁니다.
Virtual CPU 8개를 넘으면 serialized kernel execution이 scalability를 낮춥니다. Chunk-based recording은 더 많은 병렬성을 보존할 수 있으나 memory-access order를 기록하고 replay complexity를 늘립니다. 64-core 운영 guest에서도 8-core overhead가 유지된다고 가정하지 말고 diagnostic value에 맞춰 VM size를 골라야 합니다.
Practical rollout은 recording을 기본 OFF로 두고 canary 또는 incident cohort에 켜며 background snapshot으로 pre-failure context를 남길 수 있습니다. Trace collector는 kernel을 block하지 않도록 backpressure를 적용해야 합니다. Storage나 ordering이 실패하면 replayable evidence인 것처럼 보이지 않게 trace를 incomplete로 표시해야 합니다.
KRR의 재사용할 systems idea는 boundary selection입니다. Omitted execution이 instrumented interface를 통하지 않고 replay component에 영향을 줄 수 없을 때만 적게 기록해도 안전합니다. Kernel-bypass workload에서는 이 조건이 whole-machine replay의 약점을 이점으로 바꿉니다. High-rate 자료 대부분이 kernel slice와 무관하기 때문입니다.
Free debugging은 아닙니다. API, device, processor, virtualization이 바뀔 때 kernel boundary를 유지해야 합니다. 그러나 이 boundary 안에서는 KRR이 whole-VM replay에서 한 order 이상 느려지는 workload에도 deterministic kernel diagnosis를 적용할 수 있게 합니다.
출처와 저작권 안내
이 글은 Silicon & Systems가 작성한 편집 분석으로, recording architecture와 measurement, limitation을 우리 표현으로 다시 썼습니다. 원문의 문장, 표, 도판은 재수록하지 않았고 도판은 이 글을 위해 새로 만들었습니다. 전체 논문은 USENIX OSDI 2025 발표 페이지에서 확인할 수 있습니다. 저작권은 저자에게 있습니다. 2025.