diff options
author | Werner Koch <wk@gnupg.org> | 2007-11-29 10:55:46 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2007-11-29 10:55:46 +0000 |
commit | f1c4026ae146419f5112cc355a92107f7ca13abe (patch) | |
tree | 78ce43f4fea4bb94e48ef3ad883dbfa2be3e2ee6 /src/hwfeatures.c | |
parent | ceb9f97eff920b1d986e28468b73919b2abfffc7 (diff) | |
download | libgcrypt-f1c4026ae146419f5112cc355a92107f7ca13abe.tar.gz |
The ACE engine of VIA processors is now used for AES-128.
Diffstat (limited to 'src/hwfeatures.c')
-rw-r--r-- | src/hwfeatures.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/hwfeatures.c b/src/hwfeatures.c index 3594c0b3..6908c587 100644 --- a/src/hwfeatures.c +++ b/src/hwfeatures.c @@ -44,10 +44,102 @@ _gcry_get_hw_features (void) static void detect_ia32_gnuc (void) { + int has_cpuid = 0; + char vendor_id[12+1]; + /* Detect the CPUID feature by testing some undefined behaviour (16 + vs 32 bit pushf/popf). */ + asm volatile + ("pushf\n\t" /* Copy flags to EAX. */ + "popl %%eax\n\t" + "movl %%eax, %%ecx\n\t" /* Save flags into ECX. */ + "xorl $0x200000, %%eax\n\t" /* Toggle ID bit and copy it to the flags. */ + "pushl %%eax\n\t" + "popf\n\t" + "pushf\n\t" /* Copy changed flags again to EAX. */ + "popl %%eax\n\t" + "pushl %%ecx\n\t" /* Restore flags from ECX. */ + "popf\n\t" + "xorl %%eax, %%ecx\n\t" /* Compare flags against saved flags. */ + "jz .Lno_cpuid%=\n\t" /* Toggling did not work, thus no CPUID. */ + "movl $1, %0\n" /* Worked. true -> HAS_CPUID. */ + ".Lno_cpuid%=:\n\t" + : "=r" (has_cpuid) + : + : "%eax", "%ecx", "cc" + ); + + if (!has_cpuid) + return; /* No way. */ + + asm volatile + ("pushl %%ebx\n\t" /* Save GOT register. */ + "xorl %%eax, %%eax\n\t" /* 0 -> EAX. */ + "cpuid\n\t" /* Get vendor ID. */ + "leal %0, %%eax\n\t" /* EBX,EDX,ECX -> VENDOR_ID. */ + "movl %%ebx, (%%eax)\n\t" + "movl %%edx, 4(%%eax)\n\t" + "movl %%ecx, 8(%%eax)\n\t" + "popl %%ebx\n" + : "=m" (vendor_id) + : + : "%eax", "%ecx", "%edx", "cc" + ); + vendor_id[12] = 0; + + /* Check whether this is a VIA CPU and what PadLock features we + have. */ + if (!strcmp (vendor_id, "CentaurHauls")) + { + asm volatile + ("pushl %%ebx\n\t" /* Save GOT register. */ + "movl $0xC0000000, %%eax\n\t" /* Check for extended centaur */ + "cpuid\n\t" /* feature flags. */ + "popl %%ebx\n\t" /* Restore GOT register. */ + "cmpl $0xC0000001, %%eax\n\t" + "jb .Lready%=\n\t" /* EAX < 0xC0000000 => no padlock. */ + + "pushl %%ebx\n\t" /* Save GOT register. */ + "movl $0xC0000001, %%eax\n\t" /* Ask for the extended */ + "cpuid\n\t" /* feature flags. */ + "popl %%ebx\n\t" /* Restore GOT register. */ + + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x0C, %%eax\n\t" /* Test bits 2 and 3 to see whether */ + "cmpl $0x0C, %%eax\n\t" /* the RNG exists and is enabled. */ + "jnz .Lno_rng%=\n\t" + "orl $1, %0\n" /* Set our HWF_PADLOCK_RNG bit. */ + + ".Lno_rng%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC0, %%eax\n\t" /* Test bits 6 and 7 to see whether */ + "cmpl $0xC0, %%eax\n\t" /* the ACE exists and is enabled. */ + "jnz .Lno_ace%=\n\t" + "orl $2, %0\n" /* Set our HWF_PADLOCK_AES bit. */ + ".Lno_ace%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0xC00, %%eax\n\t" /* Test bits 10, 11 to see whether */ + "cmpl $0xC00, %%eax\n\t" /* the PHE exists and is enabled. */ + "jnz .Lno_phe%=\n\t" + "orl $4, %0\n" /* Set our HWF_PADLOCK_SHA bit. */ + + ".Lno_phe%=:\n\t" + "movl %%edx, %%eax\n\t" /* Take copy of feature flags. */ + "andl $0x3000, %%eax\n\t" /* Test bits 12, 13 to see whether */ + "cmpl $0x3000, %%eax\n\t" /* MONTMUL exists and is enabled. */ + "jnz .Lready%=\n\t" + "orl $8, %0\n" /* Set our HWF_PADLOCK_MMUL bit. */ + + ".Lready%=:\n" + : "+r" (hw_features) + : + : "%eax", "%edx", "cc" + ); + } } + #endif /* __i386__ && SIZEOF_UNSIGNED_LONG == 4 && __GNUC__ */ @@ -58,6 +150,8 @@ detect_ia32_gnuc (void) void _gcry_detect_hw_features (void) { + hw_features = 0; + #if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 #ifdef __GNUC__ detect_ia32_gnuc (); |