xref: /linux/tools/testing/selftests/kvm/x86/sev_dbg_test.c (revision b2128290c29902315e632ea59e0504d6bc9e9b42)
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