summary refs log tree commit diff stats
path: root/gitlab/issues/target_missing/host_missing/accel_KVM/2710.toml
blob: 775464e1d4389ec4512eca0f98ce2a1ec311cbf3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
id = 2710
title = "QEMU can't detect guest debug support on older (pre v5.7) x86 host kernels due to missing KVM_CAP_SET_GUEST_DEBUG"
state = "opened"
created_at = "2024-12-06T02:29:37.267Z"
closed_at = "n/a"
labels = ["GDB", "accel: KVM", "kind::Feature Request"]
url = "https://gitlab.com/qemu-project/qemu/-/issues/2710"
host-os = "Ubuntu"
host-arch = "x86_64"
qemu-version = "8.2+"
guest-os = "n/a"
guest-arch = "n/a"
description = """```
qemu-system-x86_64: -s: gdbstub: current accelerator doesn't support guest debugging
```"""
reproduce = "n/a"
additional = """I initially located the QEMU source code to determine whether KVM supports gdbstub by checking for `KVM_CAP_SET_GUEST_DEBUG`. The corresponding code can be found at: 
```c
// qemu/accel/kvm/kvm-all.c:2695
#ifdef TARGET_KVM_HAVE_GUEST_DEBUG
    kvm_has_guest_debug =
        (kvm_check_extension(s, KVM_CAP_SET_GUEST_DEBUG) > 0);
#endif
```
It can be observed that if the return value is <= 0 (in practice, this function only returns 0 on failure), the debug_flag is set to false.

Upon further investigation of the Linux 4.15 kernel code, I discovered that in earlier versions, support for checking VM debugging capabilities via `KVM_CAP_SET_GUEST_DEBUG` was almost non-existent (it was only supported on arm64). However, for x86_64, VM debugging is supported on the 4.15 kernel.

```c
// linu4.15/arch/x86/kvm/x86.c:2672
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
\tint r;

\tswitch (ext) {
\tcase KVM_CAP_IRQCHIP:
\tcase KVM_CAP_HLT:
\tcase KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
\tcase KVM_CAP_SET_TSS_ADDR:
\tcase KVM_CAP_EXT_CPUID:
\tcase KVM_CAP_EXT_EMUL_CPUID:
\tcase KVM_CAP_CLOCKSOURCE:
\tcase KVM_CAP_PIT:
\tcase KVM_CAP_NOP_IO_DELAY:
\tcase KVM_CAP_MP_STATE:
\tcase KVM_CAP_SYNC_MMU:
\tcase KVM_CAP_USER_NMI:
\tcase KVM_CAP_REINJECT_CONTROL:
\tcase KVM_CAP_IRQ_INJECT_STATUS:
\tcase KVM_CAP_IOEVENTFD:
\tcase KVM_CAP_IOEVENTFD_NO_LENGTH:
\tcase KVM_CAP_PIT2:
\tcase KVM_CAP_PIT_STATE2:
\tcase KVM_CAP_SET_IDENTITY_MAP_ADDR:
\tcase KVM_CAP_XEN_HVM:
\tcase KVM_CAP_VCPU_EVENTS:
\tcase KVM_CAP_HYPERV:
\tcase KVM_CAP_HYPERV_VAPIC:
\tcase KVM_CAP_HYPERV_SPIN:
\tcase KVM_CAP_HYPERV_SYNIC:
\tcase KVM_CAP_HYPERV_SYNIC2:
\tcase KVM_CAP_HYPERV_VP_INDEX:
\tcase KVM_CAP_PCI_SEGMENT:
\tcase KVM_CAP_DEBUGREGS:
\tcase KVM_CAP_X86_ROBUST_SINGLESTEP:
\tcase KVM_CAP_XSAVE:
\tcase KVM_CAP_ASYNC_PF:
\tcase KVM_CAP_GET_TSC_KHZ:
\tcase KVM_CAP_KVMCLOCK_CTRL:
\tcase KVM_CAP_READONLY_MEM:
\tcase KVM_CAP_HYPERV_TIME:
\tcase KVM_CAP_IOAPIC_POLARITY_IGNORED:
\tcase KVM_CAP_TSC_DEADLINE_TIMER:
\tcase KVM_CAP_ENABLE_CAP_VM:
\tcase KVM_CAP_DISABLE_QUIRKS:
\tcase KVM_CAP_SET_BOOT_CPU_ID:
 \tcase KVM_CAP_SPLIT_IRQCHIP:
\tcase KVM_CAP_IMMEDIATE_EXIT:
\t\tr = 1;
\t\tbreak;
\tcase KVM_CAP_ADJUST_CLOCK:
\t\tr = KVM_CLOCK_TSC_STABLE;
\t\tbreak;
\tcase KVM_CAP_X86_GUEST_MWAIT:
\t\tr = kvm_mwait_in_guest();
\t\tbreak;
\tcase KVM_CAP_X86_SMM:
\t\t/* SMBASE is usually relocated above 1M on modern chipsets,
\t\t * and SMM handlers might indeed rely on 4G segment limits,
\t\t * so do not report SMM to be available if real mode is
\t\t * emulated via vm86 mode.  Still, do not go to great lengths
\t\t * to avoid userspace's usage of the feature, because it is a
\t\t * fringe case that is not enabled except via specific settings
\t\t * of the module parameters.
\t\t */
\t\tr = kvm_x86_ops->cpu_has_high_real_mode_segbase();
\t\tbreak;
\tcase KVM_CAP_VAPIC:
\t\tr = !kvm_x86_ops->cpu_has_accelerated_tpr();
\t\tbreak;
\tcase KVM_CAP_NR_VCPUS:
\t\tr = KVM_SOFT_MAX_VCPUS;
\t\tbreak;
\tcase KVM_CAP_MAX_VCPUS:
\t\tr = KVM_MAX_VCPUS;
\t\tbreak;
\tcase KVM_CAP_NR_MEMSLOTS:
\t\tr = KVM_USER_MEM_SLOTS;
\t\tbreak;
\tcase KVM_CAP_PV_MMU:\t/* obsolete */
\t\tr = 0;
\t\tbreak;
\tcase KVM_CAP_MCE:
\t\tr = KVM_MAX_MCE_BANKS;
\t\tbreak;
\tcase KVM_CAP_XCRS:
\t\tr = boot_cpu_has(X86_FEATURE_XSAVE);
\t\tbreak;
\tcase KVM_CAP_TSC_CONTROL:
\t\tr = kvm_has_tsc_control;
\t\tbreak;
\tcase KVM_CAP_X2APIC_API:
\t\tr = KVM_X2APIC_API_VALID_FLAGS;
\t\tbreak;
\tdefault:
\t\tr = 0;
\t\tbreak;
\t}
\treturn r;

}
```

I attempted to bypass this check in QEMU and verified that the QEMU gdbstub works normally on the 4.15 kernel.

For modifications related to this part in QEMU, you can refer to the email: https://lore.kernel.org/all/20211111110604.207376-5-pbonzini@redhat.com/."""