tools/testing/selftests/kvm/lib/x86/sev.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/lib/x86/sev.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/lib/x86/sev.c
Extension
.c
Size
5256 bytes
Lines
200
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
#include <stdint.h>
#include <stdbool.h>

#include "sev.h"

/*
 * sparsebit_next_clear() can return 0 if [x, 2**64-1] are all set, and the
 * -1 would then cause an underflow back to 2**64 - 1. This is expected and
 * correct.
 *
 * If the last range in the sparsebit is [x, y] and we try to iterate,
 * sparsebit_next_set() will return 0, and sparsebit_next_clear() will try
 * and find the first range, but that's correct because the condition
 * expression would cause us to quit the loop.
 */
static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *region,
			   u8 page_type, bool private)
{
	const struct sparsebit *protected_phy_pages = region->protected_phy_pages;
	const gpa_t gpa_base = region->region.guest_phys_addr;
	const sparsebit_idx_t lowest_page_in_region = gpa_base >> vm->page_shift;
	sparsebit_idx_t i, j;

	if (!sparsebit_any_set(protected_phy_pages))
		return;

	if (!is_sev_snp_vm(vm))
		sev_register_encrypted_memory(vm, region);

	sparsebit_for_each_set_range(protected_phy_pages, i, j) {
		const u64 size = (j - i + 1) * vm->page_size;
		const u64 offset = (i - lowest_page_in_region) * vm->page_size;

		if (private)
			vm_mem_set_private(vm, gpa_base + offset, size);

		if (is_sev_snp_vm(vm))
			snp_launch_update_data(vm, gpa_base + offset,
					       (u64)addr_gpa2hva(vm, gpa_base + offset),
					       size, page_type);
		else
			sev_launch_update_data(vm, gpa_base + offset, size);

	}
}

void sev_vm_init(struct kvm_vm *vm)
{
	if (vm->type == KVM_X86_DEFAULT_VM) {
		TEST_ASSERT_EQ(vm->arch.sev_fd, -1);
		vm->arch.sev_fd = open_sev_dev_path_or_exit();
		vm_sev_ioctl(vm, KVM_SEV_INIT, NULL);
	} else {
		struct kvm_sev_init init = { 0 };
		TEST_ASSERT_EQ(vm->type, KVM_X86_SEV_VM);
		vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
	}
}

void sev_es_vm_init(struct kvm_vm *vm)
{
	if (vm->type == KVM_X86_DEFAULT_VM) {
		TEST_ASSERT_EQ(vm->arch.sev_fd, -1);
		vm->arch.sev_fd = open_sev_dev_path_or_exit();
		vm_sev_ioctl(vm, KVM_SEV_ES_INIT, NULL);
	} else {
		struct kvm_sev_init init = { 0 };
		TEST_ASSERT_EQ(vm->type, KVM_X86_SEV_ES_VM);
		vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
	}
}

void snp_vm_init(struct kvm_vm *vm)
{
	struct kvm_sev_init init = { 0 };

	TEST_ASSERT_EQ(vm->type, KVM_X86_SNP_VM);
	vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
}

void sev_vm_launch(struct kvm_vm *vm, u32 policy)
{
	struct kvm_sev_launch_start launch_start = {
		.policy = policy,
	};
	struct userspace_mem_region *region;
	struct kvm_sev_guest_status status;
	int ctr;

Annotation

Implementation Notes