Annotation of embedaddon/strongswan/src/libstrongswan/utils/cpu_feature.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2015 Martin Willi
        !             3:  * Copyright (C) 2015 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "cpu_feature.h"
        !            17: 
        !            18: #if defined __i386__ || defined(__x86_64__)
        !            19: 
        !            20: typedef enum {
        !            21:        /* Generic CPUID(1) flags */
        !            22:        CPUID1_EDX_MMX =                                (1 << 23),
        !            23:        CPUID1_EDX_SSE =                                (1 << 25),
        !            24:        CPUID1_EDX_SSE2 =                               (1 << 26),
        !            25:        CPUID1_ECX_SSE3 =                               (1 <<  0),
        !            26:        CPUID1_ECX_PCLMULQDQ =                  (1 <<  1),
        !            27:        CPUID1_ECX_SSSE3 =                              (1 <<  9),
        !            28:        CPUID1_ECX_SSE41 =                              (1 << 19),
        !            29:        CPUID1_ECX_SSE42 =                              (1 << 20),
        !            30:        CPUID1_ECX_AESNI =                              (1 << 25),
        !            31:        CPUID1_ECX_AVX =                                (1 << 28),
        !            32:        CPUID1_ECX_RDRAND =                             (1 << 30),
        !            33: 
        !            34:        /* For CentaurHauls cpuid(0xC0000001) */
        !            35:        CPUIDC1_EDX_RNG_AVAILABLE =             (1 <<  2),
        !            36:        CPUIDC1_EDX_RNG_ENABLED =               (1 <<  3),
        !            37:        CPUIDC1_EDX_ACE_AVAILABLE =             (1 <<  6),
        !            38:        CPUIDC1_EDX_ACE_ENABLED =               (1 <<  7),
        !            39:        CPUIDC1_EDX_ACE2_AVAILABLE =    (1 <<  8),
        !            40:        CPUIDC1_EDX_ACE2_ENABLED =              (1 <<  9),
        !            41:        CPUIDC1_EDX_PHE_AVAILABLE =             (1 << 10),
        !            42:        CPUIDC1_EDX_PHE_ENABLED =               (1 << 11),
        !            43:        CPUIDC1_EDX_PMM_AVAILABLE =             (1 << 12),
        !            44:        CPUIDC1_EDX_PMM_ENABLED =               (1 << 13),
        !            45: } cpuid_flag_t;
        !            46: 
        !            47: /**
        !            48:  * Get cpuid for info, return eax, ebx, ecx and edx.
        !            49:  * -fPIC requires to save ebx on IA-32.
        !            50:  */
        !            51: static void cpuid(u_int op, u_int *a, u_int *b, u_int *c, u_int *d)
        !            52: {
        !            53: #ifdef __x86_64__
        !            54:        asm("cpuid" : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) : "a" (op));
        !            55: #else /* __i386__ */
        !            56:        asm("pushl %%ebx;"
        !            57:                "cpuid;"
        !            58:                "movl %%ebx, %1;"
        !            59:                "popl %%ebx;"
        !            60:                : "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) : "a" (op));
        !            61: #endif /* __x86_64__ / __i386__*/
        !            62: }
        !            63: 
        !            64: /**
        !            65:  * Return feature if flag in reg, flag-to-feature
        !            66:  */
        !            67: static inline cpu_feature_t f2f(u_int reg, cpuid_flag_t flag, cpu_feature_t f)
        !            68: {
        !            69:        if (reg & flag)
        !            70:        {
        !            71:                return f;
        !            72:        }
        !            73:        return 0;
        !            74: }
        !            75: 
        !            76: /**
        !            77:  * Get features for a Via "CentaurHauls" CPU
        !            78:  */
        !            79: static cpu_feature_t get_via_features()
        !            80: {
        !            81:        cpu_feature_t f = 0;
        !            82:        u_int a, b, c, d;
        !            83: 
        !            84:        cpuid(0xc0000001, &a, &b, &c, &d);
        !            85: 
        !            86:        f |= f2f(d, CPUIDC1_EDX_RNG_AVAILABLE, CPU_FEATURE_PADLOCK_RNG_AVAILABLE);
        !            87:        f |= f2f(d, CPUIDC1_EDX_RNG_ENABLED, CPU_FEATURE_PADLOCK_RNG_ENABLED);
        !            88:        f |= f2f(d, CPUIDC1_EDX_ACE_AVAILABLE, CPU_FEATURE_PADLOCK_ACE_AVAILABLE);
        !            89:        f |= f2f(d, CPUIDC1_EDX_ACE_ENABLED, CPU_FEATURE_PADLOCK_ACE_ENABLED);
        !            90:        f |= f2f(d, CPUIDC1_EDX_ACE2_AVAILABLE, CPU_FEATURE_PADLOCK_ACE2_AVAILABLE);
        !            91:        f |= f2f(d, CPUIDC1_EDX_ACE2_ENABLED, CPU_FEATURE_PADLOCK_ACE2_ENABLED);
        !            92:        f |= f2f(d, CPUIDC1_EDX_PHE_AVAILABLE, CPU_FEATURE_PADLOCK_PHE_AVAILABLE);
        !            93:        f |= f2f(d, CPUIDC1_EDX_PHE_ENABLED, CPU_FEATURE_PADLOCK_PHE_ENABLED);
        !            94:        f |= f2f(d, CPUIDC1_EDX_PMM_AVAILABLE, CPU_FEATURE_PADLOCK_PMM_AVAILABLE);
        !            95:        f |= f2f(d, CPUIDC1_EDX_PMM_ENABLED, CPU_FEATURE_PADLOCK_PMM_ENABLED);
        !            96: 
        !            97:        return f;
        !            98: }
        !            99: 
        !           100: /**
        !           101:  * See header.
        !           102:  */
        !           103: cpu_feature_t cpu_feature_get_all()
        !           104: {
        !           105:        char vendor[3 * sizeof(uint32_t) + 1];
        !           106:        cpu_feature_t f = 0;
        !           107:        u_int a, b, c, d;
        !           108: 
        !           109:        cpuid(0, &a, &b, &c, &d);
        !           110:        /* VendorID string is in b-d-c (yes, in this order) */
        !           111:        snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c);
        !           112: 
        !           113:        cpuid(1, &a, &b, &c, &d);
        !           114: 
        !           115:        /* check common x86 features for CPUID(1) */
        !           116:        f |= f2f(d, CPUID1_EDX_MMX, CPU_FEATURE_MMX);
        !           117:        f |= f2f(d, CPUID1_EDX_SSE, CPU_FEATURE_SSE);
        !           118:        f |= f2f(d, CPUID1_EDX_SSE2, CPU_FEATURE_SSE2);
        !           119:        f |= f2f(c, CPUID1_ECX_SSE3, CPU_FEATURE_SSE3);
        !           120:        f |= f2f(c, CPUID1_ECX_PCLMULQDQ, CPU_FEATURE_PCLMULQDQ);
        !           121:        f |= f2f(c, CPUID1_ECX_SSSE3, CPU_FEATURE_SSSE3);
        !           122:        f |= f2f(c, CPUID1_ECX_SSE41, CPU_FEATURE_SSE41);
        !           123:        f |= f2f(c, CPUID1_ECX_SSE42, CPU_FEATURE_SSE42);
        !           124:        f |= f2f(c, CPUID1_ECX_AESNI, CPU_FEATURE_AESNI);
        !           125:        f |= f2f(c, CPUID1_ECX_AVX, CPU_FEATURE_AVX);
        !           126:        f |= f2f(c, CPUID1_ECX_RDRAND, CPU_FEATURE_RDRAND);
        !           127: 
        !           128:        if (streq(vendor, "CentaurHauls"))
        !           129:        {
        !           130:                cpuid(0xc0000000, &a, &b, &c, &d);
        !           131:                /* check Centaur Extended Feature Flags */
        !           132:                if (a >= 0xc0000001)
        !           133:                {
        !           134:                        f |= get_via_features();
        !           135:                }
        !           136:        }
        !           137:        return f;
        !           138: }
        !           139: 
        !           140: #else /* !x86 */
        !           141: 
        !           142: /**
        !           143:  * See header.
        !           144:  */
        !           145: cpu_feature_t cpu_feature_get_all()
        !           146: {
        !           147:        return 0;
        !           148: }
        !           149: 
        !           150: #endif
        !           151: 
        !           152: /**
        !           153:  * See header.
        !           154:  */
        !           155: bool cpu_feature_available(cpu_feature_t feature)
        !           156: {
        !           157:        return (cpu_feature_get_all() & feature) == feature;
        !           158: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>