|
23 | 23 | #include <asm/pkru.h>
|
24 | 24 | #include <asm/trapnr.h>
|
25 | 25 | #include <asm/fpu/xcr.h>
|
| 26 | +#include <asm/debugreg.h> |
26 | 27 |
|
27 | 28 | #include "mmu.h"
|
28 | 29 | #include "x86.h"
|
@@ -54,9 +55,14 @@ module_param_named(sev, sev_enabled, bool, 0444);
|
54 | 55 | /* enable/disable SEV-ES support */
|
55 | 56 | static bool sev_es_enabled = true;
|
56 | 57 | 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); |
57 | 62 | #else
|
58 | 63 | #define sev_enabled false
|
59 | 64 | #define sev_es_enabled false
|
| 65 | +#define sev_es_debug_swap_enabled false |
60 | 66 | #endif /* CONFIG_KVM_AMD_SEV */
|
61 | 67 |
|
62 | 68 | static u8 sev_enc_bit;
|
@@ -606,6 +612,9 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
|
606 | 612 | save->xss = svm->vcpu.arch.ia32_xss;
|
607 | 613 | save->dr6 = svm->vcpu.arch.dr6;
|
608 | 614 |
|
| 615 | + if (sev_es_debug_swap_enabled) |
| 616 | + save->sev_features |= SVM_SEV_FEAT_DEBUG_SWAP; |
| 617 | + |
609 | 618 | pr_debug("Virtual Machine Save Area (VMSA):\n");
|
610 | 619 | print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, save, sizeof(*save), false);
|
611 | 620 |
|
@@ -2261,6 +2270,9 @@ void __init sev_hardware_setup(void)
|
2261 | 2270 |
|
2262 | 2271 | sev_enabled = sev_supported;
|
2263 | 2272 | 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; |
2264 | 2276 | #endif
|
2265 | 2277 | }
|
2266 | 2278 |
|
@@ -2981,9 +2993,11 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
|
2981 | 2993 | svm_set_intercept(svm, TRAP_CR8_WRITE);
|
2982 | 2994 |
|
2983 | 2995 | 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 | + } |
2987 | 3001 |
|
2988 | 3002 | /* Can't intercept XSETBV, HV can't modify XCR0 directly */
|
2989 | 3003 | svm_clr_intercept(svm, INTERCEPT_XSETBV);
|
@@ -3053,6 +3067,22 @@ void sev_es_prepare_switch_to_guest(struct sev_es_save_area *hostsa)
|
3053 | 3067 | hostsa->xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
|
3054 | 3068 | hostsa->pkru = read_pkru();
|
3055 | 3069 | 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 | + } |
3056 | 3086 | }
|
3057 | 3087 |
|
3058 | 3088 | void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
|
|
0 commit comments