summaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel')
-rw-r--r--arch/microblaze/kernel/asm-offsets.c1
-rw-r--r--arch/microblaze/kernel/cpu/cache.c75
-rw-r--r--arch/microblaze/kernel/cpu/mb.c10
-rw-r--r--arch/microblaze/kernel/dma.c2
-rw-r--r--arch/microblaze/kernel/entry-nommu.S2
-rw-r--r--arch/microblaze/kernel/exceptions.c2
-rw-r--r--arch/microblaze/kernel/head.S3
-rw-r--r--arch/microblaze/kernel/irq.c3
-rw-r--r--arch/microblaze/kernel/microblaze_ksyms.c11
-rw-r--r--arch/microblaze/kernel/misc.S36
-rw-r--r--arch/microblaze/kernel/module.c2
-rw-r--r--arch/microblaze/kernel/traps.c34
-rw-r--r--arch/microblaze/kernel/vmlinux.lds.S3
13 files changed, 72 insertions, 112 deletions
diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c
index 0071260a672..c1b459c9757 100644
--- a/arch/microblaze/kernel/asm-offsets.c
+++ b/arch/microblaze/kernel/asm-offsets.c
@@ -16,6 +16,7 @@
#include <linux/hardirq.h>
#include <linux/thread_info.h>
#include <linux/kbuild.h>
+#include <asm/cpuinfo.h>
int main(int argc, char *argv[])
{
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index f04d8a86dea..109876e8d64 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -96,13 +96,16 @@ static inline void __disable_dcache_nomsr(void)
}
-/* Helper macro for computing the limits of cache range loops */
+/* Helper macro for computing the limits of cache range loops
+ *
+ * End address can be unaligned which is OK for C implementation.
+ * ASM implementation align it in ASM macros
+ */
#define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \
do { \
int align = ~(cache_line_length - 1); \
end = min(start + cache_size, end); \
start &= align; \
- end = ((end & align) + cache_line_length); \
} while (0);
/*
@@ -111,9 +114,9 @@ do { \
*/
#define CACHE_ALL_LOOP(cache_size, line_length, op) \
do { \
- unsigned int len = cache_size; \
+ unsigned int len = cache_size - line_length; \
int step = -line_length; \
- BUG_ON(step >= 0); \
+ WARN_ON(step >= 0); \
\
__asm__ __volatile__ (" 1: " #op " %0, r0; \
bgtid %0, 1b; \
@@ -122,26 +125,22 @@ do { \
: "memory"); \
} while (0);
-
-#define CACHE_ALL_LOOP2(cache_size, line_length, op) \
-do { \
- unsigned int len = cache_size; \
- int step = -line_length; \
- BUG_ON(step >= 0); \
- \
- __asm__ __volatile__ (" 1: " #op " r0, %0; \
- bgtid %0, 1b; \
- addk %0, %0, %1; \
- " : : "r" (len), "r" (step) \
- : "memory"); \
-} while (0);
-
-/* for wdc.flush/clear */
+/* Used for wdc.flush/clear which can use rB for offset which is not possible
+ * to use for simple wdc or wic.
+ *
+ * start address is cache aligned
+ * end address is not aligned, if end is aligned then I have to substract
+ * cacheline length because I can't flush/invalidate the next cacheline.
+ * If is not, I align it because I will flush/invalidate whole line.
+ */
#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \
do { \
int step = -line_length; \
- int count = end - start; \
- BUG_ON(count <= 0); \
+ int align = ~(line_length - 1); \
+ int count; \
+ end = ((end & align) == end) ? end - line_length : end & align; \
+ count = end - start; \
+ WARN_ON(count < 0); \
\
__asm__ __volatile__ (" 1: " #op " %0, %1; \
bgtid %1, 1b; \
@@ -154,7 +153,9 @@ do { \
#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \
do { \
int volatile temp; \
- BUG_ON(end - start <= 0); \
+ int align = ~(line_length - 1); \
+ end = ((end & align) == end) ? end - line_length : end & align; \
+ WARN_ON(end - start < 0); \
\
__asm__ __volatile__ (" 1: " #op " %1, r0; \
cmpu %0, %1, %2; \
@@ -360,8 +361,12 @@ static void __invalidate_dcache_all_noirq_wt(void)
#endif
}
-/* FIXME this is weird - should be only wdc but not work
- * MS: I am getting bus errors and other weird things */
+/* FIXME It is blindly invalidation as is expected
+ * but can't be called on noMMU in microblaze_cache_init below
+ *
+ * MS: noMMU kernel won't boot if simple wdc is used
+ * The reason should be that there are discared data which kernel needs
+ */
static void __invalidate_dcache_all_wb(void)
{
#ifndef ASM_LOOP
@@ -369,12 +374,12 @@ static void __invalidate_dcache_all_wb(void)
#endif
pr_debug("%s\n", __func__);
#ifdef ASM_LOOP
- CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
- wdc.clear)
+ CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+ wdc)
#else
for (i = 0; i < cpuinfo.dcache_size;
i += cpuinfo.dcache_line_length)
- __asm__ __volatile__ ("wdc.clear %0, r0;" \
+ __asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
}
@@ -393,7 +398,7 @@ static void __invalidate_dcache_range_wb(unsigned long start,
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc.clear %0, r0;" \
: : "r" (i));
#endif
@@ -413,7 +418,7 @@ static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -437,7 +442,7 @@ static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -465,7 +470,7 @@ static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc %0, r0;" \
: : "r" (i));
#endif
@@ -504,7 +509,7 @@ static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
#ifdef ASM_LOOP
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
#else
- for (i = start; i < end; i += cpuinfo.icache_line_length)
+ for (i = start; i < end; i += cpuinfo.dcache_line_length)
__asm__ __volatile__ ("wdc.flush %0, r0;" \
: : "r" (i));
#endif
@@ -650,7 +655,11 @@ void microblaze_cache_init(void)
}
}
}
- invalidate_dcache();
+/* FIXME Invalidation is done in U-BOOT
+ * WT cache: Data is already written to main memory
+ * WB cache: Discard data on noMMU which caused that kernel doesn't boot
+ */
+ /* invalidate_dcache(); */
enable_dcache();
invalidate_icache();
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c
index 0c912b2a8e0..4216eb1eaa3 100644
--- a/arch/microblaze/kernel/cpu/mb.c
+++ b/arch/microblaze/kernel/cpu/mb.c
@@ -98,15 +98,17 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (cpuinfo.use_icache)
count += seq_printf(m,
- "Icache:\t\t%ukB\n",
- cpuinfo.icache_size >> 10);
+ "Icache:\t\t%ukB\tline length:\t%dB\n",
+ cpuinfo.icache_size >> 10,
+ cpuinfo.icache_line_length);
else
count += seq_printf(m, "Icache:\t\tno\n");
if (cpuinfo.use_dcache) {
count += seq_printf(m,
- "Dcache:\t\t%ukB\n",
- cpuinfo.dcache_size >> 10);
+ "Dcache:\t\t%ukB\tline length:\t%dB\n",
+ cpuinfo.dcache_size >> 10,
+ cpuinfo.dcache_line_length);
if (cpuinfo.dcache_wb)
count += seq_printf(m, "\t\twrite-back\n");
else
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index ce72dd4967c..9dcd90b5df5 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -74,7 +74,7 @@ static void dma_direct_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
#ifdef NOT_COHERENT_CACHE
- consistent_free(vaddr);
+ consistent_free(size, vaddr);
#else
free_pages((unsigned long)vaddr, get_order(size));
#endif
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index 391d6197fc3..8cc18cd2cce 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -476,6 +476,8 @@ ENTRY(ret_from_fork)
nop
work_pending:
+ enable_irq
+
andi r11, r19, _TIF_NEED_RESCHED
beqi r11, 1f
bralid r15, schedule
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index d9f70f83097..02cbdfe5aa8 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -121,7 +121,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
}
printk(KERN_WARNING "Divide by zero exception " \
"in kernel mode.\n");
- die("Divide by exception", regs, SIGBUS);
+ die("Divide by zero exception", regs, SIGBUS);
break;
case MICROBLAZE_FPU_EXCEPTION:
pr_debug(KERN_WARNING "FPU exception\n");
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index da6a5f5dc76..1bf73988826 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -28,6 +28,7 @@
* for more details.
*/
+#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/thread_info.h>
#include <asm/page.h>
@@ -49,7 +50,7 @@ swapper_pg_dir:
#endif /* CONFIG_MMU */
- .text
+ __HEAD
ENTRY(_start)
#if CONFIG_KERNEL_BASE_ADDR == 0
brai TOPHYS(real_start)
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index 6f39e2c001f..8f120aca123 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -9,6 +9,7 @@
*/
#include <linux/init.h>
+#include <linux/ftrace.h>
#include <linux/kernel.h>
#include <linux/hardirq.h>
#include <linux/interrupt.h>
@@ -32,7 +33,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
static u32 concurrent_irq;
-void do_IRQ(struct pt_regs *regs)
+void __irq_entry do_IRQ(struct pt_regs *regs)
{
unsigned int irq;
struct pt_regs *old_regs = set_irq_regs(regs);
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index bc4dcb7d386..ff85f771803 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -52,3 +52,14 @@ EXPORT_SYMBOL_GPL(_ebss);
extern void _mcount(void);
EXPORT_SYMBOL(_mcount);
#endif
+
+/*
+ * Assembly functions that may be used (directly or indirectly) by modules
+ */
+EXPORT_SYMBOL(__copy_tofrom_user);
+EXPORT_SYMBOL(__strncpy_user);
+
+#ifdef CONFIG_OPT_LIB_ASM
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+#endif
diff --git a/arch/microblaze/kernel/misc.S b/arch/microblaze/kernel/misc.S
index 7cf86498326..0fb5fc6c1fc 100644
--- a/arch/microblaze/kernel/misc.S
+++ b/arch/microblaze/kernel/misc.S
@@ -93,39 +93,3 @@ early_console_reg_tlb_alloc:
nop
.size early_console_reg_tlb_alloc, . - early_console_reg_tlb_alloc
-
-/*
- * Copy a whole page (4096 bytes).
- */
-#define COPY_16_BYTES \
- lwi r7, r6, 0; \
- lwi r8, r6, 4; \
- lwi r9, r6, 8; \
- lwi r10, r6, 12; \
- swi r7, r5, 0; \
- swi r8, r5, 4; \
- swi r9, r5, 8; \
- swi r10, r5, 12
-
-
-/* FIXME DCACHE_LINE_BYTES (CONFIG_XILINX_MICROBLAZE0_DCACHE_LINE_LEN * 4)*/
-#define DCACHE_LINE_BYTES (4 * 4)
-
-.globl copy_page;
-.type copy_page, @function
-.align 4;
-copy_page:
- ori r11, r0, (PAGE_SIZE/DCACHE_LINE_BYTES) - 1
-_copy_page_loop:
- COPY_16_BYTES
-#if DCACHE_LINE_BYTES >= 32
- COPY_16_BYTES
-#endif
- addik r6, r6, DCACHE_LINE_BYTES
- addik r5, r5, DCACHE_LINE_BYTES
- bneid r11, _copy_page_loop
- addik r11, r11, -1
- rtsd r15, 8
- nop
-
- .size copy_page, . - copy_page
diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c
index cbecf110dc3..0e73f660654 100644
--- a/arch/microblaze/kernel/module.c
+++ b/arch/microblaze/kernel/module.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
void *module_alloc(unsigned long size)
{
@@ -151,6 +152,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
struct module *module)
{
+ flush_dcache();
return 0;
}
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
index 5e4570ef515..75e49202a5e 100644
--- a/arch/microblaze/kernel/traps.c
+++ b/arch/microblaze/kernel/traps.c
@@ -95,37 +95,3 @@ void dump_stack(void)
show_stack(NULL, NULL);
}
EXPORT_SYMBOL(dump_stack);
-
-#ifdef CONFIG_MMU
-void __bug(const char *file, int line, void *data)
-{
- if (data)
- printk(KERN_CRIT "kernel BUG at %s:%d (data = %p)!\n",
- file, line, data);
- else
- printk(KERN_CRIT "kernel BUG at %s:%d!\n", file, line);
-
- machine_halt();
-}
-
-int bad_trap(int trap_num, struct pt_regs *regs)
-{
- printk(KERN_CRIT
- "unimplemented trap %d called at 0x%08lx, pid %d!\n",
- trap_num, regs->pc, current->pid);
- return -ENOSYS;
-}
-
-int debug_trap(struct pt_regs *regs)
-{
- int i;
- printk(KERN_CRIT "debug trap\n");
- for (i = 0; i < 32; i++) {
- /* printk("r%i:%08X\t",i,regs->gpr[i]); */
- if ((i % 4) == 3)
- printk(KERN_CRIT "\n");
- }
- printk(KERN_CRIT "pc:%08lX\tmsr:%08lX\n", regs->pc, regs->msr);
- return -ENOSYS;
-}
-#endif
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 5ef619aad63..db72d712460 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -24,7 +24,8 @@ SECTIONS {
.text : AT(ADDR(.text) - LOAD_OFFSET) {
_text = . ;
_stext = . ;
- *(.text .text.*)
+ HEAD_TEXT
+ TEXT_TEXT
*(.fixup)
EXIT_TEXT
EXIT_CALL