]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/i386/vmx/vmx_cpu.c
xnu-4903.270.47.tar.gz
[apple/xnu.git] / osfmk / i386 / vmx / vmx_cpu.c
index 49b36f8468b46ac4b60f5ad1b627ccc3ffe857c9..f2beaaab3826cb58f5e9fcb092267bed9bdffd81 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2006-2012 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -22,7 +22,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 
@@ -46,47 +46,47 @@ lck_grp_t *vmx_lck_grp = NULL;
 lck_mtx_t *vmx_lck_mtx = NULL;
 
 /* -----------------------------------------------------------------------------
-   vmx_is_available()
-       Is the VMX facility available on this CPU?
-   -------------------------------------------------------------------------- */
+*  vmx_is_available()
+*       Is the VMX facility available on this CPU?
+*  -------------------------------------------------------------------------- */
 static inline boolean_t
 vmx_is_available(void)
 {
-       return (0 != (cpuid_features() & CPUID_FEATURE_VMX));
+       return 0 != (cpuid_features() & CPUID_FEATURE_VMX);
 }
 
 /* -----------------------------------------------------------------------------
-   vmxon_is_enabled()
-       Is the VMXON instruction enabled on this CPU?
-   -------------------------------------------------------------------------- */
+*  vmxon_is_enabled()
+*       Is the VMXON instruction enabled on this CPU?
+*  -------------------------------------------------------------------------- */
 static inline boolean_t
 vmxon_is_enabled(void)
 {
-       return (vmx_is_available() &&
-               (rdmsr64(MSR_IA32_FEATURE_CONTROL) & MSR_IA32_FEATCTL_VMXON));
+       return vmx_is_available() &&
+              (rdmsr64(MSR_IA32_FEATURE_CONTROL) & MSR_IA32_FEATCTL_VMXON);
 }
 
 #if MACH_ASSERT
 /* -----------------------------------------------------------------------------
-   vmx_is_cr0_valid()
-       Is CR0 valid for executing VMXON on this CPU?
-   -------------------------------------------------------------------------- */
+*  vmx_is_cr0_valid()
+*       Is CR0 valid for executing VMXON on this CPU?
+*  -------------------------------------------------------------------------- */
 static inline boolean_t
 vmx_is_cr0_valid(vmx_specs_t *specs)
 {
        uintptr_t cr0 = get_cr0();
-       return (0 == ((~cr0 & specs->cr0_fixed_0)|(cr0 & ~specs->cr0_fixed_1)));
+       return 0 == ((~cr0 & specs->cr0_fixed_0) | (cr0 & ~specs->cr0_fixed_1));
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_is_cr4_valid()
-       Is CR4 valid for executing VMXON on this CPU?
-   -------------------------------------------------------------------------- */
+*  vmx_is_cr4_valid()
+*       Is CR4 valid for executing VMXON on this CPU?
+*  -------------------------------------------------------------------------- */
 static inline boolean_t
 vmx_is_cr4_valid(vmx_specs_t *specs)
 {
        uintptr_t cr4 = get_cr4();
-       return (0 == ((~cr4 & specs->cr4_fixed_0)|(cr4 & ~specs->cr4_fixed_1)));
+       return 0 == ((~cr4 & specs->cr4_fixed_0) | (cr4 & ~specs->cr4_fixed_1));
 }
 
 #endif
@@ -96,19 +96,21 @@ vmx_enable(void)
 {
        uint64_t msr_image;
 
-       if (!vmx_is_available())
+       if (!vmx_is_available()) {
                return;
+       }
 
        /*
         * We don't count on EFI initializing MSR_IA32_FEATURE_CONTROL
         * and turning VMXON on and locking the bit, so we do that now.
         */
        msr_image = rdmsr64(MSR_IA32_FEATURE_CONTROL);
-       if (0 == ((msr_image & MSR_IA32_FEATCTL_LOCK)))
+       if (0 == ((msr_image & MSR_IA32_FEATCTL_LOCK))) {
                wrmsr64(MSR_IA32_FEATURE_CONTROL,
-                       (msr_image |
-                        MSR_IA32_FEATCTL_VMXON |
-                        MSR_IA32_FEATCTL_LOCK));
+                   (msr_image |
+                   MSR_IA32_FEATCTL_VMXON |
+                   MSR_IA32_FEATCTL_LOCK));
+       }
 
        set_cr4(get_cr4() | CR4_VMXE);
 }
@@ -124,12 +126,12 @@ vmx_init()
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_get_specs()
-       Obtain VMX facility specifications for this CPU and
-       enter them into the vmx_specs_t structure. If VMX is not available or
-       disabled on this CPU, set vmx_present to false and return leaving
-       the remainder of the vmx_specs_t uninitialized. 
-   -------------------------------------------------------------------------- */
+*  vmx_get_specs()
+*       Obtain VMX facility specifications for this CPU and
+*       enter them into the vmx_specs_t structure. If VMX is not available or
+*       disabled on this CPU, set vmx_present to false and return leaving
+*       the remainder of the vmx_specs_t uninitialized.
+*  -------------------------------------------------------------------------- */
 void
 vmx_cpu_init()
 {
@@ -138,20 +140,22 @@ vmx_cpu_init()
        vmx_enable();
 
        VMX_KPRINTF("[%d]vmx_cpu_init() initialized: %d\n",
-                   cpu_number(), specs->initialized);
+           cpu_number(), specs->initialized);
 
        /* if we have read the data on boot, we won't read it again on wakeup */
-       if (specs->initialized)
+       if (specs->initialized) {
                return;
-       else
+       } else {
                specs->initialized = TRUE;
+       }
 
        /* See if VMX is present, return if it is not */
        specs->vmx_present = vmx_is_available() && vmxon_is_enabled();
        VMX_KPRINTF("[%d]vmx_cpu_init() vmx_present: %d\n",
-                   cpu_number(), specs->vmx_present);
-       if (!specs->vmx_present)
+           cpu_number(), specs->vmx_present);
+       if (!specs->vmx_present) {
                return;
+       }
 
 #define rdmsr_mask(msr, mask) (uint32_t)(rdmsr64(msr) & (mask))
        specs->vmcs_id = rdmsr_mask(MSR_IA32_VMX_BASIC, VMX_VCR_VMCS_REV_ID);
@@ -159,16 +163,16 @@ vmx_cpu_init()
        /* Obtain VMX-fixed bits in CR0 */
        specs->cr0_fixed_0 = rdmsr_mask(MSR_IA32_VMX_CR0_FIXED0, 0xFFFFFFFF);
        specs->cr0_fixed_1 = rdmsr_mask(MSR_IA32_VMX_CR0_FIXED1, 0xFFFFFFFF);
-       
+
        /* Obtain VMX-fixed bits in CR4 */
        specs->cr4_fixed_0 = rdmsr_mask(MSR_IA32_VMX_CR4_FIXED0, 0xFFFFFFFF);
        specs->cr4_fixed_1 = rdmsr_mask(MSR_IA32_VMX_CR4_FIXED1, 0xFFFFFFFF);
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_on()
-       Enter VMX root operation on this CPU.
-   -------------------------------------------------------------------------- */
+*  vmx_on()
+*       Enter VMX root operation on this CPU.
+*  -------------------------------------------------------------------------- */
 static void
 vmx_on(void *arg __unused)
 {
@@ -177,12 +181,13 @@ vmx_on(void *arg __unused)
        int result;
 
        VMX_KPRINTF("[%d]vmx_on() entry state: %d\n",
-                   cpu_number(), cpu->specs.vmx_on);
+           cpu_number(), cpu->specs.vmx_on);
 
        assert(cpu->specs.vmx_present);
 
-       if (NULL == cpu->vmxon_region)
+       if (NULL == cpu->vmxon_region) {
                panic("vmx_on: VMXON region not allocated");
+       }
        vmxon_region_paddr = vmx_paddr(cpu->vmxon_region);
 
        /*
@@ -191,7 +196,7 @@ vmx_on(void *arg __unused)
        if (FALSE == cpu->specs.vmx_on) {
                assert(vmx_is_cr0_valid(&cpu->specs));
                assert(vmx_is_cr4_valid(&cpu->specs));
-       
+
                result = __vmxon(vmxon_region_paddr);
 
                if (result != VMX_SUCCEED) {
@@ -201,21 +206,21 @@ vmx_on(void *arg __unused)
                cpu->specs.vmx_on = TRUE;
        }
        VMX_KPRINTF("[%d]vmx_on() return state: %d\n",
-                   cpu_number(), cpu->specs.vmx_on);
+           cpu_number(), cpu->specs.vmx_on);
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_off()
-       Leave VMX root operation on this CPU.
-   -------------------------------------------------------------------------- */
+*  vmx_off()
+*       Leave VMX root operation on this CPU.
+*  -------------------------------------------------------------------------- */
 static void
 vmx_off(void *arg __unused)
 {
        vmx_cpu_t *cpu = &current_cpu_datap()->cpu_vmx;
        int result;
-       
+
        VMX_KPRINTF("[%d]vmx_off() entry state: %d\n",
-                   cpu_number(), cpu->specs.vmx_on);
+           cpu_number(), cpu->specs.vmx_on);
 
        if (TRUE == cpu->specs.vmx_on) {
                /* Tell the CPU to release the VMXON region */
@@ -224,44 +229,45 @@ vmx_off(void *arg __unused)
                if (result != VMX_SUCCEED) {
                        panic("vmx_off: unexpected return %d from __vmxoff()", result);
                }
-       
+
                cpu->specs.vmx_on = FALSE;
        }
 
        VMX_KPRINTF("[%d]vmx_off() return state: %d\n",
-                   cpu_number(), cpu->specs.vmx_on);
+           cpu_number(), cpu->specs.vmx_on);
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_allocate_vmxon_regions()
-       Allocate, clear and init VMXON regions for all CPUs.
-   -------------------------------------------------------------------------- */
+*  vmx_allocate_vmxon_regions()
+*       Allocate, clear and init VMXON regions for all CPUs.
+*  -------------------------------------------------------------------------- */
 static void
 vmx_allocate_vmxon_regions(void)
 {
        unsigned int i;
-       
-       for (i=0; i<real_ncpus; i++) {
+
+       for (i = 0; i < real_ncpus; i++) {
                vmx_cpu_t *cpu = &cpu_datap(i)->cpu_vmx;
 
                /* The size is defined to be always <= 4K, so we just allocate a page */
                cpu->vmxon_region = vmx_pcalloc();
-               if (NULL == cpu->vmxon_region)
+               if (NULL == cpu->vmxon_region) {
                        panic("vmx_allocate_vmxon_regions: unable to allocate VMXON region");
+               }
                *(uint32_t*)(cpu->vmxon_region) = cpu->specs.vmcs_id;
        }
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_free_vmxon_regions()
-       Free VMXON regions for all CPUs.
-   -------------------------------------------------------------------------- */
+*  vmx_free_vmxon_regions()
+*       Free VMXON regions for all CPUs.
+*  -------------------------------------------------------------------------- */
 static void
 vmx_free_vmxon_regions(void)
 {
        unsigned int i;
 
-       for (i=0; i<real_ncpus; i++) {
+       for (i = 0; i < real_ncpus; i++) {
                vmx_cpu_t *cpu = &cpu_datap(i)->cpu_vmx;
 
                vmx_pfree(cpu->vmxon_region);
@@ -270,9 +276,9 @@ vmx_free_vmxon_regions(void)
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_globally_available()
-       Checks whether VT can be turned on for all CPUs.
-   -------------------------------------------------------------------------- */
+*  vmx_globally_available()
+*       Checks whether VT can be turned on for all CPUs.
+*  -------------------------------------------------------------------------- */
 static boolean_t
 vmx_globally_available(void)
 {
@@ -280,11 +286,12 @@ vmx_globally_available(void)
        unsigned int ncpus = ml_get_max_cpus();
        boolean_t available = TRUE;
 
-       for (i=0; i<ncpus; i++) {
+       for (i = 0; i < ncpus; i++) {
                vmx_cpu_t *cpu = &cpu_datap(i)->cpu_vmx;
 
-               if (!cpu->specs.vmx_present)
+               if (!cpu->specs.vmx_present) {
                        available = FALSE;
+               }
        }
        VMX_KPRINTF("VMX available: %d\n", available);
        return available;
@@ -292,9 +299,9 @@ vmx_globally_available(void)
 
 
 /* -----------------------------------------------------------------------------
-   vmx_turn_on()
-       Turn on VT operation on all CPUs.
-   -------------------------------------------------------------------------- */
+*  vmx_turn_on()
+*       Turn on VT operation on all CPUs.
+*  -------------------------------------------------------------------------- */
 int
 host_vmxon(boolean_t exclusive)
 {
@@ -302,8 +309,9 @@ host_vmxon(boolean_t exclusive)
 
        assert(0 == get_preemption_level());
 
-       if (!vmx_globally_available())
+       if (!vmx_globally_available()) {
                return VMX_UNSUPPORTED;
+       }
 
        lck_mtx_lock(vmx_lck_mtx);
 
@@ -315,7 +323,6 @@ host_vmxon(boolean_t exclusive)
                        vmx_exclusive = exclusive;
                        vmx_use_count = 1;
                        mp_cpus_call(CPUMASK_ALL, ASYNC, vmx_on, NULL);
-
                } else {
                        vmx_use_count++;
                }
@@ -330,9 +337,9 @@ host_vmxon(boolean_t exclusive)
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_turn_off()
-       Turn off VT operation on all CPUs.
-   -------------------------------------------------------------------------- */
+*  vmx_turn_off()
+*       Turn off VT operation on all CPUs.
+*  -------------------------------------------------------------------------- */
 void
 host_vmxoff()
 {
@@ -355,23 +362,24 @@ host_vmxoff()
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_suspend()
-       Turn off VT operation on this CPU if it was on.
-       Called when a CPU goes offline.
-   -------------------------------------------------------------------------- */
+*  vmx_suspend()
+*       Turn off VT operation on this CPU if it was on.
+*       Called when a CPU goes offline.
+*  -------------------------------------------------------------------------- */
 void
 vmx_suspend()
 {
        VMX_KPRINTF("vmx_suspend\n");
 
-       if (vmx_use_count)
+       if (vmx_use_count) {
                vmx_off(NULL);
+       }
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_suspend()
-       Restore the previous VT state. Called when CPU comes back online.
-   -------------------------------------------------------------------------- */
+*  vmx_suspend()
+*       Restore the previous VT state. Called when CPU comes back online.
+*  -------------------------------------------------------------------------- */
 void
 vmx_resume(boolean_t is_wake_from_hibernate)
 {
@@ -379,8 +387,9 @@ vmx_resume(boolean_t is_wake_from_hibernate)
 
        vmx_enable();
 
-       if (vmx_use_count == 0)
+       if (vmx_use_count == 0) {
                return;
+       }
 
        /*
         * When resuming from hiberate on the boot cpu,
@@ -397,14 +406,15 @@ vmx_resume(boolean_t is_wake_from_hibernate)
 }
 
 /* -----------------------------------------------------------------------------
-   vmx_hv_support()
-       Determine if the VMX feature set is sufficent for kernel HV support.
-   -------------------------------------------------------------------------- */
+*  vmx_hv_support()
+*       Determine if the VMX feature set is sufficent for kernel HV support.
+*  -------------------------------------------------------------------------- */
 boolean_t
 vmx_hv_support()
 {
-       if (!vmx_is_available())
+       if (!vmx_is_available()) {
                return FALSE;
+       }
 
 #define CHK(msr, shift, mask) if (!VMX_CAP(msr, shift, mask)) return FALSE;