diff options
author | Nathan Whitehorn <nwhitehorn@FreeBSD.org> | 2009-11-28 17:33:19 +0000 |
---|---|---|
committer | Nathan Whitehorn <nwhitehorn@FreeBSD.org> | 2009-11-28 17:33:19 +0000 |
commit | 227f66048ee60b65d4683e77d9746c7c6b89cf44 (patch) | |
tree | 5e1aecc143405242d9ce520741a856e42d351fda /sys/powerpc | |
parent | d9c18e56274beb0c8c989c2d0eb5d3b6562f9ec6 (diff) | |
download | src-227f66048ee60b65d4683e77d9746c7c6b89cf44.tar.gz src-227f66048ee60b65d4683e77d9746c7c6b89cf44.zip |
Add a CPU features framework on PowerPC and simplify CPU setup a little
more. This provides three new sysctls to user space:
hw.cpu_features - A bitmask of available CPU features
hw.floatingpoint - Whether or not there is hardware FP support
hw.altivec - Whether or not Altivec is available
PR: powerpc/139154
MFC after: 10 days
Notes
Notes:
svn path=/head/; revision=199886
Diffstat (limited to 'sys/powerpc')
-rw-r--r-- | sys/powerpc/aim/machdep.c | 9 | ||||
-rw-r--r-- | sys/powerpc/aim/ofw_machdep.c | 3 | ||||
-rw-r--r-- | sys/powerpc/booke/machdep.c | 1 | ||||
-rw-r--r-- | sys/powerpc/include/cpu.h | 21 | ||||
-rw-r--r-- | sys/powerpc/include/md_var.h | 1 | ||||
-rw-r--r-- | sys/powerpc/powerpc/cpu.c | 195 |
6 files changed, 131 insertions, 99 deletions
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 01272b45b6c2..7c365434a950 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -130,7 +130,6 @@ extern vm_offset_t ksym_start, ksym_end; int cold = 1; int cacheline_size = 32; -int ppc64 = 0; int hw_direct_map = 1; struct pcpu __pcpu[MAXCPU]; @@ -256,6 +255,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) char *env; uint32_t msr, scratch; uint8_t *cache_check; + int ppc64; end = 0; kmdp = NULL; @@ -405,12 +405,15 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) mfsprg2 %1;" : "=r"(scratch), "=r"(ppc64)); + if (ppc64) + cpu_features |= PPC_FEATURE_64; + /* * Now copy restorebridge into all the handlers, if necessary, * and set up the trap tables. */ - if (ppc64) { + if (cpu_features & PPC_FEATURE_64) { /* Patch the two instances of rfi -> rfid */ bcopy(&rfid_patch,&rfi_patch1,4); #ifdef KDB @@ -489,7 +492,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) * in case the platform module had a better idea of what we * should do. */ - if (ppc64) + if (cpu_features & PPC_FEATURE_64) pmap_mmu_install(MMU_TYPE_G5, BUS_PROBE_GENERIC); else pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC); diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c index 773d229d3a27..6e276970edd0 100644 --- a/sys/powerpc/aim/ofw_machdep.c +++ b/sys/powerpc/aim/ofw_machdep.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <vm/vm_page.h> #include <machine/bus.h> +#include <machine/cpu.h> #include <machine/md_var.h> #include <machine/platform.h> #include <machine/ofw_machdep.h> @@ -336,7 +337,7 @@ openfirmware(void *args) /* * Clear battable[] translations */ - if (!ppc64) { + if (!(cpu_features & PPC_FEATURE_64)) { __asm __volatile("mtdbatu 2, %0\n" "mtdbatu 3, %0" : : "r" (0)); } diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c index 1eace0e8e607..9f5960b6daad 100644 --- a/sys/powerpc/booke/machdep.c +++ b/sys/powerpc/booke/machdep.c @@ -179,7 +179,6 @@ SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, CTLFLAG_RD, &cacheline_size, 0, ""); int hw_direct_map = 0; -int ppc64 = 0; static void cpu_e500_startup(void *); SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL); diff --git a/sys/powerpc/include/cpu.h b/sys/powerpc/include/cpu.h index 9856ab0588ef..16cabe7887ca 100644 --- a/sys/powerpc/include/cpu.h +++ b/sys/powerpc/include/cpu.h @@ -39,6 +39,27 @@ #include <machine/pcb.h> #include <machine/psl.h> +/* + * CPU Feature Attributes + * + * These are defined in the PowerPC ELF ABI for the AT_HWCAP vector, + * and are exported to userland via the machdep.cpu_features + * sysctl. + */ + +extern int cpu_features; + +#define PPC_FEATURE_32 0x80000000 /* Always true */ +#define PPC_FEATURE_64 0x40000000 /* Defined on a 64-bit CPU */ +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 + +#define PPC_FEATURE_BITMASK \ + "\20" \ + "\040PPC32\037PPC64\035ALTIVEC\034FPU\033MMU\031UNIFIEDCACHE" + #define TRAPF_USERMODE(frame) (((frame)->srr1 & PSL_PR) != 0) #define TRAPF_PC(frame) ((frame)->srr0) diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h index d1785adfbe0f..bfe5ed238291 100644 --- a/sys/powerpc/include/md_var.h +++ b/sys/powerpc/include/md_var.h @@ -46,7 +46,6 @@ extern u_long ns_per_tick; extern int powerpc_pow_enabled; extern int cacheline_size; -extern int ppc64; extern int hw_direct_map; void __syncicache(void *, int); diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c index 61630a4c3c8f..ebf36ee161b9 100644 --- a/sys/powerpc/powerpc/cpu.c +++ b/sys/powerpc/powerpc/cpu.c @@ -67,6 +67,7 @@ #include <sys/sysctl.h> #include <machine/bus.h> +#include <machine/cpu.h> #include <machine/hid.h> #include <machine/md_var.h> #include <machine/smp.h> @@ -74,59 +75,102 @@ int powerpc_pow_enabled; +static void cpu_6xx_setup(int cpuid, uint16_t vers); +static void cpu_e500_setup(int cpuid, uint16_t vers); +static void cpu_970_setup(int cpuid, uint16_t vers); + struct cputab { const char *name; uint16_t version; uint16_t revfmt; + int features; /* Do not include PPC_FEATURE_32 or + * PPC_FEATURE_HAS_MMU */ + void (*cpu_setup)(int cpuid, uint16_t vers); }; #define REVFMT_MAJMIN 1 /* %u.%u */ #define REVFMT_HEX 2 /* 0x%04x */ #define REVFMT_DEC 3 /* %u */ static const struct cputab models[] = { - { "Motorola PowerPC 601", MPC601, REVFMT_DEC }, - { "Motorola PowerPC 602", MPC602, REVFMT_DEC }, - { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN }, - { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN }, - { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN }, - { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN }, - { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN }, - { "Motorola PowerPC 620", MPC620, REVFMT_HEX }, - { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN }, - { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN }, - { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN }, - { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN }, - { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN }, - { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN }, - { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN }, - { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN }, - { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN }, - { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN }, - { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN }, - { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN }, - { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN }, - { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN }, - { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN }, - { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN }, - { "Unknown PowerPC CPU", 0, REVFMT_HEX } + { "Motorola PowerPC 601", MPC601, REVFMT_DEC, + PPC_FEATURE_HAS_FPU | PPC_FEATURE_UNIFIED_CACHE, cpu_6xx_setup }, + { "Motorola PowerPC 602", MPC602, REVFMT_DEC, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 603", MPC603, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 603e", MPC603e, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 603ev", MPC603ev, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 604", MPC604, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 604ev", MPC604ev, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 620", MPC620, REVFMT_HEX, + PPC_FEATURE_64 | PPC_FEATURE_HAS_FPU, NULL }, + { "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN, + PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, + cpu_970_setup }, + { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN, + PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, + cpu_970_setup }, + { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN, + PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, + cpu_970_setup }, + { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN, + PPC_FEATURE_64 | PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, + cpu_970_setup }, + { "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7455", MPC7455, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7457", MPC7457, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7447A", MPC7447A, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 7448", MPC7448, REVFMT_MAJMIN, + PPC_FEATURE_HAS_ALTIVEC | PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 8240", MPC8240, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Motorola PowerPC 8245", MPC8245, REVFMT_MAJMIN, + PPC_FEATURE_HAS_FPU, cpu_6xx_setup }, + { "Freescale e500v1 core", FSL_E500v1, REVFMT_MAJMIN, + 0, cpu_e500_setup }, + { "Freescale e500v2 core", FSL_E500v2, REVFMT_MAJMIN, + 0, cpu_e500_setup }, + { "Unknown PowerPC CPU", 0, REVFMT_HEX, 0, NULL }, }; +static void cpu_6xx_print_cacheinfo(u_int, uint16_t); +static int cpu_feature_bit(SYSCTL_HANDLER_ARGS); + static char model[64]; SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); -static void cpu_print_speed(void); +int cpu_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU; +SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLTYPE_INT | CTLFLAG_RD, + &cpu_features, sizeof(cpu_features), "IX", "PowerPC CPU features"); -static void cpu_6xx_setup(int cpuid, uint16_t vers); -static void cpu_6xx_print_cacheinfo(u_int, uint16_t); -static void cpu_e500_setup(int cpuid, uint16_t vers); -#ifndef E500 -static void cpu_970_setup(int cpuid, uint16_t vers); -#endif +/* Provide some user-friendly aliases for bits in cpu_features */ +SYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD, + 0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I", + "Floating point instructions executed in hardware"); +SYSCTL_PROC(_hw, OID_AUTO, altivec, CTLTYPE_INT | CTLFLAG_RD, + 0, PPC_FEATURE_HAS_ALTIVEC, cpu_feature_bit, "I", "CPU supports Altivec"); void cpu_setup(u_int cpuid) { u_int pvr, maj, min; uint16_t vers, rev, revfmt; + uint64_t cps; const struct cputab *cp; const char *name; @@ -175,57 +219,19 @@ cpu_setup(u_int cpuid) break; } + if (cpu_est_clockrate(0, &cps) == 0) + printf(", %lld.%02lld MHz", cps / 1000000, (cps / 10000) % 100); + printf("\n"); + + cpu_features |= cp->features; + printf("cpu%d: Features %b\n", cpuid, cpu_features, + PPC_FEATURE_BITMASK); + /* * Configure CPU */ - switch (vers) { - case MPC603: - case MPC603e: - case MPC603ev: - case MPC604ev: - case MPC750: - case IBM750FX: - case MPC7400: - case MPC7410: - case MPC7447A: - case MPC7448: - case MPC7450: - case MPC7455: - case MPC7457: - case MPC8240: - case MPC8245: - cpu_6xx_setup(cpuid, vers); - break; - -#ifndef E500 - case IBM970: - case IBM970FX: - case IBM970GX: - case IBM970MP: - cpu_970_setup(cpuid, vers); - break; -#endif - - case FSL_E500v1: - case FSL_E500v2: - cpu_e500_setup(cpuid, vers); - break; - - default: - /* HID setup is unknown */ - break; - } - - printf("\n"); -} - -void -cpu_print_speed(void) -{ - uint64_t cps; - - if (cpu_est_clockrate(0, &cps) == 0) - printf(", %lld.%02lld MHz", cps / 1000000, (cps / 10000) % 100); + if (cp->cpu_setup != NULL) + cp->cpu_setup(cpuid, vers); } /* Get current clock frequency for the given cpu id. */ @@ -351,9 +357,6 @@ cpu_6xx_setup(int cpuid, uint16_t vers) mtspr(SPR_HID0, hid0); - cpu_print_speed(); - printf("\n"); - if (bootverbose) cpu_6xx_print_cacheinfo(cpuid, vers); @@ -370,7 +373,7 @@ cpu_6xx_setup(int cpuid, uint16_t vers) break; } - printf("cpu%d: HID0 %b", cpuid, (int)hid0, bitmask); + printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); } @@ -429,16 +432,14 @@ cpu_e500_setup(int cpuid, uint16_t vers) { register_t hid0; - printf("\n"); - hid0 = mfspr(SPR_HID0); - printf("cpu%d: HID0 %b", cpuid, (int)hid0, HID0_E500_BITMASK); + printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); } -#ifndef E500 static void cpu_970_setup(int cpuid, uint16_t vers) { +#ifdef AIM uint32_t hid0_hi, hid0_lo; __asm __volatile ("mfspr %0,%2; clrldi %1,%0,32; srdi %0,%0,32;" @@ -458,11 +459,19 @@ cpu_970_setup(int cpuid, uint16_t vers) sync; isync" :: "r" (hid0_hi), "r"(hid0_lo), "K" (SPR_HID0)); - cpu_print_speed(); - printf("\n"); - __asm __volatile ("mfspr %0,%1; srdi %0,%0,32;" : "=r" (hid0_hi) : "K" (SPR_HID0)); - printf("cpu%d: HID0 %b", cpuid, (int)(hid0_hi), HID0_970_BITMASK); -} + printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); #endif +} + +static int +cpu_feature_bit(SYSCTL_HANDLER_ARGS) +{ + int result; + + result = (cpu_features & arg2) ? 1 : 0; + + return (sysctl_handle_int(oidp, &result, 0, req)); +} + |