[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[microblaze-uclinux] [patch] microblaze caches and misc cleanup



Hi Greg, David,

Microblaze patch, please apply:

(1) Cacheable address range and cache size now set as kernel 
configuration parameter CONFIG_MICROBLAZE_ICACHE_BASE and ICACHE_SIZE 
(similar for dcache).  Option is added to  "Processor type and features" 
config menu.  pgalloc.h now uses these params in the various 
cache_flush_XXX routines.

(2) Instances of "save_flags(flags); cli();" sequence converted to 
save_flags_cli(flags).  These macros (asm-microblaze/system.h) updated 
for more efficient handling of this very common usage.

(3) Misc cleanup.

Thanks,

John
Index: arch/microblaze/config.in
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/arch/microblaze/config.in,v
retrieving revision 1.6
diff -u -b -B -w -p -r1.6 config.in
--- arch/microblaze/config.in	2003/11/28 05:11:30	1.6
+++ arch/microblaze/config.in	2003/12/10 01:14:08
@@ -55,7 +55,15 @@ mainmenu_option next_comment
   bool 'Hardware Divider'       CONFIG_MICROBLAZE_HARD_DIV
   bool 'Hardware Barrel Shift'  CONFIG_MICROBLAZE_HARD_BARREL
   bool 'Instruction Cache' 	CONFIG_MICROBLAZE_ICACHE
+  if [ "$CONFIG_MICROBLAZE_ICACHE" = "y" ]; then
+     hex '  Instruction cache address base' 	CONFIG_MICROBLAZE_ICACHE_BASE 0x80000000
+     hex '  Instruction cache byte size'	CONFIG_MICROBLAZE_ICACHE_SIZE 0x8000
+  fi
   bool 'Data Cache' 		CONFIG_MICROBLAZE_DCACHE
+  if [ "$CONFIG_MICROBLAZE_DCACHE" = "y" ]; then
+     hex '  Data cache address base' 	CONFIG_MICROBLAZE_DCACHE_BASE 0x80000000
+     hex '  Data cache byte size' 	CONFIG_MICROBLAZE_DCACHE_SIZE 0x8000
+  fi
   bool 'GPIO driver'		CONFIG_XILINX_GPIO
   bool 'Ethernet driver'	CONFIG_XILINX_ENET
   bool 'SystemAce driver'       CONFIG_XILINX_SYSACE
Index: arch/microblaze/kernel/intv.S
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/arch/microblaze/kernel/intv.S,v
retrieving revision 1.3
diff -u -b -B -w -p -r1.3 intv.S
--- arch/microblaze/kernel/intv.S	2003/11/12 03:17:43	1.3
+++ arch/microblaze/kernel/intv.S	2003/12/10 01:14:09
@@ -22,7 +22,12 @@
 	.section	.intv.common, "ax"
 	.org	0x0
 	brai	C_SYMBOL_NAME(start);	// Kernel entry point (0x00)
+
+	.org	0x08
 	brai	C_SYMBOL_NAME(trap);	// Exception handler  (0x08)
+
+	.org	0x10
 	brai	C_SYMBOL_NAME(irq);	// Interrupt handler  (0x10)
-	brai	C_SYMBOL_NAME(dbtrap);	// debug trap handler (0x18)
 
+	.org	0x18
+	brai	C_SYMBOL_NAME(dbtrap);	// debug trap handler (0x18)
Index: arch/microblaze/kernel/process.c
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/arch/microblaze/kernel/process.c,v
retrieving revision 1.6
diff -u -b -B -w -p -r1.6 process.c
--- arch/microblaze/kernel/process.c	2003/09/03 23:53:51	1.6
+++ arch/microblaze/kernel/process.c	2003/12/10 01:14:09
@@ -135,7 +135,7 @@ int arch_kernel_thread (int (*fn)(void *
 	/* Clone this thread.  */
 	arg0 = flags | CLONE_VM;
 	syscall = __NR_clone;
-	asm volatile ("	bralid r17, trap; nop;"
+	asm volatile ("	bralid r17, 0x8; nop;"
 		        : "=r" (ret) 
 			: "r" (syscall), "r" (arg0)
 		        : SYSCALL_CLOBBERS);
@@ -145,7 +145,7 @@ int arch_kernel_thread (int (*fn)(void *
 		/* In child thread, call FN and exit.  */
 		arg0 = (*fn) (arg);
 		syscall = __NR_exit;
-		asm volatile ("bralid r17, trap; nop;"
+		asm volatile ("bralid r17, 0x8; nop;"
 			        : "=r" (ret) 
 				: "r" (syscall), "r" (arg0)
 			        : SYSCALL_CLOBBERS);
Index: arch/microblaze/kernel/xmbserial.c
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/arch/microblaze/kernel/xmbserial.c,v
retrieving revision 1.4
diff -u -b -B -w -p -r1.4 xmbserial.c
--- arch/microblaze/kernel/xmbserial.c	2003/10/22 07:55:27	1.4
+++ arch/microblaze/kernel/xmbserial.c	2003/12/10 01:14:10
@@ -274,7 +274,7 @@ static void xmbrs_stop(struct tty_struct
 		return;
 	
 	uartp = (volatile unsigned int *) info->addr;
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	DisableInterrupts(uartp);
 	restore_flags(flags);
 }
@@ -288,7 +288,7 @@ static void xmbrs_start(struct tty_struc
 	if (serial_paranoia_check(info, tty->device, "xmbrs_start"))
 		return;
 	uartp = (volatile unsigned int *) info->addr;
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	EnableInterrupts(uartp);
 	restore_flags(flags);
 }
@@ -514,7 +514,7 @@ static int startup(struct xmb_serial * i
 			return -ENOMEM;
 	}
 
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 
 #ifdef SERIAL_DEBUG_OPEN
 	printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
@@ -558,7 +558,7 @@ static void shutdown(struct xmb_serial *
 #endif
 	
 	uartp = (volatile unsigned int *) info->addr;
-	save_flags(flags); cli(); /* Disable interrupts */
+	save_flags_cli(flags); 		/* Disable interrupts */
 
 	/* Disable interrupts and clear RX FIFO */
 	DisableInterrupts(uartp);
@@ -650,7 +650,7 @@ static void xmbrs_flush_chars(struct tty
 
 	/* If there are chars waiting in RX buffer then enable interrupt
 	   to permit receiving them */
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	if ( (uartp[XUL_STATUS_REG_OFFSET/4] & XUL_SR_RX_FIFO_VALID_DATA) &&
 			(info->flags & ASYNC_INITIALIZED) ) {
 		EnableInterrupts(uartp);
@@ -662,7 +662,7 @@ static void xmbrs_flush_chars(struct tty
 		return;
 
 	/* Force remaining chars out */
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	EnableInterrupts(uartp);
 	force_tx_fifo_fill(info);
 	restore_flags(flags);
@@ -758,7 +758,7 @@ static void xmbrs_flush_buffer(struct tt
 	if (serial_paranoia_check(info, tty->device, "xmbrs_flush_buffer"))
 		return;
 
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 	restore_flags(flags);
 
@@ -795,7 +795,7 @@ static void xmbrs_throttle(struct tty_st
 		unsigned long		flags;
 		info->x_char = STOP_CHAR(tty);
 		uartp = (volatile unsigned int *) info->addr;
-		save_flags(flags); cli();
+		save_flags_cli(flags);
 		EnableInterrupts(uartp);
 		force_tx_fifo_fill(info);
 		restore_flags(flags);
@@ -825,7 +825,7 @@ static void xmbrs_unthrottle(struct tty_
 			unsigned long		flags;
 			info->x_char = START_CHAR(tty);
 			uartp = (volatile unsigned int *) info->addr;
-			save_flags(flags); cli();
+			save_flags_cli(flags);
 			EnableInterrupts(uartp);
 			force_tx_fifo_fill(info); 
 			restore_flags(flags);
@@ -923,7 +923,7 @@ static int get_lsr_info(struct xmb_seria
 	unsigned char		status;
 
 	uartp = (volatile unsigned int *) info->addr;
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	/* FIXME */
 	status = (uartp[XUL_STATUS_REG_OFFSET/4] & XUL_SR_TX_FIFO_EMPTY) ? TIOCSER_TEMT : 0;
 	restore_flags(flags);
@@ -945,7 +945,7 @@ static void send_break(	struct xmb_seria
 	current->state = TASK_INTERRUPTIBLE;
 	uartp = (volatile unsigned int *) info->addr;
 
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	/* uartp[XMBUART_UCR] = XMBUART_UCR_CMDBREAKSTART; */
 	schedule_timeout(duration);
 	/* uartp[XMBUART_UCR] = XMBUART_UCR_CMDBREAKSTOP; */
@@ -1114,7 +1114,7 @@ static void xmbrs_close(struct tty_struc
 	if (!info || serial_paranoia_check(info, tty->device, "xmbrs_close"))
 		return;
 	
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	
 	if (tty_hung_up_p(filp)) {
 		restore_flags(flags);
@@ -1620,7 +1620,7 @@ xmbrs_init(void)
 		return(-EBUSY);
 	}
 	
-	save_flags(flags); cli();
+	save_flags_cli(flags); 
 
 	/*
 	 *	Configure all the attached serial ports.
@@ -1721,7 +1721,7 @@ void xmbrs_put_char(char ch)
 
 	uartp = (volatile unsigned int *) XPAR_CONSOLE_UART_BASEADDR;
 
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 
 	/* wait for tx buffer not full */
 	for (i = 0; (i < 0x10000); i++) {
Index: include/asm-microblaze/bitops.h
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/include/asm-microblaze/bitops.h,v
retrieving revision 1.2
diff -u -b -B -w -p -r1.2 bitops.h
--- include/asm-microblaze/bitops.h	2003/09/22 04:34:25	1.2
+++ include/asm-microblaze/bitops.h	2003/12/10 01:14:19
@@ -61,7 +61,7 @@ extern __inline__ void set_bit(int nr, v
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	*a |= mask;
 	restore_flags(flags);
 }
@@ -90,19 +90,20 @@ extern __inline__ void clear_bit(int nr,
 
 	a += nr >> 5;
 	mask = 1 << (nr & 0x1f);
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	*a &= ~mask;
 	restore_flags(flags);
 }
 
 extern __inline__ void change_bit(int nr, volatile void * addr)
 {
-	int mask, flags;
+	int mask;
+	unsigned long flags;
 	unsigned long *ADDR = (unsigned long *) addr;
 
 	ADDR += nr >> 5;
 	mask = 1 << (nr & 31);
-	save_flags(flags); cli();
+	save_flags_cli(flags);
 	*ADDR ^= mask;
 	restore_flags(flags);
 }
Index: include/asm-microblaze/pgalloc.h
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/include/asm-microblaze/pgalloc.h,v
retrieving revision 1.3
diff -u -b -B -w -p -r1.3 pgalloc.h
--- include/asm-microblaze/pgalloc.h	2003/12/03 13:42:07	1.3
+++ include/asm-microblaze/pgalloc.h	2003/12/10 01:14:19
@@ -2,6 +2,7 @@
 #define _MICROBLAZE_PGALLOC_H
 
 /*
+ * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
  * Copyright (C) 2000 Lineo, David McCullough <davidm@lineo.com>
  * Copyright (C) 2001 Lineo, Greg Ungerer <gerg@snapgear.com>
  */
@@ -11,60 +12,57 @@
 #include <asm/page.h>
 
 /*
- * Cache handling functions
+ * Cache handling functions.
+ * Microblaze has a write-through data cache, meaning that the data cache
+ * never needs to be flushed.  The only flushing operations that are
+ * implemented are to invalidate the instruction cache.  These are called
+ * after loading a user application into memory, we must invalidate the
+ * instruction cache to make sure we don't fetch old, bad code.
  */
 
-/* The following hard-codes some assumptions, and needs to be cleaned up. 
-   We need to get cache-description #defines into xparameters.h at least
-   and use them to drive the code below.
-*/
-extern inline void __flush_cache_all(void)
+extern inline void __flush_icache_all(void)
 {
 #ifdef CONFIG_MICROBLAZE_ICACHE
 	unsigned int i;
 
 	__disable_icache();
-	__disable_dcache();
 
-	for(i=0;i<0x8000;i+=4)
-	{
-		__invalidate_icache(i+0x80000000);
-		__invalidate_dcache(i+0x80000000);
-	}
+	for(i=0;i<CONFIG_MICROBLAZE_ICACHE_SIZE;i+=4)
+		__invalidate_icache(i+CONFIG_MICROBLAZE_ICACHE_BASE);
+
 	__enable_icache();
-	__enable_dcache();
+#else
+	do { } while(0);
 #endif /* CONFIG_MICROBLAZE_ICACHE */
 }
 
-extern inline void __flush_cache_range(unsigned int start, unsigned int end)
+extern inline void __flush_icache_range(unsigned int start, unsigned int end)
 {
 #ifdef CONFIG_MICROBLAZE_ICACHE
 	unsigned int i;
 
 	__disable_icache();
-	__disable_dcache();
 
 	for(i=start;i<end;i+=4)
-	{
 		__invalidate_icache(i);
-		__invalidate_dcache(i);
-	}
+
 	__enable_icache();
-	__enable_dcache();
+#else
+	do { } while(0);
 #endif /* CONFIG_MICROBLAZE_ICACHE */
 }
 
-#define flush_cache_all()			__flush_cache_all()
+#define flush_cache_all()			__flush_icache_all()
 #define flush_cache_mm(mm)			do { } while(0)
 #define flush_cache_range(mm, start, end)	do { } while(0)
 #define flush_cache_page(vma, vmaddr)		do { } while(0)
 #define flush_page_to_ram(page)			do { } while(0)
 #define flush_dcache_page(page)			do { } while(0)
-#define flush_icache_range(start, end)		__flush_cache_range(start,end)
-#define flush_icache_user_range(vma,pg,adr,len) __flush_cache_all()
-#define flush_icache_page(vma,pg)		__flush_cache_all()
-#define flush_icache()				__flush_cache_all()
-#define flush_cache_sigtramp(vaddr)		__flush_cache_range(vaddr,vaddr+4)
+#define flush_icache_range(start, end)		__flush_icache_range(start,end)
+#define flush_icache_user_range(vma,pg,adr,len) __flush_icache_all()
+#define flush_icache_page(vma,pg)		__flush_icache_all()
+#define flush_icache()				__flush_icache_all()
+#define flush_cache_sigtramp(vaddr)		__flush_icache_range(vaddr,vaddr+4)
 
 /*
  * DAVIDM - the rest of these are just so I can check where they happen
Index: include/asm-microblaze/system.h
===================================================================
RCS file: /var/cvs/uClinux-2.4.x/include/asm-microblaze/system.h,v
retrieving revision 1.4
diff -u -b -B -w -p -r1.4 system.h
--- include/asm-microblaze/system.h	2003/09/22 04:34:25	1.4
+++ include/asm-microblaze/system.h	2003/12/10 01:14:19
@@ -40,17 +40,28 @@ extern void *switch_thread (struct threa
 
 /* Enable/disable interrupts.  */
 #define __sti() \
+{								\
+	register unsigned tmp;					\
   __asm__ __volatile__ ("					\
-			mfs 	r12, rmsr;			\
-			ori	r12, r12, 2;			\
-			mts	rmsr, r12"			\
-			::: "r12", "memory")
+			mfs 	%0, rmsr;			\
+			ori	%0, %0, 2;			\
+			mts	rmsr, %0"			\
+			: "=r" (tmp)				\
+			:					\
+			: "memory");				\
+}
+
 #define __cli() \
+{								\
+	register unsigned tmp;					\
   __asm__ __volatile__ ("					\
-			mfs	r12, rmsr;			\
-			andi	r12, r12, ~2;			\
-			mts	rmsr, r12"			\
-			::: "r12", "memory")
+			mfs 	%0, rmsr;			\
+			andi	%0, %0, ~2;			\
+			mts	rmsr, %0"			\
+			: "=r" (tmp)				\
+			:					\
+			: "memory");				\
+}
 
 #define __save_flags(flags) \
   __asm__ __volatile__ ("mfs	%0, rmsr" : "=r" (flags))
@@ -56,11 +67,30 @@ extern void *switch_thread (struct threa
   __asm__ __volatile__ ("mfs	%0, rmsr" : "=r" (flags))
 #define __restore_flags(flags) \
   __asm__ __volatile__ ("mts	rmsr, %0" :: "r" (flags))
+
 #define	__save_flags_cli(flags) \
-  do { __save_flags (flags); __cli (); } while (0) 
-#define	__save_flags_sti(flags) \
-  do { __save_flags (flags); __sti (); } while (0) 
+{								\
+	register unsigned tmp;					\
+  	__asm__ __volatile__ ("					\
+			mfs 	%0, rmsr;			\
+			andi	%1, %0, ~2;			\
+			mts	rmsr, %1;"			\
+			: "=r" (flags), "=r" (tmp)		\
+			: 					\
+			: "memory");				\
+}
 
+#define	__save_flags_sti(flags) 				\
+{								\
+	register unsigned tmp;					\
+  	__asm__ __volatile__ ("					\
+			mfs 	%0, rmsr;			\
+			ori	%1, %0, 2;			\
+			mts	rmsr, %1;"			\
+			: "=r" (flags) ,"=r" (tmp)		\
+			:					\
+			: "memory");				\
+}
 
 /* For spinlocks etc */
 #define local_irq_save(flags)	__save_flags_cli (flags)