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

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/lib/x86_64/svm.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 /*
  3  * tools/testing/selftests/kvm/lib/x86_64/svm.c
  4  * Helpers used for nested SVM testing
  5  * Largely inspired from KVM unit test svm.c
  6  *
  7  * Copyright (C) 2020, Red Hat, Inc.
  8  */
  9 
 10 #include "test_util.h"
 11 #include "kvm_util.h"
 12 #include "processor.h"
 13 #include "svm_util.h"
 14 
 15 #define SEV_DEV_PATH "/dev/sev"
 16 
 17 struct gpr64_regs guest_regs;
 18 u64 rflags;
 19 
 20 /* Allocate memory regions for nested SVM tests.
 21  *
 22  * Input Args:
 23  *   vm - The VM to allocate guest-virtual addresses in.
 24  *
 25  * Output Args:
 26  *   p_svm_gva - The guest virtual address for the struct svm_test_data.
 27  *
 28  * Return:
 29  *   Pointer to structure with the addresses of the SVM areas.
 30  */
 31 struct svm_test_data *
 32 vcpu_alloc_svm(struct kvm_vm *vm, vm_vaddr_t *p_svm_gva)
 33 {
 34         vm_vaddr_t svm_gva = vm_vaddr_alloc_page(vm);
 35         struct svm_test_data *svm = addr_gva2hva(vm, svm_gva);
 36 
 37         svm->vmcb = (void *)vm_vaddr_alloc_page(vm);
 38         svm->vmcb_hva = addr_gva2hva(vm, (uintptr_t)svm->vmcb);
 39         svm->vmcb_gpa = addr_gva2gpa(vm, (uintptr_t)svm->vmcb);
 40 
 41         svm->save_area = (void *)vm_vaddr_alloc_page(vm);
 42         svm->save_area_hva = addr_gva2hva(vm, (uintptr_t)svm->save_area);
 43         svm->save_area_gpa = addr_gva2gpa(vm, (uintptr_t)svm->save_area);
 44 
 45         svm->msr = (void *)vm_vaddr_alloc_page(vm);
 46         svm->msr_hva = addr_gva2hva(vm, (uintptr_t)svm->msr);
 47         svm->msr_gpa = addr_gva2gpa(vm, (uintptr_t)svm->msr);
 48         memset(svm->msr_hva, 0, getpagesize());
 49 
 50         *p_svm_gva = svm_gva;
 51         return svm;
 52 }
 53 
 54 static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector,
 55                          u64 base, u32 limit, u32 attr)
 56 {
 57         seg->selector = selector;
 58         seg->attrib = attr;
 59         seg->limit = limit;
 60         seg->base = base;
 61 }
 62 
 63 void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp)
 64 {
 65         struct vmcb *vmcb = svm->vmcb;
 66         uint64_t vmcb_gpa = svm->vmcb_gpa;
 67         struct vmcb_save_area *save = &vmcb->save;
 68         struct vmcb_control_area *ctrl = &vmcb->control;
 69         u32 data_seg_attr = 3 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
 70               | SVM_SELECTOR_DB_MASK | SVM_SELECTOR_G_MASK;
 71         u32 code_seg_attr = 9 | SVM_SELECTOR_S_MASK | SVM_SELECTOR_P_MASK
 72                 | SVM_SELECTOR_L_MASK | SVM_SELECTOR_G_MASK;
 73         uint64_t efer;
 74 
 75         efer = rdmsr(MSR_EFER);
 76         wrmsr(MSR_EFER, efer | EFER_SVME);
 77         wrmsr(MSR_VM_HSAVE_PA, svm->save_area_gpa);
 78 
 79         memset(vmcb, 0, sizeof(*vmcb));
 80         asm volatile ("vmsave %0\n\t" : : "a" (vmcb_gpa) : "memory");
 81         vmcb_set_seg(&save->es, get_es(), 0, -1U, data_seg_attr);
 82         vmcb_set_seg(&save->cs, get_cs(), 0, -1U, code_seg_attr);
 83         vmcb_set_seg(&save->ss, get_ss(), 0, -1U, data_seg_attr);
 84         vmcb_set_seg(&save->ds, get_ds(), 0, -1U, data_seg_attr);
 85         vmcb_set_seg(&save->gdtr, 0, get_gdt().address, get_gdt().size, 0);
 86         vmcb_set_seg(&save->idtr, 0, get_idt().address, get_idt().size, 0);
 87 
 88         ctrl->asid = 1;
 89         save->cpl = 0;
 90         save->efer = rdmsr(MSR_EFER);
 91         asm volatile ("mov %%cr4, %0" : "=r"(save->cr4) : : "memory");
 92         asm volatile ("mov %%cr3, %0" : "=r"(save->cr3) : : "memory");
 93         asm volatile ("mov %%cr0, %0" : "=r"(save->cr0) : : "memory");
 94         asm volatile ("mov %%dr7, %0" : "=r"(save->dr7) : : "memory");
 95         asm volatile ("mov %%dr6, %0" : "=r"(save->dr6) : : "memory");
 96         asm volatile ("mov %%cr2, %0" : "=r"(save->cr2) : : "memory");
 97         save->g_pat = rdmsr(MSR_IA32_CR_PAT);
 98         save->dbgctl = rdmsr(MSR_IA32_DEBUGCTLMSR);
 99         ctrl->intercept = (1ULL << INTERCEPT_VMRUN) |
100                                 (1ULL << INTERCEPT_VMMCALL);
101         ctrl->msrpm_base_pa = svm->msr_gpa;
102 
103         vmcb->save.rip = (u64)guest_rip;
104         vmcb->save.rsp = (u64)guest_rsp;
105         guest_regs.rdi = (u64)svm;
106 }
107 
108 /*
109  * save/restore 64-bit general registers except rax, rip, rsp
110  * which are directly handed through the VMCB guest processor state
111  */
112 #define SAVE_GPR_C                              \
113         "xchg %%rbx, guest_regs+0x20\n\t"       \
114         "xchg %%rcx, guest_regs+0x10\n\t"       \
115         "xchg %%rdx, guest_regs+0x18\n\t"       \
116         "xchg %%rbp, guest_regs+0x30\n\t"       \
117         "xchg %%rsi, guest_regs+0x38\n\t"       \
118         "xchg %%rdi, guest_regs+0x40\n\t"       \
119         "xchg %%r8,  guest_regs+0x48\n\t"       \
120         "xchg %%r9,  guest_regs+0x50\n\t"       \
121         "xchg %%r10, guest_regs+0x58\n\t"       \
122         "xchg %%r11, guest_regs+0x60\n\t"       \
123         "xchg %%r12, guest_regs+0x68\n\t"       \
124         "xchg %%r13, guest_regs+0x70\n\t"       \
125         "xchg %%r14, guest_regs+0x78\n\t"       \
126         "xchg %%r15, guest_regs+0x80\n\t"
127 
128 #define LOAD_GPR_C      SAVE_GPR_C
129 
130 /*
131  * selftests do not use interrupts so we dropped clgi/sti/cli/stgi
132  * for now. registers involved in LOAD/SAVE_GPR_C are eventually
133  * unmodified so they do not need to be in the clobber list.
134  */
135 void run_guest(struct vmcb *vmcb, uint64_t vmcb_gpa)
136 {
137         asm volatile (
138                 "vmload %[vmcb_gpa]\n\t"
139                 "mov rflags, %%r15\n\t" // rflags
140                 "mov %%r15, 0x170(%[vmcb])\n\t"
141                 "mov guest_regs, %%r15\n\t"     // rax
142                 "mov %%r15, 0x1f8(%[vmcb])\n\t"
143                 LOAD_GPR_C
144                 "vmrun %[vmcb_gpa]\n\t"
145                 SAVE_GPR_C
146                 "mov 0x170(%[vmcb]), %%r15\n\t" // rflags
147                 "mov %%r15, rflags\n\t"
148                 "mov 0x1f8(%[vmcb]), %%r15\n\t" // rax
149                 "mov %%r15, guest_regs\n\t"
150                 "vmsave %[vmcb_gpa]\n\t"
151                 : : [vmcb] "r" (vmcb), [vmcb_gpa] "a" (vmcb_gpa)
152                 : "r15", "memory");
153 }
154 
155 /*
156  * Open SEV_DEV_PATH if available, otherwise exit the entire program.
157  *
158  * Return:
159  *   The opened file descriptor of /dev/sev.
160  */
161 int open_sev_dev_path_or_exit(void)
162 {
163         return open_path_or_exit(SEV_DEV_PATH, 0);
164 }
165 

~ [ 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