1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <fcntl.h> 3 #include <string.h> 4 #include <sys/ioctl.h> 5 6 #include "test_util.h" 7 #include "kvm_util.h" 8 #include "processor.h" 9 #include "sev.h" 10 11 #define BUFFER_SIZE (PAGE_SIZE * 2) 12 13 static u8 *data; 14 static u8 src[BUFFER_SIZE] __aligned(PAGE_SIZE); 15 static u8 dst[BUFFER_SIZE] __aligned(PAGE_SIZE); 16 17 static void validate_dst(int i, int nr_bytes, u8 pattern) 18 { 19 for ( ; i < nr_bytes; i++) 20 TEST_ASSERT(dst[i] == pattern, 21 "Expected 0x%x at byte %u, got 0x%x", 22 pattern, i, dst[i]); 23 } 24 25 static void validate_buffers(void) 26 { 27 int i; 28 29 for (i = 0; i < BUFFER_SIZE; i++) 30 TEST_ASSERT(src[i] == dst[i], 31 "Expected src[%u] (0x%x) == dst[%u] (0x%x)", 32 i, src[i], i, dst[i]); 33 } 34 35 static void ____test_sev_dbg(struct kvm_vm *vm, int i, int j, int nr_bytes) 36 { 37 u8 pattern = guest_random_u32(&guest_rng); 38 39 if (i + nr_bytes > BUFFER_SIZE || j + nr_bytes > BUFFER_SIZE) 40 return; 41 42 memset(&src[i], pattern, nr_bytes); 43 sev_encrypt_memory(vm, &data[j], &src[i], nr_bytes); 44 sev_decrypt_memory(vm, &dst[i], &data[j], nr_bytes); 45 validate_buffers(); 46 validate_dst(i, nr_bytes, pattern); 47 } 48 49 static void __test_sev_dbg(struct kvm_vm *vm, int nr_bytes) 50 { 51 /* 52 * In a perfect world, all sizes at all combinations within the buffers 53 * would be tested. In reality, even this much testing is quite slow. 54 * Target sizes and offsets around the chunk (16 bytes) and page (4096 55 * bytes) sizes. 56 */ 57 int x[] = { 1, 8, 15, 16, 23 }; 58 int p = PAGE_SIZE - 24; 59 int i, j; 60 61 ____test_sev_dbg(vm, 0, 0, nr_bytes); 62 63 for (i = 0; i < ARRAY_SIZE(x); i++) { 64 for (j = 0; j < ARRAY_SIZE(x); j++) { 65 ____test_sev_dbg(vm, x[i], x[j], nr_bytes); 66 ____test_sev_dbg(vm, x[i], p + x[j], nr_bytes); 67 ____test_sev_dbg(vm, p + x[i], x[j], nr_bytes); 68 ____test_sev_dbg(vm, p + x[i], p + x[j], nr_bytes); 69 } 70 } 71 } 72 73 static void test_sev_dbg(u32 type, u64 policy) 74 { 75 int sizes[] = { 1, 8, 15, 16, 17, 32, 33 }; 76 struct kvm_vcpu *vcpu; 77 struct kvm_vm *vm; 78 int i; 79 80 if (!(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(type))) 81 return; 82 83 vm = vm_sev_create_with_one_vcpu(type, NULL, &vcpu); 84 85 data = addr_gva2hva(vm, vm_alloc(vm, BUFFER_SIZE, KVM_UTIL_MIN_VADDR)); 86 memset(data, 0xaa, BUFFER_SIZE); 87 88 vm_sev_launch(vm, policy, NULL); 89 90 sev_decrypt_memory(vm, dst, data, BUFFER_SIZE); 91 validate_dst(0, BUFFER_SIZE, 0xaa); 92 93 memset(src, 0x55, BUFFER_SIZE); 94 sev_encrypt_memory(vm, data, src, BUFFER_SIZE); 95 sev_decrypt_memory(vm, dst, data, BUFFER_SIZE); 96 validate_dst(0, BUFFER_SIZE, 0x55); 97 98 __test_sev_dbg(vm, PAGE_SIZE); 99 100 for (i = 0; i < ARRAY_SIZE(sizes); i++) { 101 __test_sev_dbg(vm, sizes[i]); 102 __test_sev_dbg(vm, PAGE_SIZE - sizes[i]); 103 __test_sev_dbg(vm, PAGE_SIZE + sizes[i]); 104 __test_sev_dbg(vm, BUFFER_SIZE - sizes[i]); 105 } 106 107 kvm_vm_free(vm); 108 } 109 110 int main(int argc, char *argv[]) 111 { 112 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV)); 113 114 /* Note, KVM doesn't support {de,en}crypt commands for SNP. */ 115 test_sev_dbg(KVM_X86_SEV_VM, 0); 116 test_sev_dbg(KVM_X86_SEV_ES_VM, SEV_POLICY_ES); 117 return 0; 118 } 119