Annotation of embedaddon/strongswan/src/libstrongswan/utils/cpu_feature.c, revision 1.1.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>