2 #include <sys/malloc.h>
3 #include <sys/thread.h>
8 #include <machine/cputypes.h>
9 #include <machine/md_var.h>
10 #include <machine/specialreg.h>
15 static int svm_available = 0;
16 static int svm_enabled = 0;
18 //static int svm_rvi_available = 0;
19 //static int svm_vmcb_caching_available = 0;
21 static vm_offset_t vm_hsave_va[MAXCPU];
24 * svm_init() - Identify AMD SVM support.
26 * Called in early boot. Detects AMD SVM support and extended features.
28 static int svm_init(void) {
31 /* SVM is identified by CPUID */
32 if ((amd_feature2 & AMDID2_SVM) == 0)
35 /* Processor may support SVM, but it may be disabled. */
36 vm_cr = rdmsr(MSR_AMD_VM_CR);
37 if (vm_cr & MSR_AMD_VM_CR_SVMDIS)
46 * svm_enable() - Called to enable SVM extensions on every processor.
48 static int svm_enable(void) {
52 vm_paddr_t vm_hsave_pa;
57 KKASSERT(svm_enabled == 0);
59 /* Set EFER.SVME and allocate a VM Host Save Area on every cpu */
61 for (i = 0; i < ncpus; i++) {
64 efer = rdmsr(MSR_EFER);
66 wrmsr(MSR_EFER, efer);
68 vm_hsave_va[i] = (vm_offset_t) contigmalloc(4096, M_TEMP,
72 vm_hsave_pa = vtophys(vm_hsave_va[i]);
73 wrmsr(MSR_AMD_VM_HSAVE_PA, vm_hsave_pa);
75 lwkt_migratecpu(origcpu);
83 * svm_disable() - Called to disable SVM extensions on every processor.
85 static int svm_disable(void) {
90 /* XXX Wait till no vmms are running? */
92 KKASSERT(svm_enabled == 1);
95 for (i = 0; i < ncpus; i++) {
98 wrmsr(MSR_AMD_VM_HSAVE_PA, 0);
100 contigfree((void *) vm_hsave_va[i], 4096, M_TEMP);
103 efer = rdmsr(MSR_EFER);
105 wrmsr(MSR_EFER, efer);
107 lwkt_migratecpu(origcpu);
115 * svm_vminit() - Prepare current thread for VMRUN.
117 * Allocates a VMCB for the current thread and flags the thread to return
118 * to usermode via svm_vmrun().
120 static int svm_vminit(struct guest_options *options) {
127 static int svm_vmdestroy(void) {
132 * svm_vmrun() - Execute VMRUN on a prepared VMCB for a thread.
134 * Called while a thread is returning to userspace, after being flagged as
135 * a VMM thread. svm_vmrun() continues in a loop around VMRUN/#VMEXIT
136 * handling until we are no longer a VMM thread.
138 static int svm_vmrun(void) {
142 static struct vmm_ctl ctl_svm = {
145 .enable = svm_enable,
146 .disable = svm_disable,
147 .vminit = svm_vminit,
148 .vmdestroy = svm_vmdestroy,