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