mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
Merge branch 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze
* 'for-linus' of git://git.monstr.eu/linux-2.6-microblaze: (46 commits) microblaze: Remove rt_sigsuspend wrapper microblaze: nommu: Don't clobber R11 on syscalls microblaze: Remove show_tmem function microblaze: Support for WB cache microblaze: Add PVR for Microblaze v7.30.a microblaze: Remove ancient and fake microblaze version from cpu_ver table microblaze: Remove panic_timeout init value microblaze: Do not count system calls in default microblaze: Enable DTC compilation microblaze: Core oprofile configs and hooks microblaze: Fix level interrupt ACKing microblaze: Enable futimesat syscall microblaze: Checking DTS against PVR for write-back cache microblaze: Remove duplicity from pgalloc.h microblaze: Futex support microblaze: Adding dev_arch_data functions microblaze: Fix the heartbeat gpio to be more robust microblaze: Simple __copy_tofrom_user for noMMU microblaze: Export memory_start for modules microblaze: Use lowest-common-denominator default CPU settings ...
This commit is contained in:
commit
464480f72e
50 changed files with 1712 additions and 510 deletions
|
@ -6,8 +6,15 @@ mainmenu "Linux/Microblaze Kernel Configuration"
|
|||
config MICROBLAZE
|
||||
def_bool y
|
||||
select HAVE_LMB
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select HAVE_OPROFILE
|
||||
select TRACING_SUPPORT
|
||||
|
||||
config SWAP
|
||||
def_bool n
|
||||
|
@ -57,12 +64,24 @@ config GENERIC_GPIO
|
|||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config HAVE_LATENCYTOP_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config PCI
|
||||
def_bool n
|
||||
|
||||
config NO_DMA
|
||||
def_bool y
|
||||
|
||||
config DTC
|
||||
def_bool y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
source "kernel/Kconfig.freezer"
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
menu "Kernel hacking"
|
||||
|
||||
config TRACE_IRQFLAGS_SUPPORT
|
||||
def_bool y
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config EARLY_PRINTK
|
||||
|
|
|
@ -51,6 +51,8 @@ core-y += arch/microblaze/kernel/
|
|||
core-y += arch/microblaze/mm/
|
||||
core-y += arch/microblaze/platform/
|
||||
|
||||
drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/
|
||||
|
||||
boot := arch/microblaze/boot
|
||||
|
||||
# Are we making a simpleImage.<boardname> target? If so, crack out the boardname
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
# arch/microblaze/boot/Makefile
|
||||
#
|
||||
|
||||
MKIMAGE := $(srctree)/scripts/mkuboot.sh
|
||||
|
||||
obj-y += linked_dtb.o
|
||||
|
||||
targets := linux.bin linux.bin.gz simpleImage.%
|
||||
|
||||
OBJCOPYFLAGS_linux.bin := -O binary
|
||||
OBJCOPYFLAGS := -O binary
|
||||
|
||||
# Where the DTS files live
|
||||
dtstree := $(srctree)/$(src)/dts
|
||||
|
@ -24,6 +26,7 @@ $(obj)/linux.bin: vmlinux FORCE
|
|||
[ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \
|
||||
touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image"
|
||||
$(call if_changed,objcopy)
|
||||
$(call if_changed,uimage)
|
||||
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||
|
||||
$(obj)/linux.bin.gz: $(obj)/linux.bin FORCE
|
||||
|
@ -36,8 +39,16 @@ quiet_cmd_cp = CP $< $@$2
|
|||
quiet_cmd_strip = STRIP $@
|
||||
cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@
|
||||
|
||||
quiet_cmd_uimage = UIMAGE $@.ub
|
||||
cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \
|
||||
-C none -n 'Linux-$(KERNELRELEASE)' \
|
||||
-a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \
|
||||
-d $@ $@.ub
|
||||
|
||||
$(obj)/simpleImage.%: vmlinux FORCE
|
||||
$(call if_changed,cp,.unstrip)
|
||||
$(call if_changed,objcopy)
|
||||
$(call if_changed,uimage)
|
||||
$(call if_changed,strip)
|
||||
@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
|
||||
|
||||
|
@ -53,4 +64,4 @@ $(obj)/%.dtb: $(dtstree)/%.dts FORCE
|
|||
|
||||
clean-kernel += linux.bin linux.bin.gz simpleImage.*
|
||||
|
||||
clean-files += *.dtb
|
||||
clean-files += *.dtb simpleImage.*.unstrip
|
||||
|
|
|
@ -21,20 +21,4 @@
|
|||
|
||||
#define SMP_CACHE_BYTES L1_CACHE_BYTES
|
||||
|
||||
void _enable_icache(void);
|
||||
void _disable_icache(void);
|
||||
void _invalidate_icache(unsigned int addr);
|
||||
|
||||
#define __enable_icache() _enable_icache()
|
||||
#define __disable_icache() _disable_icache()
|
||||
#define __invalidate_icache(addr) _invalidate_icache(addr)
|
||||
|
||||
void _enable_dcache(void);
|
||||
void _disable_dcache(void);
|
||||
void _invalidate_dcache(unsigned int addr);
|
||||
|
||||
#define __enable_dcache() _enable_dcache()
|
||||
#define __disable_dcache() _disable_dcache()
|
||||
#define __invalidate_dcache(addr) _invalidate_dcache(addr)
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_CACHE_H */
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
/* Somebody depends on this; sigh... */
|
||||
#include <linux/mm.h>
|
||||
|
||||
/* Look at Documentation/cachetlb.txt */
|
||||
|
||||
/*
|
||||
* Cache handling functions.
|
||||
* Microblaze has a write-through data cache, meaning that the data cache
|
||||
|
@ -27,78 +29,81 @@
|
|||
* instruction cache to make sure we don't fetch old, bad code.
|
||||
*/
|
||||
|
||||
/* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate,
|
||||
* suffix r = range */
|
||||
struct scache {
|
||||
/* icache */
|
||||
void (*ie)(void); /* enable */
|
||||
void (*id)(void); /* disable */
|
||||
void (*ifl)(void); /* flush */
|
||||
void (*iflr)(unsigned long a, unsigned long b);
|
||||
void (*iin)(void); /* invalidate */
|
||||
void (*iinr)(unsigned long a, unsigned long b);
|
||||
/* dcache */
|
||||
void (*de)(void); /* enable */
|
||||
void (*dd)(void); /* disable */
|
||||
void (*dfl)(void); /* flush */
|
||||
void (*dflr)(unsigned long a, unsigned long b);
|
||||
void (*din)(void); /* invalidate */
|
||||
void (*dinr)(unsigned long a, unsigned long b);
|
||||
};
|
||||
|
||||
/* microblaze cache */
|
||||
extern struct scache *mbc;
|
||||
|
||||
void microblaze_cache_init(void);
|
||||
|
||||
#define enable_icache() mbc->ie();
|
||||
#define disable_icache() mbc->id();
|
||||
#define flush_icache() mbc->ifl();
|
||||
#define flush_icache_range(start, end) mbc->iflr(start, end);
|
||||
#define invalidate_icache() mbc->iin();
|
||||
#define invalidate_icache_range(start, end) mbc->iinr(start, end);
|
||||
|
||||
|
||||
#define flush_icache_user_range(vma, pg, adr, len) flush_icache();
|
||||
#define flush_icache_page(vma, pg) do { } while (0)
|
||||
|
||||
#define enable_dcache() mbc->de();
|
||||
#define disable_dcache() mbc->dd();
|
||||
/* FIXME for LL-temac driver */
|
||||
#define invalidate_dcache_range(start, end) \
|
||||
__invalidate_dcache_range(start, end)
|
||||
#define invalidate_dcache() mbc->din();
|
||||
#define invalidate_dcache_range(start, end) mbc->dinr(start, end);
|
||||
#define flush_dcache() mbc->dfl();
|
||||
#define flush_dcache_range(start, end) mbc->dflr(start, end);
|
||||
|
||||
#define flush_cache_all() __invalidate_cache_all()
|
||||
#define flush_cache_mm(mm) do { } while (0)
|
||||
#define flush_cache_range(vma, start, end) __invalidate_cache_all()
|
||||
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
|
||||
|
||||
#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end)
|
||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
|
||||
/* D-cache aliasing problem can't happen - cache is between MMU and ram */
|
||||
#define flush_dcache_page(page) do { } while (0)
|
||||
#define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
#define flush_icache_range(start, len) __invalidate_icache_range(start, len)
|
||||
#define flush_icache_page(vma, pg) do { } while (0)
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
# define flush_icache_user_range(start, len) do { } while (0)
|
||||
#else
|
||||
# define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all()
|
||||
#define flush_cache_dup_mm(mm) do { } while (0)
|
||||
#define flush_cache_vmap(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) do { } while (0)
|
||||
#define flush_cache_mm(mm) do { } while (0)
|
||||
#define flush_cache_page(vma, vmaddr, pfn) do { } while (0)
|
||||
|
||||
# define flush_page_to_ram(page) do { } while (0)
|
||||
|
||||
# define flush_icache() __invalidate_icache_all()
|
||||
# define flush_cache_sigtramp(vaddr) \
|
||||
__invalidate_icache_range(vaddr, vaddr + 8)
|
||||
|
||||
# define flush_dcache_mmap_lock(mapping) do { } while (0)
|
||||
# define flush_dcache_mmap_unlock(mapping) do { } while (0)
|
||||
|
||||
# define flush_cache_dup_mm(mm) do { } while (0)
|
||||
/* MS: kgdb code use this macro, wrong len with FLASH */
|
||||
#if 0
|
||||
#define flush_cache_range(vma, start, len) { \
|
||||
flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \
|
||||
flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define flush_cache_vmap(start, end) do { } while (0)
|
||||
#define flush_cache_vunmap(start, end) do { } while (0)
|
||||
#define flush_cache_range(vma, start, len) do { } while (0)
|
||||
|
||||
struct page;
|
||||
struct mm_struct;
|
||||
struct vm_area_struct;
|
||||
|
||||
/* see arch/microblaze/kernel/cache.c */
|
||||
extern void __invalidate_icache_all(void);
|
||||
extern void __invalidate_icache_range(unsigned long start, unsigned long end);
|
||||
extern void __invalidate_icache_page(struct vm_area_struct *vma,
|
||||
struct page *page);
|
||||
extern void __invalidate_icache_user_range(struct vm_area_struct *vma,
|
||||
struct page *page,
|
||||
unsigned long adr, int len);
|
||||
extern void __invalidate_cache_sigtramp(unsigned long addr);
|
||||
|
||||
extern void __invalidate_dcache_all(void);
|
||||
extern void __invalidate_dcache_range(unsigned long start, unsigned long end);
|
||||
extern void __invalidate_dcache_page(struct vm_area_struct *vma,
|
||||
struct page *page);
|
||||
extern void __invalidate_dcache_user_range(struct vm_area_struct *vma,
|
||||
struct page *page,
|
||||
unsigned long adr, int len);
|
||||
|
||||
extern inline void __invalidate_cache_all(void)
|
||||
{
|
||||
__invalidate_icache_all();
|
||||
__invalidate_dcache_all();
|
||||
}
|
||||
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { memcpy((dst), (src), (len)); \
|
||||
flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
|
||||
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { \
|
||||
memcpy((dst), (src), (len)); \
|
||||
flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \
|
||||
} while (0)
|
||||
|
||||
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
||||
memcpy((dst), (src), (len))
|
||||
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
||||
do { \
|
||||
memcpy((dst), (src), (len)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */
|
||||
|
|
|
@ -43,7 +43,7 @@ struct cpuinfo {
|
|||
u32 use_icache;
|
||||
u32 icache_tagbits;
|
||||
u32 icache_write;
|
||||
u32 icache_line;
|
||||
u32 icache_line_length;
|
||||
u32 icache_size;
|
||||
unsigned long icache_base;
|
||||
unsigned long icache_high;
|
||||
|
@ -51,8 +51,9 @@ struct cpuinfo {
|
|||
u32 use_dcache;
|
||||
u32 dcache_tagbits;
|
||||
u32 dcache_write;
|
||||
u32 dcache_line;
|
||||
u32 dcache_line_length;
|
||||
u32 dcache_size;
|
||||
u32 dcache_wb;
|
||||
unsigned long dcache_base;
|
||||
unsigned long dcache_high;
|
||||
|
||||
|
|
|
@ -19,6 +19,18 @@ struct dev_archdata {
|
|||
struct pdev_archdata {
|
||||
};
|
||||
|
||||
static inline void dev_archdata_set_node(struct dev_archdata *ad,
|
||||
struct device_node *np)
|
||||
{
|
||||
ad->of_node = np;
|
||||
}
|
||||
|
||||
static inline struct device_node *
|
||||
dev_archdata_get_node(const struct dev_archdata *ad)
|
||||
{
|
||||
return ad->of_node;
|
||||
}
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_DEVICE_H */
|
||||
|
||||
|
||||
|
|
|
@ -1 +1,26 @@
|
|||
#ifndef _ASM_MICROBLAZE_FTRACE
|
||||
#define _ASM_MICROBLAZE_FTRACE
|
||||
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
|
||||
#define MCOUNT_ADDR ((long)(_mcount))
|
||||
#define MCOUNT_INSN_SIZE 8 /* sizeof mcount call */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
extern void _mcount(void);
|
||||
extern void ftrace_call_graph(void);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
/* reloction of mcount call site is the same as the address */
|
||||
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
struct dyn_arch_ftrace {
|
||||
};
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
||||
#endif /* _ASM_MICROBLAZE_FTRACE */
|
||||
|
|
|
@ -1 +1,126 @@
|
|||
#include <asm-generic/futex.h>
|
||||
#ifndef _ASM_MICROBLAZE_FUTEX_H
|
||||
#define _ASM_MICROBLAZE_FUTEX_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/errno.h>
|
||||
|
||||
#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
|
||||
({ \
|
||||
__asm__ __volatile__ ( \
|
||||
"1: lwx %0, %2, r0; " \
|
||||
insn \
|
||||
"2: swx %1, %2, r0; \
|
||||
addic %1, r0, 0; \
|
||||
bnei %1, 1b; \
|
||||
3: \
|
||||
.section .fixup,\"ax\"; \
|
||||
4: brid 3b; \
|
||||
addik %1, r0, %3; \
|
||||
.previous; \
|
||||
.section __ex_table,\"a\"; \
|
||||
.word 1b,4b,2b,4b; \
|
||||
.previous;" \
|
||||
: "=&r" (oldval), "=&r" (ret) \
|
||||
: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
|
||||
); \
|
||||
})
|
||||
|
||||
static inline int
|
||||
futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
pagefault_disable();
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
__futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
__futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
__futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
__futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
__futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
pagefault_enable();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ:
|
||||
ret = (oldval == cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_NE:
|
||||
ret = (oldval != cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LT:
|
||||
ret = (oldval < cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GE:
|
||||
ret = (oldval >= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_LE:
|
||||
ret = (oldval <= cmparg);
|
||||
break;
|
||||
case FUTEX_OP_CMP_GT:
|
||||
ret = (oldval > cmparg);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
|
||||
{
|
||||
int prev, cmp;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
__asm__ __volatile__ ("1: lwx %0, %2, r0; \
|
||||
cmp %1, %0, %3; \
|
||||
beqi %1, 3f; \
|
||||
2: swx %4, %2, r0; \
|
||||
addic %1, r0, 0; \
|
||||
bnei %1, 1b; \
|
||||
3: \
|
||||
.section .fixup,\"ax\"; \
|
||||
4: brid 3b; \
|
||||
addik %0, r0, %5; \
|
||||
.previous; \
|
||||
.section __ex_table,\"a\"; \
|
||||
.word 1b,4b,2b,4b; \
|
||||
.previous;" \
|
||||
: "=&r" (prev), "=&r"(cmp) \
|
||||
: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,78 +10,73 @@
|
|||
#define _ASM_MICROBLAZE_IRQFLAGS_H
|
||||
|
||||
#include <linux/irqflags.h>
|
||||
#include <asm/registers.h>
|
||||
|
||||
# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
|
||||
# define local_irq_save(flags) \
|
||||
# define raw_local_irq_save(flags) \
|
||||
do { \
|
||||
asm volatile ("# local_irq_save \n\t" \
|
||||
"msrclr %0, %1 \n\t" \
|
||||
"nop \n\t" \
|
||||
asm volatile (" msrclr %0, %1; \
|
||||
nop;" \
|
||||
: "=r"(flags) \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
# define local_irq_disable() \
|
||||
do { \
|
||||
asm volatile ("# local_irq_disable \n\t" \
|
||||
"msrclr r0, %0 \n\t" \
|
||||
"nop \n\t" \
|
||||
: \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
# define raw_local_irq_disable() \
|
||||
do { \
|
||||
asm volatile (" msrclr r0, %0; \
|
||||
nop;" \
|
||||
: \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
# define local_irq_enable() \
|
||||
do { \
|
||||
asm volatile ("# local_irq_enable \n\t" \
|
||||
"msrset r0, %0 \n\t" \
|
||||
"nop \n\t" \
|
||||
: \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
# define raw_local_irq_enable() \
|
||||
do { \
|
||||
asm volatile (" msrset r0, %0; \
|
||||
nop;" \
|
||||
: \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */
|
||||
|
||||
# define local_irq_save(flags) \
|
||||
# define raw_local_irq_save(flags) \
|
||||
do { \
|
||||
register unsigned tmp; \
|
||||
asm volatile ("# local_irq_save \n\t" \
|
||||
"mfs %0, rmsr \n\t" \
|
||||
"nop \n\t" \
|
||||
"andi %1, %0, %2 \n\t" \
|
||||
"mts rmsr, %1 \n\t" \
|
||||
"nop \n\t" \
|
||||
asm volatile (" mfs %0, rmsr; \
|
||||
nop; \
|
||||
andi %1, %0, %2; \
|
||||
mts rmsr, %1; \
|
||||
nop;" \
|
||||
: "=r"(flags), "=r" (tmp) \
|
||||
: "i"(~MSR_IE) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
# define local_irq_disable() \
|
||||
# define raw_local_irq_disable() \
|
||||
do { \
|
||||
register unsigned tmp; \
|
||||
asm volatile ("# local_irq_disable \n\t" \
|
||||
"mfs %0, rmsr \n\t" \
|
||||
"nop \n\t" \
|
||||
"andi %0, %0, %1 \n\t" \
|
||||
"mts rmsr, %0 \n\t" \
|
||||
"nop \n\t" \
|
||||
asm volatile (" mfs %0, rmsr; \
|
||||
nop; \
|
||||
andi %0, %0, %1; \
|
||||
mts rmsr, %0; \
|
||||
nop;" \
|
||||
: "=r"(tmp) \
|
||||
: "i"(~MSR_IE) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
# define local_irq_enable() \
|
||||
# define raw_local_irq_enable() \
|
||||
do { \
|
||||
register unsigned tmp; \
|
||||
asm volatile ("# local_irq_enable \n\t" \
|
||||
"mfs %0, rmsr \n\t" \
|
||||
"nop \n\t" \
|
||||
"ori %0, %0, %1 \n\t" \
|
||||
"mts rmsr, %0 \n\t" \
|
||||
"nop \n\t" \
|
||||
asm volatile (" mfs %0, rmsr; \
|
||||
nop; \
|
||||
ori %0, %0, %1; \
|
||||
mts rmsr, %0; \
|
||||
nop;" \
|
||||
: "=r"(tmp) \
|
||||
: "i"(MSR_IE) \
|
||||
: "memory"); \
|
||||
|
@ -89,35 +84,28 @@
|
|||
|
||||
# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */
|
||||
|
||||
#define local_save_flags(flags) \
|
||||
#define raw_local_irq_restore(flags) \
|
||||
do { \
|
||||
asm volatile ("# local_save_flags \n\t" \
|
||||
"mfs %0, rmsr \n\t" \
|
||||
"nop \n\t" \
|
||||
: "=r"(flags) \
|
||||
asm volatile (" mts rmsr, %0; \
|
||||
nop;" \
|
||||
: \
|
||||
: "r"(flags) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
#define local_irq_restore(flags) \
|
||||
do { \
|
||||
asm volatile ("# local_irq_restore \n\t"\
|
||||
"mts rmsr, %0 \n\t" \
|
||||
"nop \n\t" \
|
||||
: \
|
||||
: "r"(flags) \
|
||||
: "memory"); \
|
||||
} while (0)
|
||||
|
||||
static inline int irqs_disabled(void)
|
||||
static inline unsigned long get_msr(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_save_flags(flags);
|
||||
return ((flags & MSR_IE) == 0);
|
||||
asm volatile (" mfs %0, rmsr; \
|
||||
nop;" \
|
||||
: "=r"(flags) \
|
||||
: \
|
||||
: "memory"); \
|
||||
return flags;
|
||||
}
|
||||
|
||||
#define raw_irqs_disabled irqs_disabled
|
||||
#define raw_irqs_disabled_flags(flags) ((flags) == 0)
|
||||
#define raw_local_save_flags(flags) ((flags) = get_msr())
|
||||
#define raw_irqs_disabled() ((get_msr() & MSR_IE) == 0)
|
||||
#define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0)
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */
|
||||
|
|
|
@ -164,7 +164,8 @@ extern int page_is_ram(unsigned long pfn);
|
|||
# endif /* CONFIG_MMU */
|
||||
|
||||
# ifndef CONFIG_MMU
|
||||
# define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) <= max_mapnr)
|
||||
# define pfn_valid(pfn) (((pfn) >= min_low_pfn) && \
|
||||
((pfn) <= (min_low_pfn + max_mapnr)))
|
||||
# define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT)
|
||||
# else /* CONFIG_MMU */
|
||||
# define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT)
|
||||
|
|
|
@ -106,9 +106,6 @@ extern inline void free_pgd_slow(pgd_t *pgd)
|
|||
*/
|
||||
#define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); })
|
||||
#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
|
||||
/* FIXME two definition - look below */
|
||||
#define pmd_free(mm, x) do { } while (0)
|
||||
#define pgd_populate(mm, pmd, pte) BUG()
|
||||
|
||||
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
|
||||
unsigned long address)
|
||||
|
@ -192,14 +189,14 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
|
|||
* the pgd will always be present..
|
||||
*/
|
||||
#define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); })
|
||||
/*#define pmd_free(mm, x) do { } while (0)*/
|
||||
#define __pmd_free_tlb(tlb, x, addr) do { } while (0)
|
||||
#define pmd_free(mm, x) do { } while (0)
|
||||
#define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x)
|
||||
#define pgd_populate(mm, pmd, pte) BUG()
|
||||
|
||||
extern int do_check_pgt_cache(int, int);
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#define check_pgt_cache() do {} while (0)
|
||||
#define check_pgt_cache() do { } while (0)
|
||||
|
||||
#endif /* _ASM_MICROBLAZE_PGALLOC_H */
|
||||
|
|
|
@ -76,20 +76,23 @@ struct pvr_s {
|
|||
#define PVR3_FSL_LINKS_MASK 0x00000380
|
||||
|
||||
/* ICache config PVR masks */
|
||||
#define PVR4_USE_ICACHE_MASK 0x80000000
|
||||
#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000
|
||||
#define PVR4_ICACHE_USE_FSL_MASK 0x02000000
|
||||
#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000
|
||||
#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000
|
||||
#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000
|
||||
#define PVR4_USE_ICACHE_MASK 0x80000000 /* ICU */
|
||||
#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* ICTS */
|
||||
#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 /* ICW */
|
||||
#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 /* ICLL */
|
||||
#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 /* ICBS */
|
||||
#define PVR4_ICACHE_ALWAYS_USED 0x00008000 /* IAU */
|
||||
#define PVR4_ICACHE_INTERFACE 0x00002000 /* ICI */
|
||||
|
||||
/* DCache config PVR masks */
|
||||
#define PVR5_USE_DCACHE_MASK 0x80000000
|
||||
#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000
|
||||
#define PVR5_DCACHE_USE_FSL_MASK 0x02000000
|
||||
#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000
|
||||
#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000
|
||||
#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000
|
||||
#define PVR5_USE_DCACHE_MASK 0x80000000 /* DCU */
|
||||
#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* DCTS */
|
||||
#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 /* DCW */
|
||||
#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 /* DCLL */
|
||||
#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 /* DCBS */
|
||||
#define PVR5_DCACHE_ALWAYS_USED 0x00008000 /* DAU */
|
||||
#define PVR5_DCACHE_USE_WRITEBACK 0x00004000 /* DWB */
|
||||
#define PVR5_DCACHE_INTERFACE 0x00002000 /* DCI */
|
||||
|
||||
/* ICache base address PVR mask */
|
||||
#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF
|
||||
|
@ -178,11 +181,14 @@ struct pvr_s {
|
|||
((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26)
|
||||
#define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK)
|
||||
#define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK)
|
||||
/* FIXME two shifts on one line needs any comment */
|
||||
#define PVR_DCACHE_LINE_LEN(pvr) \
|
||||
(1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21))
|
||||
#define PVR_DCACHE_BYTE_SIZE(pvr) \
|
||||
(1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16))
|
||||
|
||||
#define PVR_DCACHE_USE_WRITEBACK(pvr) \
|
||||
((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14)
|
||||
|
||||
#define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK)
|
||||
#define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK)
|
||||
|
|
|
@ -35,6 +35,8 @@ extern void mmu_reset(void);
|
|||
extern void early_console_reg_tlb_alloc(unsigned int addr);
|
||||
# endif /* CONFIG_MMU */
|
||||
|
||||
extern void of_platform_reset_gpio_probe(void);
|
||||
|
||||
void time_init(void);
|
||||
void init_IRQ(void);
|
||||
void machine_early_init(const char *cmdline, unsigned int ram,
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <asm-generic/cmpxchg.h>
|
||||
#include <asm-generic/cmpxchg-local.h>
|
||||
|
||||
#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
|
||||
|
||||
struct task_struct;
|
||||
struct thread_info;
|
||||
|
||||
|
|
|
@ -272,8 +272,9 @@ static inline int clear_user(char *to, int size)
|
|||
return size;
|
||||
}
|
||||
|
||||
extern unsigned long __copy_tofrom_user(void __user *to,
|
||||
const void __user *from, unsigned long size);
|
||||
#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n))
|
||||
#define __copy_from_user_inatomic(to, from, n) \
|
||||
copy_from_user((to), (from), (n))
|
||||
|
||||
#define copy_to_user(to, from, n) \
|
||||
(access_ok(VERIFY_WRITE, (to), (n)) ? \
|
||||
|
@ -290,10 +291,6 @@ extern unsigned long __copy_tofrom_user(void __user *to,
|
|||
(void __user *)(from), (n)) \
|
||||
: -EFAULT)
|
||||
|
||||
#define __copy_from_user(to, from, n) copy_from_user((to), (from), (n))
|
||||
#define __copy_from_user_inatomic(to, from, n) \
|
||||
copy_from_user((to), (from), (n))
|
||||
|
||||
extern int __strncpy_user(char *to, const char __user *from, int len);
|
||||
extern int __strnlen_user(const char __user *sstr, int len);
|
||||
|
||||
|
@ -305,6 +302,9 @@ extern int __strnlen_user(const char __user *sstr, int len);
|
|||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
extern unsigned long __copy_tofrom_user(void __user *to,
|
||||
const void __user *from, unsigned long size);
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
|
|
|
@ -2,12 +2,22 @@
|
|||
# Makefile
|
||||
#
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
# Do not trace early boot code and low level code
|
||||
CFLAGS_REMOVE_timer.o = -pg
|
||||
CFLAGS_REMOVE_intc.o = -pg
|
||||
CFLAGS_REMOVE_early_printk.o = -pg
|
||||
CFLAGS_REMOVE_selfmod.o = -pg
|
||||
CFLAGS_REMOVE_heartbeat.o = -pg
|
||||
CFLAGS_REMOVE_ftrace.o = -pg
|
||||
endif
|
||||
|
||||
extra-y := head.o vmlinux.lds
|
||||
|
||||
obj-y += exceptions.o \
|
||||
hw_exception_handler.o init_task.o intc.o irq.o of_device.o \
|
||||
of_platform.o process.o prom.o prom_parse.o ptrace.o \
|
||||
setup.o signal.o sys_microblaze.o timer.o traps.o
|
||||
setup.o signal.o sys_microblaze.o timer.o traps.o reset.o
|
||||
|
||||
obj-y += cpu/
|
||||
|
||||
|
@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD) += selfmod.o
|
|||
obj-$(CONFIG_HEART_BEAT) += heartbeat.o
|
||||
obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o
|
||||
obj-$(CONFIG_MMU) += misc.o
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o
|
||||
|
||||
obj-y += entry$(MMU).o
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
# Build the appropriate CPU version support
|
||||
#
|
||||
|
||||
ifdef CONFIG_FUNCTION_TRACER
|
||||
CFLAGS_REMOVE_cache.o = -pg
|
||||
endif
|
||||
|
||||
EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
|
||||
-DCPU_REV=$(CPU_REV)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2007-2009 PetaLogix
|
||||
* Copyright (C) 2007 John Williams <john.williams@petalogix.com>
|
||||
* Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of this
|
||||
|
@ -13,243 +13,534 @@
|
|||
#include <asm/cacheflush.h>
|
||||
#include <linux/cache.h>
|
||||
#include <asm/cpuinfo.h>
|
||||
#include <asm/pvr.h>
|
||||
|
||||
/* Exported functions */
|
||||
|
||||
void _enable_icache(void)
|
||||
static inline void __invalidate_flush_icache(unsigned int addr)
|
||||
{
|
||||
if (cpuinfo.use_icache) {
|
||||
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
__asm__ __volatile__ (" \
|
||||
msrset r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory");
|
||||
#else
|
||||
__asm__ __volatile__ (" \
|
||||
mfs r12, rmsr; \
|
||||
nop; \
|
||||
ori r12, r12, %0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory", "r12");
|
||||
#endif
|
||||
}
|
||||
__asm__ __volatile__ ("wic %0, r0;" \
|
||||
: : "r" (addr));
|
||||
}
|
||||
|
||||
void _disable_icache(void)
|
||||
static inline void __flush_dcache(unsigned int addr)
|
||||
{
|
||||
if (cpuinfo.use_icache) {
|
||||
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
__asm__ __volatile__ (" \
|
||||
msrclr r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory");
|
||||
#else
|
||||
__asm__ __volatile__ (" \
|
||||
mfs r12, rmsr; \
|
||||
nop; \
|
||||
andi r12, r12, ~%0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory", "r12");
|
||||
#endif
|
||||
}
|
||||
__asm__ __volatile__ ("wdc.flush %0, r0;" \
|
||||
: : "r" (addr));
|
||||
}
|
||||
|
||||
void _invalidate_icache(unsigned int addr)
|
||||
static inline void __invalidate_dcache(unsigned int baseaddr,
|
||||
unsigned int offset)
|
||||
{
|
||||
if (cpuinfo.use_icache) {
|
||||
__asm__ __volatile__ (" \
|
||||
wic %0, r0" \
|
||||
: \
|
||||
: "r" (addr));
|
||||
}
|
||||
__asm__ __volatile__ ("wdc.clear %0, %1;" \
|
||||
: : "r" (baseaddr), "r" (offset));
|
||||
}
|
||||
|
||||
void _enable_dcache(void)
|
||||
static inline void __enable_icache_msr(void)
|
||||
{
|
||||
if (cpuinfo.use_dcache) {
|
||||
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
__asm__ __volatile__ (" \
|
||||
msrset r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory");
|
||||
#else
|
||||
__asm__ __volatile__ (" \
|
||||
mfs r12, rmsr; \
|
||||
nop; \
|
||||
ori r12, r12, %0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory", "r12");
|
||||
#endif
|
||||
}
|
||||
__asm__ __volatile__ (" msrset r0, %0; \
|
||||
nop; " \
|
||||
: : "i" (MSR_ICE) : "memory");
|
||||
}
|
||||
|
||||
void _disable_dcache(void)
|
||||
static inline void __disable_icache_msr(void)
|
||||
{
|
||||
#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
__asm__ __volatile__ (" \
|
||||
msrclr r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
__asm__ __volatile__ (" msrclr r0, %0; \
|
||||
nop; " \
|
||||
: : "i" (MSR_ICE) : "memory");
|
||||
}
|
||||
|
||||
static inline void __enable_dcache_msr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" msrset r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory");
|
||||
#else
|
||||
__asm__ __volatile__ (" \
|
||||
mfs r12, rmsr; \
|
||||
nop; \
|
||||
andi r12, r12, ~%0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
}
|
||||
|
||||
static inline void __disable_dcache_msr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" msrclr r0, %0; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void __enable_icache_nomsr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" mfs r12, rmsr; \
|
||||
nop; \
|
||||
ori r12, r12, %0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory", "r12");
|
||||
}
|
||||
|
||||
static inline void __disable_icache_nomsr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" mfs r12, rmsr; \
|
||||
nop; \
|
||||
andi r12, r12, ~%0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_ICE) \
|
||||
: "memory", "r12");
|
||||
}
|
||||
|
||||
static inline void __enable_dcache_nomsr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" mfs r12, rmsr; \
|
||||
nop; \
|
||||
ori r12, r12, %0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory", "r12");
|
||||
}
|
||||
|
||||
static inline void __disable_dcache_nomsr(void)
|
||||
{
|
||||
__asm__ __volatile__ (" mfs r12, rmsr; \
|
||||
nop; \
|
||||
andi r12, r12, ~%0; \
|
||||
mts rmsr, r12; \
|
||||
nop; " \
|
||||
: \
|
||||
: "i" (MSR_DCE) \
|
||||
: "memory", "r12");
|
||||
}
|
||||
|
||||
|
||||
/* Helper macro for computing the limits of cache range loops */
|
||||
#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);
|
||||
|
||||
/*
|
||||
* Helper macro to loop over the specified cache_size/line_length and
|
||||
* execute 'op' on that cacheline
|
||||
*/
|
||||
#define CACHE_ALL_LOOP(cache_size, line_length, op) \
|
||||
do { \
|
||||
unsigned int len = cache_size; \
|
||||
int step = -line_length; \
|
||||
BUG_ON(step >= 0); \
|
||||
\
|
||||
__asm__ __volatile__ (" 1: " #op " %0, r0; \
|
||||
bgtid %0, 1b; \
|
||||
addk %0, %0, %1; \
|
||||
" : : "r" (len), "r" (step) \
|
||||
: "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 */
|
||||
#define CACHE_RANGE_LOOP_2(start, end, line_length, op) \
|
||||
do { \
|
||||
int step = -line_length; \
|
||||
int count = end - start; \
|
||||
BUG_ON(count <= 0); \
|
||||
\
|
||||
__asm__ __volatile__ (" 1: " #op " %0, %1; \
|
||||
bgtid %1, 1b; \
|
||||
addk %1, %1, %2; \
|
||||
" : : "r" (start), "r" (count), \
|
||||
"r" (step) : "memory"); \
|
||||
} while (0);
|
||||
|
||||
/* It is used only first parameter for OP - for wic, wdc */
|
||||
#define CACHE_RANGE_LOOP_1(start, end, line_length, op) \
|
||||
do { \
|
||||
int step = -line_length; \
|
||||
int count = end - start; \
|
||||
BUG_ON(count <= 0); \
|
||||
\
|
||||
__asm__ __volatile__ (" 1: addk %0, %0, %1; \
|
||||
" #op " %0, r0; \
|
||||
bgtid %1, 1b; \
|
||||
addk %1, %1, %2; \
|
||||
" : : "r" (start), "r" (count), \
|
||||
"r" (step) : "memory"); \
|
||||
} while (0);
|
||||
|
||||
static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.icache_line_length, cpuinfo.icache_size);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_icache_msr();
|
||||
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
|
||||
|
||||
__enable_icache_msr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __flush_icache_range_nomsr_irq(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.icache_line_length, cpuinfo.icache_size);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_icache_nomsr();
|
||||
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
|
||||
|
||||
__enable_icache_nomsr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __flush_icache_range_noirq(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.icache_line_length, cpuinfo.icache_size);
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
|
||||
}
|
||||
|
||||
static void __flush_icache_all_msr_irq(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_icache_msr();
|
||||
|
||||
CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
|
||||
|
||||
__enable_icache_msr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __flush_icache_all_nomsr_irq(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_icache_nomsr();
|
||||
|
||||
CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
|
||||
|
||||
__enable_icache_nomsr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __flush_icache_all_noirq(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
|
||||
}
|
||||
|
||||
static void __invalidate_dcache_all_msr_irq(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_dcache_msr();
|
||||
|
||||
CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
|
||||
|
||||
__enable_dcache_msr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __invalidate_dcache_all_nomsr_irq(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_dcache_nomsr();
|
||||
|
||||
CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
|
||||
|
||||
__enable_dcache_nomsr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __invalidate_dcache_all_noirq_wt(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc)
|
||||
}
|
||||
|
||||
/* FIXME this is weird - should be only wdc but not work
|
||||
* MS: I am getting bus errors and other weird things */
|
||||
static void __invalidate_dcache_all_wb(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
|
||||
wdc.clear)
|
||||
|
||||
#if 0
|
||||
unsigned int i;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
/* Just loop through cache size and invalidate it */
|
||||
for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length)
|
||||
__invalidate_dcache(0, i);
|
||||
#endif
|
||||
}
|
||||
|
||||
void _invalidate_dcache(unsigned int addr)
|
||||
static void __invalidate_dcache_range_wb(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
__asm__ __volatile__ (" \
|
||||
wdc %0, r0" \
|
||||
: \
|
||||
: "r" (addr));
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.dcache_line_length, cpuinfo.dcache_size);
|
||||
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
|
||||
}
|
||||
|
||||
void __invalidate_icache_all(void)
|
||||
static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned flags;
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.dcache_line_length, cpuinfo.dcache_size);
|
||||
|
||||
if (cpuinfo.use_icache) {
|
||||
local_irq_save(flags);
|
||||
__disable_icache();
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
|
||||
}
|
||||
|
||||
/* Just loop through cache size and invalidate, no need to add
|
||||
CACHE_BASE address */
|
||||
for (i = 0; i < cpuinfo.icache_size;
|
||||
i += cpuinfo.icache_line)
|
||||
__invalidate_icache(i);
|
||||
static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
__enable_icache();
|
||||
local_irq_restore(flags);
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.dcache_line_length, cpuinfo.dcache_size);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_dcache_msr();
|
||||
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
|
||||
|
||||
__enable_dcache_msr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
|
||||
unsigned long end)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.dcache_line_length, cpuinfo.dcache_size);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_dcache_nomsr();
|
||||
|
||||
CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
|
||||
|
||||
__enable_dcache_nomsr();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void __flush_dcache_all_wb(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
|
||||
wdc.flush);
|
||||
}
|
||||
|
||||
static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
|
||||
{
|
||||
pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
|
||||
(unsigned int)start, (unsigned int) end);
|
||||
|
||||
CACHE_LOOP_LIMITS(start, end,
|
||||
cpuinfo.dcache_line_length, cpuinfo.dcache_size);
|
||||
CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
|
||||
}
|
||||
|
||||
/* struct for wb caches and for wt caches */
|
||||
struct scache *mbc;
|
||||
|
||||
/* new wb cache model */
|
||||
const struct scache wb_msr = {
|
||||
.ie = __enable_icache_msr,
|
||||
.id = __disable_icache_msr,
|
||||
.ifl = __flush_icache_all_noirq,
|
||||
.iflr = __flush_icache_range_noirq,
|
||||
.iin = __flush_icache_all_noirq,
|
||||
.iinr = __flush_icache_range_noirq,
|
||||
.de = __enable_dcache_msr,
|
||||
.dd = __disable_dcache_msr,
|
||||
.dfl = __flush_dcache_all_wb,
|
||||
.dflr = __flush_dcache_range_wb,
|
||||
.din = __invalidate_dcache_all_wb,
|
||||
.dinr = __invalidate_dcache_range_wb,
|
||||
};
|
||||
|
||||
/* There is only difference in ie, id, de, dd functions */
|
||||
const struct scache wb_nomsr = {
|
||||
.ie = __enable_icache_nomsr,
|
||||
.id = __disable_icache_nomsr,
|
||||
.ifl = __flush_icache_all_noirq,
|
||||
.iflr = __flush_icache_range_noirq,
|
||||
.iin = __flush_icache_all_noirq,
|
||||
.iinr = __flush_icache_range_noirq,
|
||||
.de = __enable_dcache_nomsr,
|
||||
.dd = __disable_dcache_nomsr,
|
||||
.dfl = __flush_dcache_all_wb,
|
||||
.dflr = __flush_dcache_range_wb,
|
||||
.din = __invalidate_dcache_all_wb,
|
||||
.dinr = __invalidate_dcache_range_wb,
|
||||
};
|
||||
|
||||
/* Old wt cache model with disabling irq and turn off cache */
|
||||
const struct scache wt_msr = {
|
||||
.ie = __enable_icache_msr,
|
||||
.id = __disable_icache_msr,
|
||||
.ifl = __flush_icache_all_msr_irq,
|
||||
.iflr = __flush_icache_range_msr_irq,
|
||||
.iin = __flush_icache_all_msr_irq,
|
||||
.iinr = __flush_icache_range_msr_irq,
|
||||
.de = __enable_dcache_msr,
|
||||
.dd = __disable_dcache_msr,
|
||||
.dfl = __invalidate_dcache_all_msr_irq,
|
||||
.dflr = __invalidate_dcache_range_msr_irq_wt,
|
||||
.din = __invalidate_dcache_all_msr_irq,
|
||||
.dinr = __invalidate_dcache_range_msr_irq_wt,
|
||||
};
|
||||
|
||||
const struct scache wt_nomsr = {
|
||||
.ie = __enable_icache_nomsr,
|
||||
.id = __disable_icache_nomsr,
|
||||
.ifl = __flush_icache_all_nomsr_irq,
|
||||
.iflr = __flush_icache_range_nomsr_irq,
|
||||
.iin = __flush_icache_all_nomsr_irq,
|
||||
.iinr = __flush_icache_range_nomsr_irq,
|
||||
.de = __enable_dcache_nomsr,
|
||||
.dd = __disable_dcache_nomsr,
|
||||
.dfl = __invalidate_dcache_all_nomsr_irq,
|
||||
.dflr = __invalidate_dcache_range_nomsr_irq,
|
||||
.din = __invalidate_dcache_all_nomsr_irq,
|
||||
.dinr = __invalidate_dcache_range_nomsr_irq,
|
||||
};
|
||||
|
||||
/* New wt cache model for newer Microblaze versions */
|
||||
const struct scache wt_msr_noirq = {
|
||||
.ie = __enable_icache_msr,
|
||||
.id = __disable_icache_msr,
|
||||
.ifl = __flush_icache_all_noirq,
|
||||
.iflr = __flush_icache_range_noirq,
|
||||
.iin = __flush_icache_all_noirq,
|
||||
.iinr = __flush_icache_range_noirq,
|
||||
.de = __enable_dcache_msr,
|
||||
.dd = __disable_dcache_msr,
|
||||
.dfl = __invalidate_dcache_all_noirq_wt,
|
||||
.dflr = __invalidate_dcache_range_nomsr_wt,
|
||||
.din = __invalidate_dcache_all_noirq_wt,
|
||||
.dinr = __invalidate_dcache_range_nomsr_wt,
|
||||
};
|
||||
|
||||
const struct scache wt_nomsr_noirq = {
|
||||
.ie = __enable_icache_nomsr,
|
||||
.id = __disable_icache_nomsr,
|
||||
.ifl = __flush_icache_all_noirq,
|
||||
.iflr = __flush_icache_range_noirq,
|
||||
.iin = __flush_icache_all_noirq,
|
||||
.iinr = __flush_icache_range_noirq,
|
||||
.de = __enable_dcache_nomsr,
|
||||
.dd = __disable_dcache_nomsr,
|
||||
.dfl = __invalidate_dcache_all_noirq_wt,
|
||||
.dflr = __invalidate_dcache_range_nomsr_wt,
|
||||
.din = __invalidate_dcache_all_noirq_wt,
|
||||
.dinr = __invalidate_dcache_range_nomsr_wt,
|
||||
};
|
||||
|
||||
/* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */
|
||||
#define CPUVER_7_20_A 0x0c
|
||||
#define CPUVER_7_20_D 0x0f
|
||||
|
||||
#define INFO(s) printk(KERN_INFO "cache: " s " \n");
|
||||
|
||||
void microblaze_cache_init(void)
|
||||
{
|
||||
if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
|
||||
if (cpuinfo.dcache_wb) {
|
||||
INFO("wb_msr");
|
||||
mbc = (struct scache *)&wb_msr;
|
||||
if (cpuinfo.ver_code < CPUVER_7_20_D) {
|
||||
/* MS: problem with signal handling - hw bug */
|
||||
INFO("WB won't work properly");
|
||||
}
|
||||
} else {
|
||||
if (cpuinfo.ver_code >= CPUVER_7_20_A) {
|
||||
INFO("wt_msr_noirq");
|
||||
mbc = (struct scache *)&wt_msr_noirq;
|
||||
} else {
|
||||
INFO("wt_msr");
|
||||
mbc = (struct scache *)&wt_msr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (cpuinfo.dcache_wb) {
|
||||
INFO("wb_nomsr");
|
||||
mbc = (struct scache *)&wb_nomsr;
|
||||
if (cpuinfo.ver_code < CPUVER_7_20_D) {
|
||||
/* MS: problem with signal handling - hw bug */
|
||||
INFO("WB won't work properly");
|
||||
}
|
||||
} else {
|
||||
if (cpuinfo.ver_code >= CPUVER_7_20_A) {
|
||||
INFO("wt_nomsr_noirq");
|
||||
mbc = (struct scache *)&wt_nomsr_noirq;
|
||||
} else {
|
||||
INFO("wt_nomsr");
|
||||
mbc = (struct scache *)&wt_nomsr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __invalidate_icache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned flags;
|
||||
unsigned int align;
|
||||
|
||||
if (cpuinfo.use_icache) {
|
||||
/*
|
||||
* No need to cover entire cache range,
|
||||
* just cover cache footprint
|
||||
*/
|
||||
end = min(start + cpuinfo.icache_size, end);
|
||||
align = ~(cpuinfo.icache_line - 1);
|
||||
start &= align; /* Make sure we are aligned */
|
||||
/* Push end up to the next cache line */
|
||||
end = ((end & align) + cpuinfo.icache_line);
|
||||
|
||||
local_irq_save(flags);
|
||||
__disable_icache();
|
||||
|
||||
for (i = start; i < end; i += cpuinfo.icache_line)
|
||||
__invalidate_icache(i);
|
||||
|
||||
__enable_icache();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page)
|
||||
{
|
||||
__invalidate_icache_all();
|
||||
}
|
||||
|
||||
void __invalidate_icache_user_range(struct vm_area_struct *vma,
|
||||
struct page *page, unsigned long adr,
|
||||
int len)
|
||||
{
|
||||
__invalidate_icache_all();
|
||||
}
|
||||
|
||||
void __invalidate_cache_sigtramp(unsigned long addr)
|
||||
{
|
||||
__invalidate_icache_range(addr, addr + 8);
|
||||
}
|
||||
|
||||
void __invalidate_dcache_all(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned flags;
|
||||
|
||||
if (cpuinfo.use_dcache) {
|
||||
local_irq_save(flags);
|
||||
__disable_dcache();
|
||||
|
||||
/*
|
||||
* Just loop through cache size and invalidate,
|
||||
* no need to add CACHE_BASE address
|
||||
*/
|
||||
for (i = 0; i < cpuinfo.dcache_size;
|
||||
i += cpuinfo.dcache_line)
|
||||
__invalidate_dcache(i);
|
||||
|
||||
__enable_dcache();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void __invalidate_dcache_range(unsigned long start, unsigned long end)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned flags;
|
||||
unsigned int align;
|
||||
|
||||
if (cpuinfo.use_dcache) {
|
||||
/*
|
||||
* No need to cover entire cache range,
|
||||
* just cover cache footprint
|
||||
*/
|
||||
end = min(start + cpuinfo.dcache_size, end);
|
||||
align = ~(cpuinfo.dcache_line - 1);
|
||||
start &= align; /* Make sure we are aligned */
|
||||
/* Push end up to the next cache line */
|
||||
end = ((end & align) + cpuinfo.dcache_line);
|
||||
local_irq_save(flags);
|
||||
__disable_dcache();
|
||||
|
||||
for (i = start; i < end; i += cpuinfo.dcache_line)
|
||||
__invalidate_dcache(i);
|
||||
|
||||
__enable_dcache();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page)
|
||||
{
|
||||
__invalidate_dcache_all();
|
||||
}
|
||||
|
||||
void __invalidate_dcache_user_range(struct vm_area_struct *vma,
|
||||
struct page *page, unsigned long adr,
|
||||
int len)
|
||||
{
|
||||
__invalidate_dcache_all();
|
||||
}
|
||||
|
|
|
@ -21,8 +21,14 @@
|
|||
*/
|
||||
|
||||
#define CI(c, p) { ci->c = PVR_##p(pvr); }
|
||||
|
||||
#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
|
||||
#define err_printk(x) \
|
||||
early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
|
||||
#else
|
||||
#define err_printk(x) \
|
||||
printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n");
|
||||
#endif
|
||||
|
||||
void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
|
||||
{
|
||||
|
@ -70,7 +76,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
|
|||
CI(use_icache, USE_ICACHE);
|
||||
CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
|
||||
CI(icache_write, ICACHE_ALLOW_WR);
|
||||
CI(icache_line, ICACHE_LINE_LEN);
|
||||
ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2;
|
||||
CI(icache_size, ICACHE_BYTE_SIZE);
|
||||
CI(icache_base, ICACHE_BASEADDR);
|
||||
CI(icache_high, ICACHE_HIGHADDR);
|
||||
|
@ -78,11 +84,16 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
|
|||
CI(use_dcache, USE_DCACHE);
|
||||
CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS);
|
||||
CI(dcache_write, DCACHE_ALLOW_WR);
|
||||
CI(dcache_line, DCACHE_LINE_LEN);
|
||||
ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2;
|
||||
CI(dcache_size, DCACHE_BYTE_SIZE);
|
||||
CI(dcache_base, DCACHE_BASEADDR);
|
||||
CI(dcache_high, DCACHE_HIGHADDR);
|
||||
|
||||
temp = PVR_DCACHE_USE_WRITEBACK(pvr);
|
||||
if (ci->dcache_wb != temp)
|
||||
err_printk("DCACHE WB");
|
||||
ci->dcache_wb = temp;
|
||||
|
||||
CI(use_dopb, D_OPB);
|
||||
CI(use_iopb, I_OPB);
|
||||
CI(use_dlmb, D_LMB);
|
||||
|
|
|
@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
|
|||
ci->use_icache = fcpu(cpu, "xlnx,use-icache");
|
||||
ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits");
|
||||
ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr");
|
||||
ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2;
|
||||
if (!ci->icache_line) {
|
||||
ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2;
|
||||
if (!ci->icache_line_length) {
|
||||
if (fcpu(cpu, "xlnx,icache-use-fsl"))
|
||||
ci->icache_line = 4 << 2;
|
||||
ci->icache_line_length = 4 << 2;
|
||||
else
|
||||
ci->icache_line = 1 << 2;
|
||||
ci->icache_line_length = 1 << 2;
|
||||
}
|
||||
ci->icache_size = fcpu(cpu, "i-cache-size");
|
||||
ci->icache_base = fcpu(cpu, "i-cache-baseaddr");
|
||||
|
@ -86,16 +86,17 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
|
|||
ci->use_dcache = fcpu(cpu, "xlnx,use-dcache");
|
||||
ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag");
|
||||
ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr");
|
||||
ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2;
|
||||
if (!ci->dcache_line) {
|
||||
ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2;
|
||||
if (!ci->dcache_line_length) {
|
||||
if (fcpu(cpu, "xlnx,dcache-use-fsl"))
|
||||
ci->dcache_line = 4 << 2;
|
||||
ci->dcache_line_length = 4 << 2;
|
||||
else
|
||||
ci->dcache_line = 1 << 2;
|
||||
ci->dcache_line_length = 1 << 2;
|
||||
}
|
||||
ci->dcache_size = fcpu(cpu, "d-cache-size");
|
||||
ci->dcache_base = fcpu(cpu, "d-cache-baseaddr");
|
||||
ci->dcache_high = fcpu(cpu, "d-cache-highaddr");
|
||||
ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback");
|
||||
|
||||
ci->use_dopb = fcpu(cpu, "xlnx,d-opb");
|
||||
ci->use_iopb = fcpu(cpu, "xlnx,i-opb");
|
||||
|
|
|
@ -29,11 +29,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
|
|||
{"7.20.a", 0x0c},
|
||||
{"7.20.b", 0x0d},
|
||||
{"7.20.c", 0x0e},
|
||||
/* FIXME There is no keycode defined in MBV for these versions */
|
||||
{"2.10.a", 0x10},
|
||||
{"3.00.a", 0x20},
|
||||
{"4.00.a", 0x30},
|
||||
{"4.00.b", 0x40},
|
||||
{"7.20.d", 0x0f},
|
||||
{"7.30.a", 0x10},
|
||||
{NULL, 0},
|
||||
};
|
||||
|
||||
|
|
|
@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
else
|
||||
count += seq_printf(m, "Icache:\t\tno\n");
|
||||
|
||||
if (cpuinfo.use_dcache)
|
||||
if (cpuinfo.use_dcache) {
|
||||
count += seq_printf(m,
|
||||
"Dcache:\t\t%ukB\n",
|
||||
cpuinfo.dcache_size >> 10);
|
||||
else
|
||||
if (cpuinfo.dcache_wb)
|
||||
count += seq_printf(m, "\t\twrite-back\n");
|
||||
else
|
||||
count += seq_printf(m, "\t\twrite-through\n");
|
||||
} else
|
||||
count += seq_printf(m, "Dcache:\t\tno\n");
|
||||
|
||||
count += seq_printf(m,
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
int cpu_has_pvr(void)
|
||||
{
|
||||
unsigned flags;
|
||||
unsigned long flags;
|
||||
unsigned pvr0;
|
||||
|
||||
local_save_flags(flags);
|
||||
|
|
|
@ -208,8 +208,6 @@ ENTRY(_user_exception)
|
|||
lwi r1, r1, TS_THREAD_INFO /* get the thread info */
|
||||
/* calculate kernel stack pointer */
|
||||
addik r1, r1, THREAD_SIZE - PT_SIZE
|
||||
swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */
|
||||
lwi r11, r0, PER_CPU(KM) /* load mode indicator */
|
||||
2:
|
||||
swi r11, r1, PT_MODE /* store the mode */
|
||||
lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <linux/errno.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
/* The size of a state save frame. */
|
||||
#define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE)
|
||||
|
||||
|
@ -352,10 +354,12 @@ C_ENTRY(_user_exception):
|
|||
add r12, r12, r12; /* convert num -> ptr */
|
||||
add r12, r12, r12;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Trac syscalls and stored them to r0_ram */
|
||||
lwi r3, r12, 0x400 + r0_ram
|
||||
addi r3, r3, 1
|
||||
swi r3, r12, 0x400 + r0_ram
|
||||
#endif
|
||||
|
||||
# Find and jump into the syscall handler.
|
||||
lwi r12, r12, sys_call_table
|
||||
|
@ -496,17 +500,6 @@ C_ENTRY(sys_execve):
|
|||
brid microblaze_execve; /* Do real work (tail-call).*/
|
||||
nop;
|
||||
|
||||
C_ENTRY(sys_rt_sigsuspend_wrapper):
|
||||
swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
|
||||
swi r4, r1, PTO+PT_R4;
|
||||
la r7, r1, PTO; /* add user context as 3rd arg */
|
||||
brlid r15, sys_rt_sigsuspend; /* Do real work.*/
|
||||
nop;
|
||||
lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
|
||||
lwi r4, r1, PTO+PT_R4;
|
||||
bri ret_from_trap /* fall through will not work here due to align */
|
||||
nop;
|
||||
|
||||
C_ENTRY(sys_rt_sigreturn_wrapper):
|
||||
swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
|
||||
swi r4, r1, PTO+PT_R4;
|
||||
|
@ -711,15 +704,11 @@ C_ENTRY(ret_from_exc):
|
|||
* (in a possibly modified form) after do_signal returns.
|
||||
* store return registers separately because this macros is use
|
||||
* for others exceptions */
|
||||
swi r3, r1, PTO + PT_R3;
|
||||
swi r4, r1, PTO + PT_R4;
|
||||
la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
|
||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
||||
bralid r15, do_signal; /* Handle any signals */
|
||||
nop;
|
||||
lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
|
||||
lwi r4, r1, PTO+PT_R4;
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */
|
||||
|
|
237
arch/microblaze/kernel/ftrace.c
Normal file
237
arch/microblaze/kernel/ftrace.c
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* Ftrace support for Microblaze.
|
||||
*
|
||||
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2009 PetaLogix
|
||||
*
|
||||
* Based on MIPS and PowerPC ftrace code
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <linux/ftrace.h>
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
/*
|
||||
* Hook the return address and push it in the stack of return addrs
|
||||
* in current thread info.
|
||||
*/
|
||||
void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
|
||||
{
|
||||
unsigned long old;
|
||||
int faulted, err;
|
||||
struct ftrace_graph_ent trace;
|
||||
unsigned long return_hooker = (unsigned long)
|
||||
&return_to_handler;
|
||||
|
||||
if (unlikely(atomic_read(¤t->tracing_graph_pause)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Protect against fault, even if it shouldn't
|
||||
* happen. This tool is too much intrusive to
|
||||
* ignore such a protection.
|
||||
*/
|
||||
asm volatile(" 1: lwi %0, %2, 0; \
|
||||
2: swi %3, %2, 0; \
|
||||
addik %1, r0, 0; \
|
||||
3: \
|
||||
.section .fixup, \"ax\"; \
|
||||
4: brid 3b; \
|
||||
addik %1, r0, 1; \
|
||||
.previous; \
|
||||
.section __ex_table,\"a\"; \
|
||||
.word 1b,4b; \
|
||||
.word 2b,4b; \
|
||||
.previous;" \
|
||||
: "=&r" (old), "=r" (faulted)
|
||||
: "r" (parent), "r" (return_hooker)
|
||||
);
|
||||
|
||||
if (unlikely(faulted)) {
|
||||
ftrace_graph_stop();
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0);
|
||||
if (err == -EBUSY) {
|
||||
*parent = old;
|
||||
return;
|
||||
}
|
||||
|
||||
trace.func = self_addr;
|
||||
/* Only trace if the calling function expects to */
|
||||
if (!ftrace_graph_entry(&trace)) {
|
||||
current->curr_ret_stack--;
|
||||
*parent = old;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
/* save value to addr - it is save to do it in asm */
|
||||
static int ftrace_modify_code(unsigned long addr, unsigned int value)
|
||||
{
|
||||
int faulted = 0;
|
||||
|
||||
__asm__ __volatile__(" 1: swi %2, %1, 0; \
|
||||
addik %0, r0, 0; \
|
||||
2: \
|
||||
.section .fixup, \"ax\"; \
|
||||
3: brid 2b; \
|
||||
addik %0, r0, 1; \
|
||||
.previous; \
|
||||
.section __ex_table,\"a\"; \
|
||||
.word 1b,3b; \
|
||||
.previous;" \
|
||||
: "=r" (faulted)
|
||||
: "r" (addr), "r" (value)
|
||||
);
|
||||
|
||||
if (unlikely(faulted))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MICROBLAZE_NOP 0x80000000
|
||||
#define MICROBLAZE_BRI 0xb800000C
|
||||
|
||||
static unsigned int recorded; /* if save was or not */
|
||||
static unsigned int imm; /* saving whole imm instruction */
|
||||
|
||||
/* There are two approaches howto solve ftrace_make nop function - look below */
|
||||
#undef USE_FTRACE_NOP
|
||||
|
||||
#ifdef USE_FTRACE_NOP
|
||||
static unsigned int bralid; /* saving whole bralid instruction */
|
||||
#endif
|
||||
|
||||
int ftrace_make_nop(struct module *mod,
|
||||
struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
/* we have this part of code which we are working with
|
||||
* b000c000 imm -16384
|
||||
* b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount>
|
||||
* 80000000 or r0, r0, r0
|
||||
*
|
||||
* The first solution (!USE_FTRACE_NOP-could be called branch solution)
|
||||
* b000c000 bri 12 (0xC - jump to any other instruction)
|
||||
* b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount>
|
||||
* 80000000 or r0, r0, r0
|
||||
* any other instruction
|
||||
*
|
||||
* The second solution (USE_FTRACE_NOP) - no jump just nops
|
||||
* 80000000 or r0, r0, r0
|
||||
* 80000000 or r0, r0, r0
|
||||
* 80000000 or r0, r0, r0
|
||||
*/
|
||||
int ret = 0;
|
||||
|
||||
if (recorded == 0) {
|
||||
recorded = 1;
|
||||
imm = *(unsigned int *)rec->ip;
|
||||
pr_debug("%s: imm:0x%x\n", __func__, imm);
|
||||
#ifdef USE_FTRACE_NOP
|
||||
bralid = *(unsigned int *)(rec->ip + 4);
|
||||
pr_debug("%s: bralid 0x%x\n", __func__, bralid);
|
||||
#endif /* USE_FTRACE_NOP */
|
||||
}
|
||||
|
||||
#ifdef USE_FTRACE_NOP
|
||||
ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP);
|
||||
ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP);
|
||||
#else /* USE_FTRACE_NOP */
|
||||
ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI);
|
||||
#endif /* USE_FTRACE_NOP */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ret_addr; /* initialized as 0 by default */
|
||||
|
||||
/* I believe that first is called ftrace_make_nop before this function */
|
||||
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
int ret;
|
||||
ret_addr = addr; /* saving where the barrier jump is */
|
||||
pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n",
|
||||
__func__, (unsigned int)addr, (unsigned int)rec->ip, imm);
|
||||
ret = ftrace_modify_code(rec->ip, imm);
|
||||
#ifdef USE_FTRACE_NOP
|
||||
pr_debug("%s: bralid:0x%x\n", __func__, bralid);
|
||||
ret += ftrace_modify_code(rec->ip + 4, bralid);
|
||||
#endif /* USE_FTRACE_NOP */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int __init ftrace_dyn_arch_init(void *data)
|
||||
{
|
||||
/* The return code is retured via data */
|
||||
*(unsigned long *)data = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||
{
|
||||
unsigned long ip = (unsigned long)(&ftrace_call);
|
||||
unsigned int upper = (unsigned int)func;
|
||||
unsigned int lower = (unsigned int)func;
|
||||
int ret = 0;
|
||||
|
||||
/* create proper saving to ftrace_call poll */
|
||||
upper = 0xb0000000 + (upper >> 16); /* imm func_upper */
|
||||
lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */
|
||||
|
||||
pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n",
|
||||
__func__, (unsigned int)func, (unsigned int)ip, upper, lower);
|
||||
|
||||
/* save upper and lower code */
|
||||
ret = ftrace_modify_code(ip, upper);
|
||||
ret += ftrace_modify_code(ip + 4, lower);
|
||||
|
||||
/* We just need to remove the rtsd r15, 8 by NOP */
|
||||
BUG_ON(!ret_addr);
|
||||
if (ret_addr)
|
||||
ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP);
|
||||
else
|
||||
ret = 1; /* fault */
|
||||
|
||||
/* All changes are done - lets do caches consistent */
|
||||
flush_icache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
unsigned int old_jump; /* saving place for jump instruction */
|
||||
|
||||
int ftrace_enable_ftrace_graph_caller(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
unsigned long ip = (unsigned long)(&ftrace_call_graph);
|
||||
|
||||
old_jump = *(unsigned int *)ip; /* save jump over instruction */
|
||||
ret = ftrace_modify_code(ip, MICROBLAZE_NOP);
|
||||
flush_icache();
|
||||
|
||||
pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ftrace_disable_ftrace_graph_caller(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
unsigned long ip = (unsigned long)(&ftrace_call_graph);
|
||||
|
||||
ret = ftrace_modify_code(ip, old_jump);
|
||||
flush_icache();
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
|
@ -45,6 +45,7 @@ void heartbeat(void)
|
|||
void setup_heartbeat(void)
|
||||
{
|
||||
struct device_node *gpio = NULL;
|
||||
int *prop;
|
||||
int j;
|
||||
char *gpio_list[] = {
|
||||
"xlnx,xps-gpio-1.00.a",
|
||||
|
@ -58,10 +59,14 @@ void setup_heartbeat(void)
|
|||
break;
|
||||
}
|
||||
|
||||
base_addr = *(int *) of_get_property(gpio, "reg", NULL);
|
||||
base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
|
||||
printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
|
||||
if (gpio) {
|
||||
base_addr = *(int *) of_get_property(gpio, "reg", NULL);
|
||||
base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
|
||||
printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
|
||||
|
||||
if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL))
|
||||
out_be32(base_addr + 4, 0); /* GPIO is configured as output */
|
||||
/* GPIO is configured as output */
|
||||
prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL);
|
||||
if (prop)
|
||||
out_be32(base_addr + 4, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,16 @@ unsigned int nr_irq;
|
|||
|
||||
static void intc_enable_or_unmask(unsigned int irq)
|
||||
{
|
||||
unsigned long mask = 1 << irq;
|
||||
pr_debug("enable_or_unmask: %d\n", irq);
|
||||
out_be32(INTC_BASE + SIE, 1 << irq);
|
||||
out_be32(INTC_BASE + SIE, mask);
|
||||
|
||||
/* ack level irqs because they can't be acked during
|
||||
* ack function since the handle_level_irq function
|
||||
* acks the irq before calling the interrupt handler
|
||||
*/
|
||||
if (irq_desc[irq].status & IRQ_LEVEL)
|
||||
out_be32(INTC_BASE + IAR, mask);
|
||||
}
|
||||
|
||||
static void intc_disable_or_mask(unsigned int irq)
|
||||
|
|
170
arch/microblaze/kernel/mcount.S
Normal file
170
arch/microblaze/kernel/mcount.S
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Low-level ftrace handling
|
||||
*
|
||||
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2009 PetaLogix
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General
|
||||
* Public License. See the file COPYING in the main directory of this
|
||||
* archive for more details.
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#define NOALIGN_ENTRY(name) .globl name; name:
|
||||
|
||||
/* FIXME MS: I think that I don't need to save all regs */
|
||||
#define SAVE_REGS \
|
||||
addik r1, r1, -120; \
|
||||
swi r2, r1, 4; \
|
||||
swi r3, r1, 8; \
|
||||
swi r4, r1, 12; \
|
||||
swi r5, r1, 116; \
|
||||
swi r6, r1, 16; \
|
||||
swi r7, r1, 20; \
|
||||
swi r8, r1, 24; \
|
||||
swi r9, r1, 28; \
|
||||
swi r10, r1, 32; \
|
||||
swi r11, r1, 36; \
|
||||
swi r12, r1, 40; \
|
||||
swi r13, r1, 44; \
|
||||
swi r14, r1, 48; \
|
||||
swi r16, r1, 52; \
|
||||
swi r17, r1, 56; \
|
||||
swi r18, r1, 60; \
|
||||
swi r19, r1, 64; \
|
||||
swi r20, r1, 68; \
|
||||
swi r21, r1, 72; \
|
||||
swi r22, r1, 76; \
|
||||
swi r23, r1, 80; \
|
||||
swi r24, r1, 84; \
|
||||
swi r25, r1, 88; \
|
||||
swi r26, r1, 92; \
|
||||
swi r27, r1, 96; \
|
||||
swi r28, r1, 100; \
|
||||
swi r29, r1, 104; \
|
||||
swi r30, r1, 108; \
|
||||
swi r31, r1, 112;
|
||||
|
||||
#define RESTORE_REGS \
|
||||
lwi r2, r1, 4; \
|
||||
lwi r3, r1, 8; \
|
||||
lwi r4, r1, 12; \
|
||||
lwi r5, r1, 116; \
|
||||
lwi r6, r1, 16; \
|
||||
lwi r7, r1, 20; \
|
||||
lwi r8, r1, 24; \
|
||||
lwi r9, r1, 28; \
|
||||
lwi r10, r1, 32; \
|
||||
lwi r11, r1, 36; \
|
||||
lwi r12, r1, 40; \
|
||||
lwi r13, r1, 44; \
|
||||
lwi r14, r1, 48; \
|
||||
lwi r16, r1, 52; \
|
||||
lwi r17, r1, 56; \
|
||||
lwi r18, r1, 60; \
|
||||
lwi r19, r1, 64; \
|
||||
lwi r20, r1, 68; \
|
||||
lwi r21, r1, 72; \
|
||||
lwi r22, r1, 76; \
|
||||
lwi r23, r1, 80; \
|
||||
lwi r24, r1, 84; \
|
||||
lwi r25, r1, 88; \
|
||||
lwi r26, r1, 92; \
|
||||
lwi r27, r1, 96; \
|
||||
lwi r28, r1, 100; \
|
||||
lwi r29, r1, 104; \
|
||||
lwi r30, r1, 108; \
|
||||
lwi r31, r1, 112; \
|
||||
addik r1, r1, 120;
|
||||
|
||||
ENTRY(ftrace_stub)
|
||||
rtsd r15, 8;
|
||||
nop;
|
||||
|
||||
ENTRY(_mcount)
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
ENTRY(ftrace_caller)
|
||||
/* MS: It is just barrier which is removed from C code */
|
||||
rtsd r15, 8
|
||||
nop
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
SAVE_REGS
|
||||
swi r15, r1, 0;
|
||||
/* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */
|
||||
lwi r5, r0, function_trace_stop;
|
||||
bneid r5, end;
|
||||
nop;
|
||||
/* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||
lwi r5, r0, ftrace_graph_return;
|
||||
addik r6, r0, ftrace_stub; /* asm implementation */
|
||||
cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */
|
||||
beqid r5, end_graph_tracer;
|
||||
nop;
|
||||
|
||||
lwi r6, r0, ftrace_graph_entry;
|
||||
addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */
|
||||
cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */
|
||||
beqid r5, end_graph_tracer;
|
||||
nop;
|
||||
#else /* CONFIG_DYNAMIC_FTRACE */
|
||||
NOALIGN_ENTRY(ftrace_call_graph)
|
||||
/* MS: jump over graph function - replaced from C code */
|
||||
bri end_graph_tracer
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
addik r5, r1, 120; /* MS: load parent addr */
|
||||
addik r6, r15, 0; /* MS: load current function addr */
|
||||
bralid r15, prepare_ftrace_return;
|
||||
nop;
|
||||
/* MS: graph was taken that's why - can jump over function trace */
|
||||
brid end;
|
||||
nop;
|
||||
end_graph_tracer:
|
||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||
#ifndef CONFIG_DYNAMIC_FTRACE
|
||||
/* MS: test function trace if is taken or not */
|
||||
lwi r20, r0, ftrace_trace_function;
|
||||
addik r6, r0, ftrace_stub;
|
||||
cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */
|
||||
beqid r5, end; /* MS: not taken -> jump over */
|
||||
nop;
|
||||
#else /* CONFIG_DYNAMIC_FTRACE */
|
||||
NOALIGN_ENTRY(ftrace_call)
|
||||
/* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */
|
||||
nop
|
||||
nop
|
||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||
/* static normal trace */
|
||||
lwi r6, r1, 120; /* MS: load parent addr */
|
||||
addik r5, r15, 0; /* MS: load current function addr */
|
||||
/* MS: here is dependency on previous code */
|
||||
brald r15, r20; /* MS: jump to ftrace handler */
|
||||
nop;
|
||||
end:
|
||||
lwi r15, r1, 0;
|
||||
RESTORE_REGS
|
||||
|
||||
rtsd r15, 8; /* MS: jump back */
|
||||
nop;
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
ENTRY(return_to_handler)
|
||||
nop; /* MS: just barrier for rtsd r15, 8 */
|
||||
nop;
|
||||
SAVE_REGS
|
||||
swi r15, r1, 0;
|
||||
|
||||
/* MS: find out returning address */
|
||||
bralid r15, ftrace_return_to_handler;
|
||||
nop;
|
||||
|
||||
/* MS: return value from ftrace_return_to_handler is my returning addr
|
||||
* must be before restore regs because I have to restore r3 content */
|
||||
addik r15, r3, 0;
|
||||
RESTORE_REGS
|
||||
|
||||
rtsd r15, 8; /* MS: jump back */
|
||||
nop;
|
||||
#endif /* CONFIG_FUNCTION_TRACER */
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/system.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
/*
|
||||
|
@ -47,3 +48,7 @@ extern void __umodsi3(void);
|
|||
EXPORT_SYMBOL(__umodsi3);
|
||||
extern char *_ebss;
|
||||
EXPORT_SYMBOL_GPL(_ebss);
|
||||
#ifdef CONFIG_FUNCTION_TRACER
|
||||
extern void _mcount(void);
|
||||
EXPORT_SYMBOL(_mcount);
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
void show_regs(struct pt_regs *regs)
|
||||
{
|
||||
|
|
140
arch/microblaze/kernel/reset.c
Normal file
140
arch/microblaze/kernel/reset.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2009 PetaLogix
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/prom.h>
|
||||
|
||||
/* Trigger specific functions */
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
static int handle; /* reset pin handle */
|
||||
static unsigned int reset_val;
|
||||
|
||||
static int of_reset_gpio_handle(void)
|
||||
{
|
||||
int ret; /* variable which stored handle reset gpio pin */
|
||||
struct device_node *root; /* root node */
|
||||
struct device_node *gpio; /* gpio node */
|
||||
struct of_gpio_chip *of_gc = NULL;
|
||||
enum of_gpio_flags flags ;
|
||||
const void *gpio_spec;
|
||||
|
||||
/* find out root node */
|
||||
root = of_find_node_by_path("/");
|
||||
|
||||
/* give me handle for gpio node to be possible allocate pin */
|
||||
ret = of_parse_phandles_with_args(root, "hard-reset-gpios",
|
||||
"#gpio-cells", 0, &gpio, &gpio_spec);
|
||||
if (ret) {
|
||||
pr_debug("%s: can't parse gpios property\n", __func__);
|
||||
goto err0;
|
||||
}
|
||||
|
||||
of_gc = gpio->data;
|
||||
if (!of_gc) {
|
||||
pr_debug("%s: gpio controller %s isn't registered\n",
|
||||
root->full_name, gpio->full_name);
|
||||
ret = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
ret = of_gc->xlate(of_gc, root, gpio_spec, &flags);
|
||||
if (ret < 0)
|
||||
goto err1;
|
||||
|
||||
ret += of_gc->gc.base;
|
||||
err1:
|
||||
of_node_put(gpio);
|
||||
err0:
|
||||
pr_debug("%s exited with status %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void of_platform_reset_gpio_probe(void)
|
||||
{
|
||||
int ret;
|
||||
handle = of_reset_gpio_handle();
|
||||
|
||||
if (!gpio_is_valid(handle)) {
|
||||
printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n",
|
||||
handle, "reset");
|
||||
}
|
||||
|
||||
ret = gpio_request(handle, "reset");
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "GPIO pin is already allocated\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get current setup value */
|
||||
reset_val = gpio_get_value(handle);
|
||||
/* FIXME maybe worth to perform any action */
|
||||
pr_debug("Reset: Gpio output state: 0x%x\n", reset_val);
|
||||
|
||||
/* Setup GPIO as output */
|
||||
ret = gpio_direction_output(handle, 0);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Setup output direction */
|
||||
gpio_set_value(handle, 0);
|
||||
|
||||
printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n",
|
||||
handle, reset_val);
|
||||
return;
|
||||
err:
|
||||
gpio_free(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void gpio_system_reset(void)
|
||||
{
|
||||
gpio_set_value(handle, 1 - reset_val);
|
||||
}
|
||||
#else
|
||||
#define gpio_system_reset() do {} while (0)
|
||||
void of_platform_reset_gpio_probe(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void machine_restart(char *cmd)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine restart...\n");
|
||||
gpio_system_reset();
|
||||
dump_stack();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_shutdown(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine shutdown...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine halt...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine power off...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
|
@ -52,13 +52,12 @@ void __init setup_arch(char **cmdline_p)
|
|||
/* irq_early_init(); */
|
||||
setup_cpuinfo();
|
||||
|
||||
__invalidate_icache_all();
|
||||
__enable_icache();
|
||||
microblaze_cache_init();
|
||||
|
||||
__invalidate_dcache_all();
|
||||
__enable_dcache();
|
||||
enable_dcache();
|
||||
|
||||
panic_timeout = 120;
|
||||
invalidate_icache();
|
||||
enable_icache();
|
||||
|
||||
setup_memory();
|
||||
|
||||
|
@ -131,6 +130,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
|
|||
strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE);
|
||||
#endif
|
||||
|
||||
lockdep_init();
|
||||
|
||||
/* initialize device tree for usage in early_printk */
|
||||
early_init_devtree((void *)_fdt_start);
|
||||
|
||||
|
@ -186,32 +187,3 @@ static int microblaze_debugfs_init(void)
|
|||
}
|
||||
arch_initcall(microblaze_debugfs_init);
|
||||
#endif
|
||||
|
||||
void machine_restart(char *cmd)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine restart...\n");
|
||||
dump_stack();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_shutdown(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine shutdown...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_halt(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine halt...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void machine_power_off(void)
|
||||
{
|
||||
printk(KERN_NOTICE "Machine power off...\n");
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
|
||||
|
||||
|
||||
asmlinkage long
|
||||
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
struct pt_regs *regs)
|
||||
|
@ -176,6 +175,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int signal;
|
||||
unsigned long address = 0;
|
||||
#ifdef CONFIG_MMU
|
||||
pmd_t *pmdp;
|
||||
pte_t *ptep;
|
||||
#endif
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
|
||||
|
@ -216,8 +220,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
Negative 8 offset because return is rtsd r15, 8 */
|
||||
regs->r15 = ((unsigned long)frame->tramp)-8;
|
||||
|
||||
__invalidate_cache_sigtramp((unsigned long)frame->tramp);
|
||||
address = ((unsigned long)frame->tramp);
|
||||
#ifdef CONFIG_MMU
|
||||
pmdp = pmd_offset(pud_offset(
|
||||
pgd_offset(current->mm, address),
|
||||
address), address);
|
||||
|
||||
preempt_disable();
|
||||
ptep = pte_offset_map(pmdp, address);
|
||||
if (pte_present(*ptep)) {
|
||||
address = (unsigned long) page_address(pte_page(*ptep));
|
||||
/* MS: I need add offset in page */
|
||||
address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
|
||||
/* MS address is virtual */
|
||||
address = virt_to_phys(address);
|
||||
invalidate_icache_range(address, address + 8);
|
||||
flush_dcache_range(address, address + 8);
|
||||
}
|
||||
pte_unmap(ptep);
|
||||
preempt_enable();
|
||||
#else
|
||||
flush_icache_range(address, address + 8);
|
||||
flush_dcache_range(address, address + 8);
|
||||
#endif
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
|
@ -233,6 +258,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
|
||||
set_fs(USER_DS);
|
||||
|
||||
/* the tracer may want to single-step inside the handler */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
||||
#ifdef DEBUG_SIG
|
||||
printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
|
||||
current->comm, current->pid, frame, regs->pc);
|
||||
|
|
65
arch/microblaze/kernel/stacktrace.c
Normal file
65
arch/microblaze/kernel/stacktrace.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Stack trace support for Microblaze.
|
||||
*
|
||||
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2009 PetaLogix
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/stacktrace.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/* FIXME initial support */
|
||||
void save_stack_trace(struct stack_trace *trace)
|
||||
{
|
||||
unsigned long *sp;
|
||||
unsigned long addr;
|
||||
asm("addik %0, r1, 0" : "=r" (sp));
|
||||
|
||||
while (!kstack_end(sp)) {
|
||||
addr = *sp++;
|
||||
if (__kernel_text_address(addr)) {
|
||||
if (trace->skip > 0)
|
||||
trace->skip--;
|
||||
else
|
||||
trace->entries[trace->nr_entries++] = addr;
|
||||
|
||||
if (trace->nr_entries >= trace->max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(save_stack_trace);
|
||||
|
||||
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
||||
{
|
||||
unsigned int *sp;
|
||||
unsigned long addr;
|
||||
|
||||
struct thread_info *ti = task_thread_info(tsk);
|
||||
|
||||
if (tsk == current)
|
||||
asm("addik %0, r1, 0" : "=r" (sp));
|
||||
else
|
||||
sp = (unsigned int *)ti->cpu_context.r1;
|
||||
|
||||
while (!kstack_end(sp)) {
|
||||
addr = *sp++;
|
||||
if (__kernel_text_address(addr)) {
|
||||
if (trace->skip > 0)
|
||||
trace->skip--;
|
||||
else
|
||||
trace->entries[trace->nr_entries++] = addr;
|
||||
|
||||
if (trace->nr_entries >= trace->max_entries)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
|
|
@ -183,7 +183,7 @@ ENTRY(sys_call_table)
|
|||
.long sys_rt_sigpending
|
||||
.long sys_rt_sigtimedwait
|
||||
.long sys_rt_sigqueueinfo
|
||||
.long sys_rt_sigsuspend_wrapper
|
||||
.long sys_rt_sigsuspend
|
||||
.long sys_pread64 /* 180 */
|
||||
.long sys_pwrite64
|
||||
.long sys_chown
|
||||
|
@ -303,7 +303,7 @@ ENTRY(sys_call_table)
|
|||
.long sys_mkdirat
|
||||
.long sys_mknodat
|
||||
.long sys_fchownat
|
||||
.long sys_ni_syscall
|
||||
.long sys_futimesat
|
||||
.long sys_fstatat64 /* 300 */
|
||||
.long sys_unlinkat
|
||||
.long sys_renameat
|
||||
|
|
|
@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs)
|
|||
return (cycle_t) (in_be32(TIMER_BASE + TCR1));
|
||||
}
|
||||
|
||||
static struct timecounter microblaze_tc = {
|
||||
.cc = NULL,
|
||||
};
|
||||
|
||||
static cycle_t microblaze_cc_read(const struct cyclecounter *cc)
|
||||
{
|
||||
return microblaze_read(NULL);
|
||||
}
|
||||
|
||||
static struct cyclecounter microblaze_cc = {
|
||||
.read = microblaze_cc_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.shift = 24,
|
||||
};
|
||||
|
||||
int __init init_microblaze_timecounter(void)
|
||||
{
|
||||
microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
|
||||
microblaze_cc.shift);
|
||||
|
||||
timecounter_init(µblaze_tc, µblaze_cc, sched_clock());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clocksource clocksource_microblaze = {
|
||||
.name = "microblaze_clocksource",
|
||||
.rating = 300,
|
||||
|
@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void)
|
|||
out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT);
|
||||
/* start timer1 - up counting without interrupt */
|
||||
out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT);
|
||||
|
||||
/* register timecounter - for ftrace support */
|
||||
init_microblaze_timecounter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,12 @@ SECTIONS {
|
|||
_stext = . ;
|
||||
*(.text .text.*)
|
||||
*(.fixup)
|
||||
EXIT_TEXT
|
||||
EXIT_CALL
|
||||
EXIT_TEXT
|
||||
EXIT_CALL
|
||||
SCHED_TEXT
|
||||
LOCK_TEXT
|
||||
KPROBES_TEXT
|
||||
IRQENTRY_TEXT
|
||||
. = ALIGN (4) ;
|
||||
_etext = . ;
|
||||
}
|
||||
|
@ -86,6 +87,7 @@ SECTIONS {
|
|||
_KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ;
|
||||
}
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
__init_begin = .;
|
||||
|
||||
INIT_TEXT_SECTION(PAGE_SIZE)
|
||||
|
|
|
@ -39,3 +39,10 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
|
|||
__do_strncpy_from_user(dst, src, count, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned long __copy_tofrom_user(void __user *to,
|
||||
const void __user *from, unsigned long size)
|
||||
{
|
||||
memcpy(to, from, size);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ char *klimit = _end;
|
|||
* have available.
|
||||
*/
|
||||
unsigned long memory_start;
|
||||
EXPORT_SYMBOL(memory_start);
|
||||
unsigned long memory_end; /* due to mm/nommu.c */
|
||||
unsigned long memory_size;
|
||||
|
||||
|
|
|
@ -144,7 +144,6 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
|
|||
pmd_t *pd;
|
||||
pte_t *pg;
|
||||
int err = -ENOMEM;
|
||||
/* spin_lock(&init_mm.page_table_lock); */
|
||||
/* Use upper 10 bits of VA to index the first level map */
|
||||
pd = pmd_offset(pgd_offset_k(va), va);
|
||||
/* Use middle 10 bits of VA to index the second-level map */
|
||||
|
@ -158,9 +157,7 @@ int map_page(unsigned long va, phys_addr_t pa, int flags)
|
|||
if (mem_init_done)
|
||||
flush_HPTE(0, va, pmd_val(*pd));
|
||||
/* flush_HPTE(0, va, pg); */
|
||||
|
||||
}
|
||||
/* spin_unlock(&init_mm.page_table_lock); */
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -182,12 +179,6 @@ void __init adjust_total_lowmem(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void show_tmem(unsigned long tmem)
|
||||
{
|
||||
volatile unsigned long a;
|
||||
a = a + tmem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Map in all of physical memory starting at CONFIG_KERNEL_START.
|
||||
*/
|
||||
|
@ -197,7 +188,6 @@ void __init mapin_ram(void)
|
|||
|
||||
v = CONFIG_KERNEL_START;
|
||||
p = memory_start;
|
||||
show_tmem(memory_size);
|
||||
for (s = 0; s < memory_size; s += PAGE_SIZE) {
|
||||
f = _PAGE_PRESENT | _PAGE_ACCESSED |
|
||||
_PAGE_SHARED | _PAGE_HWEXEC;
|
||||
|
|
13
arch/microblaze/oprofile/Makefile
Normal file
13
arch/microblaze/oprofile/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# arch/microblaze/oprofile/Makefile
|
||||
#
|
||||
|
||||
obj-$(CONFIG_OPROFILE) += oprofile.o
|
||||
|
||||
DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
|
||||
oprof.o cpu_buffer.o buffer_sync.o \
|
||||
event_buffer.o oprofile_files.o \
|
||||
oprofilefs.o oprofile_stats.o \
|
||||
timer_int.o )
|
||||
|
||||
oprofile-y := $(DRIVER_OBJS) microblaze_oprofile.o
|
22
arch/microblaze/oprofile/microblaze_oprofile.c
Normal file
22
arch/microblaze/oprofile/microblaze_oprofile.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Microblaze oprofile code
|
||||
*
|
||||
* Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
|
||||
* Copyright (C) 2009 PetaLogix
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <linux/oprofile.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
int __init oprofile_arch_init(struct oprofile_operations *ops)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void oprofile_arch_exit(void)
|
||||
{
|
||||
}
|
|
@ -53,31 +53,12 @@ config OPT_LIB_FUNCTION
|
|||
|
||||
config OPT_LIB_ASM
|
||||
bool "Optimalized lib function ASM"
|
||||
depends on OPT_LIB_FUNCTION
|
||||
depends on OPT_LIB_FUNCTION && (XILINX_MICROBLAZE0_USE_BARREL = 1)
|
||||
default n
|
||||
help
|
||||
Allows turn on optimalized library function (memcpy and memmove).
|
||||
Function are written in asm code.
|
||||
|
||||
# This is still a bit broken - disabling for now JW 20070504
|
||||
config ALLOW_EDIT_AUTO
|
||||
bool "Permit Display/edit of Kconfig.auto platform settings"
|
||||
default n
|
||||
help
|
||||
Allows the editing of auto-generated platform settings from
|
||||
the Kconfig.auto file. Obviously this does not change the
|
||||
underlying hardware, so be very careful if you go editing
|
||||
these settings.
|
||||
|
||||
Also, if you enable this, and edit various Kconfig.auto
|
||||
settings, YOUR CHANGES WILL BE LOST if you then disable it
|
||||
again. You have been warned!
|
||||
|
||||
If unsure, say no.
|
||||
|
||||
comment "Automatic platform settings from Kconfig.auto"
|
||||
depends on ALLOW_EDIT_AUTO
|
||||
|
||||
if PLATFORM_GENERIC=y
|
||||
source "arch/microblaze/platform/generic/Kconfig.auto"
|
||||
endif
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
# Definitions for MICROBLAZE0
|
||||
comment "Definitions for MICROBLAZE0"
|
||||
depends on ALLOW_EDIT_AUTO
|
||||
|
||||
config KERNEL_BASE_ADDR
|
||||
hex "Physical address where Linux Kernel is"
|
||||
|
@ -30,33 +29,33 @@ config KERNEL_BASE_ADDR
|
|||
BASE Address for kernel
|
||||
|
||||
config XILINX_MICROBLAZE0_FAMILY
|
||||
string "Targetted FPGA family" if ALLOW_EDIT_AUTO
|
||||
string "Targetted FPGA family"
|
||||
default "virtex5"
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_MSR_INSTR
|
||||
int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO
|
||||
default 1
|
||||
int "USE_MSR_INSTR range (0:1)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_PCMP_INSTR
|
||||
int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO
|
||||
default 1
|
||||
int "USE_PCMP_INSTR range (0:1)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_BARREL
|
||||
int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO
|
||||
default 1
|
||||
int "USE_BARREL range (0:1)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_DIV
|
||||
int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO
|
||||
default 1
|
||||
int "USE_DIV range (0:1)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_HW_MUL
|
||||
int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO
|
||||
default 2
|
||||
int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_USE_FPU
|
||||
int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO
|
||||
default 2
|
||||
int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)"
|
||||
default 0
|
||||
|
||||
config XILINX_MICROBLAZE0_HW_VER
|
||||
string "Core version number" if ALLOW_EDIT_AUTO
|
||||
string "Core version number"
|
||||
default 7.10.d
|
||||
|
|
|
@ -32,11 +32,16 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "xlnx,microblaze";
|
||||
hard-reset-gpios = <&LEDs_8Bit 2 1>;
|
||||
model = "testing";
|
||||
DDR2_SDRAM: memory@90000000 {
|
||||
device_type = "memory";
|
||||
reg = < 0x90000000 0x10000000 >;
|
||||
} ;
|
||||
aliases {
|
||||
ethernet0 = &Hard_Ethernet_MAC;
|
||||
serial0 = &RS232_Uart_1;
|
||||
} ;
|
||||
chosen {
|
||||
bootargs = "console=ttyUL0,115200 highres=on";
|
||||
linux,stdout-path = "/plb@0/serial@84000000";
|
||||
|
@ -127,7 +132,7 @@
|
|||
mb_plb: plb@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "xlnx,plb-v46-1.03.a", "simple-bus";
|
||||
compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus";
|
||||
ranges ;
|
||||
FLASH: flash@a0000000 {
|
||||
bank-width = <2>;
|
||||
|
@ -214,12 +219,12 @@
|
|||
#size-cells = <1>;
|
||||
compatible = "xlnx,compound";
|
||||
ethernet@81c00000 {
|
||||
compatible = "xlnx,xps-ll-temac-1.01.b";
|
||||
compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
|
||||
device_type = "network";
|
||||
interrupt-parent = <&xps_intc_0>;
|
||||
interrupts = < 5 2 >;
|
||||
llink-connected = <&PIM3>;
|
||||
local-mac-address = [ 02 00 00 00 00 00 ];
|
||||
local-mac-address = [ 00 0a 35 00 00 00 ];
|
||||
reg = < 0x81c00000 0x40 >;
|
||||
xlnx,bus2core-clk-ratio = <0x1>;
|
||||
xlnx,phy-type = <0x1>;
|
||||
|
@ -261,6 +266,33 @@
|
|||
xlnx,is-dual = <0x0>;
|
||||
xlnx,tri-default = <0xffffffff>;
|
||||
xlnx,tri-default-2 = <0xffffffff>;
|
||||
#gpio-cells = <2>;
|
||||
gpio-controller;
|
||||
} ;
|
||||
|
||||
gpio-leds {
|
||||
compatible = "gpio-leds";
|
||||
|
||||
heartbeat {
|
||||
label = "Heartbeat";
|
||||
gpios = <&LEDs_8Bit 4 1>;
|
||||
linux,default-trigger = "heartbeat";
|
||||
};
|
||||
|
||||
yellow {
|
||||
label = "Yellow";
|
||||
gpios = <&LEDs_8Bit 5 1>;
|
||||
};
|
||||
|
||||
red {
|
||||
label = "Red";
|
||||
gpios = <&LEDs_8Bit 6 1>;
|
||||
};
|
||||
|
||||
green {
|
||||
label = "Green";
|
||||
gpios = <&LEDs_8Bit 7 1>;
|
||||
};
|
||||
} ;
|
||||
RS232_Uart_1: serial@84000000 {
|
||||
clock-frequency = <125000000>;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
static struct of_device_id xilinx_of_bus_ids[] __initdata = {
|
||||
{ .compatible = "simple-bus", },
|
||||
|
@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = {
|
|||
static int __init microblaze_device_probe(void)
|
||||
{
|
||||
of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
|
||||
of_platform_reset_gpio_probe();
|
||||
return 0;
|
||||
}
|
||||
device_initcall(microblaze_device_probe);
|
||||
|
|
|
@ -295,6 +295,9 @@ if ($arch eq "x86_64") {
|
|||
$ld .= " -m elf64_sparc";
|
||||
$cc .= " -m64";
|
||||
$objcopy .= " -O elf64-sparc";
|
||||
} elsif ($arch eq "microblaze") {
|
||||
# Microblaze calls '_mcount' instead of plain 'mcount'.
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
||||
} else {
|
||||
die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue