diff options
50 files changed, 1686 insertions, 484 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index bbd8327f1890..fd53e500be67 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
| @@ -6,8 +6,15 @@ mainmenu "Linux/Microblaze Kernel Configuration" | |||
| 6 | config MICROBLAZE | 6 | config MICROBLAZE |
| 7 | def_bool y | 7 | def_bool y |
| 8 | select HAVE_LMB | 8 | select HAVE_LMB |
| 9 | select HAVE_FUNCTION_TRACER | ||
| 10 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | ||
| 11 | select HAVE_FUNCTION_GRAPH_TRACER | ||
| 12 | select HAVE_DYNAMIC_FTRACE | ||
| 13 | select HAVE_FTRACE_MCOUNT_RECORD | ||
| 9 | select USB_ARCH_HAS_EHCI | 14 | select USB_ARCH_HAS_EHCI |
| 10 | select ARCH_WANT_OPTIONAL_GPIOLIB | 15 | select ARCH_WANT_OPTIONAL_GPIOLIB |
| 16 | select HAVE_OPROFILE | ||
| 17 | select TRACING_SUPPORT | ||
| 11 | 18 | ||
| 12 | config SWAP | 19 | config SWAP |
| 13 | def_bool n | 20 | def_bool n |
| @@ -57,12 +64,24 @@ config GENERIC_GPIO | |||
| 57 | config GENERIC_CSUM | 64 | config GENERIC_CSUM |
| 58 | def_bool y | 65 | def_bool y |
| 59 | 66 | ||
| 67 | config STACKTRACE_SUPPORT | ||
| 68 | def_bool y | ||
| 69 | |||
| 70 | config LOCKDEP_SUPPORT | ||
| 71 | def_bool y | ||
| 72 | |||
| 73 | config HAVE_LATENCYTOP_SUPPORT | ||
| 74 | def_bool y | ||
| 75 | |||
| 60 | config PCI | 76 | config PCI |
| 61 | def_bool n | 77 | def_bool n |
| 62 | 78 | ||
| 63 | config NO_DMA | 79 | config NO_DMA |
| 64 | def_bool y | 80 | def_bool y |
| 65 | 81 | ||
| 82 | config DTC | ||
| 83 | def_bool y | ||
| 84 | |||
| 66 | source "init/Kconfig" | 85 | source "init/Kconfig" |
| 67 | 86 | ||
| 68 | source "kernel/Kconfig.freezer" | 87 | source "kernel/Kconfig.freezer" |
diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug index 242cd35bdb4b..9dc708a7f700 100644 --- a/arch/microblaze/Kconfig.debug +++ b/arch/microblaze/Kconfig.debug | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | menu "Kernel hacking" | 4 | menu "Kernel hacking" |
| 5 | 5 | ||
| 6 | config TRACE_IRQFLAGS_SUPPORT | ||
| 7 | def_bool y | ||
| 8 | |||
| 6 | source "lib/Kconfig.debug" | 9 | source "lib/Kconfig.debug" |
| 7 | 10 | ||
| 8 | config EARLY_PRINTK | 11 | config EARLY_PRINTK |
diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile index 34187354304a..d2d6cfcb1a30 100644 --- a/arch/microblaze/Makefile +++ b/arch/microblaze/Makefile | |||
| @@ -51,6 +51,8 @@ core-y += arch/microblaze/kernel/ | |||
| 51 | core-y += arch/microblaze/mm/ | 51 | core-y += arch/microblaze/mm/ |
| 52 | core-y += arch/microblaze/platform/ | 52 | core-y += arch/microblaze/platform/ |
| 53 | 53 | ||
| 54 | drivers-$(CONFIG_OPROFILE) += arch/microblaze/oprofile/ | ||
| 55 | |||
| 54 | boot := arch/microblaze/boot | 56 | boot := arch/microblaze/boot |
| 55 | 57 | ||
| 56 | # Are we making a simpleImage.<boardname> target? If so, crack out the boardname | 58 | # Are we making a simpleImage.<boardname> target? If so, crack out the boardname |
diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile index 21f13322a4ca..902cf9846c3c 100644 --- a/arch/microblaze/boot/Makefile +++ b/arch/microblaze/boot/Makefile | |||
| @@ -2,11 +2,13 @@ | |||
| 2 | # arch/microblaze/boot/Makefile | 2 | # arch/microblaze/boot/Makefile |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | MKIMAGE := $(srctree)/scripts/mkuboot.sh | ||
| 6 | |||
| 5 | obj-y += linked_dtb.o | 7 | obj-y += linked_dtb.o |
| 6 | 8 | ||
| 7 | targets := linux.bin linux.bin.gz simpleImage.% | 9 | targets := linux.bin linux.bin.gz simpleImage.% |
| 8 | 10 | ||
| 9 | OBJCOPYFLAGS_linux.bin := -O binary | 11 | OBJCOPYFLAGS := -O binary |
| 10 | 12 | ||
| 11 | # Where the DTS files live | 13 | # Where the DTS files live |
| 12 | dtstree := $(srctree)/$(src)/dts | 14 | dtstree := $(srctree)/$(src)/dts |
| @@ -24,6 +26,7 @@ $(obj)/linux.bin: vmlinux FORCE | |||
| 24 | [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \ | 26 | [ -n $(CONFIG_INITRAMFS_SOURCE) ] && [ ! -e $(CONFIG_INITRAMFS_SOURCE) ] && \ |
| 25 | touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image" | 27 | touch $(CONFIG_INITRAMFS_SOURCE) || echo "No CPIO image" |
| 26 | $(call if_changed,objcopy) | 28 | $(call if_changed,objcopy) |
| 29 | $(call if_changed,uimage) | ||
| 27 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | 30 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' |
| 28 | 31 | ||
| 29 | $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE | 32 | $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE |
| @@ -36,8 +39,16 @@ quiet_cmd_cp = CP $< $@$2 | |||
| 36 | quiet_cmd_strip = STRIP $@ | 39 | quiet_cmd_strip = STRIP $@ |
| 37 | cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@ | 40 | cmd_strip = $(STRIP) -K _start -K _end -K __log_buf -K _fdt_start vmlinux -o $@ |
| 38 | 41 | ||
| 42 | quiet_cmd_uimage = UIMAGE $@.ub | ||
| 43 | cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A microblaze -O linux -T kernel \ | ||
| 44 | -C none -n 'Linux-$(KERNELRELEASE)' \ | ||
| 45 | -a $(CONFIG_KERNEL_BASE_ADDR) -e $(CONFIG_KERNEL_BASE_ADDR) \ | ||
| 46 | -d $@ $@.ub | ||
| 47 | |||
| 39 | $(obj)/simpleImage.%: vmlinux FORCE | 48 | $(obj)/simpleImage.%: vmlinux FORCE |
| 40 | $(call if_changed,cp,.unstrip) | 49 | $(call if_changed,cp,.unstrip) |
| 50 | $(call if_changed,objcopy) | ||
| 51 | $(call if_changed,uimage) | ||
| 41 | $(call if_changed,strip) | 52 | $(call if_changed,strip) |
| 42 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' | 53 | @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' |
| 43 | 54 | ||
| @@ -53,4 +64,4 @@ $(obj)/%.dtb: $(dtstree)/%.dts FORCE | |||
| 53 | 64 | ||
| 54 | clean-kernel += linux.bin linux.bin.gz simpleImage.* | 65 | clean-kernel += linux.bin linux.bin.gz simpleImage.* |
| 55 | 66 | ||
| 56 | clean-files += *.dtb | 67 | clean-files += *.dtb simpleImage.*.unstrip |
diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h index c209c47509d5..e52210891d78 100644 --- a/arch/microblaze/include/asm/cache.h +++ b/arch/microblaze/include/asm/cache.h | |||
| @@ -21,20 +21,4 @@ | |||
| 21 | 21 | ||
| 22 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | 22 | #define SMP_CACHE_BYTES L1_CACHE_BYTES |
| 23 | 23 | ||
| 24 | void _enable_icache(void); | ||
| 25 | void _disable_icache(void); | ||
| 26 | void _invalidate_icache(unsigned int addr); | ||
| 27 | |||
| 28 | #define __enable_icache() _enable_icache() | ||
| 29 | #define __disable_icache() _disable_icache() | ||
| 30 | #define __invalidate_icache(addr) _invalidate_icache(addr) | ||
| 31 | |||
| 32 | void _enable_dcache(void); | ||
| 33 | void _disable_dcache(void); | ||
| 34 | void _invalidate_dcache(unsigned int addr); | ||
| 35 | |||
| 36 | #define __enable_dcache() _enable_dcache() | ||
| 37 | #define __disable_dcache() _disable_dcache() | ||
| 38 | #define __invalidate_dcache(addr) _invalidate_dcache(addr) | ||
| 39 | |||
| 40 | #endif /* _ASM_MICROBLAZE_CACHE_H */ | 24 | #endif /* _ASM_MICROBLAZE_CACHE_H */ |
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h index 088076e657b3..a6edd356cd08 100644 --- a/arch/microblaze/include/asm/cacheflush.h +++ b/arch/microblaze/include/asm/cacheflush.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | /* Somebody depends on this; sigh... */ | 18 | /* Somebody depends on this; sigh... */ |
| 19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
| 20 | 20 | ||
| 21 | /* Look at Documentation/cachetlb.txt */ | ||
| 22 | |||
| 21 | /* | 23 | /* |
| 22 | * Cache handling functions. | 24 | * Cache handling functions. |
| 23 | * Microblaze has a write-through data cache, meaning that the data cache | 25 | * Microblaze has a write-through data cache, meaning that the data cache |
| @@ -27,78 +29,81 @@ | |||
| 27 | * instruction cache to make sure we don't fetch old, bad code. | 29 | * instruction cache to make sure we don't fetch old, bad code. |
| 28 | */ | 30 | */ |
| 29 | 31 | ||
| 32 | /* struct cache, d=dcache, i=icache, fl = flush, iv = invalidate, | ||
| 33 | * suffix r = range */ | ||
| 34 | struct scache { | ||
| 35 | /* icache */ | ||
| 36 | void (*ie)(void); /* enable */ | ||
| 37 | void (*id)(void); /* disable */ | ||
| 38 | void (*ifl)(void); /* flush */ | ||
| 39 | void (*iflr)(unsigned long a, unsigned long b); | ||
| 40 | void (*iin)(void); /* invalidate */ | ||
| 41 | void (*iinr)(unsigned long a, unsigned long b); | ||
| 42 | /* dcache */ | ||
| 43 | void (*de)(void); /* enable */ | ||
| 44 | void (*dd)(void); /* disable */ | ||
| 45 | void (*dfl)(void); /* flush */ | ||
| 46 | void (*dflr)(unsigned long a, unsigned long b); | ||
| 47 | void (*din)(void); /* invalidate */ | ||
| 48 | void (*dinr)(unsigned long a, unsigned long b); | ||
| 49 | }; | ||
| 50 | |||
| 51 | /* microblaze cache */ | ||
| 52 | extern struct scache *mbc; | ||
| 53 | |||
| 54 | void microblaze_cache_init(void); | ||
| 55 | |||
| 56 | #define enable_icache() mbc->ie(); | ||
| 57 | #define disable_icache() mbc->id(); | ||
| 58 | #define flush_icache() mbc->ifl(); | ||
| 59 | #define flush_icache_range(start, end) mbc->iflr(start, end); | ||
| 60 | #define invalidate_icache() mbc->iin(); | ||
| 61 | #define invalidate_icache_range(start, end) mbc->iinr(start, end); | ||
| 62 | |||
| 63 | |||
| 64 | #define flush_icache_user_range(vma, pg, adr, len) flush_icache(); | ||
| 65 | #define flush_icache_page(vma, pg) do { } while (0) | ||
| 66 | |||
| 67 | #define enable_dcache() mbc->de(); | ||
| 68 | #define disable_dcache() mbc->dd(); | ||
| 30 | /* FIXME for LL-temac driver */ | 69 | /* FIXME for LL-temac driver */ |
| 31 | #define invalidate_dcache_range(start, end) \ | 70 | #define invalidate_dcache() mbc->din(); |
| 32 | __invalidate_dcache_range(start, end) | 71 | #define invalidate_dcache_range(start, end) mbc->dinr(start, end); |
| 33 | 72 | #define flush_dcache() mbc->dfl(); | |
| 34 | #define flush_cache_all() __invalidate_cache_all() | 73 | #define flush_dcache_range(start, end) mbc->dflr(start, end); |
| 35 | #define flush_cache_mm(mm) do { } while (0) | ||
| 36 | #define flush_cache_range(vma, start, end) __invalidate_cache_all() | ||
| 37 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | ||
| 38 | 74 | ||
| 39 | #define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) | ||
| 40 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 | 75 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 |
| 76 | /* D-cache aliasing problem can't happen - cache is between MMU and ram */ | ||
| 41 | #define flush_dcache_page(page) do { } while (0) | 77 | #define flush_dcache_page(page) do { } while (0) |
| 42 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 78 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
| 43 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 79 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
| 44 | 80 | ||
| 45 | #define flush_icache_range(start, len) __invalidate_icache_range(start, len) | ||
| 46 | #define flush_icache_page(vma, pg) do { } while (0) | ||
| 47 | |||
| 48 | #ifndef CONFIG_MMU | ||
| 49 | # define flush_icache_user_range(start, len) do { } while (0) | ||
| 50 | #else | ||
| 51 | # define flush_icache_user_range(vma, pg, adr, len) __invalidate_icache_all() | ||
| 52 | |||
| 53 | # define flush_page_to_ram(page) do { } while (0) | ||
| 54 | 81 | ||
| 55 | # define flush_icache() __invalidate_icache_all() | 82 | #define flush_cache_dup_mm(mm) do { } while (0) |
| 56 | # define flush_cache_sigtramp(vaddr) \ | 83 | #define flush_cache_vmap(start, end) do { } while (0) |
| 57 | __invalidate_icache_range(vaddr, vaddr + 8) | 84 | #define flush_cache_vunmap(start, end) do { } while (0) |
| 58 | 85 | #define flush_cache_mm(mm) do { } while (0) | |
| 59 | # define flush_dcache_mmap_lock(mapping) do { } while (0) | 86 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
| 60 | # define flush_dcache_mmap_unlock(mapping) do { } while (0) | ||
| 61 | 87 | ||
| 62 | # define flush_cache_dup_mm(mm) do { } while (0) | 88 | /* MS: kgdb code use this macro, wrong len with FLASH */ |
| 89 | #if 0 | ||
| 90 | #define flush_cache_range(vma, start, len) { \ | ||
| 91 | flush_icache_range((unsigned) (start), (unsigned) (start) + (len)); \ | ||
| 92 | flush_dcache_range((unsigned) (start), (unsigned) (start) + (len)); \ | ||
| 93 | } | ||
| 63 | #endif | 94 | #endif |
| 64 | 95 | ||
| 65 | #define flush_cache_vmap(start, end) do { } while (0) | 96 | #define flush_cache_range(vma, start, len) do { } while (0) |
| 66 | #define flush_cache_vunmap(start, end) do { } while (0) | ||
| 67 | |||
| 68 | struct page; | ||
| 69 | struct mm_struct; | ||
| 70 | struct vm_area_struct; | ||
| 71 | |||
| 72 | /* see arch/microblaze/kernel/cache.c */ | ||
| 73 | extern void __invalidate_icache_all(void); | ||
| 74 | extern void __invalidate_icache_range(unsigned long start, unsigned long end); | ||
| 75 | extern void __invalidate_icache_page(struct vm_area_struct *vma, | ||
| 76 | struct page *page); | ||
| 77 | extern void __invalidate_icache_user_range(struct vm_area_struct *vma, | ||
| 78 | struct page *page, | ||
| 79 | unsigned long adr, int len); | ||
| 80 | extern void __invalidate_cache_sigtramp(unsigned long addr); | ||
| 81 | |||
| 82 | extern void __invalidate_dcache_all(void); | ||
| 83 | extern void __invalidate_dcache_range(unsigned long start, unsigned long end); | ||
| 84 | extern void __invalidate_dcache_page(struct vm_area_struct *vma, | ||
| 85 | struct page *page); | ||
| 86 | extern void __invalidate_dcache_user_range(struct vm_area_struct *vma, | ||
| 87 | struct page *page, | ||
| 88 | unsigned long adr, int len); | ||
| 89 | |||
| 90 | extern inline void __invalidate_cache_all(void) | ||
| 91 | { | ||
| 92 | __invalidate_icache_all(); | ||
| 93 | __invalidate_dcache_all(); | ||
| 94 | } | ||
| 95 | 97 | ||
| 96 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 98 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
| 97 | do { memcpy((dst), (src), (len)); \ | 99 | do { \ |
| 98 | flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ | 100 | memcpy((dst), (src), (len)); \ |
| 101 | flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ | ||
| 99 | } while (0) | 102 | } while (0) |
| 100 | 103 | ||
| 101 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ | 104 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ |
| 102 | memcpy((dst), (src), (len)) | 105 | do { \ |
| 106 | memcpy((dst), (src), (len)); \ | ||
| 107 | } while (0) | ||
| 103 | 108 | ||
| 104 | #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ | 109 | #endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ |
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h index 52f28f6dc4eb..b4f5ca33aebf 100644 --- a/arch/microblaze/include/asm/cpuinfo.h +++ b/arch/microblaze/include/asm/cpuinfo.h | |||
| @@ -43,7 +43,7 @@ struct cpuinfo { | |||
| 43 | u32 use_icache; | 43 | u32 use_icache; |
| 44 | u32 icache_tagbits; | 44 | u32 icache_tagbits; |
| 45 | u32 icache_write; | 45 | u32 icache_write; |
| 46 | u32 icache_line; | 46 | u32 icache_line_length; |
| 47 | u32 icache_size; | 47 | u32 icache_size; |
| 48 | unsigned long icache_base; | 48 | unsigned long icache_base; |
| 49 | unsigned long icache_high; | 49 | unsigned long icache_high; |
| @@ -51,8 +51,9 @@ struct cpuinfo { | |||
| 51 | u32 use_dcache; | 51 | u32 use_dcache; |
| 52 | u32 dcache_tagbits; | 52 | u32 dcache_tagbits; |
| 53 | u32 dcache_write; | 53 | u32 dcache_write; |
| 54 | u32 dcache_line; | 54 | u32 dcache_line_length; |
| 55 | u32 dcache_size; | 55 | u32 dcache_size; |
| 56 | u32 dcache_wb; | ||
| 56 | unsigned long dcache_base; | 57 | unsigned long dcache_base; |
| 57 | unsigned long dcache_high; | 58 | unsigned long dcache_high; |
| 58 | 59 | ||
diff --git a/arch/microblaze/include/asm/device.h b/arch/microblaze/include/asm/device.h index 30286db27c1c..78a038452c0f 100644 --- a/arch/microblaze/include/asm/device.h +++ b/arch/microblaze/include/asm/device.h | |||
| @@ -19,6 +19,18 @@ struct dev_archdata { | |||
| 19 | struct pdev_archdata { | 19 | struct pdev_archdata { |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | static inline void dev_archdata_set_node(struct dev_archdata *ad, | ||
| 23 | struct device_node *np) | ||
| 24 | { | ||
| 25 | ad->of_node = np; | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline struct device_node * | ||
| 29 | dev_archdata_get_node(const struct dev_archdata *ad) | ||
| 30 | { | ||
| 31 | return ad->of_node; | ||
| 32 | } | ||
| 33 | |||
| 22 | #endif /* _ASM_MICROBLAZE_DEVICE_H */ | 34 | #endif /* _ASM_MICROBLAZE_DEVICE_H */ |
| 23 | 35 | ||
| 24 | 36 | ||
diff --git a/arch/microblaze/include/asm/ftrace.h b/arch/microblaze/include/asm/ftrace.h index 8b137891791f..fd2fa2eca62f 100644 --- a/arch/microblaze/include/asm/ftrace.h +++ b/arch/microblaze/include/asm/ftrace.h | |||
| @@ -1 +1,26 @@ | |||
| 1 | #ifndef _ASM_MICROBLAZE_FTRACE | ||
| 2 | #define _ASM_MICROBLAZE_FTRACE | ||
| 1 | 3 | ||
| 4 | #ifdef CONFIG_FUNCTION_TRACER | ||
| 5 | |||
| 6 | #define MCOUNT_ADDR ((long)(_mcount)) | ||
| 7 | #define MCOUNT_INSN_SIZE 8 /* sizeof mcount call */ | ||
| 8 | |||
| 9 | #ifndef __ASSEMBLY__ | ||
| 10 | extern void _mcount(void); | ||
| 11 | extern void ftrace_call_graph(void); | ||
| 12 | #endif | ||
| 13 | |||
| 14 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 15 | /* reloction of mcount call site is the same as the address */ | ||
| 16 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | ||
| 17 | { | ||
| 18 | return addr; | ||
| 19 | } | ||
| 20 | |||
| 21 | struct dyn_arch_ftrace { | ||
| 22 | }; | ||
| 23 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
| 24 | |||
| 25 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
| 26 | #endif /* _ASM_MICROBLAZE_FTRACE */ | ||
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h index 0b745828f42b..8dbb6e7a03a2 100644 --- a/arch/microblaze/include/asm/futex.h +++ b/arch/microblaze/include/asm/futex.h | |||
| @@ -1 +1,126 @@ | |||
| 1 | #include <asm-generic/futex.h> | 1 | #ifndef _ASM_MICROBLAZE_FUTEX_H |
| 2 | #define _ASM_MICROBLAZE_FUTEX_H | ||
| 3 | |||
| 4 | #ifdef __KERNEL__ | ||
| 5 | |||
| 6 | #include <linux/futex.h> | ||
| 7 | #include <linux/uaccess.h> | ||
| 8 | #include <asm/errno.h> | ||
| 9 | |||
| 10 | #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \ | ||
| 11 | ({ \ | ||
| 12 | __asm__ __volatile__ ( \ | ||
| 13 | "1: lwx %0, %2, r0; " \ | ||
| 14 | insn \ | ||
| 15 | "2: swx %1, %2, r0; \ | ||
| 16 | addic %1, r0, 0; \ | ||
| 17 | bnei %1, 1b; \ | ||
| 18 | 3: \ | ||
| 19 | .section .fixup,\"ax\"; \ | ||
| 20 | 4: brid 3b; \ | ||
| 21 | addik %1, r0, %3; \ | ||
| 22 | .previous; \ | ||
| 23 | .section __ex_table,\"a\"; \ | ||
| 24 | .word 1b,4b,2b,4b; \ | ||
| 25 | .previous;" \ | ||
| 26 | : "=&r" (oldval), "=&r" (ret) \ | ||
| 27 | : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \ | ||
| 28 | ); \ | ||
| 29 | }) | ||
| 30 | |||
| 31 | static inline int | ||
| 32 | futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | ||
| 33 | { | ||
| 34 | int op = (encoded_op >> 28) & 7; | ||
| 35 | int cmp = (encoded_op >> 24) & 15; | ||
| 36 | int oparg = (encoded_op << 8) >> 20; | ||
| 37 | int cmparg = (encoded_op << 20) >> 20; | ||
| 38 | int oldval = 0, ret; | ||
| 39 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
| 40 | oparg = 1 << oparg; | ||
| 41 | |||
| 42 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
| 43 | return -EFAULT; | ||
| 44 | |||
| 45 | pagefault_disable(); | ||
| 46 | |||
| 47 | switch (op) { | ||
| 48 | case FUTEX_OP_SET: | ||
| 49 | __futex_atomic_op("or %1,%4,%4;", ret, oldval, uaddr, oparg); | ||
| 50 | break; | ||
| 51 | case FUTEX_OP_ADD: | ||
| 52 | __futex_atomic_op("add %1,%0,%4;", ret, oldval, uaddr, oparg); | ||
| 53 | break; | ||
| 54 | case FUTEX_OP_OR: | ||
| 55 | __futex_atomic_op("or %1,%0,%4;", ret, oldval, uaddr, oparg); | ||
| 56 | break; | ||
| 57 | case FUTEX_OP_ANDN: | ||
| 58 | __futex_atomic_op("and %1,%0,%4;", ret, oldval, uaddr, oparg); | ||
| 59 | break; | ||
| 60 | case FUTEX_OP_XOR: | ||
| 61 | __futex_atomic_op("xor %1,%0,%4;", ret, oldval, uaddr, oparg); | ||
| 62 | break; | ||
| 63 | default: | ||
| 64 | ret = -ENOSYS; | ||
| 65 | } | ||
| 66 | |||
| 67 | pagefault_enable(); | ||
| 68 | |||
| 69 | if (!ret) { | ||
| 70 | switch (cmp) { | ||
| 71 | case FUTEX_OP_CMP_EQ: | ||
| 72 | ret = (oldval == cmparg); | ||
| 73 | break; | ||
| 74 | case FUTEX_OP_CMP_NE: | ||
| 75 | ret = (oldval != cmparg); | ||
| 76 | break; | ||
| 77 | case FUTEX_OP_CMP_LT: | ||
| 78 | ret = (oldval < cmparg); | ||
| 79 | break; | ||
| 80 | case FUTEX_OP_CMP_GE: | ||
| 81 | ret = (oldval >= cmparg); | ||
| 82 | break; | ||
| 83 | case FUTEX_OP_CMP_LE: | ||
| 84 | ret = (oldval <= cmparg); | ||
| 85 | break; | ||
| 86 | case FUTEX_OP_CMP_GT: | ||
| 87 | ret = (oldval > cmparg); | ||
| 88 | break; | ||
| 89 | default: | ||
| 90 | ret = -ENOSYS; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | static inline int | ||
| 97 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 98 | { | ||
| 99 | int prev, cmp; | ||
| 100 | |||
| 101 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
| 102 | return -EFAULT; | ||
| 103 | |||
| 104 | __asm__ __volatile__ ("1: lwx %0, %2, r0; \ | ||
| 105 | cmp %1, %0, %3; \ | ||
| 106 | beqi %1, 3f; \ | ||
| 107 | 2: swx %4, %2, r0; \ | ||
| 108 | addic %1, r0, 0; \ | ||
| 109 | bnei %1, 1b; \ | ||
| 110 | 3: \ | ||
| 111 | .section .fixup,\"ax\"; \ | ||
| 112 | 4: brid 3b; \ | ||
| 113 | addik %0, r0, %5; \ | ||
| 114 | .previous; \ | ||
| 115 | .section __ex_table,\"a\"; \ | ||
| 116 | .word 1b,4b,2b,4b; \ | ||
| 117 | .previous;" \ | ||
| 118 | : "=&r" (prev), "=&r"(cmp) \ | ||
| 119 | : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)); | ||
| 120 | |||
| 121 | return prev; | ||
| 122 | } | ||
| 123 | |||
| 124 | #endif /* __KERNEL__ */ | ||
| 125 | |||
| 126 | #endif | ||
diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h index dea65645a4f8..2c38c6d80176 100644 --- a/arch/microblaze/include/asm/irqflags.h +++ b/arch/microblaze/include/asm/irqflags.h | |||
| @@ -10,78 +10,73 @@ | |||
| 10 | #define _ASM_MICROBLAZE_IRQFLAGS_H | 10 | #define _ASM_MICROBLAZE_IRQFLAGS_H |
| 11 | 11 | ||
| 12 | #include <linux/irqflags.h> | 12 | #include <linux/irqflags.h> |
| 13 | #include <asm/registers.h> | ||
| 13 | 14 | ||
| 14 | # if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | 15 | # if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR |
| 15 | 16 | ||
| 16 | # define local_irq_save(flags) \ | 17 | # define raw_local_irq_save(flags) \ |
| 17 | do { \ | 18 | do { \ |
| 18 | asm volatile ("# local_irq_save \n\t" \ | 19 | asm volatile (" msrclr %0, %1; \ |
| 19 | "msrclr %0, %1 \n\t" \ | 20 | nop;" \ |
| 20 | "nop \n\t" \ | ||
| 21 | : "=r"(flags) \ | 21 | : "=r"(flags) \ |
| 22 | : "i"(MSR_IE) \ | 22 | : "i"(MSR_IE) \ |
| 23 | : "memory"); \ | 23 | : "memory"); \ |
| 24 | } while (0) | 24 | } while (0) |
| 25 | 25 | ||
| 26 | # define local_irq_disable() \ | 26 | # define raw_local_irq_disable() \ |
| 27 | do { \ | 27 | do { \ |
| 28 | asm volatile ("# local_irq_disable \n\t" \ | 28 | asm volatile (" msrclr r0, %0; \ |
| 29 | "msrclr r0, %0 \n\t" \ | 29 | nop;" \ |
| 30 | "nop \n\t" \ | 30 | : \ |
| 31 | : \ | 31 | : "i"(MSR_IE) \ |
| 32 | : "i"(MSR_IE) \ | 32 | : "memory"); \ |
| 33 | : "memory"); \ | ||
| 34 | } while (0) | 33 | } while (0) |
| 35 | 34 | ||
| 36 | # define local_irq_enable() \ | 35 | # define raw_local_irq_enable() \ |
| 37 | do { \ | 36 | do { \ |
| 38 | asm volatile ("# local_irq_enable \n\t" \ | 37 | asm volatile (" msrset r0, %0; \ |
| 39 | "msrset r0, %0 \n\t" \ | 38 | nop;" \ |
| 40 | "nop \n\t" \ | 39 | : \ |
| 41 | : \ | 40 | : "i"(MSR_IE) \ |
| 42 | : "i"(MSR_IE) \ | 41 | : "memory"); \ |
| 43 | : "memory"); \ | ||
| 44 | } while (0) | 42 | } while (0) |
| 45 | 43 | ||
| 46 | # else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */ | 44 | # else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */ |
| 47 | 45 | ||
| 48 | # define local_irq_save(flags) \ | 46 | # define raw_local_irq_save(flags) \ |
| 49 | do { \ | 47 | do { \ |
| 50 | register unsigned tmp; \ | 48 | register unsigned tmp; \ |
| 51 | asm volatile ("# local_irq_save \n\t" \ | 49 | asm volatile (" mfs %0, rmsr; \ |
| 52 | "mfs %0, rmsr \n\t" \ | 50 | nop; \ |
| 53 | "nop \n\t" \ | 51 | andi %1, %0, %2; \ |
| 54 | "andi %1, %0, %2 \n\t" \ | 52 | mts rmsr, %1; \ |
| 55 | "mts rmsr, %1 \n\t" \ | 53 | nop;" \ |
| 56 | "nop \n\t" \ | ||
| 57 | : "=r"(flags), "=r" (tmp) \ | 54 | : "=r"(flags), "=r" (tmp) \ |
| 58 | : "i"(~MSR_IE) \ | 55 | : "i"(~MSR_IE) \ |
| 59 | : "memory"); \ | 56 | : "memory"); \ |
| 60 | } while (0) | 57 | } while (0) |
| 61 | 58 | ||
| 62 | # define local_irq_disable() \ | 59 | # define raw_local_irq_disable() \ |
| 63 | do { \ | 60 | do { \ |
| 64 | register unsigned tmp; \ | 61 | register unsigned tmp; \ |
| 65 | asm volatile ("# local_irq_disable \n\t" \ | 62 | asm volatile (" mfs %0, rmsr; \ |
| 66 | "mfs %0, rmsr \n\t" \ | 63 | nop; \ |
| 67 | "nop \n\t" \ | 64 | andi %0, %0, %1; \ |
| 68 | "andi %0, %0, %1 \n\t" \ | 65 | mts rmsr, %0; \ |
| 69 | "mts rmsr, %0 \n\t" \ | 66 | nop;" \ |
| 70 | "nop \n\t" \ | ||
| 71 | : "=r"(tmp) \ | 67 | : "=r"(tmp) \ |
| 72 | : "i"(~MSR_IE) \ | 68 | : "i"(~MSR_IE) \ |
| 73 | : "memory"); \ | 69 | : "memory"); \ |
| 74 | } while (0) | 70 | } while (0) |
| 75 | 71 | ||
| 76 | # define local_irq_enable() \ | 72 | # define raw_local_irq_enable() \ |
| 77 | do { \ | 73 | do { \ |
| 78 | register unsigned tmp; \ | 74 | register unsigned tmp; \ |
| 79 | asm volatile ("# local_irq_enable \n\t" \ | 75 | asm volatile (" mfs %0, rmsr; \ |
| 80 | "mfs %0, rmsr \n\t" \ | 76 | nop; \ |
| 81 | "nop \n\t" \ | 77 | ori %0, %0, %1; \ |
| 82 | "ori %0, %0, %1 \n\t" \ | 78 | mts rmsr, %0; \ |
| 83 | "mts rmsr, %0 \n\t" \ | 79 | nop;" \ |
| 84 | "nop \n\t" \ | ||
| 85 | : "=r"(tmp) \ | 80 | : "=r"(tmp) \ |
| 86 | : "i"(MSR_IE) \ | 81 | : "i"(MSR_IE) \ |
| 87 | : "memory"); \ | 82 | : "memory"); \ |
| @@ -89,35 +84,28 @@ | |||
| 89 | 84 | ||
| 90 | # endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ | 85 | # endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ |
| 91 | 86 | ||
| 92 | #define local_save_flags(flags) \ | 87 | #define raw_local_irq_restore(flags) \ |
| 93 | do { \ | 88 | do { \ |
| 94 | asm volatile ("# local_save_flags \n\t" \ | 89 | asm volatile (" mts rmsr, %0; \ |
| 95 | "mfs %0, rmsr \n\t" \ | 90 | nop;" \ |
| 96 | "nop \n\t" \ | ||
| 97 | : "=r"(flags) \ | ||
| 98 | : \ | 91 | : \ |
| 92 | : "r"(flags) \ | ||
| 99 | : "memory"); \ | 93 | : "memory"); \ |
| 100 | } while (0) | 94 | } while (0) |
| 101 | 95 | ||
| 102 | #define local_irq_restore(flags) \ | 96 | static inline unsigned long get_msr(void) |
| 103 | do { \ | ||
| 104 | asm volatile ("# local_irq_restore \n\t"\ | ||
| 105 | "mts rmsr, %0 \n\t" \ | ||
| 106 | "nop \n\t" \ | ||
| 107 | : \ | ||
| 108 | : "r"(flags) \ | ||
| 109 | : "memory"); \ | ||
| 110 | } while (0) | ||
| 111 | |||
| 112 | static inline int irqs_disabled(void) | ||
| 113 | { | 97 | { |
| 114 | unsigned long flags; | 98 | unsigned long flags; |
| 115 | 99 | asm volatile (" mfs %0, rmsr; \ | |
| 116 | local_save_flags(flags); | 100 | nop;" \ |
| 117 | return ((flags & MSR_IE) == 0); | 101 | : "=r"(flags) \ |
| 102 | : \ | ||
| 103 | : "memory"); \ | ||
| 104 | return flags; | ||
| 118 | } | 105 | } |
| 119 | 106 | ||
| 120 | #define raw_irqs_disabled irqs_disabled | 107 | #define raw_local_save_flags(flags) ((flags) = get_msr()) |
| 121 | #define raw_irqs_disabled_flags(flags) ((flags) == 0) | 108 | #define raw_irqs_disabled() ((get_msr() & MSR_IE) == 0) |
| 109 | #define raw_irqs_disabled_flags(flags) ((flags & MSR_IE) == 0) | ||
| 122 | 110 | ||
| 123 | #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */ | 111 | #endif /* _ASM_MICROBLAZE_IRQFLAGS_H */ |
diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 880c988c2237..9b66c0fa9a32 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h | |||
| @@ -164,7 +164,8 @@ extern int page_is_ram(unsigned long pfn); | |||
| 164 | # endif /* CONFIG_MMU */ | 164 | # endif /* CONFIG_MMU */ |
| 165 | 165 | ||
| 166 | # ifndef CONFIG_MMU | 166 | # ifndef CONFIG_MMU |
| 167 | # define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) <= max_mapnr) | 167 | # define pfn_valid(pfn) (((pfn) >= min_low_pfn) && \ |
| 168 | ((pfn) <= (min_low_pfn + max_mapnr))) | ||
| 168 | # define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) | 169 | # define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) |
| 169 | # else /* CONFIG_MMU */ | 170 | # else /* CONFIG_MMU */ |
| 170 | # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) | 171 | # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) |
diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h index b0131da1387b..7547f5064560 100644 --- a/arch/microblaze/include/asm/pgalloc.h +++ b/arch/microblaze/include/asm/pgalloc.h | |||
| @@ -106,9 +106,6 @@ extern inline void free_pgd_slow(pgd_t *pgd) | |||
| 106 | */ | 106 | */ |
| 107 | #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) | 107 | #define pmd_alloc_one_fast(mm, address) ({ BUG(); ((pmd_t *)1); }) |
| 108 | #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) | 108 | #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) |
| 109 | /* FIXME two definition - look below */ | ||
| 110 | #define pmd_free(mm, x) do { } while (0) | ||
| 111 | #define pgd_populate(mm, pmd, pte) BUG() | ||
| 112 | 109 | ||
| 113 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 110 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
| 114 | unsigned long address) | 111 | unsigned long address) |
| @@ -192,14 +189,14 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage) | |||
| 192 | * the pgd will always be present.. | 189 | * the pgd will always be present.. |
| 193 | */ | 190 | */ |
| 194 | #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) | 191 | #define pmd_alloc_one(mm, address) ({ BUG(); ((pmd_t *)2); }) |
| 195 | /*#define pmd_free(mm, x) do { } while (0)*/ | 192 | #define pmd_free(mm, x) do { } while (0) |
| 196 | #define __pmd_free_tlb(tlb, x, addr) do { } while (0) | 193 | #define __pmd_free_tlb(tlb, x, addr) pmd_free((tlb)->mm, x) |
| 197 | #define pgd_populate(mm, pmd, pte) BUG() | 194 | #define pgd_populate(mm, pmd, pte) BUG() |
| 198 | 195 | ||
| 199 | extern int do_check_pgt_cache(int, int); | 196 | extern int do_check_pgt_cache(int, int); |
| 200 | 197 | ||
| 201 | #endif /* CONFIG_MMU */ | 198 | #endif /* CONFIG_MMU */ |
| 202 | 199 | ||
| 203 | #define check_pgt_cache() do {} while (0) | 200 | #define check_pgt_cache() do { } while (0) |
| 204 | 201 | ||
| 205 | #endif /* _ASM_MICROBLAZE_PGALLOC_H */ | 202 | #endif /* _ASM_MICROBLAZE_PGALLOC_H */ |
diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h index 66f1b30dd097..e38abc7714b6 100644 --- a/arch/microblaze/include/asm/pvr.h +++ b/arch/microblaze/include/asm/pvr.h | |||
| @@ -76,20 +76,23 @@ struct pvr_s { | |||
| 76 | #define PVR3_FSL_LINKS_MASK 0x00000380 | 76 | #define PVR3_FSL_LINKS_MASK 0x00000380 |
| 77 | 77 | ||
| 78 | /* ICache config PVR masks */ | 78 | /* ICache config PVR masks */ |
| 79 | #define PVR4_USE_ICACHE_MASK 0x80000000 | 79 | #define PVR4_USE_ICACHE_MASK 0x80000000 /* ICU */ |
| 80 | #define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 | 80 | #define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* ICTS */ |
| 81 | #define PVR4_ICACHE_USE_FSL_MASK 0x02000000 | 81 | #define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 /* ICW */ |
| 82 | #define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 | 82 | #define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 /* ICLL */ |
| 83 | #define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 | 83 | #define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 /* ICBS */ |
| 84 | #define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 | 84 | #define PVR4_ICACHE_ALWAYS_USED 0x00008000 /* IAU */ |
| 85 | #define PVR4_ICACHE_INTERFACE 0x00002000 /* ICI */ | ||
| 85 | 86 | ||
| 86 | /* DCache config PVR masks */ | 87 | /* DCache config PVR masks */ |
| 87 | #define PVR5_USE_DCACHE_MASK 0x80000000 | 88 | #define PVR5_USE_DCACHE_MASK 0x80000000 /* DCU */ |
| 88 | #define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 | 89 | #define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 /* DCTS */ |
| 89 | #define PVR5_DCACHE_USE_FSL_MASK 0x02000000 | 90 | #define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 /* DCW */ |
| 90 | #define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 | 91 | #define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 /* DCLL */ |
| 91 | #define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 | 92 | #define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 /* DCBS */ |
| 92 | #define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 | 93 | #define PVR5_DCACHE_ALWAYS_USED 0x00008000 /* DAU */ |
| 94 | #define PVR5_DCACHE_USE_WRITEBACK 0x00004000 /* DWB */ | ||
| 95 | #define PVR5_DCACHE_INTERFACE 0x00002000 /* DCI */ | ||
| 93 | 96 | ||
| 94 | /* ICache base address PVR mask */ | 97 | /* ICache base address PVR mask */ |
| 95 | #define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF | 98 | #define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF |
| @@ -178,11 +181,14 @@ struct pvr_s { | |||
| 178 | ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) | 181 | ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) |
| 179 | #define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK) | 182 | #define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK) |
| 180 | #define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK) | 183 | #define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK) |
| 184 | /* FIXME two shifts on one line needs any comment */ | ||
| 181 | #define PVR_DCACHE_LINE_LEN(pvr) \ | 185 | #define PVR_DCACHE_LINE_LEN(pvr) \ |
| 182 | (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) | 186 | (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) |
| 183 | #define PVR_DCACHE_BYTE_SIZE(pvr) \ | 187 | #define PVR_DCACHE_BYTE_SIZE(pvr) \ |
| 184 | (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) | 188 | (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) |
| 185 | 189 | ||
| 190 | #define PVR_DCACHE_USE_WRITEBACK(pvr) \ | ||
| 191 | ((pvr.pvr[5] & PVR5_DCACHE_USE_WRITEBACK) >> 14) | ||
| 186 | 192 | ||
| 187 | #define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK) | 193 | #define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK) |
| 188 | #define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK) | 194 | #define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK) |
diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index ed67c9ed15b8..7f31394985e0 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h | |||
| @@ -35,6 +35,8 @@ extern void mmu_reset(void); | |||
| 35 | extern void early_console_reg_tlb_alloc(unsigned int addr); | 35 | extern void early_console_reg_tlb_alloc(unsigned int addr); |
| 36 | # endif /* CONFIG_MMU */ | 36 | # endif /* CONFIG_MMU */ |
| 37 | 37 | ||
| 38 | extern void of_platform_reset_gpio_probe(void); | ||
| 39 | |||
| 38 | void time_init(void); | 40 | void time_init(void); |
| 39 | void init_IRQ(void); | 41 | void init_IRQ(void); |
| 40 | void machine_early_init(const char *cmdline, unsigned int ram, | 42 | void machine_early_init(const char *cmdline, unsigned int ram, |
diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h index b1ed61590660..157970688b2a 100644 --- a/arch/microblaze/include/asm/system.h +++ b/arch/microblaze/include/asm/system.h | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | #include <asm-generic/cmpxchg.h> | 16 | #include <asm-generic/cmpxchg.h> |
| 17 | #include <asm-generic/cmpxchg-local.h> | 17 | #include <asm-generic/cmpxchg-local.h> |
| 18 | 18 | ||
| 19 | #define __ARCH_WANT_INTERRUPTS_ON_CTXSW | ||
| 20 | |||
| 19 | struct task_struct; | 21 | struct task_struct; |
| 20 | struct thread_info; | 22 | struct thread_info; |
| 21 | 23 | ||
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 5431b4631a7a..371bd6e56d9a 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
| @@ -272,8 +272,9 @@ static inline int clear_user(char *to, int size) | |||
| 272 | return size; | 272 | return size; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | extern unsigned long __copy_tofrom_user(void __user *to, | 275 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) |
| 276 | const void __user *from, unsigned long size); | 276 | #define __copy_from_user_inatomic(to, from, n) \ |
| 277 | copy_from_user((to), (from), (n)) | ||
| 277 | 278 | ||
| 278 | #define copy_to_user(to, from, n) \ | 279 | #define copy_to_user(to, from, n) \ |
| 279 | (access_ok(VERIFY_WRITE, (to), (n)) ? \ | 280 | (access_ok(VERIFY_WRITE, (to), (n)) ? \ |
| @@ -290,10 +291,6 @@ extern unsigned long __copy_tofrom_user(void __user *to, | |||
| 290 | (void __user *)(from), (n)) \ | 291 | (void __user *)(from), (n)) \ |
| 291 | : -EFAULT) | 292 | : -EFAULT) |
| 292 | 293 | ||
| 293 | #define __copy_from_user(to, from, n) copy_from_user((to), (from), (n)) | ||
| 294 | #define __copy_from_user_inatomic(to, from, n) \ | ||
| 295 | copy_from_user((to), (from), (n)) | ||
| 296 | |||
| 297 | extern int __strncpy_user(char *to, const char __user *from, int len); | 294 | extern int __strncpy_user(char *to, const char __user *from, int len); |
| 298 | extern int __strnlen_user(const char __user *sstr, int len); | 295 | extern int __strnlen_user(const char __user *sstr, int len); |
| 299 | 296 | ||
| @@ -305,6 +302,9 @@ extern int __strnlen_user(const char __user *sstr, int len); | |||
| 305 | 302 | ||
| 306 | #endif /* CONFIG_MMU */ | 303 | #endif /* CONFIG_MMU */ |
| 307 | 304 | ||
| 305 | extern unsigned long __copy_tofrom_user(void __user *to, | ||
| 306 | const void __user *from, unsigned long size); | ||
| 307 | |||
| 308 | /* | 308 | /* |
| 309 | * The exception table consists of pairs of addresses: the first is the | 309 | * The exception table consists of pairs of addresses: the first is the |
| 310 | * address of an instruction that is allowed to fault, and the second is | 310 | * address of an instruction that is allowed to fault, and the second is |
diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile index d487729683de..b07594eccf9b 100644 --- a/arch/microblaze/kernel/Makefile +++ b/arch/microblaze/kernel/Makefile | |||
| @@ -2,12 +2,22 @@ | |||
| 2 | # Makefile | 2 | # Makefile |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ifdef CONFIG_FUNCTION_TRACER | ||
| 6 | # Do not trace early boot code and low level code | ||
| 7 | CFLAGS_REMOVE_timer.o = -pg | ||
| 8 | CFLAGS_REMOVE_intc.o = -pg | ||
| 9 | CFLAGS_REMOVE_early_printk.o = -pg | ||
| 10 | CFLAGS_REMOVE_selfmod.o = -pg | ||
| 11 | CFLAGS_REMOVE_heartbeat.o = -pg | ||
| 12 | CFLAGS_REMOVE_ftrace.o = -pg | ||
| 13 | endif | ||
| 14 | |||
| 5 | extra-y := head.o vmlinux.lds | 15 | extra-y := head.o vmlinux.lds |
| 6 | 16 | ||
| 7 | obj-y += exceptions.o \ | 17 | obj-y += exceptions.o \ |
| 8 | hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ | 18 | hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ |
| 9 | of_platform.o process.o prom.o prom_parse.o ptrace.o \ | 19 | of_platform.o process.o prom.o prom_parse.o ptrace.o \ |
| 10 | setup.o signal.o sys_microblaze.o timer.o traps.o | 20 | setup.o signal.o sys_microblaze.o timer.o traps.o reset.o |
| 11 | 21 | ||
| 12 | obj-y += cpu/ | 22 | obj-y += cpu/ |
| 13 | 23 | ||
| @@ -16,5 +26,7 @@ obj-$(CONFIG_SELFMOD) += selfmod.o | |||
| 16 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o | 26 | obj-$(CONFIG_HEART_BEAT) += heartbeat.o |
| 17 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o | 27 | obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o |
| 18 | obj-$(CONFIG_MMU) += misc.o | 28 | obj-$(CONFIG_MMU) += misc.o |
| 29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
| 30 | obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o mcount.o | ||
| 19 | 31 | ||
| 20 | obj-y += entry$(MMU).o | 32 | obj-y += entry$(MMU).o |
diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile index 20646e549271..59cc7bceaf8c 100644 --- a/arch/microblaze/kernel/cpu/Makefile +++ b/arch/microblaze/kernel/cpu/Makefile | |||
| @@ -2,6 +2,10 @@ | |||
| 2 | # Build the appropriate CPU version support | 2 | # Build the appropriate CPU version support |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ifdef CONFIG_FUNCTION_TRACER | ||
| 6 | CFLAGS_REMOVE_cache.o = -pg | ||
| 7 | endif | ||
| 8 | |||
| 5 | EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ | 9 | EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ |
| 6 | -DCPU_REV=$(CPU_REV) | 10 | -DCPU_REV=$(CPU_REV) |
| 7 | 11 | ||
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index af866a450125..d9d63831cc2f 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | 4 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> |
| 5 | * Copyright (C) 2007-2009 PetaLogix | 5 | * Copyright (C) 2007-2009 PetaLogix |
| 6 | * Copyright (C) 2007 John Williams <john.williams@petalogix.com> | 6 | * Copyright (C) 2007-2009 John Williams <john.williams@petalogix.com> |
| 7 | * | 7 | * |
| 8 | * This file is subject to the terms and conditions of the GNU General | 8 | * This file is subject to the terms and conditions of the GNU General |
| 9 | * Public License. See the file COPYING in the main directory of this | 9 | * Public License. See the file COPYING in the main directory of this |
| @@ -13,243 +13,534 @@ | |||
| 13 | #include <asm/cacheflush.h> | 13 | #include <asm/cacheflush.h> |
| 14 | #include <linux/cache.h> | 14 | #include <linux/cache.h> |
| 15 | #include <asm/cpuinfo.h> | 15 | #include <asm/cpuinfo.h> |
| 16 | #include <asm/pvr.h> | ||
| 16 | 17 | ||
| 17 | /* Exported functions */ | 18 | static inline void __invalidate_flush_icache(unsigned int addr) |
| 19 | { | ||
| 20 | __asm__ __volatile__ ("wic %0, r0;" \ | ||
| 21 | : : "r" (addr)); | ||
| 22 | } | ||
| 23 | |||
| 24 | static inline void __flush_dcache(unsigned int addr) | ||
| 25 | { | ||
| 26 | __asm__ __volatile__ ("wdc.flush %0, r0;" \ | ||
| 27 | : : "r" (addr)); | ||
| 28 | } | ||
| 29 | |||
| 30 | static inline void __invalidate_dcache(unsigned int baseaddr, | ||
| 31 | unsigned int offset) | ||
| 32 | { | ||
| 33 | __asm__ __volatile__ ("wdc.clear %0, %1;" \ | ||
| 34 | : : "r" (baseaddr), "r" (offset)); | ||
| 35 | } | ||
| 18 | 36 | ||
| 19 | void _enable_icache(void) | 37 | static inline void __enable_icache_msr(void) |
| 20 | { | 38 | { |
| 21 | if (cpuinfo.use_icache) { | 39 | __asm__ __volatile__ (" msrset r0, %0; \ |
| 22 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | 40 | nop; " \ |
| 23 | __asm__ __volatile__ (" \ | 41 | : : "i" (MSR_ICE) : "memory"); |
| 24 | msrset r0, %0; \ | 42 | } |
| 25 | nop; " \ | 43 | |
| 26 | : \ | 44 | static inline void __disable_icache_msr(void) |
| 27 | : "i" (MSR_ICE) \ | 45 | { |
| 46 | __asm__ __volatile__ (" msrclr r0, %0; \ | ||
| 47 | nop; " \ | ||
| 48 | : : "i" (MSR_ICE) : "memory"); | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline void __enable_dcache_msr(void) | ||
| 52 | { | ||
| 53 | __asm__ __volatile__ (" msrset r0, %0; \ | ||
| 54 | nop; " \ | ||
| 55 | : \ | ||
| 56 | : "i" (MSR_DCE) \ | ||
| 28 | : "memory"); | 57 | : "memory"); |
| 29 | #else | ||
| 30 | __asm__ __volatile__ (" \ | ||
| 31 | mfs r12, rmsr; \ | ||
| 32 | nop; \ | ||
| 33 | ori r12, r12, %0; \ | ||
| 34 | mts rmsr, r12; \ | ||
| 35 | nop; " \ | ||
| 36 | : \ | ||
| 37 | : "i" (MSR_ICE) \ | ||
| 38 | : "memory", "r12"); | ||
| 39 | #endif | ||
| 40 | } | ||
| 41 | } | 58 | } |
| 42 | 59 | ||
| 43 | void _disable_icache(void) | 60 | static inline void __disable_dcache_msr(void) |
| 44 | { | 61 | { |
| 45 | if (cpuinfo.use_icache) { | 62 | __asm__ __volatile__ (" msrclr r0, %0; \ |
| 46 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | 63 | nop; " \ |
| 47 | __asm__ __volatile__ (" \ | 64 | : \ |
| 48 | msrclr r0, %0; \ | 65 | : "i" (MSR_DCE) \ |
| 49 | nop; " \ | ||
| 50 | : \ | ||
| 51 | : "i" (MSR_ICE) \ | ||
| 52 | : "memory"); | 66 | : "memory"); |
| 53 | #else | 67 | } |
| 54 | __asm__ __volatile__ (" \ | 68 | |
| 55 | mfs r12, rmsr; \ | 69 | static inline void __enable_icache_nomsr(void) |
| 56 | nop; \ | 70 | { |
| 57 | andi r12, r12, ~%0; \ | 71 | __asm__ __volatile__ (" mfs r12, rmsr; \ |
| 58 | mts rmsr, r12; \ | 72 | nop; \ |
| 59 | nop; " \ | 73 | ori r12, r12, %0; \ |
| 60 | : \ | 74 | mts rmsr, r12; \ |
| 61 | : "i" (MSR_ICE) \ | 75 | nop; " \ |
| 76 | : \ | ||
| 77 | : "i" (MSR_ICE) \ | ||
| 62 | : "memory", "r12"); | 78 | : "memory", "r12"); |
| 63 | #endif | ||
| 64 | } | ||
| 65 | } | 79 | } |
| 66 | 80 | ||
| 67 | void _invalidate_icache(unsigned int addr) | 81 | static inline void __disable_icache_nomsr(void) |
| 68 | { | 82 | { |
| 69 | if (cpuinfo.use_icache) { | 83 | __asm__ __volatile__ (" mfs r12, rmsr; \ |
| 70 | __asm__ __volatile__ (" \ | 84 | nop; \ |
| 71 | wic %0, r0" \ | 85 | andi r12, r12, ~%0; \ |
| 72 | : \ | 86 | mts rmsr, r12; \ |
| 73 | : "r" (addr)); | 87 | nop; " \ |
| 74 | } | 88 | : \ |
| 89 | : "i" (MSR_ICE) \ | ||
| 90 | : "memory", "r12"); | ||
| 75 | } | 91 | } |
| 76 | 92 | ||
| 77 | void _enable_dcache(void) | 93 | static inline void __enable_dcache_nomsr(void) |
| 78 | { | 94 | { |
| 79 | if (cpuinfo.use_dcache) { | 95 | __asm__ __volatile__ (" mfs r12, rmsr; \ |
| 80 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | 96 | nop; \ |
| 81 | __asm__ __volatile__ (" \ | 97 | ori r12, r12, %0; \ |
| 82 | msrset r0, %0; \ | 98 | mts rmsr, r12; \ |
| 83 | nop; " \ | 99 | nop; " \ |
| 84 | : \ | 100 | : \ |
| 85 | : "i" (MSR_DCE) \ | 101 | : "i" (MSR_DCE) \ |
| 86 | : "memory"); | ||
| 87 | #else | ||
| 88 | __asm__ __volatile__ (" \ | ||
| 89 | mfs r12, rmsr; \ | ||
| 90 | nop; \ | ||
| 91 | ori r12, r12, %0; \ | ||
| 92 | mts rmsr, r12; \ | ||
| 93 | nop; " \ | ||
| 94 | : \ | ||
| 95 | : "i" (MSR_DCE) \ | ||
| 96 | : "memory", "r12"); | 102 | : "memory", "r12"); |
| 97 | #endif | ||
| 98 | } | ||
| 99 | } | 103 | } |
| 100 | 104 | ||
| 101 | void _disable_dcache(void) | 105 | static inline void __disable_dcache_nomsr(void) |
| 102 | { | 106 | { |
| 103 | #if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR | 107 | __asm__ __volatile__ (" mfs r12, rmsr; \ |
| 104 | __asm__ __volatile__ (" \ | 108 | nop; \ |
| 105 | msrclr r0, %0; \ | 109 | andi r12, r12, ~%0; \ |
| 106 | nop; " \ | 110 | mts rmsr, r12; \ |
| 107 | : \ | 111 | nop; " \ |
| 108 | : "i" (MSR_DCE) \ | 112 | : \ |
| 109 | : "memory"); | 113 | : "i" (MSR_DCE) \ |
| 110 | #else | ||
| 111 | __asm__ __volatile__ (" \ | ||
| 112 | mfs r12, rmsr; \ | ||
| 113 | nop; \ | ||
| 114 | andi r12, r12, ~%0; \ | ||
| 115 | mts rmsr, r12; \ | ||
| 116 | nop; " \ | ||
| 117 | : \ | ||
| 118 | : "i" (MSR_DCE) \ | ||
| 119 | : "memory", "r12"); | 114 | : "memory", "r12"); |
| 120 | #endif | ||
| 121 | } | 115 | } |
| 122 | 116 | ||
| 123 | void _invalidate_dcache(unsigned int addr) | 117 | |
| 118 | /* Helper macro for computing the limits of cache range loops */ | ||
| 119 | #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size) \ | ||
| 120 | do { \ | ||
| 121 | int align = ~(cache_line_length - 1); \ | ||
| 122 | end = min(start + cache_size, end); \ | ||
| 123 | start &= align; \ | ||
| 124 | end = ((end & align) + cache_line_length); \ | ||
| 125 | } while (0); | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Helper macro to loop over the specified cache_size/line_length and | ||
| 129 | * execute 'op' on that cacheline | ||
| 130 | */ | ||
| 131 | #define CACHE_ALL_LOOP(cache_size, line_length, op) \ | ||
| 132 | do { \ | ||
| 133 | unsigned int len = cache_size; \ | ||
| 134 | int step = -line_length; \ | ||
| 135 | BUG_ON(step >= 0); \ | ||
| 136 | \ | ||
| 137 | __asm__ __volatile__ (" 1: " #op " %0, r0; \ | ||
| 138 | bgtid %0, 1b; \ | ||
| 139 | addk %0, %0, %1; \ | ||
| 140 | " : : "r" (len), "r" (step) \ | ||
| 141 | : "memory"); \ | ||
| 142 | } while (0); | ||
| 143 | |||
| 144 | |||
| 145 | #define CACHE_ALL_LOOP2(cache_size, line_length, op) \ | ||
| 146 | do { \ | ||
| 147 | unsigned int len = cache_size; \ | ||
| 148 | int step = -line_length; \ | ||
| 149 | BUG_ON(step >= 0); \ | ||
| 150 | \ | ||
| 151 | __asm__ __volatile__ (" 1: " #op " r0, %0; \ | ||
| 152 | bgtid %0, 1b; \ | ||
| 153 | addk %0, %0, %1; \ | ||
| 154 | " : : "r" (len), "r" (step) \ | ||
| 155 | : "memory"); \ | ||
| 156 | } while (0); | ||
| 157 | |||
| 158 | /* for wdc.flush/clear */ | ||
| 159 | #define CACHE_RANGE_LOOP_2(start, end, line_length, op) \ | ||
| 160 | do { \ | ||
| 161 | int step = -line_length; \ | ||
| 162 | int count = end - start; \ | ||
| 163 | BUG_ON(count <= 0); \ | ||
| 164 | \ | ||
| 165 | __asm__ __volatile__ (" 1: " #op " %0, %1; \ | ||
| 166 | bgtid %1, 1b; \ | ||
| 167 | addk %1, %1, %2; \ | ||
| 168 | " : : "r" (start), "r" (count), \ | ||
| 169 | "r" (step) : "memory"); \ | ||
| 170 | } while (0); | ||
| 171 | |||
| 172 | /* It is used only first parameter for OP - for wic, wdc */ | ||
| 173 | #define CACHE_RANGE_LOOP_1(start, end, line_length, op) \ | ||
| 174 | do { \ | ||
| 175 | int step = -line_length; \ | ||
| 176 | int count = end - start; \ | ||
| 177 | BUG_ON(count <= 0); \ | ||
| 178 | \ | ||
| 179 | __asm__ __volatile__ (" 1: addk %0, %0, %1; \ | ||
| 180 | " #op " %0, r0; \ | ||
| 181 | bgtid %1, 1b; \ | ||
| 182 | addk %1, %1, %2; \ | ||
| 183 | " : : "r" (start), "r" (count), \ | ||
| 184 | "r" (step) : "memory"); \ | ||
| 185 | } while (0); | ||
| 186 | |||
| 187 | static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end) | ||
| 124 | { | 188 | { |
| 125 | __asm__ __volatile__ (" \ | 189 | unsigned long flags; |
| 126 | wdc %0, r0" \ | 190 | |
| 127 | : \ | 191 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, |
| 128 | : "r" (addr)); | 192 | (unsigned int)start, (unsigned int) end); |
| 193 | |||
| 194 | CACHE_LOOP_LIMITS(start, end, | ||
| 195 | cpuinfo.icache_line_length, cpuinfo.icache_size); | ||
| 196 | |||
| 197 | local_irq_save(flags); | ||
| 198 | __disable_icache_msr(); | ||
| 199 | |||
| 200 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); | ||
| 201 | |||
| 202 | __enable_icache_msr(); | ||
| 203 | local_irq_restore(flags); | ||
| 129 | } | 204 | } |
| 130 | 205 | ||
| 131 | void __invalidate_icache_all(void) | 206 | static void __flush_icache_range_nomsr_irq(unsigned long start, |
| 207 | unsigned long end) | ||
| 132 | { | 208 | { |
| 133 | unsigned int i; | 209 | unsigned long flags; |
| 134 | unsigned flags; | ||
| 135 | 210 | ||
| 136 | if (cpuinfo.use_icache) { | 211 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, |
| 137 | local_irq_save(flags); | 212 | (unsigned int)start, (unsigned int) end); |
| 138 | __disable_icache(); | ||
| 139 | 213 | ||
| 140 | /* Just loop through cache size and invalidate, no need to add | 214 | CACHE_LOOP_LIMITS(start, end, |
| 141 | CACHE_BASE address */ | 215 | cpuinfo.icache_line_length, cpuinfo.icache_size); |
| 142 | for (i = 0; i < cpuinfo.icache_size; | ||
| 143 | i += cpuinfo.icache_line) | ||
| 144 | __invalidate_icache(i); | ||
| 145 | 216 | ||
| 146 | __enable_icache(); | 217 | local_irq_save(flags); |
| 147 | local_irq_restore(flags); | 218 | __disable_icache_nomsr(); |
| 148 | } | 219 | |
| 220 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); | ||
| 221 | |||
| 222 | __enable_icache_nomsr(); | ||
| 223 | local_irq_restore(flags); | ||
| 149 | } | 224 | } |
| 150 | 225 | ||
| 151 | void __invalidate_icache_range(unsigned long start, unsigned long end) | 226 | static void __flush_icache_range_noirq(unsigned long start, |
| 227 | unsigned long end) | ||
| 152 | { | 228 | { |
| 153 | unsigned int i; | 229 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, |
| 154 | unsigned flags; | 230 | (unsigned int)start, (unsigned int) end); |
| 155 | unsigned int align; | 231 | |
| 156 | 232 | CACHE_LOOP_LIMITS(start, end, | |
| 157 | if (cpuinfo.use_icache) { | 233 | cpuinfo.icache_line_length, cpuinfo.icache_size); |
| 158 | /* | 234 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic); |
| 159 | * No need to cover entire cache range, | 235 | } |
| 160 | * just cover cache footprint | 236 | |
| 161 | */ | 237 | static void __flush_icache_all_msr_irq(void) |
| 162 | end = min(start + cpuinfo.icache_size, end); | 238 | { |
| 163 | align = ~(cpuinfo.icache_line - 1); | 239 | unsigned long flags; |
| 164 | start &= align; /* Make sure we are aligned */ | 240 | |
| 165 | /* Push end up to the next cache line */ | 241 | pr_debug("%s\n", __func__); |
| 166 | end = ((end & align) + cpuinfo.icache_line); | 242 | |
| 167 | 243 | local_irq_save(flags); | |
| 168 | local_irq_save(flags); | 244 | __disable_icache_msr(); |
| 169 | __disable_icache(); | 245 | |
| 170 | 246 | CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); | |
| 171 | for (i = start; i < end; i += cpuinfo.icache_line) | 247 | |
| 172 | __invalidate_icache(i); | 248 | __enable_icache_msr(); |
| 173 | 249 | local_irq_restore(flags); | |
| 174 | __enable_icache(); | 250 | } |
| 175 | local_irq_restore(flags); | 251 | |
| 176 | } | 252 | static void __flush_icache_all_nomsr_irq(void) |
| 253 | { | ||
| 254 | unsigned long flags; | ||
| 255 | |||
| 256 | pr_debug("%s\n", __func__); | ||
| 257 | |||
| 258 | local_irq_save(flags); | ||
| 259 | __disable_icache_nomsr(); | ||
| 260 | |||
| 261 | CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); | ||
| 262 | |||
| 263 | __enable_icache_nomsr(); | ||
| 264 | local_irq_restore(flags); | ||
| 177 | } | 265 | } |
| 178 | 266 | ||
| 179 | void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) | 267 | static void __flush_icache_all_noirq(void) |
| 180 | { | 268 | { |
| 181 | __invalidate_icache_all(); | 269 | pr_debug("%s\n", __func__); |
| 270 | CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic); | ||
| 182 | } | 271 | } |
| 183 | 272 | ||
| 184 | void __invalidate_icache_user_range(struct vm_area_struct *vma, | 273 | static void __invalidate_dcache_all_msr_irq(void) |
| 185 | struct page *page, unsigned long adr, | ||
| 186 | int len) | ||
| 187 | { | 274 | { |
| 188 | __invalidate_icache_all(); | 275 | unsigned long flags; |
| 276 | |||
| 277 | pr_debug("%s\n", __func__); | ||
| 278 | |||
| 279 | local_irq_save(flags); | ||
| 280 | __disable_dcache_msr(); | ||
| 281 | |||
| 282 | CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); | ||
| 283 | |||
| 284 | __enable_dcache_msr(); | ||
| 285 | local_irq_restore(flags); | ||
| 189 | } | 286 | } |
| 190 | 287 | ||
| 191 | void __invalidate_cache_sigtramp(unsigned long addr) | 288 | static void __invalidate_dcache_all_nomsr_irq(void) |
| 192 | { | 289 | { |
| 193 | __invalidate_icache_range(addr, addr + 8); | 290 | unsigned long flags; |
| 291 | |||
| 292 | pr_debug("%s\n", __func__); | ||
| 293 | |||
| 294 | local_irq_save(flags); | ||
| 295 | __disable_dcache_nomsr(); | ||
| 296 | |||
| 297 | CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc); | ||
| 298 | |||
| 299 | __enable_dcache_nomsr(); | ||
| 300 | local_irq_restore(flags); | ||
| 194 | } | 301 | } |
| 195 | 302 | ||
| 196 | void __invalidate_dcache_all(void) | 303 | static void __invalidate_dcache_all_noirq_wt(void) |
| 197 | { | 304 | { |
| 198 | unsigned int i; | 305 | pr_debug("%s\n", __func__); |
| 199 | unsigned flags; | 306 | CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc) |
| 200 | |||
| 201 | if (cpuinfo.use_dcache) { | ||
| 202 | local_irq_save(flags); | ||
| 203 | __disable_dcache(); | ||
| 204 | |||
| 205 | /* | ||
| 206 | * Just loop through cache size and invalidate, | ||
| 207 | * no need to add CACHE_BASE address | ||
| 208 | */ | ||
| 209 | for (i = 0; i < cpuinfo.dcache_size; | ||
| 210 | i += cpuinfo.dcache_line) | ||
| 211 | __invalidate_dcache(i); | ||
| 212 | |||
| 213 | __enable_dcache(); | ||
| 214 | local_irq_restore(flags); | ||
| 215 | } | ||
| 216 | } | 307 | } |
| 217 | 308 | ||
| 218 | void __invalidate_dcache_range(unsigned long start, unsigned long end) | 309 | /* FIXME this is weird - should be only wdc but not work |
| 310 | * MS: I am getting bus errors and other weird things */ | ||
| 311 | static void __invalidate_dcache_all_wb(void) | ||
| 219 | { | 312 | { |
| 313 | pr_debug("%s\n", __func__); | ||
| 314 | CACHE_ALL_LOOP2(cpuinfo.dcache_size, cpuinfo.dcache_line_length, | ||
| 315 | wdc.clear) | ||
| 316 | |||
| 317 | #if 0 | ||
| 220 | unsigned int i; | 318 | unsigned int i; |
| 221 | unsigned flags; | 319 | |
| 222 | unsigned int align; | 320 | pr_debug("%s\n", __func__); |
| 223 | 321 | ||
| 224 | if (cpuinfo.use_dcache) { | 322 | /* Just loop through cache size and invalidate it */ |
| 225 | /* | 323 | for (i = 0; i < cpuinfo.dcache_size; i += cpuinfo.dcache_line_length) |
| 226 | * No need to cover entire cache range, | 324 | __invalidate_dcache(0, i); |
| 227 | * just cover cache footprint | 325 | #endif |
| 228 | */ | 326 | } |
| 229 | end = min(start + cpuinfo.dcache_size, end); | 327 | |
| 230 | align = ~(cpuinfo.dcache_line - 1); | 328 | static void __invalidate_dcache_range_wb(unsigned long start, |
| 231 | start &= align; /* Make sure we are aligned */ | 329 | unsigned long end) |
| 232 | /* Push end up to the next cache line */ | 330 | { |
| 233 | end = ((end & align) + cpuinfo.dcache_line); | 331 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, |
| 234 | local_irq_save(flags); | 332 | (unsigned int)start, (unsigned int) end); |
| 235 | __disable_dcache(); | 333 | |
| 236 | 334 | CACHE_LOOP_LIMITS(start, end, | |
| 237 | for (i = start; i < end; i += cpuinfo.dcache_line) | 335 | cpuinfo.dcache_line_length, cpuinfo.dcache_size); |
| 238 | __invalidate_dcache(i); | 336 | CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear); |
| 239 | 337 | } | |
| 240 | __enable_dcache(); | 338 | |
| 241 | local_irq_restore(flags); | 339 | static void __invalidate_dcache_range_nomsr_wt(unsigned long start, |
| 242 | } | 340 | unsigned long end) |
| 341 | { | ||
| 342 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, | ||
| 343 | (unsigned int)start, (unsigned int) end); | ||
| 344 | CACHE_LOOP_LIMITS(start, end, | ||
| 345 | cpuinfo.dcache_line_length, cpuinfo.dcache_size); | ||
| 346 | |||
| 347 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); | ||
| 243 | } | 348 | } |
| 244 | 349 | ||
| 245 | void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) | 350 | static void __invalidate_dcache_range_msr_irq_wt(unsigned long start, |
| 351 | unsigned long end) | ||
| 246 | { | 352 | { |
| 247 | __invalidate_dcache_all(); | 353 | unsigned long flags; |
| 354 | |||
| 355 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, | ||
| 356 | (unsigned int)start, (unsigned int) end); | ||
| 357 | CACHE_LOOP_LIMITS(start, end, | ||
| 358 | cpuinfo.dcache_line_length, cpuinfo.dcache_size); | ||
| 359 | |||
| 360 | local_irq_save(flags); | ||
| 361 | __disable_dcache_msr(); | ||
| 362 | |||
| 363 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); | ||
| 364 | |||
| 365 | __enable_dcache_msr(); | ||
| 366 | local_irq_restore(flags); | ||
| 367 | } | ||
| 368 | |||
| 369 | static void __invalidate_dcache_range_nomsr_irq(unsigned long start, | ||
| 370 | unsigned long end) | ||
| 371 | { | ||
| 372 | unsigned long flags; | ||
| 373 | |||
| 374 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, | ||
| 375 | (unsigned int)start, (unsigned int) end); | ||
| 376 | |||
| 377 | CACHE_LOOP_LIMITS(start, end, | ||
| 378 | cpuinfo.dcache_line_length, cpuinfo.dcache_size); | ||
| 379 | |||
| 380 | local_irq_save(flags); | ||
| 381 | __disable_dcache_nomsr(); | ||
| 382 | |||
| 383 | CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc); | ||
| 384 | |||
| 385 | __enable_dcache_nomsr(); | ||
| 386 | local_irq_restore(flags); | ||
| 387 | } | ||
| 388 | |||
| 389 | static void __flush_dcache_all_wb(void) | ||
| 390 | { | ||
| 391 | pr_debug("%s\n", __func__); | ||
| 392 | CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, | ||
| 393 | wdc.flush); | ||
| 248 | } | 394 | } |
| 249 | 395 | ||
| 250 | void __invalidate_dcache_user_range(struct vm_area_struct *vma, | 396 | static void __flush_dcache_range_wb(unsigned long start, unsigned long end) |
| 251 | struct page *page, unsigned long adr, | ||
| 252 | int len) | ||
| 253 | { | 397 | { |
| 254 | __invalidate_dcache_all(); | 398 | pr_debug("%s: start 0x%x, end 0x%x\n", __func__, |
| 399 | (unsigned int)start, (unsigned int) end); | ||
| 400 | |||
| 401 | CACHE_LOOP_LIMITS(start, end, | ||
| 402 | cpuinfo.dcache_line_length, cpuinfo.dcache_size); | ||
| 403 | CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush); | ||
| 404 | } | ||
| 405 | |||
| 406 | /* struct for wb caches and for wt caches */ | ||
| 407 | struct scache *mbc; | ||
| 408 | |||
| 409 | /* new wb cache model */ | ||
| 410 | const struct scache wb_msr = { | ||
| 411 | .ie = __enable_icache_msr, | ||
| 412 | .id = __disable_icache_msr, | ||
| 413 | .ifl = __flush_icache_all_noirq, | ||
| 414 | .iflr = __flush_icache_range_noirq, | ||
| 415 | .iin = __flush_icache_all_noirq, | ||
| 416 | .iinr = __flush_icache_range_noirq, | ||
| 417 | .de = __enable_dcache_msr, | ||
| 418 | .dd = __disable_dcache_msr, | ||
| 419 | .dfl = __flush_dcache_all_wb, | ||
| 420 | .dflr = __flush_dcache_range_wb, | ||
| 421 | .din = __invalidate_dcache_all_wb, | ||
| 422 | .dinr = __invalidate_dcache_range_wb, | ||
| 423 | }; | ||
| 424 | |||
| 425 | /* There is only difference in ie, id, de, dd functions */ | ||
| 426 | const struct scache wb_nomsr = { | ||
| 427 | .ie = __enable_icache_nomsr, | ||
| 428 | .id = __disable_icache_nomsr, | ||
| 429 | .ifl = __flush_icache_all_noirq, | ||
| 430 | .iflr = __flush_icache_range_noirq, | ||
| 431 | .iin = __flush_icache_all_noirq, | ||
| 432 | .iinr = __flush_icache_range_noirq, | ||
| 433 | .de = __enable_dcache_nomsr, | ||
| 434 | .dd = __disable_dcache_nomsr, | ||
| 435 | .dfl = __flush_dcache_all_wb, | ||
| 436 | .dflr = __flush_dcache_range_wb, | ||
| 437 | .din = __invalidate_dcache_all_wb, | ||
| 438 | .dinr = __invalidate_dcache_range_wb, | ||
| 439 | }; | ||
| 440 | |||
| 441 | /* Old wt cache model with disabling irq and turn off cache */ | ||
| 442 | const struct scache wt_msr = { | ||
| 443 | .ie = __enable_icache_msr, | ||
| 444 | .id = __disable_icache_msr, | ||
| 445 | .ifl = __flush_icache_all_msr_irq, | ||
| 446 | .iflr = __flush_icache_range_msr_irq, | ||
| 447 | .iin = __flush_icache_all_msr_irq, | ||
| 448 | .iinr = __flush_icache_range_msr_irq, | ||
| 449 | .de = __enable_dcache_msr, | ||
| 450 | .dd = __disable_dcache_msr, | ||
| 451 | .dfl = __invalidate_dcache_all_msr_irq, | ||
| 452 | .dflr = __invalidate_dcache_range_msr_irq_wt, | ||
| 453 | .din = __invalidate_dcache_all_msr_irq, | ||
| 454 | .dinr = __invalidate_dcache_range_msr_irq_wt, | ||
| 455 | }; | ||
| 456 | |||
| 457 | const struct scache wt_nomsr = { | ||
| 458 | .ie = __enable_icache_nomsr, | ||
| 459 | .id = __disable_icache_nomsr, | ||
| 460 | .ifl = __flush_icache_all_nomsr_irq, | ||
| 461 | .iflr = __flush_icache_range_nomsr_irq, | ||
| 462 | .iin = __flush_icache_all_nomsr_irq, | ||
| 463 | .iinr = __flush_icache_range_nomsr_irq, | ||
| 464 | .de = __enable_dcache_nomsr, | ||
| 465 | .dd = __disable_dcache_nomsr, | ||
| 466 | .dfl = __invalidate_dcache_all_nomsr_irq, | ||
| 467 | .dflr = __invalidate_dcache_range_nomsr_irq, | ||
| 468 | .din = __invalidate_dcache_all_nomsr_irq, | ||
| 469 | .dinr = __invalidate_dcache_range_nomsr_irq, | ||
| 470 | }; | ||
| 471 | |||
| 472 | /* New wt cache model for newer Microblaze versions */ | ||
| 473 | const struct scache wt_msr_noirq = { | ||
| 474 | .ie = __enable_icache_msr, | ||
| 475 | .id = __disable_icache_msr, | ||
| 476 | .ifl = __flush_icache_all_noirq, | ||
| 477 | .iflr = __flush_icache_range_noirq, | ||
| 478 | .iin = __flush_icache_all_noirq, | ||
| 479 | .iinr = __flush_icache_range_noirq, | ||
| 480 | .de = __enable_dcache_msr, | ||
| 481 | .dd = __disable_dcache_msr, | ||
| 482 | .dfl = __invalidate_dcache_all_noirq_wt, | ||
| 483 | .dflr = __invalidate_dcache_range_nomsr_wt, | ||
| 484 | .din = __invalidate_dcache_all_noirq_wt, | ||
| 485 | .dinr = __invalidate_dcache_range_nomsr_wt, | ||
| 486 | }; | ||
| 487 | |||
| 488 | const struct scache wt_nomsr_noirq = { | ||
| 489 | .ie = __enable_icache_nomsr, | ||
| 490 | .id = __disable_icache_nomsr, | ||
| 491 | .ifl = __flush_icache_all_noirq, | ||
| 492 | .iflr = __flush_icache_range_noirq, | ||
| 493 | .iin = __flush_icache_all_noirq, | ||
| 494 | .iinr = __flush_icache_range_noirq, | ||
| 495 | .de = __enable_dcache_nomsr, | ||
| 496 | .dd = __disable_dcache_nomsr, | ||
| 497 | .dfl = __invalidate_dcache_all_noirq_wt, | ||
| 498 | .dflr = __invalidate_dcache_range_nomsr_wt, | ||
| 499 | .din = __invalidate_dcache_all_noirq_wt, | ||
| 500 | .dinr = __invalidate_dcache_range_nomsr_wt, | ||
| 501 | }; | ||
| 502 | |||
| 503 | /* CPU version code for 7.20.c - see arch/microblaze/kernel/cpu/cpuinfo.c */ | ||
| 504 | #define CPUVER_7_20_A 0x0c | ||
| 505 | #define CPUVER_7_20_D 0x0f | ||
| 506 | |||
| 507 | #define INFO(s) printk(KERN_INFO "cache: " s " \n"); | ||
| 508 | |||
| 509 | void microblaze_cache_init(void) | ||
| 510 | { | ||
| 511 | if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) { | ||
| 512 | if (cpuinfo.dcache_wb) { | ||
| 513 | INFO("wb_msr"); | ||
| 514 | mbc = (struct scache *)&wb_msr; | ||
| 515 | if (cpuinfo.ver_code < CPUVER_7_20_D) { | ||
| 516 | /* MS: problem with signal handling - hw bug */ | ||
| 517 | INFO("WB won't work properly"); | ||
| 518 | } | ||
| 519 | } else { | ||
| 520 | if (cpuinfo.ver_code >= CPUVER_7_20_A) { | ||
| 521 | INFO("wt_msr_noirq"); | ||
| 522 | mbc = (struct scache *)&wt_msr_noirq; | ||
| 523 | } else { | ||
| 524 | INFO("wt_msr"); | ||
| 525 | mbc = (struct scache *)&wt_msr; | ||
| 526 | } | ||
| 527 | } | ||
| 528 | } else { | ||
| 529 | if (cpuinfo.dcache_wb) { | ||
| 530 | INFO("wb_nomsr"); | ||
| 531 | mbc = (struct scache *)&wb_nomsr; | ||
| 532 | if (cpuinfo.ver_code < CPUVER_7_20_D) { | ||
| 533 | /* MS: problem with signal handling - hw bug */ | ||
| 534 | INFO("WB won't work properly"); | ||
| 535 | } | ||
| 536 | } else { | ||
| 537 | if (cpuinfo.ver_code >= CPUVER_7_20_A) { | ||
| 538 | INFO("wt_nomsr_noirq"); | ||
| 539 | mbc = (struct scache *)&wt_nomsr_noirq; | ||
| 540 | } else { | ||
| 541 | INFO("wt_nomsr"); | ||
| 542 | mbc = (struct scache *)&wt_nomsr; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | } | ||
| 255 | } | 546 | } |
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c index c259786e7faa..f72dbd66c844 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c | |||
| @@ -21,8 +21,14 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #define CI(c, p) { ci->c = PVR_##p(pvr); } | 23 | #define CI(c, p) { ci->c = PVR_##p(pvr); } |
| 24 | |||
| 25 | #if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) | ||
| 24 | #define err_printk(x) \ | 26 | #define err_printk(x) \ |
| 25 | early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); | 27 | early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); |
| 28 | #else | ||
| 29 | #define err_printk(x) \ | ||
| 30 | printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n"); | ||
| 31 | #endif | ||
| 26 | 32 | ||
| 27 | void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) | 33 | void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) |
| 28 | { | 34 | { |
| @@ -70,7 +76,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) | |||
| 70 | CI(use_icache, USE_ICACHE); | 76 | CI(use_icache, USE_ICACHE); |
| 71 | CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); | 77 | CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); |
| 72 | CI(icache_write, ICACHE_ALLOW_WR); | 78 | CI(icache_write, ICACHE_ALLOW_WR); |
| 73 | CI(icache_line, ICACHE_LINE_LEN); | 79 | ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2; |
| 74 | CI(icache_size, ICACHE_BYTE_SIZE); | 80 | CI(icache_size, ICACHE_BYTE_SIZE); |
| 75 | CI(icache_base, ICACHE_BASEADDR); | 81 | CI(icache_base, ICACHE_BASEADDR); |
| 76 | CI(icache_high, ICACHE_HIGHADDR); | 82 | CI(icache_high, ICACHE_HIGHADDR); |
| @@ -78,11 +84,16 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) | |||
| 78 | CI(use_dcache, USE_DCACHE); | 84 | CI(use_dcache, USE_DCACHE); |
| 79 | CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); | 85 | CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); |
| 80 | CI(dcache_write, DCACHE_ALLOW_WR); | 86 | CI(dcache_write, DCACHE_ALLOW_WR); |
| 81 | CI(dcache_line, DCACHE_LINE_LEN); | 87 | ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2; |
| 82 | CI(dcache_size, DCACHE_BYTE_SIZE); | 88 | CI(dcache_size, DCACHE_BYTE_SIZE); |
| 83 | CI(dcache_base, DCACHE_BASEADDR); | 89 | CI(dcache_base, DCACHE_BASEADDR); |
| 84 | CI(dcache_high, DCACHE_HIGHADDR); | 90 | CI(dcache_high, DCACHE_HIGHADDR); |
| 85 | 91 | ||
| 92 | temp = PVR_DCACHE_USE_WRITEBACK(pvr); | ||
| 93 | if (ci->dcache_wb != temp) | ||
| 94 | err_printk("DCACHE WB"); | ||
| 95 | ci->dcache_wb = temp; | ||
| 96 | |||
| 86 | CI(use_dopb, D_OPB); | 97 | CI(use_dopb, D_OPB); |
| 87 | CI(use_iopb, I_OPB); | 98 | CI(use_iopb, I_OPB); |
| 88 | CI(use_dlmb, D_LMB); | 99 | CI(use_dlmb, D_LMB); |
diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c index adb448f93d5f..6095aa6b5c88 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo-static.c +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c | |||
| @@ -72,12 +72,12 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) | |||
| 72 | ci->use_icache = fcpu(cpu, "xlnx,use-icache"); | 72 | ci->use_icache = fcpu(cpu, "xlnx,use-icache"); |
| 73 | ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); | 73 | ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); |
| 74 | ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); | 74 | ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); |
| 75 | ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2; | 75 | ci->icache_line_length = fcpu(cpu, "xlnx,icache-line-len") << 2; |
| 76 | if (!ci->icache_line) { | 76 | if (!ci->icache_line_length) { |
| 77 | if (fcpu(cpu, "xlnx,icache-use-fsl")) | 77 | if (fcpu(cpu, "xlnx,icache-use-fsl")) |
| 78 | ci->icache_line = 4 << 2; | 78 | ci->icache_line_length = 4 << 2; |
| 79 | else | 79 | else |
| 80 | ci->icache_line = 1 << 2; | 80 | ci->icache_line_length = 1 << 2; |
| 81 | } | 81 | } |
| 82 | ci->icache_size = fcpu(cpu, "i-cache-size"); | 82 | ci->icache_size = fcpu(cpu, "i-cache-size"); |
| 83 | ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); | 83 | ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); |
| @@ -86,16 +86,17 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) | |||
| 86 | ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); | 86 | ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); |
| 87 | ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); | 87 | ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); |
| 88 | ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); | 88 | ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); |
| 89 | ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2; | 89 | ci->dcache_line_length = fcpu(cpu, "xlnx,dcache-line-len") << 2; |
| 90 | if (!ci->dcache_line) { | 90 | if (!ci->dcache_line_length) { |
| 91 | if (fcpu(cpu, "xlnx,dcache-use-fsl")) | 91 | if (fcpu(cpu, "xlnx,dcache-use-fsl")) |
| 92 | ci->dcache_line = 4 << 2; | 92 | ci->dcache_line_length = 4 << 2; |
| 93 | else | 93 | else |
| 94 | ci->dcache_line = 1 << 2; | 94 | ci->dcache_line_length = 1 << 2; |
| 95 | } | 95 | } |
| 96 | ci->dcache_size = fcpu(cpu, "d-cache-size"); | 96 | ci->dcache_size = fcpu(cpu, "d-cache-size"); |
| 97 | ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); | 97 | ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); |
| 98 | ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); | 98 | ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); |
| 99 | ci->dcache_wb = fcpu(cpu, "xlnx,dcache-use-writeback"); | ||
| 99 | 100 | ||
| 100 | ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); | 101 | ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); |
| 101 | ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); | 102 | ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); |
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c index 3539babc1c18..991d71311b0e 100644 --- a/arch/microblaze/kernel/cpu/cpuinfo.c +++ b/arch/microblaze/kernel/cpu/cpuinfo.c | |||
| @@ -29,11 +29,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = { | |||
| 29 | {"7.20.a", 0x0c}, | 29 | {"7.20.a", 0x0c}, |
| 30 | {"7.20.b", 0x0d}, | 30 | {"7.20.b", 0x0d}, |
| 31 | {"7.20.c", 0x0e}, | 31 | {"7.20.c", 0x0e}, |
| 32 | /* FIXME There is no keycode defined in MBV for these versions */ | 32 | {"7.20.d", 0x0f}, |
| 33 | {"2.10.a", 0x10}, | 33 | {"7.30.a", 0x10}, |
| 34 | {"3.00.a", 0x20}, | ||
| 35 | {"4.00.a", 0x30}, | ||
| 36 | {"4.00.b", 0x40}, | ||
| 37 | {NULL, 0}, | 34 | {NULL, 0}, |
| 38 | }; | 35 | }; |
| 39 | 36 | ||
diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c index 4dcfccdbc364..0c912b2a8e03 100644 --- a/arch/microblaze/kernel/cpu/mb.c +++ b/arch/microblaze/kernel/cpu/mb.c | |||
| @@ -103,11 +103,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 103 | else | 103 | else |
| 104 | count += seq_printf(m, "Icache:\t\tno\n"); | 104 | count += seq_printf(m, "Icache:\t\tno\n"); |
| 105 | 105 | ||
| 106 | if (cpuinfo.use_dcache) | 106 | if (cpuinfo.use_dcache) { |
| 107 | count += seq_printf(m, | 107 | count += seq_printf(m, |
| 108 | "Dcache:\t\t%ukB\n", | 108 | "Dcache:\t\t%ukB\n", |
| 109 | cpuinfo.dcache_size >> 10); | 109 | cpuinfo.dcache_size >> 10); |
| 110 | else | 110 | if (cpuinfo.dcache_wb) |
| 111 | count += seq_printf(m, "\t\twrite-back\n"); | ||
| 112 | else | ||
| 113 | count += seq_printf(m, "\t\twrite-through\n"); | ||
| 114 | } else | ||
| 111 | count += seq_printf(m, "Dcache:\t\tno\n"); | 115 | count += seq_printf(m, "Dcache:\t\tno\n"); |
| 112 | 116 | ||
| 113 | count += seq_printf(m, | 117 | count += seq_printf(m, |
diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c index c9a4340ddd53..9bee9382bf74 100644 --- a/arch/microblaze/kernel/cpu/pvr.c +++ b/arch/microblaze/kernel/cpu/pvr.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | 45 | ||
| 46 | int cpu_has_pvr(void) | 46 | int cpu_has_pvr(void) |
| 47 | { | 47 | { |
| 48 | unsigned flags; | 48 | unsigned long flags; |
| 49 | unsigned pvr0; | 49 | unsigned pvr0; |
| 50 | 50 | ||
| 51 | local_save_flags(flags); | 51 | local_save_flags(flags); |
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 9083d85376a4..95b0855802df 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S | |||
| @@ -208,8 +208,6 @@ ENTRY(_user_exception) | |||
| 208 | lwi r1, r1, TS_THREAD_INFO /* get the thread info */ | 208 | lwi r1, r1, TS_THREAD_INFO /* get the thread info */ |
| 209 | /* calculate kernel stack pointer */ | 209 | /* calculate kernel stack pointer */ |
| 210 | addik r1, r1, THREAD_SIZE - PT_SIZE | 210 | addik r1, r1, THREAD_SIZE - PT_SIZE |
| 211 | swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ | ||
| 212 | lwi r11, r0, PER_CPU(KM) /* load mode indicator */ | ||
| 213 | 2: | 211 | 2: |
| 214 | swi r11, r1, PT_MODE /* store the mode */ | 212 | swi r11, r1, PT_MODE /* store the mode */ |
| 215 | lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ | 213 | lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index e3ecb36dd554..3bad4ff49471 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
| 32 | #include <asm/signal.h> | 32 | #include <asm/signal.h> |
| 33 | 33 | ||
| 34 | #undef DEBUG | ||
| 35 | |||
| 34 | /* The size of a state save frame. */ | 36 | /* The size of a state save frame. */ |
| 35 | #define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE) | 37 | #define STATE_SAVE_SIZE (PT_SIZE + STATE_SAVE_ARG_SPACE) |
| 36 | 38 | ||
| @@ -352,10 +354,12 @@ C_ENTRY(_user_exception): | |||
| 352 | add r12, r12, r12; /* convert num -> ptr */ | 354 | add r12, r12, r12; /* convert num -> ptr */ |
| 353 | add r12, r12, r12; | 355 | add r12, r12, r12; |
| 354 | 356 | ||
| 357 | #ifdef DEBUG | ||
| 355 | /* Trac syscalls and stored them to r0_ram */ | 358 | /* Trac syscalls and stored them to r0_ram */ |
| 356 | lwi r3, r12, 0x400 + r0_ram | 359 | lwi r3, r12, 0x400 + r0_ram |
| 357 | addi r3, r3, 1 | 360 | addi r3, r3, 1 |
| 358 | swi r3, r12, 0x400 + r0_ram | 361 | swi r3, r12, 0x400 + r0_ram |
| 362 | #endif | ||
| 359 | 363 | ||
| 360 | # Find and jump into the syscall handler. | 364 | # Find and jump into the syscall handler. |
| 361 | lwi r12, r12, sys_call_table | 365 | lwi r12, r12, sys_call_table |
| @@ -496,17 +500,6 @@ C_ENTRY(sys_execve): | |||
| 496 | brid microblaze_execve; /* Do real work (tail-call).*/ | 500 | brid microblaze_execve; /* Do real work (tail-call).*/ |
| 497 | nop; | 501 | nop; |
| 498 | 502 | ||
| 499 | C_ENTRY(sys_rt_sigsuspend_wrapper): | ||
| 500 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | ||
| 501 | swi r4, r1, PTO+PT_R4; | ||
| 502 | la r7, r1, PTO; /* add user context as 3rd arg */ | ||
| 503 | brlid r15, sys_rt_sigsuspend; /* Do real work.*/ | ||
| 504 | nop; | ||
| 505 | lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | ||
| 506 | lwi r4, r1, PTO+PT_R4; | ||
| 507 | bri ret_from_trap /* fall through will not work here due to align */ | ||
| 508 | nop; | ||
| 509 | |||
| 510 | C_ENTRY(sys_rt_sigreturn_wrapper): | 503 | C_ENTRY(sys_rt_sigreturn_wrapper): |
| 511 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | 504 | swi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ |
| 512 | swi r4, r1, PTO+PT_R4; | 505 | swi r4, r1, PTO+PT_R4; |
| @@ -711,15 +704,11 @@ C_ENTRY(ret_from_exc): | |||
| 711 | * (in a possibly modified form) after do_signal returns. | 704 | * (in a possibly modified form) after do_signal returns. |
| 712 | * store return registers separately because this macros is use | 705 | * store return registers separately because this macros is use |
| 713 | * for others exceptions */ | 706 | * for others exceptions */ |
| 714 | swi r3, r1, PTO + PT_R3; | ||
| 715 | swi r4, r1, PTO + PT_R4; | ||
| 716 | la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ | 707 | la r5, r1, PTO; /* Arg 1: struct pt_regs *regs */ |
| 717 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | 708 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ |
| 718 | addi r7, r0, 0; /* Arg 3: int in_syscall */ | 709 | addi r7, r0, 0; /* Arg 3: int in_syscall */ |
| 719 | bralid r15, do_signal; /* Handle any signals */ | 710 | bralid r15, do_signal; /* Handle any signals */ |
| 720 | nop; | 711 | nop; |
| 721 | lwi r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */ | ||
| 722 | lwi r4, r1, PTO+PT_R4; | ||
| 723 | 712 | ||
| 724 | /* Finally, return to user state. */ | 713 | /* Finally, return to user state. */ |
| 725 | 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ | 714 | 1: swi r0, r0, PER_CPU(KM); /* Now officially in user state. */ |
diff --git a/arch/microblaze/kernel/ftrace.c b/arch/microblaze/kernel/ftrace.c new file mode 100644 index 000000000000..388b31ca65a1 --- /dev/null +++ b/arch/microblaze/kernel/ftrace.c | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | /* | ||
| 2 | * Ftrace support for Microblaze. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> | ||
| 5 | * Copyright (C) 2009 PetaLogix | ||
| 6 | * | ||
| 7 | * Based on MIPS and PowerPC ftrace code | ||
| 8 | * | ||
| 9 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 10 | * License. See the file "COPYING" in the main directory of this archive | ||
| 11 | * for more details. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <asm/cacheflush.h> | ||
| 15 | #include <linux/ftrace.h> | ||
| 16 | |||
| 17 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 18 | /* | ||
| 19 | * Hook the return address and push it in the stack of return addrs | ||
| 20 | * in current thread info. | ||
| 21 | */ | ||
| 22 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | ||
| 23 | { | ||
| 24 | unsigned long old; | ||
| 25 | int faulted, err; | ||
| 26 | struct ftrace_graph_ent trace; | ||
| 27 | unsigned long return_hooker = (unsigned long) | ||
| 28 | &return_to_handler; | ||
| 29 | |||
| 30 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | ||
| 31 | return; | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Protect against fault, even if it shouldn't | ||
| 35 | * happen. This tool is too much intrusive to | ||
| 36 | * ignore such a protection. | ||
| 37 | */ | ||
| 38 | asm volatile(" 1: lwi %0, %2, 0; \ | ||
| 39 | 2: swi %3, %2, 0; \ | ||
| 40 | addik %1, r0, 0; \ | ||
| 41 | 3: \ | ||
| 42 | .section .fixup, \"ax\"; \ | ||
| 43 | 4: brid 3b; \ | ||
| 44 | addik %1, r0, 1; \ | ||
| 45 | .previous; \ | ||
| 46 | .section __ex_table,\"a\"; \ | ||
| 47 | .word 1b,4b; \ | ||
| 48 | .word 2b,4b; \ | ||
| 49 | .previous;" \ | ||
| 50 | : "=&r" (old), "=r" (faulted) | ||
| 51 | : "r" (parent), "r" (return_hooker) | ||
| 52 | ); | ||
| 53 | |||
| 54 | if (unlikely(faulted)) { | ||
| 55 | ftrace_graph_stop(); | ||
| 56 | WARN_ON(1); | ||
| 57 | return; | ||
| 58 | } | ||
| 59 | |||
| 60 | err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0); | ||
| 61 | if (err == -EBUSY) { | ||
| 62 | *parent = old; | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | trace.func = self_addr; | ||
| 67 | /* Only trace if the calling function expects to */ | ||
| 68 | if (!ftrace_graph_entry(&trace)) { | ||
| 69 | current->curr_ret_stack--; | ||
| 70 | *parent = old; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
| 74 | |||
| 75 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 76 | /* save value to addr - it is save to do it in asm */ | ||
| 77 | static int ftrace_modify_code(unsigned long addr, unsigned int value) | ||
| 78 | { | ||
| 79 | int faulted = 0; | ||
| 80 | |||
| 81 | __asm__ __volatile__(" 1: swi %2, %1, 0; \ | ||
| 82 | addik %0, r0, 0; \ | ||
| 83 | 2: \ | ||
| 84 | .section .fixup, \"ax\"; \ | ||
| 85 | 3: brid 2b; \ | ||
| 86 | addik %0, r0, 1; \ | ||
| 87 | .previous; \ | ||
| 88 | .section __ex_table,\"a\"; \ | ||
| 89 | .word 1b,3b; \ | ||
| 90 | .previous;" \ | ||
| 91 | : "=r" (faulted) | ||
| 92 | : "r" (addr), "r" (value) | ||
| 93 | ); | ||
| 94 | |||
| 95 | if (unlikely(faulted)) | ||
| 96 | return -EFAULT; | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | #define MICROBLAZE_NOP 0x80000000 | ||
| 102 | #define MICROBLAZE_BRI 0xb800000C | ||
| 103 | |||
| 104 | static unsigned int recorded; /* if save was or not */ | ||
| 105 | static unsigned int imm; /* saving whole imm instruction */ | ||
| 106 | |||
| 107 | /* There are two approaches howto solve ftrace_make nop function - look below */ | ||
| 108 | #undef USE_FTRACE_NOP | ||
| 109 | |||
| 110 | #ifdef USE_FTRACE_NOP | ||
| 111 | static unsigned int bralid; /* saving whole bralid instruction */ | ||
| 112 | #endif | ||
| 113 | |||
| 114 | int ftrace_make_nop(struct module *mod, | ||
| 115 | struct dyn_ftrace *rec, unsigned long addr) | ||
| 116 | { | ||
| 117 | /* we have this part of code which we are working with | ||
| 118 | * b000c000 imm -16384 | ||
| 119 | * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> | ||
| 120 | * 80000000 or r0, r0, r0 | ||
| 121 | * | ||
| 122 | * The first solution (!USE_FTRACE_NOP-could be called branch solution) | ||
| 123 | * b000c000 bri 12 (0xC - jump to any other instruction) | ||
| 124 | * b9fc8e30 bralid r15, -29136 // c0008e30 <_mcount> | ||
| 125 | * 80000000 or r0, r0, r0 | ||
| 126 | * any other instruction | ||
| 127 | * | ||
| 128 | * The second solution (USE_FTRACE_NOP) - no jump just nops | ||
| 129 | * 80000000 or r0, r0, r0 | ||
| 130 | * 80000000 or r0, r0, r0 | ||
| 131 | * 80000000 or r0, r0, r0 | ||
| 132 | */ | ||
| 133 | int ret = 0; | ||
| 134 | |||
| 135 | if (recorded == 0) { | ||
| 136 | recorded = 1; | ||
| 137 | imm = *(unsigned int *)rec->ip; | ||
| 138 | pr_debug("%s: imm:0x%x\n", __func__, imm); | ||
| 139 | #ifdef USE_FTRACE_NOP | ||
| 140 | bralid = *(unsigned int *)(rec->ip + 4); | ||
| 141 | pr_debug("%s: bralid 0x%x\n", __func__, bralid); | ||
| 142 | #endif /* USE_FTRACE_NOP */ | ||
| 143 | } | ||
| 144 | |||
| 145 | #ifdef USE_FTRACE_NOP | ||
| 146 | ret = ftrace_modify_code(rec->ip, MICROBLAZE_NOP); | ||
| 147 | ret += ftrace_modify_code(rec->ip + 4, MICROBLAZE_NOP); | ||
| 148 | #else /* USE_FTRACE_NOP */ | ||
| 149 | ret = ftrace_modify_code(rec->ip, MICROBLAZE_BRI); | ||
| 150 | #endif /* USE_FTRACE_NOP */ | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int ret_addr; /* initialized as 0 by default */ | ||
| 155 | |||
| 156 | /* I believe that first is called ftrace_make_nop before this function */ | ||
| 157 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | ||
| 158 | { | ||
| 159 | int ret; | ||
| 160 | ret_addr = addr; /* saving where the barrier jump is */ | ||
| 161 | pr_debug("%s: addr:0x%x, rec->ip: 0x%x, imm:0x%x\n", | ||
| 162 | __func__, (unsigned int)addr, (unsigned int)rec->ip, imm); | ||
| 163 | ret = ftrace_modify_code(rec->ip, imm); | ||
| 164 | #ifdef USE_FTRACE_NOP | ||
| 165 | pr_debug("%s: bralid:0x%x\n", __func__, bralid); | ||
| 166 | ret += ftrace_modify_code(rec->ip + 4, bralid); | ||
| 167 | #endif /* USE_FTRACE_NOP */ | ||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | |||
| 171 | int __init ftrace_dyn_arch_init(void *data) | ||
| 172 | { | ||
| 173 | /* The return code is retured via data */ | ||
| 174 | *(unsigned long *)data = 0; | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | int ftrace_update_ftrace_func(ftrace_func_t func) | ||
| 180 | { | ||
| 181 | unsigned long ip = (unsigned long)(&ftrace_call); | ||
| 182 | unsigned int upper = (unsigned int)func; | ||
| 183 | unsigned int lower = (unsigned int)func; | ||
| 184 | int ret = 0; | ||
| 185 | |||
| 186 | /* create proper saving to ftrace_call poll */ | ||
| 187 | upper = 0xb0000000 + (upper >> 16); /* imm func_upper */ | ||
| 188 | lower = 0x32800000 + (lower & 0xFFFF); /* addik r20, r0, func_lower */ | ||
| 189 | |||
| 190 | pr_debug("%s: func=0x%x, ip=0x%x, upper=0x%x, lower=0x%x\n", | ||
| 191 | __func__, (unsigned int)func, (unsigned int)ip, upper, lower); | ||
| 192 | |||
| 193 | /* save upper and lower code */ | ||
| 194 | ret = ftrace_modify_code(ip, upper); | ||
| 195 | ret += ftrace_modify_code(ip + 4, lower); | ||
| 196 | |||
| 197 | /* We just need to remove the rtsd r15, 8 by NOP */ | ||
| 198 | BUG_ON(!ret_addr); | ||
| 199 | if (ret_addr) | ||
| 200 | ret += ftrace_modify_code(ret_addr, MICROBLAZE_NOP); | ||
| 201 | else | ||
| 202 | ret = 1; /* fault */ | ||
| 203 | |||
| 204 | /* All changes are done - lets do caches consistent */ | ||
| 205 | flush_icache(); | ||
| 206 | return ret; | ||
| 207 | } | ||
| 208 | |||
| 209 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 210 | unsigned int old_jump; /* saving place for jump instruction */ | ||
| 211 | |||
| 212 | int ftrace_enable_ftrace_graph_caller(void) | ||
| 213 | { | ||
| 214 | unsigned int ret; | ||
| 215 | unsigned long ip = (unsigned long)(&ftrace_call_graph); | ||
| 216 | |||
| 217 | old_jump = *(unsigned int *)ip; /* save jump over instruction */ | ||
| 218 | ret = ftrace_modify_code(ip, MICROBLAZE_NOP); | ||
| 219 | flush_icache(); | ||
| 220 | |||
| 221 | pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump); | ||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | int ftrace_disable_ftrace_graph_caller(void) | ||
| 226 | { | ||
| 227 | unsigned int ret; | ||
| 228 | unsigned long ip = (unsigned long)(&ftrace_call_graph); | ||
| 229 | |||
| 230 | ret = ftrace_modify_code(ip, old_jump); | ||
| 231 | flush_icache(); | ||
| 232 | |||
| 233 | pr_debug("%s\n", __func__); | ||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
| 237 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c index 1bdf20222b92..522751737cfa 100644 --- a/arch/microblaze/kernel/heartbeat.c +++ b/arch/microblaze/kernel/heartbeat.c | |||
| @@ -45,6 +45,7 @@ void heartbeat(void) | |||
| 45 | void setup_heartbeat(void) | 45 | void setup_heartbeat(void) |
| 46 | { | 46 | { |
| 47 | struct device_node *gpio = NULL; | 47 | struct device_node *gpio = NULL; |
| 48 | int *prop; | ||
| 48 | int j; | 49 | int j; |
| 49 | char *gpio_list[] = { | 50 | char *gpio_list[] = { |
| 50 | "xlnx,xps-gpio-1.00.a", | 51 | "xlnx,xps-gpio-1.00.a", |
| @@ -58,10 +59,14 @@ void setup_heartbeat(void) | |||
| 58 | break; | 59 | break; |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | base_addr = *(int *) of_get_property(gpio, "reg", NULL); | 62 | if (gpio) { |
| 62 | base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); | 63 | base_addr = *(int *) of_get_property(gpio, "reg", NULL); |
| 63 | printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); | 64 | base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); |
| 65 | printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); | ||
| 64 | 66 | ||
| 65 | if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL)) | 67 | /* GPIO is configured as output */ |
| 66 | out_be32(base_addr + 4, 0); /* GPIO is configured as output */ | 68 | prop = (int *) of_get_property(gpio, "xlnx,is-bidir", NULL); |
| 69 | if (prop) | ||
| 70 | out_be32(base_addr + 4, 0); | ||
| 71 | } | ||
| 67 | } | 72 | } |
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c index 6eea6f92b84e..03172c1da770 100644 --- a/arch/microblaze/kernel/intc.c +++ b/arch/microblaze/kernel/intc.c | |||
| @@ -42,8 +42,16 @@ unsigned int nr_irq; | |||
| 42 | 42 | ||
| 43 | static void intc_enable_or_unmask(unsigned int irq) | 43 | static void intc_enable_or_unmask(unsigned int irq) |
| 44 | { | 44 | { |
| 45 | unsigned long mask = 1 << irq; | ||
| 45 | pr_debug("enable_or_unmask: %d\n", irq); | 46 | pr_debug("enable_or_unmask: %d\n", irq); |
| 46 | out_be32(INTC_BASE + SIE, 1 << irq); | 47 | out_be32(INTC_BASE + SIE, mask); |
| 48 | |||
| 49 | /* ack level irqs because they can't be acked during | ||
| 50 | * ack function since the handle_level_irq function | ||
| 51 | * acks the irq before calling the interrupt handler | ||
| 52 | */ | ||
| 53 | if (irq_desc[irq].status & IRQ_LEVEL) | ||
| 54 | out_be32(INTC_BASE + IAR, mask); | ||
| 47 | } | 55 | } |
| 48 | 56 | ||
| 49 | static void intc_disable_or_mask(unsigned int irq) | 57 | static void intc_disable_or_mask(unsigned int irq) |
diff --git a/arch/microblaze/kernel/mcount.S b/arch/microblaze/kernel/mcount.S new file mode 100644 index 000000000000..e7eaa7a8cbd3 --- /dev/null +++ b/arch/microblaze/kernel/mcount.S | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | /* | ||
| 2 | * Low-level ftrace handling | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> | ||
| 5 | * Copyright (C) 2009 PetaLogix | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General | ||
| 8 | * Public License. See the file COPYING in the main directory of this | ||
| 9 | * archive for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/linkage.h> | ||
| 13 | |||
| 14 | #define NOALIGN_ENTRY(name) .globl name; name: | ||
| 15 | |||
| 16 | /* FIXME MS: I think that I don't need to save all regs */ | ||
| 17 | #define SAVE_REGS \ | ||
| 18 | addik r1, r1, -120; \ | ||
| 19 | swi r2, r1, 4; \ | ||
| 20 | swi r3, r1, 8; \ | ||
| 21 | swi r4, r1, 12; \ | ||
| 22 | swi r5, r1, 116; \ | ||
| 23 | swi r6, r1, 16; \ | ||
| 24 | swi r7, r1, 20; \ | ||
| 25 | swi r8, r1, 24; \ | ||
| 26 | swi r9, r1, 28; \ | ||
| 27 | swi r10, r1, 32; \ | ||
| 28 | swi r11, r1, 36; \ | ||
| 29 | swi r12, r1, 40; \ | ||
| 30 | swi r13, r1, 44; \ | ||
| 31 | swi r14, r1, 48; \ | ||
| 32 | swi r16, r1, 52; \ | ||
| 33 | swi r17, r1, 56; \ | ||
| 34 | swi r18, r1, 60; \ | ||
| 35 | swi r19, r1, 64; \ | ||
| 36 | swi r20, r1, 68; \ | ||
| 37 | swi r21, r1, 72; \ | ||
| 38 | swi r22, r1, 76; \ | ||
| 39 | swi r23, r1, 80; \ | ||
| 40 | swi r24, r1, 84; \ | ||
| 41 | swi r25, r1, 88; \ | ||
| 42 | swi r26, r1, 92; \ | ||
| 43 | swi r27, r1, 96; \ | ||
| 44 | swi r28, r1, 100; \ | ||
| 45 | swi r29, r1, 104; \ | ||
| 46 | swi r30, r1, 108; \ | ||
| 47 | swi r31, r1, 112; | ||
| 48 | |||
| 49 | #define RESTORE_REGS \ | ||
| 50 | lwi r2, r1, 4; \ | ||
| 51 | lwi r3, r1, 8; \ | ||
| 52 | lwi r4, r1, 12; \ | ||
| 53 | lwi r5, r1, 116; \ | ||
| 54 | lwi r6, r1, 16; \ | ||
| 55 | lwi r7, r1, 20; \ | ||
| 56 | lwi r8, r1, 24; \ | ||
| 57 | lwi r9, r1, 28; \ | ||
| 58 | lwi r10, r1, 32; \ | ||
| 59 | lwi r11, r1, 36; \ | ||
| 60 | lwi r12, r1, 40; \ | ||
| 61 | lwi r13, r1, 44; \ | ||
| 62 | lwi r14, r1, 48; \ | ||
| 63 | lwi r16, r1, 52; \ | ||
| 64 | lwi r17, r1, 56; \ | ||
| 65 | lwi r18, r1, 60; \ | ||
| 66 | lwi r19, r1, 64; \ | ||
| 67 | lwi r20, r1, 68; \ | ||
| 68 | lwi r21, r1, 72; \ | ||
| 69 | lwi r22, r1, 76; \ | ||
| 70 | lwi r23, r1, 80; \ | ||
| 71 | lwi r24, r1, 84; \ | ||
| 72 | lwi r25, r1, 88; \ | ||
| 73 | lwi r26, r1, 92; \ | ||
| 74 | lwi r27, r1, 96; \ | ||
| 75 | lwi r28, r1, 100; \ | ||
| 76 | lwi r29, r1, 104; \ | ||
| 77 | lwi r30, r1, 108; \ | ||
| 78 | lwi r31, r1, 112; \ | ||
| 79 | addik r1, r1, 120; | ||
| 80 | |||
| 81 | ENTRY(ftrace_stub) | ||
| 82 | rtsd r15, 8; | ||
| 83 | nop; | ||
| 84 | |||
| 85 | ENTRY(_mcount) | ||
| 86 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
| 87 | ENTRY(ftrace_caller) | ||
| 88 | /* MS: It is just barrier which is removed from C code */ | ||
| 89 | rtsd r15, 8 | ||
| 90 | nop | ||
| 91 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
| 92 | SAVE_REGS | ||
| 93 | swi r15, r1, 0; | ||
| 94 | /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST begin of checking */ | ||
| 95 | lwi r5, r0, function_trace_stop; | ||
| 96 | bneid r5, end; | ||
| 97 | nop; | ||
| 98 | /* MS: HAVE_FUNCTION_TRACE_MCOUNT_TEST end of checking */ | ||
| 99 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 100 | #ifndef CONFIG_DYNAMIC_FTRACE | ||
| 101 | lwi r5, r0, ftrace_graph_return; | ||
| 102 | addik r6, r0, ftrace_stub; /* asm implementation */ | ||
| 103 | cmpu r5, r5, r6; /* ftrace_graph_return != ftrace_stub */ | ||
| 104 | beqid r5, end_graph_tracer; | ||
| 105 | nop; | ||
| 106 | |||
| 107 | lwi r6, r0, ftrace_graph_entry; | ||
| 108 | addik r5, r0, ftrace_graph_entry_stub; /* implemented in C */ | ||
| 109 | cmpu r5, r5, r6; /* ftrace_graph_entry != ftrace_graph_entry_stub */ | ||
| 110 | beqid r5, end_graph_tracer; | ||
| 111 | nop; | ||
| 112 | #else /* CONFIG_DYNAMIC_FTRACE */ | ||
| 113 | NOALIGN_ENTRY(ftrace_call_graph) | ||
| 114 | /* MS: jump over graph function - replaced from C code */ | ||
| 115 | bri end_graph_tracer | ||
| 116 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
| 117 | addik r5, r1, 120; /* MS: load parent addr */ | ||
| 118 | addik r6, r15, 0; /* MS: load current function addr */ | ||
| 119 | bralid r15, prepare_ftrace_return; | ||
| 120 | nop; | ||
| 121 | /* MS: graph was taken that's why - can jump over function trace */ | ||
| 122 | brid end; | ||
| 123 | nop; | ||
| 124 | end_graph_tracer: | ||
| 125 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
| 126 | #ifndef CONFIG_DYNAMIC_FTRACE | ||
| 127 | /* MS: test function trace if is taken or not */ | ||
| 128 | lwi r20, r0, ftrace_trace_function; | ||
| 129 | addik r6, r0, ftrace_stub; | ||
| 130 | cmpu r5, r20, r6; /* ftrace_trace_function != ftrace_stub */ | ||
| 131 | beqid r5, end; /* MS: not taken -> jump over */ | ||
| 132 | nop; | ||
| 133 | #else /* CONFIG_DYNAMIC_FTRACE */ | ||
| 134 | NOALIGN_ENTRY(ftrace_call) | ||
| 135 | /* instruction for setup imm FUNC_part1, addik r20, r0, FUNC_part2 */ | ||
| 136 | nop | ||
| 137 | nop | ||
| 138 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
| 139 | /* static normal trace */ | ||
| 140 | lwi r6, r1, 120; /* MS: load parent addr */ | ||
| 141 | addik r5, r15, 0; /* MS: load current function addr */ | ||
| 142 | /* MS: here is dependency on previous code */ | ||
| 143 | brald r15, r20; /* MS: jump to ftrace handler */ | ||
| 144 | nop; | ||
| 145 | end: | ||
| 146 | lwi r15, r1, 0; | ||
| 147 | RESTORE_REGS | ||
| 148 | |||
| 149 | rtsd r15, 8; /* MS: jump back */ | ||
| 150 | nop; | ||
| 151 | |||
| 152 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 153 | ENTRY(return_to_handler) | ||
| 154 | nop; /* MS: just barrier for rtsd r15, 8 */ | ||
| 155 | nop; | ||
| 156 | SAVE_REGS | ||
| 157 | swi r15, r1, 0; | ||
| 158 | |||
| 159 | /* MS: find out returning address */ | ||
| 160 | bralid r15, ftrace_return_to_handler; | ||
| 161 | nop; | ||
| 162 | |||
| 163 | /* MS: return value from ftrace_return_to_handler is my returning addr | ||
| 164 | * must be before restore regs because I have to restore r3 content */ | ||
| 165 | addik r15, r3, 0; | ||
| 166 | RESTORE_REGS | ||
| 167 | |||
| 168 | rtsd r15, 8; /* MS: jump back */ | ||
| 169 | nop; | ||
| 170 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index 59ff20e33e0c..bc4dcb7d3861 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <asm/page.h> | 19 | #include <asm/page.h> |
| 20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
| 21 | #include <linux/ftrace.h> | ||
| 21 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
| 22 | 23 | ||
| 23 | /* | 24 | /* |
| @@ -47,3 +48,7 @@ extern void __umodsi3(void); | |||
| 47 | EXPORT_SYMBOL(__umodsi3); | 48 | EXPORT_SYMBOL(__umodsi3); |
| 48 | extern char *_ebss; | 49 | extern char *_ebss; |
| 49 | EXPORT_SYMBOL_GPL(_ebss); | 50 | EXPORT_SYMBOL_GPL(_ebss); |
| 51 | #ifdef CONFIG_FUNCTION_TRACER | ||
| 52 | extern void _mcount(void); | ||
| 53 | EXPORT_SYMBOL(_mcount); | ||
| 54 | #endif | ||
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c index c592d475b3d8..812f1bf06c9e 100644 --- a/arch/microblaze/kernel/process.c +++ b/arch/microblaze/kernel/process.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/bitops.h> | 15 | #include <linux/bitops.h> |
| 16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
| 17 | #include <asm/pgalloc.h> | 17 | #include <asm/pgalloc.h> |
| 18 | #include <asm/cacheflush.h> | ||
| 18 | 19 | ||
| 19 | void show_regs(struct pt_regs *regs) | 20 | void show_regs(struct pt_regs *regs) |
| 20 | { | 21 | { |
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c new file mode 100644 index 000000000000..a1721a33042e --- /dev/null +++ b/arch/microblaze/kernel/reset.c | |||
| @@ -0,0 +1,140 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> | ||
| 3 | * Copyright (C) 2009 PetaLogix | ||
| 4 | * | ||
| 5 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 6 | * License. See the file "COPYING" in the main directory of this archive | ||
| 7 | * for more details. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/of_platform.h> | ||
| 12 | #include <asm/prom.h> | ||
| 13 | |||
| 14 | /* Trigger specific functions */ | ||
| 15 | #ifdef CONFIG_GPIOLIB | ||
| 16 | |||
| 17 | #include <linux/of_gpio.h> | ||
| 18 | |||
| 19 | static int handle; /* reset pin handle */ | ||
| 20 | static unsigned int reset_val; | ||
| 21 | |||
| 22 | static int of_reset_gpio_handle(void) | ||
| 23 | { | ||
| 24 | int ret; /* variable which stored handle reset gpio pin */ | ||
| 25 | struct device_node *root; /* root node */ | ||
| 26 | struct device_node *gpio; /* gpio node */ | ||
| 27 | struct of_gpio_chip *of_gc = NULL; | ||
| 28 | enum of_gpio_flags flags ; | ||
| 29 | const void *gpio_spec; | ||
| 30 | |||
| 31 | /* find out root node */ | ||
| 32 | root = of_find_node_by_path("/"); | ||
| 33 | |||
| 34 | /* give me handle for gpio node to be possible allocate pin */ | ||
| 35 | ret = of_parse_phandles_with_args(root, "hard-reset-gpios", | ||
| 36 | "#gpio-cells", 0, &gpio, &gpio_spec); | ||
| 37 | if (ret) { | ||
| 38 | pr_debug("%s: can't parse gpios property\n", __func__); | ||
| 39 | goto err0; | ||
| 40 | } | ||
| 41 | |||
| 42 | of_gc = gpio->data; | ||
| 43 | if (!of_gc) { | ||
| 44 | pr_debug("%s: gpio controller %s isn't registered\n", | ||
| 45 | root->full_name, gpio->full_name); | ||
| 46 | ret = -ENODEV; | ||
| 47 | goto err1; | ||
| 48 | } | ||
| 49 | |||
| 50 | ret = of_gc->xlate(of_gc, root, gpio_spec, &flags); | ||
| 51 | if (ret < 0) | ||
| 52 | goto err1; | ||
| 53 | |||
| 54 | ret += of_gc->gc.base; | ||
| 55 | err1: | ||
| 56 | of_node_put(gpio); | ||
| 57 | err0: | ||
| 58 | pr_debug("%s exited with status %d\n", __func__, ret); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | |||
| 62 | void of_platform_reset_gpio_probe(void) | ||
| 63 | { | ||
| 64 | int ret; | ||
| 65 | handle = of_reset_gpio_handle(); | ||
| 66 | |||
| 67 | if (!gpio_is_valid(handle)) { | ||
| 68 | printk(KERN_INFO "Skipping unavailable RESET gpio %d (%s)\n", | ||
| 69 | handle, "reset"); | ||
| 70 | } | ||
| 71 | |||
| 72 | ret = gpio_request(handle, "reset"); | ||
| 73 | if (ret < 0) { | ||
| 74 | printk(KERN_INFO "GPIO pin is already allocated\n"); | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | |||
| 78 | /* get current setup value */ | ||
| 79 | reset_val = gpio_get_value(handle); | ||
| 80 | /* FIXME maybe worth to perform any action */ | ||
| 81 | pr_debug("Reset: Gpio output state: 0x%x\n", reset_val); | ||
| 82 | |||
| 83 | /* Setup GPIO as output */ | ||
| 84 | ret = gpio_direction_output(handle, 0); | ||
| 85 | if (ret < 0) | ||
| 86 | goto err; | ||
| 87 | |||
| 88 | /* Setup output direction */ | ||
| 89 | gpio_set_value(handle, 0); | ||
| 90 | |||
| 91 | printk(KERN_INFO "RESET: Registered gpio device: %d, current val: %d\n", | ||
| 92 | handle, reset_val); | ||
| 93 | return; | ||
| 94 | err: | ||
| 95 | gpio_free(handle); | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | |||
| 99 | |||
| 100 | static void gpio_system_reset(void) | ||
| 101 | { | ||
| 102 | gpio_set_value(handle, 1 - reset_val); | ||
| 103 | } | ||
| 104 | #else | ||
| 105 | #define gpio_system_reset() do {} while (0) | ||
| 106 | void of_platform_reset_gpio_probe(void) | ||
| 107 | { | ||
| 108 | return; | ||
| 109 | } | ||
| 110 | #endif | ||
| 111 | |||
| 112 | void machine_restart(char *cmd) | ||
| 113 | { | ||
| 114 | printk(KERN_NOTICE "Machine restart...\n"); | ||
| 115 | gpio_system_reset(); | ||
| 116 | dump_stack(); | ||
| 117 | while (1) | ||
| 118 | ; | ||
| 119 | } | ||
| 120 | |||
| 121 | void machine_shutdown(void) | ||
| 122 | { | ||
| 123 | printk(KERN_NOTICE "Machine shutdown...\n"); | ||
| 124 | while (1) | ||
| 125 | ; | ||
| 126 | } | ||
| 127 | |||
| 128 | void machine_halt(void) | ||
| 129 | { | ||
| 130 | printk(KERN_NOTICE "Machine halt...\n"); | ||
| 131 | while (1) | ||
| 132 | ; | ||
| 133 | } | ||
| 134 | |||
| 135 | void machine_power_off(void) | ||
| 136 | { | ||
| 137 | printk(KERN_NOTICE "Machine power off...\n"); | ||
| 138 | while (1) | ||
| 139 | ; | ||
| 140 | } | ||
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c index 8c1e0f4dcf18..5372b24ad049 100644 --- a/arch/microblaze/kernel/setup.c +++ b/arch/microblaze/kernel/setup.c | |||
| @@ -52,13 +52,12 @@ void __init setup_arch(char **cmdline_p) | |||
| 52 | /* irq_early_init(); */ | 52 | /* irq_early_init(); */ |
| 53 | setup_cpuinfo(); | 53 | setup_cpuinfo(); |
| 54 | 54 | ||
| 55 | __invalidate_icache_all(); | 55 | microblaze_cache_init(); |
| 56 | __enable_icache(); | ||
| 57 | 56 | ||
| 58 | __invalidate_dcache_all(); | 57 | enable_dcache(); |
| 59 | __enable_dcache(); | ||
| 60 | 58 | ||
| 61 | panic_timeout = 120; | 59 | invalidate_icache(); |
| 60 | enable_icache(); | ||
| 62 | 61 | ||
| 63 | setup_memory(); | 62 | setup_memory(); |
| 64 | 63 | ||
| @@ -131,6 +130,8 @@ void __init machine_early_init(const char *cmdline, unsigned int ram, | |||
| 131 | strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); | 130 | strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); |
| 132 | #endif | 131 | #endif |
| 133 | 132 | ||
| 133 | lockdep_init(); | ||
| 134 | |||
| 134 | /* initialize device tree for usage in early_printk */ | 135 | /* initialize device tree for usage in early_printk */ |
| 135 | early_init_devtree((void *)_fdt_start); | 136 | early_init_devtree((void *)_fdt_start); |
| 136 | 137 | ||
| @@ -186,32 +187,3 @@ static int microblaze_debugfs_init(void) | |||
| 186 | } | 187 | } |
| 187 | arch_initcall(microblaze_debugfs_init); | 188 | arch_initcall(microblaze_debugfs_init); |
| 188 | #endif | 189 | #endif |
| 189 | |||
| 190 | void machine_restart(char *cmd) | ||
| 191 | { | ||
| 192 | printk(KERN_NOTICE "Machine restart...\n"); | ||
| 193 | dump_stack(); | ||
| 194 | while (1) | ||
| 195 | ; | ||
| 196 | } | ||
| 197 | |||
| 198 | void machine_shutdown(void) | ||
| 199 | { | ||
| 200 | printk(KERN_NOTICE "Machine shutdown...\n"); | ||
| 201 | while (1) | ||
| 202 | ; | ||
| 203 | } | ||
| 204 | |||
| 205 | void machine_halt(void) | ||
| 206 | { | ||
| 207 | printk(KERN_NOTICE "Machine halt...\n"); | ||
| 208 | while (1) | ||
| 209 | ; | ||
| 210 | } | ||
| 211 | |||
| 212 | void machine_power_off(void) | ||
| 213 | { | ||
| 214 | printk(KERN_NOTICE "Machine power off...\n"); | ||
| 215 | while (1) | ||
| 216 | ; | ||
| 217 | } | ||
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 1c80e4fc40ce..d8d3bb396cd6 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c | |||
| @@ -44,7 +44,6 @@ | |||
| 44 | 44 | ||
| 45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); | 45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); |
| 46 | 46 | ||
| 47 | |||
| 48 | asmlinkage long | 47 | asmlinkage long |
| 49 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 48 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
| 50 | struct pt_regs *regs) | 49 | struct pt_regs *regs) |
| @@ -176,6 +175,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 176 | struct rt_sigframe __user *frame; | 175 | struct rt_sigframe __user *frame; |
| 177 | int err = 0; | 176 | int err = 0; |
| 178 | int signal; | 177 | int signal; |
| 178 | unsigned long address = 0; | ||
| 179 | #ifdef CONFIG_MMU | ||
| 180 | pmd_t *pmdp; | ||
| 181 | pte_t *ptep; | ||
| 182 | #endif | ||
| 179 | 183 | ||
| 180 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 184 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
| 181 | 185 | ||
| @@ -216,8 +220,29 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 216 | Negative 8 offset because return is rtsd r15, 8 */ | 220 | Negative 8 offset because return is rtsd r15, 8 */ |
| 217 | regs->r15 = ((unsigned long)frame->tramp)-8; | 221 | regs->r15 = ((unsigned long)frame->tramp)-8; |
| 218 | 222 | ||
| 219 | __invalidate_cache_sigtramp((unsigned long)frame->tramp); | 223 | address = ((unsigned long)frame->tramp); |
| 220 | 224 | #ifdef CONFIG_MMU | |
| 225 | pmdp = pmd_offset(pud_offset( | ||
| 226 | pgd_offset(current->mm, address), | ||
| 227 | address), address); | ||
| 228 | |||
| 229 | preempt_disable(); | ||
| 230 | ptep = pte_offset_map(pmdp, address); | ||
| 231 | if (pte_present(*ptep)) { | ||
| 232 | address = (unsigned long) page_address(pte_page(*ptep)); | ||
| 233 | /* MS: I need add offset in page */ | ||
| 234 | address += ((unsigned long)frame->tramp) & ~PAGE_MASK; | ||
| 235 | /* MS address is virtual */ | ||
| 236 | address = virt_to_phys(address); | ||
| 237 | invalidate_icache_range(address, address + 8); | ||
| 238 | flush_dcache_range(address, address + 8); | ||
| 239 | } | ||
| 240 | pte_unmap(ptep); | ||
| 241 | preempt_enable(); | ||
| 242 | #else | ||
| 243 | flush_icache_range(address, address + 8); | ||
| 244 | flush_dcache_range(address, address + 8); | ||
| 245 | #endif | ||
| 221 | if (err) | 246 | if (err) |
| 222 | goto give_sigsegv; | 247 | goto give_sigsegv; |
| 223 | 248 | ||
| @@ -233,6 +258,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
| 233 | 258 | ||
| 234 | set_fs(USER_DS); | 259 | set_fs(USER_DS); |
| 235 | 260 | ||
| 261 | /* the tracer may want to single-step inside the handler */ | ||
| 262 | if (test_thread_flag(TIF_SINGLESTEP)) | ||
| 263 | ptrace_notify(SIGTRAP); | ||
| 264 | |||
| 236 | #ifdef DEBUG_SIG | 265 | #ifdef DEBUG_SIG |
| 237 | printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", | 266 | printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", |
| 238 | current->comm, current->pid, frame, regs->pc); | 267 | current->comm, current->pid, frame, regs->pc); |
diff --git a/arch/microblaze/kernel/stacktrace.c b/arch/microblaze/kernel/stacktrace.c new file mode 100644 index 000000000000..123692f22647 --- /dev/null +++ b/arch/microblaze/kernel/stacktrace.c | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* | ||
| 2 | * Stack trace support for Microblaze. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> | ||
| 5 | * Copyright (C) 2009 PetaLogix | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License. See the file "COPYING" in the main directory of this archive | ||
| 9 | * for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sched.h> | ||
| 13 | #include <linux/stacktrace.h> | ||
| 14 | #include <linux/thread_info.h> | ||
| 15 | #include <linux/ptrace.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | /* FIXME initial support */ | ||
| 19 | void save_stack_trace(struct stack_trace *trace) | ||
| 20 | { | ||
| 21 | unsigned long *sp; | ||
| 22 | unsigned long addr; | ||
| 23 | asm("addik %0, r1, 0" : "=r" (sp)); | ||
| 24 | |||
| 25 | while (!kstack_end(sp)) { | ||
| 26 | addr = *sp++; | ||
| 27 | if (__kernel_text_address(addr)) { | ||
| 28 | if (trace->skip > 0) | ||
| 29 | trace->skip--; | ||
| 30 | else | ||
| 31 | trace->entries[trace->nr_entries++] = addr; | ||
| 32 | |||
| 33 | if (trace->nr_entries >= trace->max_entries) | ||
| 34 | break; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | EXPORT_SYMBOL_GPL(save_stack_trace); | ||
| 39 | |||
| 40 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
| 41 | { | ||
| 42 | unsigned int *sp; | ||
| 43 | unsigned long addr; | ||
| 44 | |||
| 45 | struct thread_info *ti = task_thread_info(tsk); | ||
| 46 | |||
| 47 | if (tsk == current) | ||
| 48 | asm("addik %0, r1, 0" : "=r" (sp)); | ||
| 49 | else | ||
| 50 | sp = (unsigned int *)ti->cpu_context.r1; | ||
| 51 | |||
| 52 | while (!kstack_end(sp)) { | ||
| 53 | addr = *sp++; | ||
| 54 | if (__kernel_text_address(addr)) { | ||
| 55 | if (trace->skip > 0) | ||
| 56 | trace->skip--; | ||
| 57 | else | ||
| 58 | trace->entries[trace->nr_entries++] = addr; | ||
| 59 | |||
| 60 | if (trace->nr_entries >= trace->max_entries) | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); | ||
diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S index b96f365ea6b1..4088be7d4e29 100644 --- a/arch/microblaze/kernel/syscall_table.S +++ b/arch/microblaze/kernel/syscall_table.S | |||
| @@ -183,7 +183,7 @@ ENTRY(sys_call_table) | |||
| 183 | .long sys_rt_sigpending | 183 | .long sys_rt_sigpending |
| 184 | .long sys_rt_sigtimedwait | 184 | .long sys_rt_sigtimedwait |
| 185 | .long sys_rt_sigqueueinfo | 185 | .long sys_rt_sigqueueinfo |
| 186 | .long sys_rt_sigsuspend_wrapper | 186 | .long sys_rt_sigsuspend |
| 187 | .long sys_pread64 /* 180 */ | 187 | .long sys_pread64 /* 180 */ |
| 188 | .long sys_pwrite64 | 188 | .long sys_pwrite64 |
| 189 | .long sys_chown | 189 | .long sys_chown |
| @@ -303,7 +303,7 @@ ENTRY(sys_call_table) | |||
| 303 | .long sys_mkdirat | 303 | .long sys_mkdirat |
| 304 | .long sys_mknodat | 304 | .long sys_mknodat |
| 305 | .long sys_fchownat | 305 | .long sys_fchownat |
| 306 | .long sys_ni_syscall | 306 | .long sys_futimesat |
| 307 | .long sys_fstatat64 /* 300 */ | 307 | .long sys_fstatat64 /* 300 */ |
| 308 | .long sys_unlinkat | 308 | .long sys_unlinkat |
| 309 | .long sys_renameat | 309 | .long sys_renameat |
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index 5499deae7fa6..ed61b2f17719 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
| @@ -183,6 +183,31 @@ static cycle_t microblaze_read(struct clocksource *cs) | |||
| 183 | return (cycle_t) (in_be32(TIMER_BASE + TCR1)); | 183 | return (cycle_t) (in_be32(TIMER_BASE + TCR1)); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static struct timecounter microblaze_tc = { | ||
| 187 | .cc = NULL, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static cycle_t microblaze_cc_read(const struct cyclecounter *cc) | ||
| 191 | { | ||
| 192 | return microblaze_read(NULL); | ||
| 193 | } | ||
| 194 | |||
| 195 | static struct cyclecounter microblaze_cc = { | ||
| 196 | .read = microblaze_cc_read, | ||
| 197 | .mask = CLOCKSOURCE_MASK(32), | ||
| 198 | .shift = 24, | ||
| 199 | }; | ||
| 200 | |||
| 201 | int __init init_microblaze_timecounter(void) | ||
| 202 | { | ||
| 203 | microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, | ||
| 204 | microblaze_cc.shift); | ||
| 205 | |||
| 206 | timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); | ||
| 207 | |||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 186 | static struct clocksource clocksource_microblaze = { | 211 | static struct clocksource clocksource_microblaze = { |
| 187 | .name = "microblaze_clocksource", | 212 | .name = "microblaze_clocksource", |
| 188 | .rating = 300, | 213 | .rating = 300, |
| @@ -204,6 +229,9 @@ static int __init microblaze_clocksource_init(void) | |||
| 204 | out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); | 229 | out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); |
| 205 | /* start timer1 - up counting without interrupt */ | 230 | /* start timer1 - up counting without interrupt */ |
| 206 | out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); | 231 | out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); |
| 232 | |||
| 233 | /* register timecounter - for ftrace support */ | ||
| 234 | init_microblaze_timecounter(); | ||
| 207 | return 0; | 235 | return 0; |
| 208 | } | 236 | } |
| 209 | 237 | ||
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index e704188d7855..5ef619aad634 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S | |||
| @@ -26,11 +26,12 @@ SECTIONS { | |||
| 26 | _stext = . ; | 26 | _stext = . ; |
| 27 | *(.text .text.*) | 27 | *(.text .text.*) |
| 28 | *(.fixup) | 28 | *(.fixup) |
| 29 | EXIT_TEXT | 29 | EXIT_TEXT |
| 30 | EXIT_CALL | 30 | EXIT_CALL |
| 31 | SCHED_TEXT | 31 | SCHED_TEXT |
| 32 | LOCK_TEXT | 32 | LOCK_TEXT |
| 33 | KPROBES_TEXT | 33 | KPROBES_TEXT |
| 34 | IRQENTRY_TEXT | ||
| 34 | . = ALIGN (4) ; | 35 | . = ALIGN (4) ; |
| 35 | _etext = . ; | 36 | _etext = . ; |
| 36 | } | 37 | } |
| @@ -86,6 +87,7 @@ SECTIONS { | |||
| 86 | _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; | 87 | _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 90 | . = ALIGN(PAGE_SIZE); | ||
| 89 | __init_begin = .; | 91 | __init_begin = .; |
| 90 | 92 | ||
| 91 | INIT_TEXT_SECTION(PAGE_SIZE) | 93 | INIT_TEXT_SECTION(PAGE_SIZE) |
diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c index 8eb9df5a26c9..a853fe089c44 100644 --- a/arch/microblaze/lib/uaccess.c +++ b/arch/microblaze/lib/uaccess.c | |||
| @@ -39,3 +39,10 @@ long strncpy_from_user(char *dst, const char __user *src, long count) | |||
| 39 | __do_strncpy_from_user(dst, src, count, res); | 39 | __do_strncpy_from_user(dst, src, count, res); |
| 40 | return res; | 40 | return res; |
| 41 | } | 41 | } |
| 42 | |||
| 43 | unsigned long __copy_tofrom_user(void __user *to, | ||
| 44 | const void __user *from, unsigned long size) | ||
| 45 | { | ||
| 46 | memcpy(to, from, size); | ||
| 47 | return 0; | ||
| 48 | } | ||
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index a44892e7cd5b..a57cedf36715 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c | |||
| @@ -41,6 +41,7 @@ char *klimit = _end; | |||
| 41 | * have available. | 41 | * have available. |
| 42 | */ | 42 | */ |
| 43 | unsigned long memory_start; | 43 | unsigned long memory_start; |
| 44 | EXPORT_SYMBOL(memory_start); | ||
| 44 | unsigned long memory_end; /* due to mm/nommu.c */ | 45 | unsigned long memory_end; /* due to mm/nommu.c */ |
| 45 | unsigned long memory_size; | 46 | unsigned long memory_size; |
| 46 | 47 | ||
diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c index 46c4ca5d15c5..2820081b21ab 100644 --- a/arch/microblaze/mm/pgtable.c +++ b/arch/microblaze/mm/pgtable.c | |||
| @@ -144,7 +144,6 @@ int map_page(unsigned long va, phys_addr_t pa, int flags) | |||
| 144 | pmd_t *pd; | 144 | pmd_t *pd; |
| 145 | pte_t *pg; | 145 | pte_t *pg; |
| 146 | int err = -ENOMEM; | 146 | int err = -ENOMEM; |
| 147 | /* spin_lock(&init_mm.page_table_lock); */ | ||
| 148 | /* Use upper 10 bits of VA to index the first level map */ | 147 | /* Use upper 10 bits of VA to index the first level map */ |
| 149 | pd = pmd_offset(pgd_offset_k(va), va); | 148 | pd = pmd_offset(pgd_offset_k(va), va); |
| 150 | /* Use middle 10 bits of VA to index the second-level map */ | 149 | /* 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) | |||
| 158 | if (mem_init_done) | 157 | if (mem_init_done) |
| 159 | flush_HPTE(0, va, pmd_val(*pd)); | 158 | flush_HPTE(0, va, pmd_val(*pd)); |
| 160 | /* flush_HPTE(0, va, pg); */ | 159 | /* flush_HPTE(0, va, pg); */ |
| 161 | |||
| 162 | } | 160 | } |
| 163 | /* spin_unlock(&init_mm.page_table_lock); */ | ||
| 164 | return err; | 161 | return err; |
| 165 | } | 162 | } |
| 166 | 163 | ||
| @@ -182,12 +179,6 @@ void __init adjust_total_lowmem(void) | |||
| 182 | #endif | 179 | #endif |
| 183 | } | 180 | } |
| 184 | 181 | ||
| 185 | static void show_tmem(unsigned long tmem) | ||
| 186 | { | ||
| 187 | volatile unsigned long a; | ||
| 188 | a = a + tmem; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | 182 | /* |
| 192 | * Map in all of physical memory starting at CONFIG_KERNEL_START. | 183 | * Map in all of physical memory starting at CONFIG_KERNEL_START. |
| 193 | */ | 184 | */ |
| @@ -197,7 +188,6 @@ void __init mapin_ram(void) | |||
| 197 | 188 | ||
| 198 | v = CONFIG_KERNEL_START; | 189 | v = CONFIG_KERNEL_START; |
| 199 | p = memory_start; | 190 | p = memory_start; |
| 200 | show_tmem(memory_size); | ||
| 201 | for (s = 0; s < memory_size; s += PAGE_SIZE) { | 191 | for (s = 0; s < memory_size; s += PAGE_SIZE) { |
| 202 | f = _PAGE_PRESENT | _PAGE_ACCESSED | | 192 | f = _PAGE_PRESENT | _PAGE_ACCESSED | |
| 203 | _PAGE_SHARED | _PAGE_HWEXEC; | 193 | _PAGE_SHARED | _PAGE_HWEXEC; |
diff --git a/arch/microblaze/oprofile/Makefile b/arch/microblaze/oprofile/Makefile new file mode 100644 index 000000000000..0d0348c8af97 --- /dev/null +++ b/arch/microblaze/oprofile/Makefile | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | # | ||
| 2 | # arch/microblaze/oprofile/Makefile | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_OPROFILE) += oprofile.o | ||
| 6 | |||
| 7 | DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ | ||
| 8 | oprof.o cpu_buffer.o buffer_sync.o \ | ||
| 9 | event_buffer.o oprofile_files.o \ | ||
| 10 | oprofilefs.o oprofile_stats.o \ | ||
| 11 | timer_int.o ) | ||
| 12 | |||
| 13 | oprofile-y := $(DRIVER_OBJS) microblaze_oprofile.o | ||
diff --git a/arch/microblaze/oprofile/microblaze_oprofile.c b/arch/microblaze/oprofile/microblaze_oprofile.c new file mode 100644 index 000000000000..def17e59888e --- /dev/null +++ b/arch/microblaze/oprofile/microblaze_oprofile.c | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Microblaze oprofile code | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> | ||
| 5 | * Copyright (C) 2009 PetaLogix | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 8 | * License. See the file "COPYING" in the main directory of this archive | ||
| 9 | * for more details. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/oprofile.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | |||
| 15 | int __init oprofile_arch_init(struct oprofile_operations *ops) | ||
| 16 | { | ||
| 17 | return -1; | ||
| 18 | } | ||
| 19 | |||
| 20 | void oprofile_arch_exit(void) | ||
| 21 | { | ||
| 22 | } | ||
diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform index 8e9b4752d3ff..669c7eec293e 100644 --- a/arch/microblaze/platform/Kconfig.platform +++ b/arch/microblaze/platform/Kconfig.platform | |||
| @@ -53,31 +53,12 @@ config OPT_LIB_FUNCTION | |||
| 53 | 53 | ||
| 54 | config OPT_LIB_ASM | 54 | config OPT_LIB_ASM |
| 55 | bool "Optimalized lib function ASM" | 55 | bool "Optimalized lib function ASM" |
| 56 | depends on OPT_LIB_FUNCTION | 56 | depends on OPT_LIB_FUNCTION && (XILINX_MICROBLAZE0_USE_BARREL = 1) |
| 57 | default n | 57 | default n |
| 58 | help | 58 | help |
| 59 | Allows turn on optimalized library function (memcpy and memmove). | 59 | Allows turn on optimalized library function (memcpy and memmove). |
| 60 | Function are written in asm code. | 60 | Function are written in asm code. |
| 61 | 61 | ||
| 62 | # This is still a bit broken - disabling for now JW 20070504 | ||
| 63 | config ALLOW_EDIT_AUTO | ||
| 64 | bool "Permit Display/edit of Kconfig.auto platform settings" | ||
| 65 | default n | ||
| 66 | help | ||
| 67 | Allows the editing of auto-generated platform settings from | ||
| 68 | the Kconfig.auto file. Obviously this does not change the | ||
| 69 | underlying hardware, so be very careful if you go editing | ||
| 70 | these settings. | ||
| 71 | |||
| 72 | Also, if you enable this, and edit various Kconfig.auto | ||
| 73 | settings, YOUR CHANGES WILL BE LOST if you then disable it | ||
| 74 | again. You have been warned! | ||
| 75 | |||
| 76 | If unsure, say no. | ||
| 77 | |||
| 78 | comment "Automatic platform settings from Kconfig.auto" | ||
| 79 | depends on ALLOW_EDIT_AUTO | ||
| 80 | |||
| 81 | if PLATFORM_GENERIC=y | 62 | if PLATFORM_GENERIC=y |
| 82 | source "arch/microblaze/platform/generic/Kconfig.auto" | 63 | source "arch/microblaze/platform/generic/Kconfig.auto" |
| 83 | endif | 64 | endif |
diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto index fbca22d9c8b9..5d86fc19029d 100644 --- a/arch/microblaze/platform/generic/Kconfig.auto +++ b/arch/microblaze/platform/generic/Kconfig.auto | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | # Definitions for MICROBLAZE0 | 22 | # Definitions for MICROBLAZE0 |
| 23 | comment "Definitions for MICROBLAZE0" | 23 | comment "Definitions for MICROBLAZE0" |
| 24 | depends on ALLOW_EDIT_AUTO | ||
| 25 | 24 | ||
| 26 | config KERNEL_BASE_ADDR | 25 | config KERNEL_BASE_ADDR |
| 27 | hex "Physical address where Linux Kernel is" | 26 | hex "Physical address where Linux Kernel is" |
| @@ -30,33 +29,33 @@ config KERNEL_BASE_ADDR | |||
| 30 | BASE Address for kernel | 29 | BASE Address for kernel |
| 31 | 30 | ||
| 32 | config XILINX_MICROBLAZE0_FAMILY | 31 | config XILINX_MICROBLAZE0_FAMILY |
| 33 | string "Targetted FPGA family" if ALLOW_EDIT_AUTO | 32 | string "Targetted FPGA family" |
| 34 | default "virtex5" | 33 | default "virtex5" |
| 35 | 34 | ||
| 36 | config XILINX_MICROBLAZE0_USE_MSR_INSTR | 35 | config XILINX_MICROBLAZE0_USE_MSR_INSTR |
| 37 | int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO | 36 | int "USE_MSR_INSTR range (0:1)" |
| 38 | default 1 | 37 | default 0 |
| 39 | 38 | ||
| 40 | config XILINX_MICROBLAZE0_USE_PCMP_INSTR | 39 | config XILINX_MICROBLAZE0_USE_PCMP_INSTR |
| 41 | int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO | 40 | int "USE_PCMP_INSTR range (0:1)" |
| 42 | default 1 | 41 | default 0 |
| 43 | 42 | ||
| 44 | config XILINX_MICROBLAZE0_USE_BARREL | 43 | config XILINX_MICROBLAZE0_USE_BARREL |
| 45 | int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO | 44 | int "USE_BARREL range (0:1)" |
| 46 | default 1 | 45 | default 0 |
| 47 | 46 | ||
| 48 | config XILINX_MICROBLAZE0_USE_DIV | 47 | config XILINX_MICROBLAZE0_USE_DIV |
| 49 | int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO | 48 | int "USE_DIV range (0:1)" |
| 50 | default 1 | 49 | default 0 |
| 51 | 50 | ||
| 52 | config XILINX_MICROBLAZE0_USE_HW_MUL | 51 | config XILINX_MICROBLAZE0_USE_HW_MUL |
| 53 | int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO | 52 | int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" |
| 54 | default 2 | 53 | default 0 |
| 55 | 54 | ||
| 56 | config XILINX_MICROBLAZE0_USE_FPU | 55 | config XILINX_MICROBLAZE0_USE_FPU |
| 57 | int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO | 56 | int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" |
| 58 | default 2 | 57 | default 0 |
| 59 | 58 | ||
| 60 | config XILINX_MICROBLAZE0_HW_VER | 59 | config XILINX_MICROBLAZE0_HW_VER |
| 61 | string "Core version number" if ALLOW_EDIT_AUTO | 60 | string "Core version number" |
| 62 | default 7.10.d | 61 | default 7.10.d |
diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts index 29993f62b30a..2d5c41767cd0 100644 --- a/arch/microblaze/platform/generic/system.dts +++ b/arch/microblaze/platform/generic/system.dts | |||
| @@ -32,11 +32,16 @@ | |||
| 32 | #address-cells = <1>; | 32 | #address-cells = <1>; |
| 33 | #size-cells = <1>; | 33 | #size-cells = <1>; |
| 34 | compatible = "xlnx,microblaze"; | 34 | compatible = "xlnx,microblaze"; |
| 35 | hard-reset-gpios = <&LEDs_8Bit 2 1>; | ||
| 35 | model = "testing"; | 36 | model = "testing"; |
| 36 | DDR2_SDRAM: memory@90000000 { | 37 | DDR2_SDRAM: memory@90000000 { |
| 37 | device_type = "memory"; | 38 | device_type = "memory"; |
| 38 | reg = < 0x90000000 0x10000000 >; | 39 | reg = < 0x90000000 0x10000000 >; |
| 39 | } ; | 40 | } ; |
| 41 | aliases { | ||
| 42 | ethernet0 = &Hard_Ethernet_MAC; | ||
| 43 | serial0 = &RS232_Uart_1; | ||
| 44 | } ; | ||
| 40 | chosen { | 45 | chosen { |
| 41 | bootargs = "console=ttyUL0,115200 highres=on"; | 46 | bootargs = "console=ttyUL0,115200 highres=on"; |
| 42 | linux,stdout-path = "/plb@0/serial@84000000"; | 47 | linux,stdout-path = "/plb@0/serial@84000000"; |
| @@ -127,7 +132,7 @@ | |||
| 127 | mb_plb: plb@0 { | 132 | mb_plb: plb@0 { |
| 128 | #address-cells = <1>; | 133 | #address-cells = <1>; |
| 129 | #size-cells = <1>; | 134 | #size-cells = <1>; |
| 130 | compatible = "xlnx,plb-v46-1.03.a", "simple-bus"; | 135 | compatible = "xlnx,plb-v46-1.03.a", "xlnx,plb-v46-1.00.a", "simple-bus"; |
| 131 | ranges ; | 136 | ranges ; |
| 132 | FLASH: flash@a0000000 { | 137 | FLASH: flash@a0000000 { |
| 133 | bank-width = <2>; | 138 | bank-width = <2>; |
| @@ -214,12 +219,12 @@ | |||
| 214 | #size-cells = <1>; | 219 | #size-cells = <1>; |
| 215 | compatible = "xlnx,compound"; | 220 | compatible = "xlnx,compound"; |
| 216 | ethernet@81c00000 { | 221 | ethernet@81c00000 { |
| 217 | compatible = "xlnx,xps-ll-temac-1.01.b"; | 222 | compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a"; |
| 218 | device_type = "network"; | 223 | device_type = "network"; |
| 219 | interrupt-parent = <&xps_intc_0>; | 224 | interrupt-parent = <&xps_intc_0>; |
| 220 | interrupts = < 5 2 >; | 225 | interrupts = < 5 2 >; |
| 221 | llink-connected = <&PIM3>; | 226 | llink-connected = <&PIM3>; |
| 222 | local-mac-address = [ 02 00 00 00 00 00 ]; | 227 | local-mac-address = [ 00 0a 35 00 00 00 ]; |
| 223 | reg = < 0x81c00000 0x40 >; | 228 | reg = < 0x81c00000 0x40 >; |
| 224 | xlnx,bus2core-clk-ratio = <0x1>; | 229 | xlnx,bus2core-clk-ratio = <0x1>; |
| 225 | xlnx,phy-type = <0x1>; | 230 | xlnx,phy-type = <0x1>; |
| @@ -261,6 +266,33 @@ | |||
| 261 | xlnx,is-dual = <0x0>; | 266 | xlnx,is-dual = <0x0>; |
| 262 | xlnx,tri-default = <0xffffffff>; | 267 | xlnx,tri-default = <0xffffffff>; |
| 263 | xlnx,tri-default-2 = <0xffffffff>; | 268 | xlnx,tri-default-2 = <0xffffffff>; |
| 269 | #gpio-cells = <2>; | ||
| 270 | gpio-controller; | ||
| 271 | } ; | ||
| 272 | |||
| 273 | gpio-leds { | ||
| 274 | compatible = "gpio-leds"; | ||
| 275 | |||
| 276 | heartbeat { | ||
| 277 | label = "Heartbeat"; | ||
| 278 | gpios = <&LEDs_8Bit 4 1>; | ||
| 279 | linux,default-trigger = "heartbeat"; | ||
| 280 | }; | ||
| 281 | |||
| 282 | yellow { | ||
| 283 | label = "Yellow"; | ||
| 284 | gpios = <&LEDs_8Bit 5 1>; | ||
| 285 | }; | ||
| 286 | |||
| 287 | red { | ||
| 288 | label = "Red"; | ||
| 289 | gpios = <&LEDs_8Bit 6 1>; | ||
| 290 | }; | ||
| 291 | |||
| 292 | green { | ||
| 293 | label = "Green"; | ||
| 294 | gpios = <&LEDs_8Bit 7 1>; | ||
| 295 | }; | ||
| 264 | } ; | 296 | } ; |
| 265 | RS232_Uart_1: serial@84000000 { | 297 | RS232_Uart_1: serial@84000000 { |
| 266 | clock-frequency = <125000000>; | 298 | clock-frequency = <125000000>; |
diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c index 56e0234fa34b..5b89b58c5aed 100644 --- a/arch/microblaze/platform/platform.c +++ b/arch/microblaze/platform/platform.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
| 15 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
| 16 | #include <asm/setup.h> | ||
| 16 | 17 | ||
| 17 | static struct of_device_id xilinx_of_bus_ids[] __initdata = { | 18 | static struct of_device_id xilinx_of_bus_ids[] __initdata = { |
| 18 | { .compatible = "simple-bus", }, | 19 | { .compatible = "simple-bus", }, |
| @@ -26,6 +27,7 @@ static struct of_device_id xilinx_of_bus_ids[] __initdata = { | |||
| 26 | static int __init microblaze_device_probe(void) | 27 | static int __init microblaze_device_probe(void) |
| 27 | { | 28 | { |
| 28 | of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); | 29 | of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); |
| 30 | of_platform_reset_gpio_probe(); | ||
| 29 | return 0; | 31 | return 0; |
| 30 | } | 32 | } |
| 31 | device_initcall(microblaze_device_probe); | 33 | device_initcall(microblaze_device_probe); |
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index f0d14452632b..9cf0a6fad6ba 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl | |||
| @@ -295,6 +295,9 @@ if ($arch eq "x86_64") { | |||
| 295 | $ld .= " -m elf64_sparc"; | 295 | $ld .= " -m elf64_sparc"; |
| 296 | $cc .= " -m64"; | 296 | $cc .= " -m64"; |
| 297 | $objcopy .= " -O elf64-sparc"; | 297 | $objcopy .= " -O elf64-sparc"; |
| 298 | } elsif ($arch eq "microblaze") { | ||
| 299 | # Microblaze calls '_mcount' instead of plain 'mcount'. | ||
| 300 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$"; | ||
| 298 | } else { | 301 | } else { |
| 299 | die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; | 302 | die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; |
| 300 | } | 303 | } |
