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
This commit is contained in:
parent
d9c18e5627
commit
227f66048e
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user