Skip to content

Commit d1f85fb

Browse files
aiksean-jc
authored andcommitted
KVM: SEV: Enable data breakpoints in SEV-ES
Add support for "DebugSwap for SEV-ES guests", which provides support for swapping DR[0-3] and DR[0-3]_ADDR_MASK on VMRUN and VMEXIT, i.e. allows KVM to expose debug capabilities to SEV-ES guests. Without DebugSwap support, the CPU doesn't save/load most _guest_ debug registers (except DR6/7), and KVM cannot manually context switch guest DRs due the VMSA being encrypted. Enable DebugSwap if and only if the CPU also supports NoNestedDataBp, which causes the CPU to ignore nested #DBs, i.e. #DBs that occur when vectoring a #DB. Without NoNestedDataBp, a malicious guest can DoS the host by putting the CPU into an infinite loop of vectoring #DBs (see https://bugzilla.redhat.com/show_bug.cgi?id=1278496) Set the features bit in sev_es_sync_vmsa() which is the last point when VMSA is not encrypted yet as sev_(es_)init_vmcb() (where the most init happens) is called not only when VCPU is initialised but also on intrahost migration when VMSA is encrypted. Eliminate DR7 intercepts as KVM can't modify guest DR7, and intercepting DR7 would completely defeat the purpose of enabling DebugSwap. Make X86_FEATURE_DEBUG_SWAP appear in /proc/cpuinfo (by not adding "") to let the operator know if the VM can debug. Signed-off-by: Alexey Kardashevskiy <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent c2690b5 commit d1f85fb

File tree

4 files changed

+36
-3
lines changed

4 files changed

+36
-3
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@
434434
#define X86_FEATURE_SEV_ES (19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */
435435
#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */
436436
#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
437+
#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* AMD SEV-ES full debug state swap support */
437438

438439
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
439440
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */

arch/x86/include/asm/svm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_
288288

289289
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
290290

291+
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
291292

292293
struct vmcb_seg {
293294
u16 selector;

arch/x86/kvm/svm/sev.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <asm/pkru.h>
2424
#include <asm/trapnr.h>
2525
#include <asm/fpu/xcr.h>
26+
#include <asm/debugreg.h>
2627

2728
#include "mmu.h"
2829
#include "x86.h"
@@ -54,9 +55,14 @@ module_param_named(sev, sev_enabled, bool, 0444);
5455
/* enable/disable SEV-ES support */
5556
static bool sev_es_enabled = true;
5657
module_param_named(sev_es, sev_es_enabled, bool, 0444);
58+
59+
/* enable/disable SEV-ES DebugSwap support */
60+
static bool sev_es_debug_swap_enabled = true;
61+
module_param_named(debug_swap, sev_es_debug_swap_enabled, bool, 0444);
5762
#else
5863
#define sev_enabled false
5964
#define sev_es_enabled false
65+
#define sev_es_debug_swap_enabled false
6066
#endif /* CONFIG_KVM_AMD_SEV */
6167

6268
static u8 sev_enc_bit;
@@ -606,6 +612,9 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
606612
save->xss = svm->vcpu.arch.ia32_xss;
607613
save->dr6 = svm->vcpu.arch.dr6;
608614

615+
if (sev_es_debug_swap_enabled)
616+
save->sev_features |= SVM_SEV_FEAT_DEBUG_SWAP;
617+
609618
pr_debug("Virtual Machine Save Area (VMSA):\n");
610619
print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, save, sizeof(*save), false);
611620

@@ -2261,6 +2270,9 @@ void __init sev_hardware_setup(void)
22612270

22622271
sev_enabled = sev_supported;
22632272
sev_es_enabled = sev_es_supported;
2273+
if (!sev_es_enabled || !cpu_feature_enabled(X86_FEATURE_DEBUG_SWAP) ||
2274+
!cpu_feature_enabled(X86_FEATURE_NO_NESTED_DATA_BP))
2275+
sev_es_debug_swap_enabled = false;
22642276
#endif
22652277
}
22662278

@@ -2981,9 +2993,11 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
29812993
svm_set_intercept(svm, TRAP_CR8_WRITE);
29822994

29832995
vmcb->control.intercepts[INTERCEPT_DR] = 0;
2984-
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ);
2985-
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE);
2986-
recalc_intercepts(svm);
2996+
if (!sev_es_debug_swap_enabled) {
2997+
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ);
2998+
vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE);
2999+
recalc_intercepts(svm);
3000+
}
29873001

29883002
/* Can't intercept XSETBV, HV can't modify XCR0 directly */
29893003
svm_clr_intercept(svm, INTERCEPT_XSETBV);
@@ -3053,6 +3067,22 @@ void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
30533067
hostsa->xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
30543068
hostsa->pkru = read_pkru();
30553069
hostsa->xss = host_xss;
3070+
3071+
/*
3072+
* If DebugSwap is enabled, debug registers are loaded but NOT saved by
3073+
* the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both
3074+
* saves and loads debug registers (Type-A).
3075+
*/
3076+
if (sev_es_debug_swap_enabled) {
3077+
hostsa->dr0 = native_get_debugreg(0);
3078+
hostsa->dr1 = native_get_debugreg(1);
3079+
hostsa->dr2 = native_get_debugreg(2);
3080+
hostsa->dr3 = native_get_debugreg(3);
3081+
hostsa->dr0_addr_mask = amd_get_dr_addr_mask(0);
3082+
hostsa->dr1_addr_mask = amd_get_dr_addr_mask(1);
3083+
hostsa->dr2_addr_mask = amd_get_dr_addr_mask(2);
3084+
hostsa->dr3_addr_mask = amd_get_dr_addr_mask(3);
3085+
}
30563086
}
30573087

30583088
void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)

tools/arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@
434434
#define X86_FEATURE_SEV_ES (19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */
435435
#define X86_FEATURE_V_TSC_AUX (19*32+ 9) /* "" Virtual TSC_AUX */
436436
#define X86_FEATURE_SME_COHERENT (19*32+10) /* "" AMD hardware-enforced cache coherency */
437+
#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* AMD SEV-ES full debug state swap support */
437438

438439
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
439440
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* "" No Nested Data Breakpoints */

0 commit comments

Comments
 (0)