From 92df0bda99adc2fcec6c8a8c15b49127117bb64b Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Mon, 12 Jan 2009 19:17:35 +0000 Subject: [PATCH] Add basic amd64 support for VIA Nano processors. --- sys/amd64/amd64/amd64_mem.c | 12 +++++- sys/amd64/amd64/identcpu.c | 76 +++++++++++++++++++++++++++++----- sys/amd64/amd64/initcpu.c | 75 +++++++++++++++++++++++++++++++++ sys/amd64/amd64/msi.c | 14 ++++++- sys/amd64/include/md_var.h | 2 + sys/amd64/include/specialreg.h | 36 ++++++++++++++++ 6 files changed, 200 insertions(+), 15 deletions(-) diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index 7f1f428801ce..2b5a73db2151 100644 --- a/sys/amd64/amd64/amd64_mem.c +++ b/sys/amd64/amd64/amd64_mem.c @@ -678,9 +678,17 @@ amd64_mem_drvinit(void *unused) return; if ((cpu_id & 0xf00) != 0x600 && (cpu_id & 0xf00) != 0xf00) return; - if (cpu_vendor_id != CPU_VENDOR_INTEL && - cpu_vendor_id != CPU_VENDOR_AMD) + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: + case CPU_VENDOR_AMD: + break; + case CPU_VENDOR_CENTAUR: + if (cpu_exthigh >= 0x80000008) + break; + /* FALLTHROUGH */ + default: return; + } mem_range_softc.mr_op = &amd64_mrops; } SYSINIT(amd64memdev, SI_SUB_DRIVERS, SI_ORDER_FIRST, amd64_mem_drvinit, NULL); diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index e7516cce835d..793c96fa4a5d 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -72,6 +72,7 @@ void panicifcpuunsupported(void); static u_int find_cpu_vendor_id(void); static void print_AMD_info(void); static void print_AMD_assoc(int i); +static void print_via_padlock_info(void); int cpu_class; char machine[] = "amd64"; @@ -132,24 +133,33 @@ printcpuinfo(void) } } - if (cpu_vendor_id == CPU_VENDOR_INTEL) { + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: /* Please make up your mind folks! */ strcat(cpu_model, "EM64T"); - } else if (cpu_vendor_id == CPU_VENDOR_AMD) { + break; + case CPU_VENDOR_AMD: /* * Values taken from AMD Processor Recognition * http://www.amd.com/K6/k6docs/pdf/20734g.pdf * (also describes ``Features'' encodings. */ strcpy(cpu_model, "AMD "); - switch (cpu_id & 0xF00) { - case 0xf00: + if ((cpu_id & 0xf00) == 0xf00) strcat(cpu_model, "AMD64 Processor"); - break; - default: + else strcat(cpu_model, "Unknown"); - break; - } + break; + case CPU_VENDOR_CENTAUR: + strcpy(cpu_model, "VIA "); + if ((cpu_id & 0xff0) == 0x6f0) + strcat(cpu_model, "Nano Processor"); + else + strcat(cpu_model, "Unknown"); + break; + default: + strcat(cpu_model, "Unknown"); + break; } /* @@ -181,7 +191,8 @@ printcpuinfo(void) printf(" Id = 0x%x", cpu_id); if (cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD) { + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_CENTAUR) { printf(" Stepping = %u", cpu_id & 0xf); if (cpu_high > 0) { u_int cmp = 1, htt = 1; @@ -353,6 +364,9 @@ printcpuinfo(void) ); } + if (cpu_vendor_id == CPU_VENDOR_CENTAUR) + print_via_padlock_info(); + if ((cpu_feature & CPUID_HTT) && cpu_vendor_id == CPU_VENDOR_AMD) cpu_feature &= ~CPUID_HTT; @@ -376,6 +390,11 @@ printcpuinfo(void) AMD64_CPU_MODEL(cpu_id) >= 0x3)) tsc_is_invariant = 1; break; + case CPU_VENDOR_CENTAUR: + if (AMD64_CPU_FAMILY(cpu_id) == 0x6 && + AMD64_CPU_MODEL(cpu_id) >= 0xf) + tsc_is_invariant = 1; + break; } if (tsc_is_invariant) printf("\n TSC: P-state invariant"); @@ -457,7 +476,7 @@ EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL, EVENTHANDLER_PRI_ANY); /* - * Final stage of CPU identification. -- Should I check TI? + * Final stage of CPU identification. */ void identify_cpu(void) @@ -479,7 +498,8 @@ identify_cpu(void) cpu_feature2 = regs[2]; if (cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD) { + cpu_vendor_id == CPU_VENDOR_AMD || + cpu_vendor_id == CPU_VENDOR_CENTAUR) { do_cpuid(0x80000000, regs); cpu_exthigh = regs[0]; } @@ -600,3 +620,37 @@ print_AMD_info(void) print_AMD_l2_assoc((regs[2] >> 12) & 0x0f); } } + +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; + + printf("\n VIA Padlock Features=0x%b", regs[3], + "\020" + "\003RNG" /* RNG */ + "\007AES" /* ACE */ + "\011AES-CTR" /* ACE2 */ + "\013SHA1,SHA256" /* PHE */ + "\015RSA" /* PMM */ + ); +} diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 23cf08220fd9..edf1a986e134 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -54,6 +54,8 @@ u_int cpu_feature2; /* Feature flags */ u_int amd_feature; /* AMD feature flags */ u_int amd_feature2; /* AMD feature flags */ u_int amd_pminfo; /* AMD advanced power management info */ +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 */ @@ -81,4 +152,8 @@ initializecpu(void) wrmsr(MSR_EFER, msr); pg_nx = PG_NX; } + if (cpu_vendor_id == CPU_VENDOR_CENTAUR && + AMD64_CPU_FAMILY(cpu_id) == 0x6 && + AMD64_CPU_MODEL(cpu_id) >= 0xf) + init_via(); } diff --git a/sys/amd64/amd64/msi.c b/sys/amd64/amd64/msi.c index f8d92d6ad4ee..0596c097e7a1 100644 --- a/sys/amd64/amd64/msi.c +++ b/sys/amd64/amd64/msi.c @@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include /* Fields in address for Intel MSI messages. */ @@ -212,9 +213,18 @@ msi_init(void) { /* Check if we have a supported CPU. */ - if (!(cpu_vendor_id == CPU_VENDOR_INTEL || - cpu_vendor_id == CPU_VENDOR_AMD)) + switch (cpu_vendor_id) { + case CPU_VENDOR_INTEL: + case CPU_VENDOR_AMD: + break; + case CPU_VENDOR_CENTAUR: + if (AMD64_CPU_FAMILY(cpu_id) == 0x6 && + AMD64_CPU_MODEL(cpu_id) >= 0xf) + break; + /* FALLTHROUGH */ + default: return; + } msi_enabled = 1; intr_register_pic(&msi_pic); diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index b0807b307654..2125b9fcfdd3 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -45,6 +45,8 @@ extern u_int cpu_feature2; extern u_int amd_feature; extern u_int amd_feature2; extern u_int amd_pminfo; +extern u_int via_feature_rng; +extern u_int via_feature_xcrypt; extern u_int cpu_fxsr; extern u_int cpu_high; extern u_int cpu_id; diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h index c08668c9ea65..eb2ff9b8f545 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -459,4 +459,40 @@ #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 + +/* VIA ACE xcrypt-* instruction context control options */ +#define VIA_CRYPT_CWLO_ROUND_M 0x0000000f +#define VIA_CRYPT_CWLO_ALG_M 0x00000070 +#define VIA_CRYPT_CWLO_ALG_AES 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_M 0x00000080 +#define VIA_CRYPT_CWLO_KEYGEN_HW 0x00000000 +#define VIA_CRYPT_CWLO_KEYGEN_SW 0x00000080 +#define VIA_CRYPT_CWLO_NORMAL 0x00000000 +#define VIA_CRYPT_CWLO_INTERMEDIATE 0x00000100 +#define VIA_CRYPT_CWLO_ENCRYPT 0x00000000 +#define VIA_CRYPT_CWLO_DECRYPT 0x00000200 +#define VIA_CRYPT_CWLO_KEY128 0x0000000a /* 128bit, 10 rds */ +#define VIA_CRYPT_CWLO_KEY192 0x0000040c /* 192bit, 12 rds */ +#define VIA_CRYPT_CWLO_KEY256 0x0000080e /* 256bit, 15 rds */ + #endif /* !_MACHINE_SPECIALREG_H_ */