[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)