diff --git a/sys/arch/arm/arm/cpufunc.c b/sys/arch/arm/arm/cpufunc.c index fb0beb7734b0..01b931113886 100644 --- a/sys/arch/arm/arm/cpufunc.c +++ b/sys/arch/arm/arm/cpufunc.c @@ -1,4 +1,4 @@ -/* $NetBSD: cpufunc.c,v 1.18 2001/11/26 22:26:44 thorpej Exp $ */ +/* $NetBSD: cpufunc.c,v 1.19 2001/11/29 02:24:58 thorpej Exp $ */ /* * arm7tdmi support code Copyright (c) 2001 John Fremlin @@ -58,6 +58,21 @@ #include +/* PRIMARY CACHE VARIABLES */ +int arm_picache_size; +int arm_picache_line_size; +int arm_picache_ways; + +int arm_pdcache_size; /* and unified */ +int arm_pdcache_line_size; +int arm_pdcache_ways; + +int arm_pcache_type; +int arm_pcache_unified; + +int arm_dcache_align; +int arm_dcache_align_mask; + #ifdef CPU_ARM3 struct cpu_functions arm3_cpufuncs = { /* CPU functions */ @@ -703,6 +718,70 @@ struct cpu_functions cpufuncs; u_int cputype; u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ +static void +get_cachetype() +{ + u_int ctype, isize, dsize; + u_int multiplier; + + __asm __volatile("mrc p15, 0, %0, c0, c0, 1" + : "=r" (ctype)); + + /* + * ...and thus spake the ARM ARM: + * + * If an value corresponding to an unimplemented or + * reserved ID register is encountered, the System Control + * processor returns the value of the main ID register. + */ + if (ctype == cpufunc_id()) + goto out; + + if ((ctype & CPU_CT_S) == 0) + arm_pcache_unified = 1; + + /* + * If you want to know how this code works, go read the ARM ARM. + */ + + arm_pcache_type = CPU_CT_CTYPE(ctype); + + if (arm_pcache_unified == 0) { + isize = CPU_CT_ISIZE(ctype); + multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; + arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); + if (CPU_CT_xSIZE_ASSOC(isize) == 0) { + if (isize & CPU_CT_xSIZE_M) + arm_picache_line_size = 0; /* not present */ + else + arm_picache_ways = 1; + } else { + arm_picache_ways = multiplier << + (CPU_CT_xSIZE_ASSOC(isize) - 1); + } + arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); + } + + dsize = CPU_CT_DSIZE(ctype); + multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; + arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); + if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { + if (dsize & CPU_CT_xSIZE_M) + arm_pdcache_line_size = 0; /* not present */ + else + arm_pdcache_ways = 0; + } else { + arm_pdcache_ways = multiplier << + (CPU_CT_xSIZE_ASSOC(dsize) - 1); + } + arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); + + arm_dcache_align = arm_pdcache_line_size; + + out: + arm_dcache_align_mask = arm_dcache_align - 1; +} + /* * Cannot panic here as we may not have a console yet ... */ @@ -719,6 +798,8 @@ set_cpufuncs() (cputype & 0x00000f00) == 0x00000300) { cpufuncs = arm3_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; + /* XXX Cache info? */ + arm_dcache_align_mask = -1; return 0; } #endif /* CPU_ARM3 */ @@ -727,6 +808,8 @@ set_cpufuncs() (cputype & 0x00000f00) == 0x00000600) { cpufuncs = arm6_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; + /* XXX Cache info? */ + arm_dcache_align_mask = -1; return 0; } #endif /* CPU_ARM6 */ @@ -736,6 +819,8 @@ set_cpufuncs() (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V3) { cpufuncs = arm7_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; + /* XXX Cache info? */ + arm_dcache_align_mask = -1; return 0; } #endif /* CPU_ARM7 */ @@ -745,6 +830,7 @@ set_cpufuncs() (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) { cpufuncs = arm7tdmi_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; + get_cachetype(); return 0; } #endif @@ -753,6 +839,7 @@ set_cpufuncs() (cputype & 0x0000f000) == 0x00008000) { cpufuncs = arm8_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */ + get_cachetype(); return 0; } #endif /* CPU_ARM8 */ @@ -761,6 +848,7 @@ set_cpufuncs() pte_cache_mode = PT_C; /* Select write-through cacheing. */ cpufuncs = arm9_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ + get_cachetype(); return 0; } #endif /* CPU_ARM9 */ @@ -769,6 +857,7 @@ set_cpufuncs() cputype == CPU_ID_SA1110) { cpufuncs = sa110_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ + get_cachetype(); return 0; } #endif /* CPU_SA110 */ @@ -777,6 +866,7 @@ set_cpufuncs() pte_cache_mode = PT_C; /* Select write-through cacheing. */ cpufuncs = xscale_writethrough_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ + get_cachetype(); return 0; } #endif /* CPU_XSCALE */ diff --git a/sys/arch/arm/arm32/cpu.c b/sys/arch/arm/arm32/cpu.c index f6821ff96c4f..2a4ceb7eb3f0 100644 --- a/sys/arch/arm/arm32/cpu.c +++ b/sys/arch/arm/arm32/cpu.c @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.11 2001/11/24 01:26:24 thorpej Exp $ */ +/* $NetBSD: cpu.c,v 1.12 2001/11/29 02:24:58 thorpej Exp $ */ /* * Copyright (c) 1995 Mark Brinicombe. @@ -311,6 +311,25 @@ const struct cpu_classtab cpu_classes[] = { * The remaining fields in the cpu structure are filled in appropriately. */ +static const char *wtnames[] = { + "write-through", + "write-back", + "write-back", + "**unknown 3**", + "**unknown 4**", + "write-back-locking", /* XXX XScale-specific? */ + "write-back-locking-A", + "write-back-locking-B", + "**unknown 8**", + "**unknown 9**", + "**unknown 10**", + "**unknown 11**", + "**unknown 12**", + "**unknown 13**", + "**unknown 14**", + "**unknown 15**", +}; + void identify_arm_cpu(dv, cpu_number) struct device *dv; @@ -377,9 +396,29 @@ identify_arm_cpu(dv, cpu_number) strcat(cpu->cpu_model, " branch prediction enabled"); /* Print the info */ - printf(": %s\n", cpu->cpu_model); + /* Print cache info. */ + if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) + goto skip_pcache; + + if (arm_pcache_unified) { + printf("%s: %dKB/%dB %d-way %s unified cache\n", + dv->dv_xname, arm_pdcache_size / 1024, + arm_pdcache_line_size, arm_pdcache_ways, + wtnames[arm_pcache_type]); + } else { + printf("%s: %dKB/%dB %d-way Instruction cache\n", + dv->dv_xname, arm_picache_size / 1024, + arm_picache_line_size, arm_picache_ways); + printf("%s: %dKB/%dB %d-way %s Data cache\n", + dv->dv_xname, arm_pdcache_size / 1024, + arm_pdcache_line_size, arm_pdcache_ways, + wtnames[arm_pcache_type]); + } + + skip_pcache: + switch (cpu->cpu_class) { #ifdef CPU_ARM2 case CPU_CLASS_ARM2: diff --git a/sys/arch/arm/include/armreg.h b/sys/arch/arm/include/armreg.h index 8fef25c9e550..71547cd3567b 100644 --- a/sys/arch/arm/include/armreg.h +++ b/sys/arch/arm/include/armreg.h @@ -1,4 +1,4 @@ -/* $NetBSD: armreg.h,v 1.8 2001/07/18 16:31:17 rjs Exp $ */ +/* $NetBSD: armreg.h,v 1.9 2001/11/29 02:24:59 thorpej Exp $ */ /* * Copyright (c) 1998, 2001 Ben Harris @@ -224,17 +224,21 @@ #define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE /* Cache type register definitions */ -#define CPU_CT_IINFO_MASK 0x00000fff -#define CPU_CT_IINFO_SHIFT 0 -#define CPU_CT_DINFO_MASK 0x00fff000 -#define CPU_CT_DINFO_SHIFT 12 -#define CPU_CT_HARVARD 0x01000000 -#define CPU_CT_TYPE_MASK 0x1e000000 -/* "Info" subfields -- see ARM ARM for meanings. */ -#define CPU_CT_LINE_MASK 0x00000003 -#define CPU_CT_M_BIT 0x00000004 -#define CPU_CT_ASSOC_MASK 0x00000038 -#define CPU_CT_SIZE_MASK 0x000001c0 +#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */ +#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */ +#define CPU_CT_S (1U << 24) /* split cache */ +#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */ + +#define CPU_CT_CTYPE_WT 0 /* write-through */ +#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */ +#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */ +#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */ +#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */ + +#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */ +#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */ +#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */ +#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */ /* Fault status register definitions */ diff --git a/sys/arch/arm/include/cpufunc.h b/sys/arch/arm/include/cpufunc.h index a9ab15222b47..a720ba21680b 100644 --- a/sys/arch/arm/include/cpufunc.h +++ b/sys/arch/arm/include/cpufunc.h @@ -1,4 +1,4 @@ -/* $NetBSD: cpufunc.h,v 1.13 2001/11/28 00:18:46 thorpej Exp $ */ +/* $NetBSD: cpufunc.h,v 1.14 2001/11/29 02:24:59 thorpej Exp $ */ /* * Copyright (c) 1997 Mark Brinicombe. @@ -396,6 +396,25 @@ int get_pc_str_offset __P((void)); void cpu_reset __P((void)) __attribute__((__noreturn__)); +/* + * Cache info variables. + */ + +/* PRIMARY CACHE VARIABLES */ +int arm_picache_size; +int arm_picache_line_size; +int arm_picache_ways; + +int arm_pdcache_size; /* and unified */ +int arm_pdcache_line_size; +int arm_pdcache_ways; + +int arm_pcache_type; +int arm_pcache_unified; + +int arm_dcache_align; +int arm_dcache_align_mask; + #endif /* _KERNEL */ #endif /* _ARM32_CPUFUNC_H_ */