~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/lib/x86_64/sev.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 #include <stdint.h>
  3 #include <stdbool.h>
  4 
  5 #include "sev.h"
  6 
  7 /*
  8  * sparsebit_next_clear() can return 0 if [x, 2**64-1] are all set, and the
  9  * -1 would then cause an underflow back to 2**64 - 1. This is expected and
 10  * correct.
 11  *
 12  * If the last range in the sparsebit is [x, y] and we try to iterate,
 13  * sparsebit_next_set() will return 0, and sparsebit_next_clear() will try
 14  * and find the first range, but that's correct because the condition
 15  * expression would cause us to quit the loop.
 16  */
 17 static void encrypt_region(struct kvm_vm *vm, struct userspace_mem_region *region)
 18 {
 19         const struct sparsebit *protected_phy_pages = region->protected_phy_pages;
 20         const vm_paddr_t gpa_base = region->region.guest_phys_addr;
 21         const sparsebit_idx_t lowest_page_in_region = gpa_base >> vm->page_shift;
 22         sparsebit_idx_t i, j;
 23 
 24         if (!sparsebit_any_set(protected_phy_pages))
 25                 return;
 26 
 27         sev_register_encrypted_memory(vm, region);
 28 
 29         sparsebit_for_each_set_range(protected_phy_pages, i, j) {
 30                 const uint64_t size = (j - i + 1) * vm->page_size;
 31                 const uint64_t offset = (i - lowest_page_in_region) * vm->page_size;
 32 
 33                 sev_launch_update_data(vm, gpa_base + offset, size);
 34         }
 35 }
 36 
 37 void sev_vm_init(struct kvm_vm *vm)
 38 {
 39         if (vm->type == KVM_X86_DEFAULT_VM) {
 40                 assert(vm->arch.sev_fd == -1);
 41                 vm->arch.sev_fd = open_sev_dev_path_or_exit();
 42                 vm_sev_ioctl(vm, KVM_SEV_INIT, NULL);
 43         } else {
 44                 struct kvm_sev_init init = { 0 };
 45                 assert(vm->type == KVM_X86_SEV_VM);
 46                 vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
 47         }
 48 }
 49 
 50 void sev_es_vm_init(struct kvm_vm *vm)
 51 {
 52         if (vm->type == KVM_X86_DEFAULT_VM) {
 53                 assert(vm->arch.sev_fd == -1);
 54                 vm->arch.sev_fd = open_sev_dev_path_or_exit();
 55                 vm_sev_ioctl(vm, KVM_SEV_ES_INIT, NULL);
 56         } else {
 57                 struct kvm_sev_init init = { 0 };
 58                 assert(vm->type == KVM_X86_SEV_ES_VM);
 59                 vm_sev_ioctl(vm, KVM_SEV_INIT2, &init);
 60         }
 61 }
 62 
 63 void sev_vm_launch(struct kvm_vm *vm, uint32_t policy)
 64 {
 65         struct kvm_sev_launch_start launch_start = {
 66                 .policy = policy,
 67         };
 68         struct userspace_mem_region *region;
 69         struct kvm_sev_guest_status status;
 70         int ctr;
 71 
 72         vm_sev_ioctl(vm, KVM_SEV_LAUNCH_START, &launch_start);
 73         vm_sev_ioctl(vm, KVM_SEV_GUEST_STATUS, &status);
 74 
 75         TEST_ASSERT_EQ(status.policy, policy);
 76         TEST_ASSERT_EQ(status.state, SEV_GUEST_STATE_LAUNCH_UPDATE);
 77 
 78         hash_for_each(vm->regions.slot_hash, ctr, region, slot_node)
 79                 encrypt_region(vm, region);
 80 
 81         if (policy & SEV_POLICY_ES)
 82                 vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL);
 83 
 84         vm->arch.is_pt_protected = true;
 85 }
 86 
 87 void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement)
 88 {
 89         struct kvm_sev_launch_measure launch_measure;
 90         struct kvm_sev_guest_status guest_status;
 91 
 92         launch_measure.len = 256;
 93         launch_measure.uaddr = (__u64)measurement;
 94         vm_sev_ioctl(vm, KVM_SEV_LAUNCH_MEASURE, &launch_measure);
 95 
 96         vm_sev_ioctl(vm, KVM_SEV_GUEST_STATUS, &guest_status);
 97         TEST_ASSERT_EQ(guest_status.state, SEV_GUEST_STATE_LAUNCH_SECRET);
 98 }
 99 
100 void sev_vm_launch_finish(struct kvm_vm *vm)
101 {
102         struct kvm_sev_guest_status status;
103 
104         vm_sev_ioctl(vm, KVM_SEV_GUEST_STATUS, &status);
105         TEST_ASSERT(status.state == SEV_GUEST_STATE_LAUNCH_UPDATE ||
106                     status.state == SEV_GUEST_STATE_LAUNCH_SECRET,
107                     "Unexpected guest state: %d", status.state);
108 
109         vm_sev_ioctl(vm, KVM_SEV_LAUNCH_FINISH, NULL);
110 
111         vm_sev_ioctl(vm, KVM_SEV_GUEST_STATUS, &status);
112         TEST_ASSERT_EQ(status.state, SEV_GUEST_STATE_RUNNING);
113 }
114 
115 struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,
116                                            struct kvm_vcpu **cpu)
117 {
118         struct vm_shape shape = {
119                 .mode = VM_MODE_DEFAULT,
120                 .type = type,
121         };
122         struct kvm_vm *vm;
123         struct kvm_vcpu *cpus[1];
124 
125         vm = __vm_create_with_vcpus(shape, 1, 0, guest_code, cpus);
126         *cpu = cpus[0];
127 
128         return vm;
129 }
130 
131 void vm_sev_launch(struct kvm_vm *vm, uint32_t policy, uint8_t *measurement)
132 {
133         sev_vm_launch(vm, policy);
134 
135         if (!measurement)
136                 measurement = alloca(256);
137 
138         sev_vm_launch_measure(vm, measurement);
139 
140         sev_vm_launch_finish(vm);
141 }
142 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php