Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 24 Feb 2014 01:41:58 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262420 - in head/sys/arm: arm include
Message-ID:  <201402240141.s1O1fw7I043720@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Mon Feb 24 01:41:58 2014
New Revision: 262420
URL: http://svnweb.freebsd.org/changeset/base/262420

Log:
  Add a new cache maintenance function, idcache_inv_all, to the table, and
  implementations for each of the chips we support.  Most chips up through
  armv6 can use the armv4 implementation which has a single coprocessor
  opcode for this operation.  The rather more complex armv7 implementation
  comes from netbsd.

Modified:
  head/sys/arm/arm/cpufunc.c
  head/sys/arm/arm/cpufunc_asm_armv4.S
  head/sys/arm/arm/cpufunc_asm_armv6.S
  head/sys/arm/arm/cpufunc_asm_armv7.S
  head/sys/arm/include/cpufunc.h

Modified: head/sys/arm/arm/cpufunc.c
==============================================================================
--- head/sys/arm/arm/cpufunc.c	Mon Feb 24 01:17:23 2014	(r262419)
+++ head/sys/arm/arm/cpufunc.c	Mon Feb 24 01:41:58 2014	(r262420)
@@ -146,6 +146,7 @@ struct cpu_functions arm7tdmi_cpufuncs =
 	(void *)arm7tdmi_cache_flushID,	/* dcache_inv_range	*/
 	(void *)cpufunc_nullop,		/* dcache_wb_range	*/
 
+	cpufunc_nullop,			/* idcache_inv_all	*/
 	arm7tdmi_cache_flushID,		/* idcache_wbinv_all	*/
 	(void *)arm7tdmi_cache_flushID,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -208,6 +209,7 @@ struct cpu_functions arm8_cpufuncs = {
 /*XXX*/	(void *)arm8_cache_purgeID,	/* dcache_inv_range	*/
 	(void *)arm8_cache_cleanID,	/* dcache_wb_range	*/
 
+	cpufunc_nullop,			/* idcache_inv_all	*/
 	arm8_cache_purgeID,		/* idcache_wbinv_all	*/
 	(void *)arm8_cache_purgeID,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -269,6 +271,7 @@ struct cpu_functions arm9_cpufuncs = {
 	arm9_dcache_inv_range,		/* dcache_inv_range	*/
 	arm9_dcache_wb_range,		/* dcache_wb_range	*/
 
+	armv4_idcache_inv_all,		/* idcache_inv_all	*/
 	arm9_idcache_wbinv_all,		/* idcache_wbinv_all	*/
 	arm9_idcache_wbinv_range,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -331,6 +334,7 @@ struct cpu_functions armv5_ec_cpufuncs =
 	armv5_ec_dcache_inv_range,	/* dcache_inv_range	*/
 	armv5_ec_dcache_wb_range,	/* dcache_wb_range	*/
 
+	armv4_idcache_inv_all,		/* idcache_inv_all	*/
 	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
 	armv5_ec_idcache_wbinv_range,	/* idcache_wbinv_range	*/
 
@@ -392,6 +396,7 @@ struct cpu_functions sheeva_cpufuncs = {
 	sheeva_dcache_inv_range,	/* dcache_inv_range	*/
 	sheeva_dcache_wb_range,		/* dcache_wb_range	*/
 
+	armv4_idcache_inv_all,		/* idcache_inv_all	*/
 	armv5_ec_idcache_wbinv_all,	/* idcache_wbinv_all	*/
 	sheeva_idcache_wbinv_range,	/* idcache_wbinv_all	*/
 
@@ -454,6 +459,7 @@ struct cpu_functions arm10_cpufuncs = {
 	arm10_dcache_inv_range,		/* dcache_inv_range	*/
 	arm10_dcache_wb_range,		/* dcache_wb_range	*/
 
+	armv4_idcache_inv_all,		/* idcache_inv_all	*/
 	arm10_idcache_wbinv_all,	/* idcache_wbinv_all	*/
 	arm10_idcache_wbinv_range,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -515,6 +521,7 @@ struct cpu_functions pj4bv7_cpufuncs = {
 	armv7_dcache_inv_range,		/* dcache_inv_range	*/
 	armv7_dcache_wb_range,		/* dcache_wb_range	*/
 
+	armv7_idcache_inv_all,		/* idcache_inv_all	*/
 	armv7_idcache_wbinv_all,	/* idcache_wbinv_all	*/
 	armv7_idcache_wbinv_range,	/* idcache_wbinv_all	*/
 
@@ -577,6 +584,7 @@ struct cpu_functions sa110_cpufuncs = {
 /*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
 	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
 
+	sa1_cache_flushID,		/* idcache_inv_all	*/
 	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
 	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -638,6 +646,7 @@ struct cpu_functions sa11x0_cpufuncs = {
 /*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
 	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
 
+	sa1_cache_flushID,		/* idcache_inv_all	*/
 	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
 	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -699,6 +708,7 @@ struct cpu_functions ixp12x0_cpufuncs = 
 /*XXX*/	sa1_cache_purgeD_rng,		/* dcache_inv_range	*/
 	sa1_cache_cleanD_rng,		/* dcache_wb_range	*/
 
+	sa1_cache_flushID,		/* idcache_inv_all	*/
 	sa1_cache_purgeID,		/* idcache_wbinv_all	*/
 	sa1_cache_purgeID_rng,		/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -763,6 +773,7 @@ struct cpu_functions xscale_cpufuncs = {
 	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
 	xscale_cache_cleanD_rng,	/* dcache_wb_range	*/
 
+	xscale_cache_flushID,		/* idcache_inv_all	*/
 	xscale_cache_purgeID,		/* idcache_wbinv_all	*/
 	xscale_cache_purgeID_rng,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all 	*/
@@ -826,6 +837,7 @@ struct cpu_functions xscalec3_cpufuncs =
 	xscale_cache_flushD_rng,	/* dcache_inv_range	*/
 	xscalec3_cache_cleanD_rng,	/* dcache_wb_range	*/
 
+	xscale_cache_flushID,		/* idcache_inv_all	*/
 	xscalec3_cache_purgeID,		/* idcache_wbinv_all	*/
 	xscalec3_cache_purgeID_rng,	/* idcache_wbinv_range	*/
 	xscalec3_l2cache_purge,		/* l2cache_wbinv_all	*/
@@ -888,6 +900,7 @@ struct cpu_functions fa526_cpufuncs = {
 	fa526_dcache_inv_range,		/* dcache_inv_range	*/
 	fa526_dcache_wb_range,		/* dcache_wb_range	*/
 
+	armv4_idcache_inv_all,		/* idcache_inv_all	*/
 	fa526_idcache_wbinv_all,	/* idcache_wbinv_all	*/
 	fa526_idcache_wbinv_range,	/* idcache_wbinv_range	*/
 	cpufunc_nullop,			/* l2cache_wbinv_all	*/
@@ -949,6 +962,7 @@ struct cpu_functions arm1136_cpufuncs = 
 	armv6_dcache_inv_range,         /* dcache_inv_range     */
 	armv6_dcache_wb_range,          /* dcache_wb_range      */
 	
+	armv6_idcache_inv_all,		/* idcache_inv_all	*/
 	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
 	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
 	
@@ -1010,6 +1024,7 @@ struct cpu_functions arm1176_cpufuncs = 
 	armv6_dcache_inv_range,         /* dcache_inv_range     */
 	armv6_dcache_wb_range,          /* dcache_wb_range      */
 	
+	armv6_idcache_inv_all,		/* idcache_inv_all	*/
 	arm11x6_idcache_wbinv_all,      /* idcache_wbinv_all    */
 	arm11x6_idcache_wbinv_range,    /* idcache_wbinv_range  */
 	
@@ -1072,6 +1087,7 @@ struct cpu_functions cortexa_cpufuncs = 
 	armv7_dcache_inv_range,         /* dcache_inv_range     */
 	armv7_dcache_wb_range,          /* dcache_wb_range      */
 	
+	armv7_idcache_inv_all,		/* idcache_inv_all	*/
 	armv7_idcache_wbinv_all,        /* idcache_wbinv_all    */
 	armv7_idcache_wbinv_range,      /* idcache_wbinv_range  */
 	

Modified: head/sys/arm/arm/cpufunc_asm_armv4.S
==============================================================================
--- head/sys/arm/arm/cpufunc_asm_armv4.S	Mon Feb 24 01:17:23 2014	(r262419)
+++ head/sys/arm/arm/cpufunc_asm_armv4.S	Mon Feb 24 01:41:58 2014	(r262420)
@@ -71,3 +71,9 @@ ENTRY(armv4_drain_writebuf)
 	RET
 END(armv4_drain_writebuf)
 
+ENTRY(armv4_idcache_inv_all)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* invalidate all I+D cache */
+	RET
+END(armv4_drain_writebuf)
+

Modified: head/sys/arm/arm/cpufunc_asm_armv6.S
==============================================================================
--- head/sys/arm/arm/cpufunc_asm_armv6.S	Mon Feb 24 01:17:23 2014	(r262419)
+++ head/sys/arm/arm/cpufunc_asm_armv6.S	Mon Feb 24 01:41:58 2014	(r262420)
@@ -148,3 +148,9 @@ ENTRY(armv6_dcache_wbinv_all)
 END(armv6_idcache_wbinv_all)
 END(armv6_dcache_wbinv_all)
 
+ENTRY(armv6_idcache_inv_all)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c7, 0	/* invalidate all I+D cache */
+	RET
+END(armv6_idcache_inv_all)
+

Modified: head/sys/arm/arm/cpufunc_asm_armv7.S
==============================================================================
--- head/sys/arm/arm/cpufunc_asm_armv7.S	Mon Feb 24 01:17:23 2014	(r262419)
+++ head/sys/arm/arm/cpufunc_asm_armv7.S	Mon Feb 24 01:41:58 2014	(r262420)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2010 Per Odlund <per.odlund@armagedon.se>
  * Copyright (C) 2011 MARVELL INTERNATIONAL LTD.
  * All rights reserved.
  *
@@ -305,3 +306,40 @@ ENTRY(armv7_auxctrl)
 	RET
 END(armv7_auxctrl)
 
+ENTRY(armv7_idcache_inv_all)
+	mov     r0, #0
+	mcr     p15, 2, r0, c0, c0, 0   @ set cache level to L1
+	mrc     p15, 1, r0, c0, c0, 0   @ read CCSIDR
+
+	ubfx    r2, r0, #13, #15        @ get num sets - 1 from CCSIDR
+	ubfx    r3, r0, #3, #10         @ get numways - 1 from CCSIDR
+	clz     r1, r3                  @ number of bits to MSB of way
+	lsl     r3, r3, r1              @ shift into position
+	mov     ip, #1                  @
+	lsl     ip, ip, r1              @ ip now contains the way decr
+
+	ubfx    r0, r0, #0, #3          @ get linesize from CCSIDR
+	add     r0, r0, #4              @ apply bias
+	lsl     r2, r2, r0              @ shift sets by log2(linesize)
+	add     r3, r3, r2              @ merge numsets - 1 with numways - 1
+	sub     ip, ip, r2              @ subtract numsets - 1 from way decr
+	mov     r1, #1
+	lsl     r1, r1, r0              @ r1 now contains the set decr
+	mov     r2, ip                  @ r2 now contains set way decr
+
+	/* r3 = ways/sets, r2 = way decr, r1 = set decr, r0 and ip are free */
+1:      mcr     p15, 0, r3, c7, c6, 2   @ invalidate line
+	movs    r0, r3                  @ get current way/set
+	beq     2f                      @ at 0 means we are done.
+	movs    r0, r0, lsl #10         @ clear way bits leaving only set bits
+	subne   r3, r3, r1              @ non-zero?, decrement set #
+	subeq   r3, r3, r2              @ zero?, decrement way # and restore set count
+	b       1b
+
+2:	dsb                             @ wait for stores to finish
+	mov     r0, #0                  @ and ...
+	mcr     p15, 0, r0, c7, c5, 0   @ invalidate instruction+branch cache
+	isb                             @ instruction sync barrier
+	bx      lr                      @ return
+END(armv7_l1cache_inv_all)
+

Modified: head/sys/arm/include/cpufunc.h
==============================================================================
--- head/sys/arm/include/cpufunc.h	Mon Feb 24 01:17:23 2014	(r262419)
+++ head/sys/arm/include/cpufunc.h	Mon Feb 24 01:41:58 2014	(r262420)
@@ -104,6 +104,12 @@ struct cpu_functions {
 	 *
 	 * There are some rules that must be followed:
 	 *
+	 *	ID-cache Invalidate All:
+	 *		Unlike other functions, this one must never write back.
+	 *		It is used to intialize the MMU when it is in an unknown
+	 *		state (such as when it may have lines tagged as valid
+	 *		that belong to a previous set of mappings).
+	 *                                          
 	 *	I-cache Synch (all or range):
 	 *		The goal is to synchronize the instruction stream,
 	 *		so you may beed to write-back dirty D-cache blocks
@@ -138,6 +144,7 @@ struct cpu_functions {
 	void	(*cf_dcache_inv_range)	(vm_offset_t, vm_size_t);
 	void	(*cf_dcache_wb_range)	(vm_offset_t, vm_size_t);
 
+	void	(*cf_idcache_inv_all)	(void);
 	void	(*cf_idcache_wbinv_all)	(void);
 	void	(*cf_idcache_wbinv_range) (vm_offset_t, vm_size_t);
 	void	(*cf_l2cache_wbinv_all) (void);
@@ -238,6 +245,7 @@ void tlb_broadcast(int);
 #define	cpu_dcache_inv_range(a, s) cpufuncs.cf_dcache_inv_range((a), (s))
 #define	cpu_dcache_wb_range(a, s) cpufuncs.cf_dcache_wb_range((a), (s))
 
+#define	cpu_idcache_inv_all()	cpufuncs.cf_idcache_inv_all()
 #define	cpu_idcache_wbinv_all()	cpufuncs.cf_idcache_wbinv_all()
 #define	cpu_idcache_wbinv_range(a, s) cpufuncs.cf_idcache_wbinv_range((a), (s))
 #define cpu_l2cache_wbinv_all()	cpufuncs.cf_l2cache_wbinv_all()
@@ -495,6 +503,7 @@ void	armv6_dcache_wbinv_range	(vm_offset
 void	armv6_dcache_inv_range		(vm_offset_t, vm_size_t);
 void	armv6_dcache_wb_range		(vm_offset_t, vm_size_t);
 
+void	armv6_idcache_inv_all		(void);
 void	armv6_idcache_wbinv_all		(void);
 void	armv6_idcache_wbinv_range	(vm_offset_t, vm_size_t);
 
@@ -503,6 +512,7 @@ void	armv7_tlb_flushID		(void);
 void	armv7_tlb_flushID_SE		(u_int);
 void	armv7_icache_sync_range		(vm_offset_t, vm_size_t);
 void	armv7_idcache_wbinv_range	(vm_offset_t, vm_size_t);
+void	armv7_idcache_inv_all		(void);
 void	armv7_dcache_wbinv_all		(void);
 void	armv7_idcache_wbinv_all		(void);
 void	armv7_dcache_wbinv_range	(vm_offset_t, vm_size_t);
@@ -587,6 +597,7 @@ void	armv4_tlb_flushD	(void);
 void	armv4_tlb_flushD_SE	(u_int va);
 
 void	armv4_drain_writebuf	(void);
+void	armv4_idcache_inv_all	(void);
 #endif
 
 #if defined(CPU_IXP12X0)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402240141.s1O1fw7I043720>