VIA CPU support: Detect and enable CPU features (RNG, ACE etc.).
authorSascha Wildner <saw@online.de>
Sat, 5 Sep 2009 06:36:27 +0000 (08:36 +0200)
committerAlex Hornung <ahornung@gmail.com>
Fri, 2 Oct 2009 15:17:24 +0000 (16:17 +0100)
Taken from: FreeBSD

sys/cpu/amd64/include/specialreg.h
sys/cpu/i386/include/specialreg.h
sys/platform/pc32/i386/identcpu.c
sys/platform/pc32/i386/initcpu.c
sys/platform/pc64/amd64/initcpu.c

index 757c5bb..0a4be7b 100644 (file)
 #define        MSR_TOP_MEM2    0xc001001d      /* boundary for ram above 4G */
 #define        MSR_K8_UCODE_UPDATE     0xc0010020      /* update microcode */
 
+/* VIA ACE crypto featureset: for via_feature_rng */
+#define        VIA_HAS_RNG             1       /* cpu has RNG */
+
+/* VIA ACE crypto featureset: for via_feature_xcrypt */
+#define        VIA_HAS_AES             1       /* cpu has AES */
+#define        VIA_HAS_SHA             2       /* cpu has SHA1 & SHA256 */
+#define        VIA_HAS_MM              4       /* cpu has RSA instructions */
+#define        VIA_HAS_AESCTR          8       /* cpu has AES-CTR instructions */
+
+/* Centaur Extended Feature flags */
+#define        VIA_CPUID_HAS_RNG       0x000004
+#define        VIA_CPUID_DO_RNG        0x000008
+#define        VIA_CPUID_HAS_ACE       0x000040
+#define        VIA_CPUID_DO_ACE        0x000080
+#define        VIA_CPUID_HAS_ACE2      0x000100
+#define        VIA_CPUID_DO_ACE2       0x000200
+#define        VIA_CPUID_HAS_PHE       0x000400
+#define        VIA_CPUID_DO_PHE        0x000800
+#define        VIA_CPUID_HAS_PMM       0x001000
+#define        VIA_CPUID_DO_PMM        0x002000
+
 #endif /* !_CPU_SPECIALREG_H_ */
index e0207ec..b9301ce 100644 (file)
 #define        AMD_WT_ALLOC_PRE        0x20000 /* programmable range enable */
 #define        AMD_WT_ALLOC_FRE        0x10000 /* fixed (A0000-FFFFF) range enable */
 
+/* VIA ACE crypto featureset: for via_feature_rng */
+#define        VIA_HAS_RNG             1       /* cpu has RNG */
+
+/* VIA ACE crypto featureset: for via_feature_xcrypt */
+#define        VIA_HAS_AES             1       /* cpu has AES */
+#define        VIA_HAS_SHA             2       /* cpu has SHA1 & SHA256 */
+#define        VIA_HAS_MM              4       /* cpu has RSA instructions */
+#define        VIA_HAS_AESCTR          8       /* cpu has AES-CTR instructions */
+
+/* Centaur Extended Feature flags */
+#define        VIA_CPUID_HAS_RNG       0x000004
+#define        VIA_CPUID_DO_RNG        0x000008
+#define        VIA_CPUID_HAS_ACE       0x000040
+#define        VIA_CPUID_DO_ACE        0x000080
+#define        VIA_CPUID_HAS_ACE2      0x000100
+#define        VIA_CPUID_DO_ACE2       0x000200
+#define        VIA_CPUID_HAS_PHE       0x000400
+#define        VIA_CPUID_DO_PHE        0x000800
+#define        VIA_CPUID_HAS_PMM       0x001000
+#define        VIA_CPUID_DO_PMM        0x002000
+
 #ifndef LOCORE
 
 #ifndef _SYS_TYPES_H_
index 4120c4c..45d0531 100644 (file)
@@ -80,6 +80,7 @@ static void print_AMD_features(void);
 static void print_AMD_info(void);
 static void print_AMD_assoc(int i);
 static void print_transmeta_info(void);
+static void print_via_padlock_info(void);
 static void setup_tmx86_longrun(void);
 static void print_via_padlock_info(void);
 
@@ -725,6 +726,9 @@ printcpuinfo(void)
                        if (strcmp(cpu_vendor, "CentaurHauls") == 0)
                                print_via_padlock_info();
 
+                       if (strcmp(cpu_vendor, "CentaurHauls") == 0)
+                               print_via_padlock_info();
+
                        /*
                         * If this CPU supports hyperthreading then mention
                         * the number of logical CPU's it contains.
@@ -1418,6 +1422,40 @@ print_transmeta_info(void)
               crusoe_frequency, crusoe_voltage, crusoe_percentage);
 }
 
+static void
+print_via_padlock_info(void)
+{
+       u_int regs[4];
+
+       /* Check for supported models. */
+       switch (cpu_id & 0xff0) {
+       case 0x690:
+               if ((cpu_id & 0xf) < 3)
+                       return;
+       case 0x6a0:
+       case 0x6d0:
+       case 0x6f0:
+               break;
+       default:
+               return;
+       }
+
+       do_cpuid(0xc0000000, regs);
+       if (regs[0] >= 0xc0000001)
+               do_cpuid(0xc0000001, regs);
+       else
+               return;
+
+       kprintf("\n  VIA Padlock Features=0x%b", regs[3],
+       "\020"
+       "\003RNG"               /* RNG */
+       "\007AES"               /* ACE */
+       "\011AES-CTR"           /* ACE2 */
+       "\013SHA1,SHA256"       /* PHE */
+       "\015RSA"               /* PMM */
+       );
+}
+
 void
 additional_cpu_info(const char *line)
 {
index bfc387f..7ddc65f 100644 (file)
@@ -69,6 +69,14 @@ static int   hw_instruction_sse;
 SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD,
     &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU");
 
+u_int  via_feature_rng = 0;    /* VIA RNG features */
+u_int  via_feature_xcrypt = 0; /* VIA ACE features */
+
+SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
+       &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU");
+SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD,
+       &via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU");
+
 #ifndef CPU_DISABLE_SSE
 u_int  cpu_fxsr;               /* SSE enabled */
 #endif
@@ -495,6 +503,70 @@ init_mendocino(void)
 #endif /* CPU_PPRO2CELERON */
 }
 
+/*
+ * Initialize special VIA C3/C7 features
+ */
+static void
+init_via(void)
+{
+       u_int regs[4], val;
+       u_int64_t msreg;
+
+       do_cpuid(0xc0000000, regs);
+       val = regs[0];
+       if (val >= 0xc0000001) {
+               do_cpuid(0xc0000001, regs);
+               val = regs[3];
+       } else
+               val = 0;
+
+       /* Enable RNG if present and disabled */
+       if (val & VIA_CPUID_HAS_RNG) {
+               if (!(val & VIA_CPUID_DO_RNG)) {
+                       msreg = rdmsr(0x110B);
+                       msreg |= 0x40;
+                       wrmsr(0x110B, msreg);
+               }
+               via_feature_rng = VIA_HAS_RNG;
+       }
+       /* Enable AES engine if present and disabled */
+       if (val & VIA_CPUID_HAS_ACE) {
+               if (!(val & VIA_CPUID_DO_ACE)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_AES;
+       }
+       /* Enable ACE2 engine if present and disabled */
+       if (val & VIA_CPUID_HAS_ACE2) {
+               if (!(val & VIA_CPUID_DO_ACE2)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_AESCTR;
+       }
+       /* Enable SHA engine if present and disabled */
+       if (val & VIA_CPUID_HAS_PHE) {
+               if (!(val & VIA_CPUID_DO_PHE)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28/**/);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_SHA;
+       }
+       /* Enable MM engine if present and disabled */
+       if (val & VIA_CPUID_HAS_PMM) {
+               if (!(val & VIA_CPUID_DO_PMM)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28/**/);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_MM;
+       }
+}
+
 #endif /* I686_CPU */
 
 /*
@@ -608,6 +680,20 @@ initializecpu(void)
                        }
                } else if (strcmp(cpu_vendor, "AuthenticAMD") == 0) {
                        init_686_amd();
+               } else if (strcmp(cpu_vendor, "CentaurHauls") == 0) {
+                       switch (cpu_id & 0xff0) {
+                       case 0x690:
+                               if ((cpu_id & 0xf) < 3)
+                                       break;
+                               /* fall through. */
+                       case 0x6a0:
+                       case 0x6d0:
+                       case 0x6f0:
+                               init_via();
+                               break;
+                       default:
+                               break;
+                       }
                }
                break;
 #endif
index 8c6771a..11f4b89 100644 (file)
@@ -54,6 +54,8 @@ u_int cpu_feature;            /* Feature flags */
 u_int  cpu_feature2;           /* Feature flags */
 u_int  amd_feature;            /* AMD feature flags */
 u_int  amd_feature2;           /* AMD feature flags */
+u_int  via_feature_rng;        /* VIA RNG features */
+u_int  via_feature_xcrypt;     /* VIA ACE features */
 u_int  cpu_high;               /* Highest arg to CPUID */
 u_int  cpu_exthigh;            /* Highest arg to extended CPUID */
 u_int  cpu_id;                 /* Stepping ID */
@@ -64,6 +66,75 @@ u_int        cpu_vendor_id;          /* CPU vendor ID */
 u_int  cpu_fxsr;               /* SSE enabled */
 u_int  cpu_mxcsr_mask;         /* Valid bits in mxcsr */
 
+SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
+       &via_feature_rng, 0, "VIA C3/C7 RNG feature available in CPU");
+SYSCTL_UINT(_hw, OID_AUTO, via_feature_xcrypt, CTLFLAG_RD,
+       &via_feature_xcrypt, 0, "VIA C3/C7 xcrypt feature available in CPU");
+
+/*
+ * Initialize special VIA C3/C7 features
+ */
+static void
+init_via(void)
+{
+       u_int regs[4], val;
+       u_int64_t msreg;
+
+       do_cpuid(0xc0000000, regs);
+       val = regs[0];
+       if (val >= 0xc0000001) {
+               do_cpuid(0xc0000001, regs);
+               val = regs[3];
+       } else
+               val = 0;
+
+       /* Enable RNG if present and disabled */
+       if (val & VIA_CPUID_HAS_RNG) {
+               if (!(val & VIA_CPUID_DO_RNG)) {
+                       msreg = rdmsr(0x110B);
+                       msreg |= 0x40;
+                       wrmsr(0x110B, msreg);
+               }
+               via_feature_rng = VIA_HAS_RNG;
+       }
+       /* Enable AES engine if present and disabled */
+       if (val & VIA_CPUID_HAS_ACE) {
+               if (!(val & VIA_CPUID_DO_ACE)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_AES;
+       }
+       /* Enable ACE2 engine if present and disabled */
+       if (val & VIA_CPUID_HAS_ACE2) {
+               if (!(val & VIA_CPUID_DO_ACE2)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_AESCTR;
+       }
+       /* Enable SHA engine if present and disabled */
+       if (val & VIA_CPUID_HAS_PHE) {
+               if (!(val & VIA_CPUID_DO_PHE)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28/**/);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_SHA;
+       }
+       /* Enable MM engine if present and disabled */
+       if (val & VIA_CPUID_HAS_PMM) {
+               if (!(val & VIA_CPUID_DO_PMM)) {
+                       msreg = rdmsr(0x1107);
+                       msreg |= (0x01 << 28/**/);
+                       wrmsr(0x1107, msreg);
+               }
+               via_feature_xcrypt |= VIA_HAS_MM;
+       }
+}
+
 /*
  * Initialize CPU control registers
  */
@@ -83,4 +154,8 @@ initializecpu(void)
                pg_nx = PG_NX;
 #endif
        }
+       if (cpu_vendor_id == CPU_VENDOR_CENTAUR &&
+           AMD64_CPU_FAMILY(cpu_id) == 0x6 &&
+           AMD64_CPU_MODEL(cpu_id) >= 0xf)
+               init_via();
 }