diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 4354f0a6e403..2f4c3a1f58a9 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -1,2295 +1,2296 @@ /* $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */ /*- * arm7tdmi support code Copyright (c) 2001 John Fremlin * arm8 support code Copyright (c) 1997 ARM Limited * arm8 support code Copyright (c) 1997 Causality Limited * arm9 support code Copyright (C) 2001 ARM Ltd * Copyright (c) 1997 Mark Brinicombe. * Copyright (c) 1997 Causality Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Causality Limited. * 4. The name of Causality Limited may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * RiscBSD kernel project * * cpufuncs.c * * C functions for supporting CPU / MMU / TLB specific operations. * * Created : 30/01/97 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CPU_XSCALE_80200 #include #include #endif #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) #include #include #endif #if defined(CPU_XSCALE_81342) #include #endif #ifdef CPU_XSCALE_IXP425 #include #include #endif /* 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; /* 1 == use cpu_sleep(), 0 == don't */ int cpu_do_powersave; int ctrl; #ifdef CPU_ARM7TDMI struct cpu_functions arm7tdmi_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* domain */ arm7tdmi_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ arm7tdmi_tlb_flushID, /* tlb_flushID */ arm7tdmi_tlb_flushID_SE, /* tlb_flushID_SE */ arm7tdmi_tlb_flushID, /* tlb_flushI */ arm7tdmi_tlb_flushID_SE, /* tlb_flushI_SE */ arm7tdmi_tlb_flushID, /* tlb_flushD */ arm7tdmi_tlb_flushID_SE, /* tlb_flushD_SE */ /* Cache operations */ cpufunc_nullop, /* icache_sync_all */ (void *)cpufunc_nullop, /* icache_sync_range */ arm7tdmi_cache_flushID, /* dcache_wbinv_all */ (void *)arm7tdmi_cache_flushID, /* dcache_wbinv_range */ (void *)arm7tdmi_cache_flushID, /* dcache_inv_range */ (void *)cpufunc_nullop, /* dcache_wb_range */ arm7tdmi_cache_flushID, /* idcache_wbinv_all */ (void *)arm7tdmi_cache_flushID, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ cpufunc_nullop, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ late_abort_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm7tdmi_context_switch, /* context_switch */ arm7tdmi_setup /* cpu setup */ }; #endif /* CPU_ARM7TDMI */ #ifdef CPU_ARM8 struct cpu_functions arm8_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* domain */ arm8_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ arm8_tlb_flushID, /* tlb_flushID */ arm8_tlb_flushID_SE, /* tlb_flushID_SE */ arm8_tlb_flushID, /* tlb_flushI */ arm8_tlb_flushID_SE, /* tlb_flushI_SE */ arm8_tlb_flushID, /* tlb_flushD */ arm8_tlb_flushID_SE, /* tlb_flushD_SE */ /* Cache operations */ cpufunc_nullop, /* icache_sync_all */ (void *)cpufunc_nullop, /* icache_sync_range */ arm8_cache_purgeID, /* dcache_wbinv_all */ (void *)arm8_cache_purgeID, /* dcache_wbinv_range */ /*XXX*/ (void *)arm8_cache_purgeID, /* dcache_inv_range */ (void *)arm8_cache_cleanID, /* dcache_wb_range */ arm8_cache_purgeID, /* idcache_wbinv_all */ (void *)arm8_cache_purgeID, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ cpufunc_nullop, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm8_context_switch, /* context_switch */ arm8_setup /* cpu setup */ }; #endif /* CPU_ARM8 */ #ifdef CPU_ARM9 struct cpu_functions arm9_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* Domain */ arm9_setttb, /* Setttb */ cpufunc_faultstatus, /* Faultstatus */ cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ arm9_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ arm9_icache_sync_all, /* icache_sync_all */ arm9_icache_sync_range, /* icache_sync_range */ arm9_dcache_wbinv_all, /* dcache_wbinv_all */ arm9_dcache_wbinv_range, /* dcache_wbinv_range */ arm9_dcache_inv_range, /* dcache_inv_range */ arm9_dcache_wb_range, /* dcache_wb_range */ arm9_idcache_wbinv_all, /* idcache_wbinv_all */ arm9_idcache_wbinv_range, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm9_context_switch, /* context_switch */ arm9_setup /* cpu setup */ }; #endif /* CPU_ARM9 */ #if defined(CPU_ARM9E) || defined(CPU_ARM10) struct cpu_functions armv5_ec_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* Domain */ armv5_ec_setttb, /* Setttb */ cpufunc_faultstatus, /* Faultstatus */ cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ arm10_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ arm10_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ armv5_ec_dcache_wbinv_range, /* dcache_wbinv_range */ armv5_ec_dcache_inv_range, /* dcache_inv_range */ armv5_ec_dcache_wb_range, /* dcache_wb_range */ armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ armv5_ec_idcache_wbinv_range, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm10_context_switch, /* context_switch */ arm10_setup /* cpu setup */ }; struct cpu_functions sheeva_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* Domain */ sheeva_setttb, /* Setttb */ cpufunc_faultstatus, /* Faultstatus */ cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ arm10_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ arm10_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ armv5_ec_icache_sync_all, /* icache_sync_all */ armv5_ec_icache_sync_range, /* icache_sync_range */ armv5_ec_dcache_wbinv_all, /* dcache_wbinv_all */ sheeva_dcache_wbinv_range, /* dcache_wbinv_range */ sheeva_dcache_inv_range, /* dcache_inv_range */ sheeva_dcache_wb_range, /* dcache_wb_range */ armv5_ec_idcache_wbinv_all, /* idcache_wbinv_all */ sheeva_idcache_wbinv_range, /* idcache_wbinv_all */ sheeva_l2cache_wbinv_all, /* l2cache_wbinv_all */ sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */ sheeva_l2cache_inv_range, /* l2cache_inv_range */ sheeva_l2cache_wb_range, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm10_context_switch, /* context_switch */ arm10_setup /* cpu setup */ }; #endif /* CPU_ARM9E || CPU_ARM10 */ #ifdef CPU_ARM10 struct cpu_functions arm10_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* Domain */ arm10_setttb, /* Setttb */ cpufunc_faultstatus, /* Faultstatus */ cpufunc_faultaddress, /* Faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ arm10_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ arm10_tlb_flushI_SE, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ arm10_icache_sync_all, /* icache_sync_all */ arm10_icache_sync_range, /* icache_sync_range */ arm10_dcache_wbinv_all, /* dcache_wbinv_all */ arm10_dcache_wbinv_range, /* dcache_wbinv_range */ arm10_dcache_inv_range, /* dcache_inv_range */ arm10_dcache_wb_range, /* dcache_wb_range */ arm10_idcache_wbinv_all, /* idcache_wbinv_all */ arm10_idcache_wbinv_range, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ arm10_context_switch, /* context_switch */ arm10_setup /* cpu setup */ }; #endif /* CPU_ARM10 */ #ifdef CPU_SA110 struct cpu_functions sa110_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* domain */ sa1_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ sa1_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ sa1_cache_syncI, /* icache_sync_all */ sa1_cache_syncI_rng, /* icache_sync_range */ sa1_cache_purgeD, /* dcache_wbinv_all */ sa1_cache_purgeD_rng, /* dcache_wbinv_range */ /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ sa1_cache_cleanD_rng, /* dcache_wb_range */ sa1_cache_purgeID, /* idcache_wbinv_all */ sa1_cache_purgeID_rng, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ sa110_context_switch, /* context_switch */ sa110_setup /* cpu setup */ }; #endif /* CPU_SA110 */ #if defined(CPU_SA1100) || defined(CPU_SA1110) struct cpu_functions sa11x0_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* domain */ sa1_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ sa1_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ sa1_cache_syncI, /* icache_sync_all */ sa1_cache_syncI_rng, /* icache_sync_range */ sa1_cache_purgeD, /* dcache_wbinv_all */ sa1_cache_purgeD_rng, /* dcache_wbinv_range */ /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ sa1_cache_cleanD_rng, /* dcache_wb_range */ sa1_cache_purgeID, /* idcache_wbinv_all */ sa1_cache_purgeID_rng, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ sa11x0_drain_readbuf, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ sa11x0_cpu_sleep, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ sa11x0_context_switch, /* context_switch */ sa11x0_setup /* cpu setup */ }; #endif /* CPU_SA1100 || CPU_SA1110 */ #ifdef CPU_IXP12X0 struct cpu_functions ixp12x0_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ cpufunc_nullop, /* cpwait */ /* MMU functions */ cpufunc_control, /* control */ cpufunc_domains, /* domain */ sa1_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ sa1_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ sa1_cache_syncI, /* icache_sync_all */ sa1_cache_syncI_rng, /* icache_sync_range */ sa1_cache_purgeD, /* dcache_wbinv_all */ sa1_cache_purgeD_rng, /* dcache_wbinv_range */ /*XXX*/ sa1_cache_purgeD_rng, /* dcache_inv_range */ sa1_cache_cleanD_rng, /* dcache_wb_range */ sa1_cache_purgeID, /* idcache_wbinv_all */ sa1_cache_purgeID_rng, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ ixp12x0_drain_readbuf, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ (void *)cpufunc_nullop, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ ixp12x0_context_switch, /* context_switch */ ixp12x0_setup /* cpu setup */ }; #endif /* CPU_IXP12X0 */ #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) struct cpu_functions xscale_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ xscale_cpwait, /* cpwait */ /* MMU functions */ xscale_control, /* control */ cpufunc_domains, /* domain */ xscale_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ xscale_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ xscale_cache_syncI, /* icache_sync_all */ xscale_cache_syncI_rng, /* icache_sync_range */ xscale_cache_purgeD, /* dcache_wbinv_all */ xscale_cache_purgeD_rng, /* dcache_wbinv_range */ xscale_cache_flushD_rng, /* dcache_inv_range */ xscale_cache_cleanD_rng, /* dcache_wb_range */ xscale_cache_purgeID, /* idcache_wbinv_all */ xscale_cache_purgeID_rng, /* idcache_wbinv_range */ cpufunc_nullop, /* l2cache_wbinv_all */ (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ xscale_context_switch, /* context_switch */ xscale_setup /* cpu setup */ }; #endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 CPU_XSCALE_80219 */ #ifdef CPU_XSCALE_81342 struct cpu_functions xscalec3_cpufuncs = { /* CPU functions */ cpufunc_id, /* id */ xscale_cpwait, /* cpwait */ /* MMU functions */ xscale_control, /* control */ cpufunc_domains, /* domain */ xscalec3_setttb, /* setttb */ cpufunc_faultstatus, /* faultstatus */ cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ armv4_tlb_flushID, /* tlb_flushID */ xscale_tlb_flushID_SE, /* tlb_flushID_SE */ armv4_tlb_flushI, /* tlb_flushI */ (void *)armv4_tlb_flushI, /* tlb_flushI_SE */ armv4_tlb_flushD, /* tlb_flushD */ armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ xscalec3_cache_syncI, /* icache_sync_all */ xscalec3_cache_syncI_rng, /* icache_sync_range */ xscalec3_cache_purgeD, /* dcache_wbinv_all */ xscalec3_cache_purgeD_rng, /* dcache_wbinv_range */ xscale_cache_flushD_rng, /* dcache_inv_range */ xscalec3_cache_cleanD_rng, /* dcache_wb_range */ xscalec3_cache_purgeID, /* idcache_wbinv_all */ xscalec3_cache_purgeID_rng, /* idcache_wbinv_range */ xscalec3_l2cache_purge, /* l2cache_wbinv_all */ xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */ xscalec3_l2cache_flush_rng, /* l2cache_inv_range */ xscalec3_l2cache_clean_rng, /* l2cache_wb_range */ /* Other functions */ cpufunc_nullop, /* flush_prefetchbuf */ armv4_drain_writebuf, /* drain_writebuf */ cpufunc_nullop, /* flush_brnchtgt_C */ (void *)cpufunc_nullop, /* flush_brnchtgt_E */ xscale_cpu_sleep, /* sleep */ /* Soft functions */ cpufunc_null_fixup, /* dataabt_fixup */ cpufunc_null_fixup, /* prefetchabt_fixup */ xscalec3_context_switch, /* context_switch */ xscale_setup /* cpu setup */ }; #endif /* CPU_XSCALE_81342 */ #if defined(CPU_FA526) struct cpu_functions fa526_cpufuncs = { /* CPU functions */ .cf_id = cpufunc_id, .cf_cpwait = cpufunc_nullop, /* MMU functions */ .cf_control = cpufunc_control, .cf_domains = cpufunc_domains, .cf_setttb = fa526_setttb, .cf_faultstatus = cpufunc_faultstatus, .cf_faultaddress = cpufunc_faultaddress, /* TLB functions */ .cf_tlb_flushID = armv4_tlb_flushID, .cf_tlb_flushID_SE = fa526_tlb_flushID_SE, .cf_tlb_flushI = armv4_tlb_flushI, .cf_tlb_flushI_SE = fa526_tlb_flushI_SE, .cf_tlb_flushD = armv4_tlb_flushD, .cf_tlb_flushD_SE = armv4_tlb_flushD_SE, /* Cache operations */ .cf_icache_sync_all = fa526_icache_sync_all, .cf_icache_sync_range = fa526_icache_sync_range, .cf_dcache_wbinv_all = fa526_dcache_wbinv_all, .cf_dcache_wbinv_range = fa526_dcache_wbinv_range, .cf_dcache_inv_range = fa526_dcache_inv_range, .cf_dcache_wb_range = fa526_dcache_wb_range, .cf_idcache_wbinv_all = fa526_idcache_wbinv_all, .cf_idcache_wbinv_range = fa526_idcache_wbinv_range, .cf_l2cache_wbinv_all = cpufunc_nullop, .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, .cf_l2cache_inv_range = (void *)cpufunc_nullop, .cf_l2cache_wb_range = (void *)cpufunc_nullop, /* Other functions */ .cf_flush_prefetchbuf = fa526_flush_prefetchbuf, .cf_drain_writebuf = armv4_drain_writebuf, .cf_flush_brnchtgt_C = cpufunc_nullop, .cf_flush_brnchtgt_E = fa526_flush_brnchtgt_E, .cf_sleep = fa526_cpu_sleep, /* Soft functions */ .cf_dataabt_fixup = cpufunc_null_fixup, .cf_prefetchabt_fixup = cpufunc_null_fixup, .cf_context_switch = fa526_context_switch, .cf_setup = fa526_setup }; #endif /* CPU_FA526 */ /* * Global constants also used by locore.s */ struct cpu_functions cpufuncs; u_int cputype; u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \ defined (CPU_ARM9E) || defined (CPU_ARM10) || \ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_FA526) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) static void get_cachetype_cp15(void); /* Additional cache information local to this file. Log2 of some of the above numbers. */ static int arm_dcache_l2_nsets; static int arm_dcache_l2_assoc; static int arm_dcache_l2_linesize; static void get_cachetype_cp15() { 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 = 1; } 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; arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); out: arm_dcache_align_mask = arm_dcache_align - 1; } #endif /* ARM7TDMI || ARM8 || ARM9 || XSCALE */ #if defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ defined(CPU_IXP12X0) /* Cache information for CPUs without cache type registers. */ struct cachetab { u_int32_t ct_cpuid; int ct_pcache_type; int ct_pcache_unified; int ct_pdcache_size; int ct_pdcache_line_size; int ct_pdcache_ways; int ct_picache_size; int ct_picache_line_size; int ct_picache_ways; }; struct cachetab cachetab[] = { /* cpuid, cache type, u, dsiz, ls, wy, isiz, ls, wy */ /* XXX is this type right for SA-1? */ { CPU_ID_SA110, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, { CPU_ID_SA1100, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, { CPU_ID_SA1110, CPU_CT_CTYPE_WB1, 0, 8192, 32, 32, 16384, 32, 32 }, { CPU_ID_IXP1200, CPU_CT_CTYPE_WB1, 0, 16384, 32, 32, 16384, 32, 32 }, /* XXX */ { 0, 0, 0, 0, 0, 0, 0, 0} }; static void get_cachetype_table(void); static void get_cachetype_table() { int i; u_int32_t cpuid = cpufunc_id(); for (i = 0; cachetab[i].ct_cpuid != 0; i++) { if (cachetab[i].ct_cpuid == (cpuid & CPU_ID_CPU_MASK)) { arm_pcache_type = cachetab[i].ct_pcache_type; arm_pcache_unified = cachetab[i].ct_pcache_unified; arm_pdcache_size = cachetab[i].ct_pdcache_size; arm_pdcache_line_size = cachetab[i].ct_pdcache_line_size; arm_pdcache_ways = cachetab[i].ct_pdcache_ways; arm_picache_size = cachetab[i].ct_picache_size; arm_picache_line_size = cachetab[i].ct_picache_line_size; arm_picache_ways = cachetab[i].ct_picache_ways; } } arm_dcache_align = arm_pdcache_line_size; arm_dcache_align_mask = arm_dcache_align - 1; } #endif /* SA110 || SA1100 || SA1111 || IXP12X0 */ /* * Cannot panic here as we may not have a console yet ... */ int set_cpufuncs() { cputype = cpufunc_id(); cputype &= CPU_ID_CPU_MASK; /* * NOTE: cpu_do_powersave defaults to off. If we encounter a * CPU type where we want to use it by default, then we set it. */ #ifdef CPU_ARM7TDMI if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && CPU_ID_IS7(cputype) && (cputype & CPU_ID_7ARCH_MASK) == CPU_ID_7ARCH_V4T) { cpufuncs = arm7tdmi_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; get_cachetype_cp15(); pmap_pte_init_generic(); goto out; } #endif #ifdef CPU_ARM8 if ((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD && (cputype & 0x0000f000) == 0x00008000) { cpufuncs = arm8_cpufuncs; cpu_reset_needs_v4_MMU_disable = 0; /* XXX correct? */ get_cachetype_cp15(); pmap_pte_init_arm8(); goto out; } #endif /* CPU_ARM8 */ #ifdef CPU_ARM9 if (((cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_ARM_LTD || (cputype & CPU_ID_IMPLEMENTOR_MASK) == CPU_ID_TI) && (cputype & 0x0000f000) == 0x00009000) { cpufuncs = arm9_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ get_cachetype_cp15(); arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); arm9_dcache_index_max = 0U - arm9_dcache_index_inc; #ifdef ARM9_CACHE_WRITE_THROUGH pmap_pte_init_arm9(); #else pmap_pte_init_generic(); #endif goto out; } #endif /* CPU_ARM9 */ #if defined(CPU_ARM9E) || defined(CPU_ARM10) if (cputype == CPU_ID_ARM926EJS || cputype == CPU_ID_ARM1026EJS || cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD || cputype == CPU_ID_MV88FR571_41) { if (cputype == CPU_ID_MV88FR131 || cputype == CPU_ID_MV88FR571_VD || cputype == CPU_ID_MV88FR571_41) { cpufuncs = sheeva_cpufuncs; /* * Workaround for Marvell MV78100 CPU: Cache prefetch * mechanism may affect the cache coherency validity, * so it needs to be disabled. * * Refer to errata document MV-S501058-00C.pdf (p. 3.1 * L2 Prefetching Mechanism) for details. */ if (cputype == CPU_ID_MV88FR571_VD || cputype == CPU_ID_MV88FR571_41) { sheeva_control_ext(0xffffffff, FC_DCACHE_STREAM_EN | FC_WR_ALLOC_EN | FC_BRANCH_TARG_BUF_DIS | FC_L2CACHE_EN | FC_L2_PREF_DIS); } else { sheeva_control_ext(0xffffffff, FC_DCACHE_STREAM_EN | FC_WR_ALLOC_EN | FC_BRANCH_TARG_BUF_DIS | FC_L2CACHE_EN); } } else cpufuncs = armv5_ec_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ get_cachetype_cp15(); pmap_pte_init_generic(); goto out; } #endif /* CPU_ARM9E || CPU_ARM10 */ #ifdef CPU_ARM10 if (/* cputype == CPU_ID_ARM1020T || */ cputype == CPU_ID_ARM1020E) { /* * Select write-through cacheing (this isn't really an * option on ARM1020T). */ cpufuncs = arm10_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* V4 or higher */ get_cachetype_cp15(); arm10_dcache_sets_inc = 1U << arm_dcache_l2_linesize; arm10_dcache_sets_max = (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) - arm10_dcache_sets_inc; arm10_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); arm10_dcache_index_max = 0U - arm10_dcache_index_inc; pmap_pte_init_generic(); goto out; } #endif /* CPU_ARM10 */ #ifdef CPU_SA110 if (cputype == CPU_ID_SA110) { cpufuncs = sa110_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ get_cachetype_table(); pmap_pte_init_sa1(); goto out; } #endif /* CPU_SA110 */ #ifdef CPU_SA1100 if (cputype == CPU_ID_SA1100) { cpufuncs = sa11x0_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ get_cachetype_table(); pmap_pte_init_sa1(); /* Use powersave on this CPU. */ cpu_do_powersave = 1; goto out; } #endif /* CPU_SA1100 */ #ifdef CPU_SA1110 if (cputype == CPU_ID_SA1110) { cpufuncs = sa11x0_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ get_cachetype_table(); pmap_pte_init_sa1(); /* Use powersave on this CPU. */ cpu_do_powersave = 1; goto out; } #endif /* CPU_SA1110 */ #ifdef CPU_FA526 if (cputype == CPU_ID_FA526) { cpufuncs = fa526_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ get_cachetype_cp15(); pmap_pte_init_generic(); /* Use powersave on this CPU. */ cpu_do_powersave = 1; goto out; } #endif /* CPU_FA526 */ #ifdef CPU_IXP12X0 if (cputype == CPU_ID_IXP1200) { cpufuncs = ixp12x0_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; get_cachetype_table(); pmap_pte_init_sa1(); goto out; } #endif /* CPU_IXP12X0 */ #ifdef CPU_XSCALE_80200 if (cputype == CPU_ID_80200) { int rev = cpufunc_id() & CPU_ID_REVISION_MASK; i80200_icu_init(); #if defined(XSCALE_CCLKCFG) /* * Crank CCLKCFG to maximum legal value. */ __asm __volatile ("mcr p14, 0, %0, c6, c0, 0" : : "r" (XSCALE_CCLKCFG)); #endif /* * XXX Disable ECC in the Bus Controller Unit; we * don't really support it, yet. Clear any pending * error indications. */ __asm __volatile("mcr p13, 0, %0, c0, c1, 0" : : "r" (BCUCTL_E0|BCUCTL_E1|BCUCTL_EV)); cpufuncs = xscale_cpufuncs; /* * i80200 errata: Step-A0 and A1 have a bug where * D$ dirty bits are not cleared on "invalidate by * address". * * Workaround: Clean cache line before invalidating. */ if (rev == 0 || rev == 1) cpufuncs.cf_dcache_inv_range = xscale_cache_purgeD_rng; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ get_cachetype_cp15(); pmap_pte_init_xscale(); goto out; } #endif /* CPU_XSCALE_80200 */ #if defined(CPU_XSCALE_80321) || defined(CPU_XSCALE_80219) if (cputype == CPU_ID_80321_400 || cputype == CPU_ID_80321_600 || cputype == CPU_ID_80321_400_B0 || cputype == CPU_ID_80321_600_B0 || cputype == CPU_ID_80219_400 || cputype == CPU_ID_80219_600) { cpufuncs = xscale_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ get_cachetype_cp15(); pmap_pte_init_xscale(); goto out; } #endif /* CPU_XSCALE_80321 */ #if defined(CPU_XSCALE_81342) if (cputype == CPU_ID_81342) { cpufuncs = xscalec3_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ get_cachetype_cp15(); pmap_pte_init_xscale(); goto out; } #endif /* CPU_XSCALE_81342 */ #ifdef CPU_XSCALE_PXA2X0 /* ignore core revision to test PXA2xx CPUs */ if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA250 || (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X || (cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA210) { cpufuncs = xscale_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ get_cachetype_cp15(); pmap_pte_init_xscale(); /* Use powersave on this CPU. */ cpu_do_powersave = 1; goto out; } #endif /* CPU_XSCALE_PXA2X0 */ #ifdef CPU_XSCALE_IXP425 if (cputype == CPU_ID_IXP425_533 || cputype == CPU_ID_IXP425_400 || cputype == CPU_ID_IXP425_266 || cputype == CPU_ID_IXP435) { cpufuncs = xscale_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* XScale needs it */ get_cachetype_cp15(); pmap_pte_init_xscale(); goto out; } #endif /* CPU_XSCALE_IXP425 */ /* * Bzzzz. And the answer was ... */ panic("No support for this CPU type (%08x) in kernel", cputype); return(ARCHITECTURE_NOT_PRESENT); out: uma_set_align(arm_dcache_align_mask); return (0); } /* * Fixup routines for data and prefetch aborts. * * Several compile time symbols are used * * DEBUG_FAULT_CORRECTION - Print debugging information during the * correction of registers after a fault. * ARM6_LATE_ABORT - ARM6 supports both early and late aborts * when defined should use late aborts */ /* * Null abort fixup routine. * For use when no fixup is required. */ int cpufunc_null_fixup(arg) void *arg; { return(ABORT_FIXUP_OK); } #if defined(CPU_ARM7TDMI) #ifdef DEBUG_FAULT_CORRECTION #define DFC_PRINTF(x) printf x #define DFC_DISASSEMBLE(x) disassemble(x) #else #define DFC_PRINTF(x) /* nothing */ #define DFC_DISASSEMBLE(x) /* nothing */ #endif /* * "Early" data abort fixup. * * For ARM2, ARM2as, ARM3 and ARM6 (in early-abort mode). Also used * indirectly by ARM6 (in late-abort mode) and ARM7[TDMI]. * * In early aborts, we may have to fix up LDM, STM, LDC and STC. */ int early_abort_fixup(arg) void *arg; { trapframe_t *frame = arg; u_int fault_pc; u_int fault_instruction; int saved_lr = 0; if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { /* Ok an abort in SVC mode */ /* * Copy the SVC r14 into the usr r14 - The usr r14 is garbage * as the fault happened in svc mode but we need it in the * usr slot so we can treat the registers as an array of ints * during fixing. * NOTE: This PC is in the position but writeback is not * allowed on r15. * Doing it like this is more efficient than trapping this * case in all possible locations in the following fixup code. */ saved_lr = frame->tf_usr_lr; frame->tf_usr_lr = frame->tf_svc_lr; /* * Note the trapframe does not have the SVC r13 so a fault * from an instruction with writeback to r13 in SVC mode is * not allowed. This should not happen as the kstack is * always valid. */ } /* Get fault address and status from the CPU */ fault_pc = frame->tf_pc; fault_instruction = *((volatile unsigned int *)fault_pc); /* Decode the fault instruction and fix the registers as needed */ if ((fault_instruction & 0x0e000000) == 0x08000000) { int base; int loop; int count; int *registers = &frame->tf_r0; DFC_PRINTF(("LDM/STM\n")); DFC_DISASSEMBLE(fault_pc); if (fault_instruction & (1 << 21)) { DFC_PRINTF(("This instruction must be corrected\n")); base = (fault_instruction >> 16) & 0x0f; if (base == 15) return ABORT_FIXUP_FAILED; /* Count registers transferred */ count = 0; for (loop = 0; loop < 16; ++loop) { if (fault_instruction & (1<tf_r0; /* REGISTER CORRECTION IS REQUIRED FOR THESE INSTRUCTIONS */ DFC_DISASSEMBLE(fault_pc); /* Only need to fix registers if write back is turned on */ if ((fault_instruction & (1 << 21)) != 0) { base = (fault_instruction >> 16) & 0x0f; if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) return ABORT_FIXUP_FAILED; if (base == 15) return ABORT_FIXUP_FAILED; offset = (fault_instruction & 0xff) << 2; DFC_PRINTF(("r%d=%08x\n", base, registers[base])); if ((fault_instruction & (1 << 23)) != 0) offset = -offset; registers[base] += offset; DFC_PRINTF(("r%d=%08x\n", base, registers[base])); } } else if ((fault_instruction & 0x0e000000) == 0x0c000000) return ABORT_FIXUP_FAILED; if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { /* Ok an abort in SVC mode */ /* * Copy the SVC r14 into the usr r14 - The usr r14 is garbage * as the fault happened in svc mode but we need it in the * usr slot so we can treat the registers as an array of ints * during fixing. * NOTE: This PC is in the position but writeback is not * allowed on r15. * Doing it like this is more efficient than trapping this * case in all possible locations in the prior fixup code. */ frame->tf_svc_lr = frame->tf_usr_lr; frame->tf_usr_lr = saved_lr; /* * Note the trapframe does not have the SVC r13 so a fault * from an instruction with writeback to r13 in SVC mode is * not allowed. This should not happen as the kstack is * always valid. */ } return(ABORT_FIXUP_OK); } #endif /* CPU_ARM2/250/3/6/7 */ #if defined(CPU_ARM7TDMI) /* * "Late" (base updated) data abort fixup * * For ARM6 (in late-abort mode) and ARM7. * * In this model, all data-transfer instructions need fixing up. We defer * LDM, STM, LDC and STC fixup to the early-abort handler. */ int late_abort_fixup(arg) void *arg; { trapframe_t *frame = arg; u_int fault_pc; u_int fault_instruction; int saved_lr = 0; if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { /* Ok an abort in SVC mode */ /* * Copy the SVC r14 into the usr r14 - The usr r14 is garbage * as the fault happened in svc mode but we need it in the * usr slot so we can treat the registers as an array of ints * during fixing. * NOTE: This PC is in the position but writeback is not * allowed on r15. * Doing it like this is more efficient than trapping this * case in all possible locations in the following fixup code. */ saved_lr = frame->tf_usr_lr; frame->tf_usr_lr = frame->tf_svc_lr; /* * Note the trapframe does not have the SVC r13 so a fault * from an instruction with writeback to r13 in SVC mode is * not allowed. This should not happen as the kstack is * always valid. */ } /* Get fault address and status from the CPU */ fault_pc = frame->tf_pc; fault_instruction = *((volatile unsigned int *)fault_pc); /* Decode the fault instruction and fix the registers as needed */ /* Was is a swap instruction ? */ if ((fault_instruction & 0x0fb00ff0) == 0x01000090) { DFC_DISASSEMBLE(fault_pc); } else if ((fault_instruction & 0x0c000000) == 0x04000000) { /* Was is a ldr/str instruction */ /* This is for late abort only */ int base; int offset; int *registers = &frame->tf_r0; DFC_DISASSEMBLE(fault_pc); /* This is for late abort only */ if ((fault_instruction & (1 << 24)) == 0 || (fault_instruction & (1 << 21)) != 0) { /* postindexed ldr/str with no writeback */ base = (fault_instruction >> 16) & 0x0f; if (base == 13 && (frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) return ABORT_FIXUP_FAILED; if (base == 15) return ABORT_FIXUP_FAILED; DFC_PRINTF(("late abt fix: r%d=%08x : ", base, registers[base])); if ((fault_instruction & (1 << 25)) == 0) { /* Immediate offset - easy */ offset = fault_instruction & 0xfff; if ((fault_instruction & (1 << 23))) offset = -offset; registers[base] += offset; DFC_PRINTF(("imm=%08x ", offset)); } else { /* offset is a shifted register */ int shift; offset = fault_instruction & 0x0f; if (offset == base) return ABORT_FIXUP_FAILED; /* * Register offset - hard we have to * cope with shifts ! */ offset = registers[offset]; if ((fault_instruction & (1 << 4)) == 0) /* shift with amount */ shift = (fault_instruction >> 7) & 0x1f; else { /* shift with register */ if ((fault_instruction & (1 << 7)) != 0) /* undefined for now so bail out */ return ABORT_FIXUP_FAILED; shift = ((fault_instruction >> 8) & 0xf); if (base == shift) return ABORT_FIXUP_FAILED; DFC_PRINTF(("shift reg=%d ", shift)); shift = registers[shift]; } DFC_PRINTF(("shift=%08x ", shift)); switch (((fault_instruction >> 5) & 0x3)) { case 0 : /* Logical left */ offset = (int)(((u_int)offset) << shift); break; case 1 : /* Logical Right */ if (shift == 0) shift = 32; offset = (int)(((u_int)offset) >> shift); break; case 2 : /* Arithmetic Right */ if (shift == 0) shift = 32; offset = (int)(((int)offset) >> shift); break; case 3 : /* Rotate right (rol or rxx) */ return ABORT_FIXUP_FAILED; break; } DFC_PRINTF(("abt: fixed LDR/STR with " "register offset\n")); if ((fault_instruction & (1 << 23))) offset = -offset; DFC_PRINTF(("offset=%08x ", offset)); registers[base] += offset; } DFC_PRINTF(("r%d=%08x\n", base, registers[base])); } } if ((frame->tf_spsr & PSR_MODE) == PSR_SVC32_MODE) { /* Ok an abort in SVC mode */ /* * Copy the SVC r14 into the usr r14 - The usr r14 is garbage * as the fault happened in svc mode but we need it in the * usr slot so we can treat the registers as an array of ints * during fixing. * NOTE: This PC is in the position but writeback is not * allowed on r15. * Doing it like this is more efficient than trapping this * case in all possible locations in the prior fixup code. */ frame->tf_svc_lr = frame->tf_usr_lr; frame->tf_usr_lr = saved_lr; /* * Note the trapframe does not have the SVC r13 so a fault * from an instruction with writeback to r13 in SVC mode is * not allowed. This should not happen as the kstack is * always valid. */ } /* * Now let the early-abort fixup routine have a go, in case it * was an LDM, STM, LDC or STC that faulted. */ return early_abort_fixup(arg); } #endif /* CPU_ARM7TDMI */ /* * CPU Setup code */ #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined (CPU_ARM9) || \ defined(CPU_ARM9E) || \ defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ defined(CPU_ARM10) || defined(CPU_ARM11) || \ defined(CPU_FA526) #define IGN 0 #define OR 1 #define BIC 2 struct cpu_option { char *co_name; int co_falseop; int co_trueop; int co_value; }; static u_int parse_cpu_options(char *, struct cpu_option *, u_int); static u_int parse_cpu_options(args, optlist, cpuctrl) char *args; struct cpu_option *optlist; u_int cpuctrl; { int integer; if (args == NULL) return(cpuctrl); while (optlist->co_name) { if (get_bootconf_option(args, optlist->co_name, BOOTOPT_TYPE_BOOLEAN, &integer)) { if (integer) { if (optlist->co_trueop == OR) cpuctrl |= optlist->co_value; else if (optlist->co_trueop == BIC) cpuctrl &= ~optlist->co_value; } else { if (optlist->co_falseop == OR) cpuctrl |= optlist->co_value; else if (optlist->co_falseop == BIC) cpuctrl &= ~optlist->co_value; } } ++optlist; } return(cpuctrl); } #endif /* CPU_ARM7TDMI || CPU_ARM8 || CPU_SA110 || XSCALE*/ #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) struct cpu_option arm678_options[] = { #ifdef COMPAT_12 { "nocache", IGN, BIC, CPU_CONTROL_IDC_ENABLE }, { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, #endif /* COMPAT_12 */ { "cpu.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, { "cpu.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; #endif /* CPU_ARM6 || CPU_ARM7 || CPU_ARM7TDMI || CPU_ARM8 */ #ifdef CPU_ARM7TDMI struct cpu_option arm7tdmi_options[] = { { "arm7.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, { "arm7.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, { "arm7.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "arm7.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, #ifdef COMPAT_12 { "fpaclk2", BIC, OR, CPU_CONTROL_CPCLK }, #endif /* COMPAT_12 */ { "arm700.fpaclk", BIC, OR, CPU_CONTROL_CPCLK }, { NULL, IGN, IGN, 0 } }; void arm7tdmi_setup(args) char *args; { int cpuctrl; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); cpuctrl = parse_cpu_options(args, arm7tdmi_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #endif /* CPU_ARM7TDMI */ #ifdef CPU_ARM8 struct cpu_option arm8_options[] = { { "arm8.cache", BIC, OR, CPU_CONTROL_IDC_ENABLE }, { "arm8.nocache", OR, BIC, CPU_CONTROL_IDC_ENABLE }, { "arm8.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "arm8.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, #ifdef COMPAT_12 { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, #endif /* COMPAT_12 */ { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, { "arm8.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, { NULL, IGN, IGN, 0 } }; void arm8_setup(args) char *args; { int integer; int cpuctrl, cpuctrlmask; int clocktest; int setclock = 0; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IDC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, arm678_options, cpuctrl); cpuctrl = parse_cpu_options(args, arm8_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif /* Get clock configuration */ clocktest = arm8_clock_config(0, 0) & 0x0f; /* Special ARM8 clock and test configuration */ if (get_bootconf_option(args, "arm8.clock.reset", BOOTOPT_TYPE_BOOLEAN, &integer)) { clocktest = 0; setclock = 1; } if (get_bootconf_option(args, "arm8.clock.dynamic", BOOTOPT_TYPE_BOOLEAN, &integer)) { if (integer) clocktest |= 0x01; else clocktest &= ~(0x01); setclock = 1; } if (get_bootconf_option(args, "arm8.clock.sync", BOOTOPT_TYPE_BOOLEAN, &integer)) { if (integer) clocktest |= 0x02; else clocktest &= ~(0x02); setclock = 1; } if (get_bootconf_option(args, "arm8.clock.fast", BOOTOPT_TYPE_BININT, &integer)) { clocktest = (clocktest & ~0xc0) | (integer & 3) << 2; setclock = 1; } if (get_bootconf_option(args, "arm8.test", BOOTOPT_TYPE_BININT, &integer)) { clocktest |= (integer & 7) << 5; setclock = 1; } /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* Set the clock/test register */ if (setclock) arm8_clock_config(0x7f, clocktest); } #endif /* CPU_ARM8 */ #ifdef CPU_ARM9 struct cpu_option arm9_options[] = { { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm9.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm9.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "arm9.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { "arm9.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void arm9_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_ROUNDROBIN; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_VECRELOC | CPU_CONTROL_ROUNDROBIN; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, arm9_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ cpu_control(cpuctrlmask, cpuctrl); ctrl = cpuctrl; } #endif /* CPU_ARM9 */ #if defined(CPU_ARM9E) || defined(CPU_ARM10) struct cpu_option arm10_options[] = { { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm10.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm10.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "arm10.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { "arm10.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void arm10_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BPRD_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, arm10_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Now really make sure they are clean. */ __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; /* Set the control register */ ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* And again. */ cpu_idcache_wbinv_all(); } #endif /* CPU_ARM9E || CPU_ARM10 */ #ifdef CPU_ARM11 struct cpu_option arm11_options[] = { { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm11.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "arm11.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "arm11.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { NULL, IGN, IGN, 0 } }; void arm11_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE /* | CPU_CONTROL_BPRD_ENABLE */; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_ROUNDROBIN | CPU_CONTROL_CPCLK; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, arm11_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Now really make sure they are clean. */ __asm __volatile ("mcr\tp15, 0, r0, c7, c7, 0" : : ); /* Set the control register */ curcpu()->ci_ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); /* And again. */ cpu_idcache_wbinv_all(); } #endif /* CPU_ARM11 */ #ifdef CPU_SA110 struct cpu_option sa110_options[] = { #ifdef COMPAT_12 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, #endif /* COMPAT_12 */ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "sa110.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "sa110.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "sa110.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { "sa110.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void sa110_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_CPCLK; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, sa110_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; /* cpu_control(cpuctrlmask, cpuctrl);*/ cpu_control(0xffffffff, cpuctrl); /* * enable clockswitching, note that this doesn't read or write to r0, * r0 is just to make it valid asm */ __asm ("mcr 15, 0, r0, c15, c1, 2"); } #endif /* CPU_SA110 */ #if defined(CPU_SA1100) || defined(CPU_SA1110) struct cpu_option sa11x0_options[] = { #ifdef COMPAT_12 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, #endif /* COMPAT_12 */ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "sa11x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "sa11x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "sa11x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { "sa11x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void sa11x0_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, sa11x0_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #endif /* CPU_SA1100 || CPU_SA1110 */ #if defined(CPU_FA526) struct cpu_option fa526_options[] = { #ifdef COMPAT_12 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "nowritebuf", IGN, BIC, CPU_CONTROL_WBUF_ENABLE }, #endif /* COMPAT_12 */ { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void fa526_setup(char *args) { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE - | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE; + | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE + | CPU_CONTROL_BPRD_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, fa526_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } #endif /* CPU_FA526 */ #if defined(CPU_IXP12X0) struct cpu_option ixp12x0_options[] = { { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "ixp12x0.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "ixp12x0.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "ixp12x0.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { "cpu.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { "cpu.nowritebuf", OR, BIC, CPU_CONTROL_WBUF_ENABLE }, { "ixp12x0.writebuf", BIC, OR, CPU_CONTROL_WBUF_ENABLE }, { NULL, IGN, IGN, 0 } }; void ixp12x0_setup(args) char *args; { int cpuctrl, cpuctrlmask; cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_VECRELOC; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, ixp12x0_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; /* Clear out the cache */ cpu_idcache_wbinv_all(); /* Set the control register */ ctrl = cpuctrl; /* cpu_control(0xffffffff, cpuctrl); */ cpu_control(cpuctrlmask, cpuctrl); } #endif /* CPU_IXP12X0 */ #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) struct cpu_option xscale_options[] = { #ifdef COMPAT_12 { "branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, #endif /* COMPAT_12 */ { "cpu.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, { "cpu.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "cpu.nocache", OR, BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "xscale.branchpredict", BIC, OR, CPU_CONTROL_BPRD_ENABLE }, { "xscale.cache", BIC, OR, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) }, { "xscale.icache", BIC, OR, CPU_CONTROL_IC_ENABLE }, { "xscale.dcache", BIC, OR, CPU_CONTROL_DC_ENABLE }, { NULL, IGN, IGN, 0 } }; void xscale_setup(args) char *args; { uint32_t auxctl; int cpuctrl, cpuctrlmask; /* * The XScale Write Buffer is always enabled. Our option * is to enable/disable coalescing. Note that bits 6:3 * must always be enabled. */ cpuctrl = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE; cpuctrlmask = CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE | CPU_CONTROL_SYST_ENABLE | CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE | CPU_CONTROL_WBUF_ENABLE | CPU_CONTROL_ROM_ENABLE | CPU_CONTROL_BEND_ENABLE | CPU_CONTROL_AFLT_ENABLE | CPU_CONTROL_LABT_ENABLE | CPU_CONTROL_BPRD_ENABLE | CPU_CONTROL_CPCLK | CPU_CONTROL_VECRELOC | \ CPU_CONTROL_L2_ENABLE; #ifndef ARM32_DISABLE_ALIGNMENT_FAULTS cpuctrl |= CPU_CONTROL_AFLT_ENABLE; #endif cpuctrl = parse_cpu_options(args, xscale_options, cpuctrl); #ifdef __ARMEB__ cpuctrl |= CPU_CONTROL_BEND_ENABLE; #endif if (vector_page == ARM_VECTORS_HIGH) cpuctrl |= CPU_CONTROL_VECRELOC; #ifdef CPU_XSCALE_CORE3 cpuctrl |= CPU_CONTROL_L2_ENABLE; #endif /* Clear out the cache */ cpu_idcache_wbinv_all(); /* * Set the control register. Note that bits 6:3 must always * be set to 1. */ ctrl = cpuctrl; /* cpu_control(cpuctrlmask, cpuctrl);*/ cpu_control(0xffffffff, cpuctrl); /* Make sure write coalescing is turned on */ __asm __volatile("mrc p15, 0, %0, c1, c0, 1" : "=r" (auxctl)); #ifdef XSCALE_NO_COALESCE_WRITES auxctl |= XSCALE_AUXCTL_K; #else auxctl &= ~XSCALE_AUXCTL_K; #endif #ifdef CPU_XSCALE_CORE3 auxctl |= XSCALE_AUXCTL_LLR; auxctl |= XSCALE_AUXCTL_MD_MASK; #endif __asm __volatile("mcr p15, 0, %0, c1, c0, 1" : : "r" (auxctl)); } #endif /* CPU_XSCALE_80200 || CPU_XSCALE_80321 || CPU_XSCALE_PXA2X0 || CPU_XSCALE_IXP425 CPU_XSCALE_80219 */ diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c index 294d5a99dbbc..55e342fb7543 100644 --- a/sys/arm/arm/identcpu.c +++ b/sys/arm/arm/identcpu.c @@ -1,454 +1,458 @@ /* $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz Exp $ */ /*- * Copyright (c) 1995 Mark Brinicombe. * Copyright (c) 1995 Brini. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Brini. * 4. The name of the company nor the name of the author may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * RiscBSD kernel project * * cpu.c * * Probing and configuration for the master CPU * * Created : 10/10/95 */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include char machine[] = "arm"; SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "Machine class"); static const char * const generic_steppings[16] = { "rev 0", "rev 1", "rev 2", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const sa110_steppings[16] = { "rev 0", "step J", "step K", "step S", "step T", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const sa1100_steppings[16] = { "rev 0", "step B", "step C", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "step D", "step E", "rev 10" "step G", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const sa1110_steppings[16] = { "step A-0", "rev 1", "rev 2", "rev 3", "step B-0", "step B-1", "step B-2", "step B-3", "step B-4", "step B-5", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const ixp12x0_steppings[16] = { "(IXP1200 step A)", "(IXP1200 step B)", "rev 2", "(IXP1200 step C)", "(IXP1200 step D)", "(IXP1240/1250 step A)", "(IXP1240 step B)", "(IXP1250 step B)", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const xscale_steppings[16] = { "step A-0", "step A-1", "step B-0", "step C-0", "step D-0", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const i80219_steppings[16] = { "step A-0", "rev 1", "rev 2", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const i80321_steppings[16] = { "step A-0", "step B-0", "rev 2", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const i81342_steppings[16] = { "step A-0", "rev 1", "rev 2", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; /* Steppings for PXA2[15]0 */ static const char * const pxa2x0_steppings[16] = { "step A-0", "step A-1", "step B-0", "step B-1", "step B-2", "step C-0", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; /* Steppings for PXA255/26x. * rev 5: PXA26x B0, rev 6: PXA255 A0 */ static const char * const pxa255_steppings[16] = { "rev 0", "rev 1", "rev 2", "step A-0", "rev 4", "step B-0", "step A-0", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; /* Stepping for PXA27x */ static const char * const pxa27x_steppings[16] = { "step A-0", "step A-1", "step B-0", "step B-1", "step C-0", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; static const char * const ixp425_steppings[16] = { "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3", "rev 4", "rev 5", "rev 6", "rev 7", "rev 8", "rev 9", "rev 10", "rev 11", "rev 12", "rev 13", "rev 14", "rev 15", }; struct cpuidtab { u_int32_t cpuid; enum cpu_class cpu_class; const char *cpu_name; const char * const *cpu_steppings; }; const struct cpuidtab cpuids[] = { { CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2", generic_steppings }, { CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250", generic_steppings }, { CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3", generic_steppings }, { CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600", generic_steppings }, { CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610", generic_steppings }, { CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620", generic_steppings }, { CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700", generic_steppings }, { CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710", generic_steppings }, { CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500", generic_steppings }, { CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a", generic_steppings }, { CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE", generic_steppings }, { CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T", generic_steppings }, { CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T", generic_steppings }, { CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)", generic_steppings }, { CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)", generic_steppings }, { CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810", generic_steppings }, { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T", generic_steppings }, { CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T", generic_steppings }, { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T", generic_steppings }, { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S", generic_steppings }, { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T", generic_steppings }, { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S", generic_steppings }, { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S", generic_steppings }, { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", generic_steppings }, + { CPU_ID_FA526, CPU_CLASS_ARM9, "FA526", + generic_steppings }, + { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", generic_steppings }, { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E", generic_steppings }, { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S", generic_steppings }, { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S", generic_steppings }, { CPU_ID_SA110, CPU_CLASS_SA1, "SA-110", sa110_steppings }, { CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100", sa1100_steppings }, { CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110", sa1110_steppings }, { CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200", ixp12x0_steppings }, { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200", xscale_steppings }, { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz", i80321_steppings }, { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz", i80321_steppings }, { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz", i80321_steppings }, { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz", i80321_steppings }, { CPU_ID_81342, CPU_CLASS_XSCALE, "i81342", i81342_steppings }, { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz", i80219_steppings }, { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz", i80219_steppings }, { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x", pxa27x_steppings }, { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250", pxa2x0_steppings }, { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210", pxa2x0_steppings }, { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250", pxa2x0_steppings }, { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210", pxa2x0_steppings }, { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255", pxa255_steppings }, { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210", pxa2x0_steppings }, { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz", ixp425_steppings }, { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz", ixp425_steppings }, { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz", ixp425_steppings }, /* XXX ixp435 steppings? */ { CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435", ixp425_steppings }, { CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S", generic_steppings }, { CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1", generic_steppings }, { CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131", generic_steppings }, { CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD", generic_steppings }, { CPU_ID_MV88FR571_41, CPU_CLASS_MARVELL, "Early Feroceon 88FR571", generic_steppings }, { 0, CPU_CLASS_NONE, NULL, NULL } }; struct cpu_classtab { const char *class_name; const char *class_option; }; const struct cpu_classtab cpu_classes[] = { { "unknown", NULL }, /* CPU_CLASS_NONE */ { "ARM2", "CPU_ARM2" }, /* CPU_CLASS_ARM2 */ { "ARM2as", "CPU_ARM250" }, /* CPU_CLASS_ARM2AS */ { "ARM3", "CPU_ARM3" }, /* CPU_CLASS_ARM3 */ { "ARM6", "CPU_ARM6" }, /* CPU_CLASS_ARM6 */ { "ARM7", "CPU_ARM7" }, /* CPU_CLASS_ARM7 */ { "ARM7TDMI", "CPU_ARM7TDMI" }, /* CPU_CLASS_ARM7TDMI */ { "ARM8", "CPU_ARM8" }, /* CPU_CLASS_ARM8 */ + { "ARM9", "CPU_ARM9" }, /* CPU_CLASS_ARM9 */ { "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */ { "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */ { "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */ { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */ { "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */ { "SA-1", "CPU_SA110" }, /* CPU_CLASS_SA1 */ { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */ { "ARM11J", "CPU_ARM11" }, /* CPU_CLASS_ARM11J */ }; /* * Report the type of the specified arm processor. This uses the generic and * arm specific information in the cpu structure to identify the processor. * The remaining fields in the cpu structure are filled in appropriately. */ static const char * const 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**", "write-back-locking-C", "**unknown 15**", }; extern int ctrl; enum cpu_class cpu_class = CPU_CLASS_NONE; void identify_arm_cpu(void) { u_int cpuid; int i; cpuid = cpu_id(); if (cpuid == 0) { printf("Processor failed probe - no CPU ID\n"); return; } for (i = 0; cpuids[i].cpuid != 0; i++) if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) { cpu_class = cpuids[i].cpu_class; printf("CPU: %s %s (%s core)\n", cpuids[i].cpu_name, cpuids[i].cpu_steppings[cpuid & CPU_ID_REVISION_MASK], cpu_classes[cpu_class].class_name); break; } if (cpuids[i].cpuid == 0) printf("unknown CPU (ID = 0x%x)\n", cpuid); printf(" "); switch (cpu_class) { case CPU_CLASS_ARM6: case CPU_CLASS_ARM7: case CPU_CLASS_ARM7TDMI: case CPU_CLASS_ARM8: if ((ctrl & CPU_CONTROL_IDC_ENABLE) == 0) printf(" IDC disabled"); else printf(" IDC enabled"); break; case CPU_CLASS_ARM9TDMI: case CPU_CLASS_ARM9ES: case CPU_CLASS_ARM9EJS: case CPU_CLASS_ARM10E: case CPU_CLASS_ARM10EJ: case CPU_CLASS_SA1: case CPU_CLASS_XSCALE: case CPU_CLASS_ARM11J: if ((ctrl & CPU_CONTROL_DC_ENABLE) == 0) printf(" DC disabled"); else printf(" DC enabled"); if ((ctrl & CPU_CONTROL_IC_ENABLE) == 0) printf(" IC disabled"); else printf(" IC enabled"); #ifdef CPU_XSCALE_81342 if ((ctrl & CPU_CONTROL_L2_ENABLE) == 0) printf(" L2 disabled"); else printf(" L2 enabled"); #endif break; default: break; } if ((ctrl & CPU_CONTROL_WBUF_ENABLE) == 0) printf(" WB disabled"); else printf(" WB enabled"); if (ctrl & CPU_CONTROL_LABT_ENABLE) printf(" LABT"); else printf(" EABT"); if (ctrl & CPU_CONTROL_BPRD_ENABLE) printf(" branch prediction enabled"); printf("\n"); /* Print cache info. */ if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0) return; if (arm_pcache_unified) { printf(" %dKB/%dB %d-way %s unified cache\n", arm_pdcache_size / 1024, arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]); } else { printf(" %dKB/%dB %d-way Instruction cache\n", arm_picache_size / 1024, arm_picache_line_size, arm_picache_ways); printf(" %dKB/%dB %d-way %s Data cache\n", arm_pdcache_size / 1024, arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]); } } diff --git a/sys/arm/include/md_var.h b/sys/arm/include/md_var.h index 1f622e2471c9..7a19d33c865e 100644 --- a/sys/arm/include/md_var.h +++ b/sys/arm/include/md_var.h @@ -1,79 +1,80 @@ /*- * Copyright (c) 1995 Bruce D. Evans. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: FreeBSD: src/sys/i386/include/md_var.h,v 1.40 2001/07/12 * $FreeBSD$ */ #ifndef _MACHINE_MD_VAR_H_ #define _MACHINE_MD_VAR_H_ extern char sigcode[]; extern int szsigcode; extern uint32_t *vm_page_dump; extern int vm_page_dump_size; extern int (*_arm_memcpy)(void *, void *, int, int); extern int (*_arm_bzero)(void *, int, int); extern int _min_memcpy_size; extern int _min_bzero_size; #define DST_IS_USER 0x1 #define SRC_IS_USER 0x2 #define IS_PHYSICAL 0x4 enum cpu_class { CPU_CLASS_NONE, CPU_CLASS_ARM2, CPU_CLASS_ARM2AS, CPU_CLASS_ARM3, CPU_CLASS_ARM6, CPU_CLASS_ARM7, CPU_CLASS_ARM7TDMI, CPU_CLASS_ARM8, + CPU_CLASS_ARM9, CPU_CLASS_ARM9TDMI, CPU_CLASS_ARM9ES, CPU_CLASS_ARM9EJS, CPU_CLASS_ARM10E, CPU_CLASS_ARM10EJ, CPU_CLASS_SA1, CPU_CLASS_XSCALE, CPU_CLASS_ARM11J, CPU_CLASS_MARVELL }; extern enum cpu_class cpu_class; struct dumperinfo; extern int busdma_swi_pending; void busdma_swi(void); void dump_add_page(vm_paddr_t); void dump_drop_page(vm_paddr_t); void minidumpsys(struct dumperinfo *); #endif /* !_MACHINE_MD_VAR_H_ */