[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251121193204.952988-2-yosry.ahmed@linux.dev>
Date: Fri, 21 Nov 2025 19:32:02 +0000
From: Yosry Ahmed <yosry.ahmed@...ux.dev>
To: Sean Christopherson <seanjc@...gle.com>
Cc: Paolo Bonzini <pbonzini@...hat.com>,
Ken Hofsass <hofsass@...gle.com>,
kvm@...r.kernel.org,
linux-kernel@...r.kernel.org,
Yosry Ahmed <yosry.ahmed@...ux.dev>
Subject: [PATCH 1/3] KVM: x86: Add CR3 to guest debug info
Add the value of CR3 to the information returned to userspace on
KVM_EXIT_DEBUG. Use KVM_CAP_X86_GUEST_DEBUG_CR3 to advertise this.
During guest debugging, the value of CR3 can be used by VM debuggers to
(roughly) identify the process running in the guest. This can be used to
index debugging events by process, or filter events from some processes
and quickly skip them.
Currently, debuggers would need to use the KVM_GET_SREGS ioctl on every
event to get the value of CR3, which considerably slows things down.
This can be easily avoided by adding the value of CR3 to the captured
debugging info.
Signed-off-by: Ken Hofsass <hofsass@...gle.com>
Co-developed-by: Ken Hofsass <hofsass@...gle.com>
Signed-off-by: Yosry Ahmed <yosry.ahmed@...ux.dev>
---
arch/x86/include/uapi/asm/kvm.h | 1 +
arch/x86/kvm/svm/svm.c | 2 ++
arch/x86/kvm/vmx/vmx.c | 2 ++
arch/x86/kvm/x86.c | 3 +++
include/uapi/linux/kvm.h | 1 +
5 files changed, 9 insertions(+)
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index 7ceff6583652..c351e458189b 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -293,6 +293,7 @@ struct kvm_debug_exit_arch {
__u64 pc;
__u64 dr6;
__u64 dr7;
+ __u64 cr3;
};
#define KVM_GUESTDBG_USE_SW_BP 0x00010000
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index f56c2d895011..85982e96b927 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1920,6 +1920,7 @@ static int db_interception(struct kvm_vcpu *vcpu)
kvm_run->debug.arch.dr7 = svm->vmcb->save.dr7;
kvm_run->debug.arch.pc =
svm->vmcb->save.cs.base + svm->vmcb->save.rip;
+ kvm_run->debug.arch.cr3 = svm->vmcb->save.cr3;
kvm_run->debug.arch.exception = DB_VECTOR;
return 0;
}
@@ -1934,6 +1935,7 @@ static int bp_interception(struct kvm_vcpu *vcpu)
kvm_run->exit_reason = KVM_EXIT_DEBUG;
kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
+ kvm_run->debug.arch.cr3 = svm->vmcb->save.cr3;
kvm_run->debug.arch.exception = BP_VECTOR;
return 0;
}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 4cbe8c84b636..9fd8a6140af4 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5454,6 +5454,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
kvm_run->exit_reason = KVM_EXIT_DEBUG;
kvm_run->debug.arch.pc = kvm_get_linear_rip(vcpu);
kvm_run->debug.arch.exception = ex_no;
+ kvm_run->debug.arch.cr3 = kvm_read_cr3(vcpu);
break;
case AC_VECTOR:
if (vmx_guest_inject_ac(vcpu)) {
@@ -5685,6 +5686,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
vcpu->run->debug.arch.dr6 = DR6_BD | DR6_ACTIVE_LOW;
vcpu->run->debug.arch.dr7 = dr7;
vcpu->run->debug.arch.pc = kvm_get_linear_rip(vcpu);
+ vcpu->run->debug.arch.cr3 = kvm_read_cr3(vcpu);
vcpu->run->debug.arch.exception = DB_VECTOR;
vcpu->run->exit_reason = KVM_EXIT_DEBUG;
return 0;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0c6d899d53dd..636ad63ac34a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4855,6 +4855,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_MEMORY_FAULT_INFO:
case KVM_CAP_X86_GUEST_MODE:
case KVM_CAP_ONE_REG:
+ case KVM_CAP_X86_GUEST_DEBUG_CR3:
r = 1;
break;
case KVM_CAP_PRE_FAULT_MEMORY:
@@ -9195,6 +9196,7 @@ static int kvm_vcpu_do_singlestep(struct kvm_vcpu *vcpu)
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
kvm_run->debug.arch.dr6 = DR6_BS | DR6_ACTIVE_LOW;
kvm_run->debug.arch.pc = kvm_get_linear_rip(vcpu);
+ kvm_run->debug.arch.cr3 = kvm_read_cr3(vcpu);
kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG;
return 0;
@@ -9277,6 +9279,7 @@ static bool kvm_vcpu_check_code_breakpoint(struct kvm_vcpu *vcpu,
if (dr6 != 0) {
kvm_run->debug.arch.dr6 = dr6 | DR6_ACTIVE_LOW;
kvm_run->debug.arch.pc = eip;
+ kvm_run->debug.arch.cr3 = kvm_read_cr3(vcpu);
kvm_run->debug.arch.exception = DB_VECTOR;
kvm_run->exit_reason = KVM_EXIT_DEBUG;
*r = 0;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 52f6000ab020..58842b74fca1 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -963,6 +963,7 @@ struct kvm_enable_cap {
#define KVM_CAP_RISCV_MP_STATE_RESET 242
#define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
#define KVM_CAP_GUEST_MEMFD_FLAGS 244
+#define KVM_CAP_X86_GUEST_DEBUG_CR3 245
struct kvm_irq_routing_irqchip {
__u32 irqchip;
--
2.52.0.rc2.455.g230fcf2819-goog
Powered by blists - more mailing lists