diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 13:09:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 13:09:39 -0400 |
commit | 87c1f0f8c9442c86cbb343b9324bef8312029d7d (patch) | |
tree | 47f97d468a83d2f13d08fe9603fc91e23cb60c8e /arch | |
parent | 165bc513f7ec54d3fa3660f5c851c4bbc533d577 (diff) | |
parent | 164c013858a2e89b450cd8021a8be896f9e05697 (diff) |
Merge tag 'metag-for-v3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag
Pull arch/metag update from James Hogan:
- Various fixes for the interrupting perf counter handling in metag's
perf backend.
- Add OProfile support based on perf.
- Sets up cache partitions for SMP so bootloader doesn't have to.
- Patch from Paul Bolle to remove ARCH_POPULATES_NODE_MAP again
(touches microblaze too).
- Add TLS pointer regset to metag ptrace api.
- Add exported metag DSP extended context handling header <asm/ech.h>.
- Increase defconfig log buffer size to 128KiB.
- Various fixes, typos, missing exports.
* tag 'metag-for-v3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag:
metag: defconfigs: increase log buffer 8KiB => 128KiB
metag: avoid unnecessary builtin dtb rebuilds
metag: add exported <asm/ech.h> for extended context handling
metag: export _metag_da_present and cpu_2_hwthread_id
metag: ptrace: Implement NT_METAG_TLS
memblock: Kill ARCH_POPULATES_NODE_MAP once more
metag: cachepart: fix get_global_dcache_size() typo
metag: cachepart: take into account small cache bits
metag: smp: copy cache partition and enable GCOn
metag: OProfile support
metag: perf: prepare for use by oprofile
metag: perf: don't reset TXTACTCYC
metag: perf: use hard_processor_id() to get thread
metag: perf: fix frequency sampling (dynamic period)
metag: perf: add missing prev_count updates
metag: perf: fixes for interrupting perf counters
metag: perf: fix wrap handling in delta calculation
metag: perf: fix core internal / perf channel mux
Diffstat (limited to 'arch')
-rw-r--r-- | arch/metag/Kconfig | 4 | ||||
-rw-r--r-- | arch/metag/Makefile | 2 | ||||
-rw-r--r-- | arch/metag/boot/dts/Makefile | 10 | ||||
-rw-r--r-- | arch/metag/configs/meta1_defconfig | 1 | ||||
-rw-r--r-- | arch/metag/configs/meta2_defconfig | 1 | ||||
-rw-r--r-- | arch/metag/configs/meta2_smp_defconfig | 1 | ||||
-rw-r--r-- | arch/metag/include/asm/metag_mem.h | 3 | ||||
-rw-r--r-- | arch/metag/include/uapi/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/metag/include/uapi/asm/ech.h | 15 | ||||
-rw-r--r-- | arch/metag/kernel/cachepart.c | 16 | ||||
-rw-r--r-- | arch/metag/kernel/da.c | 2 | ||||
-rw-r--r-- | arch/metag/kernel/head.S | 8 | ||||
-rw-r--r-- | arch/metag/kernel/perf/perf_event.c | 74 | ||||
-rw-r--r-- | arch/metag/kernel/ptrace.c | 34 | ||||
-rw-r--r-- | arch/metag/kernel/setup.c | 1 | ||||
-rw-r--r-- | arch/metag/kernel/smp.c | 115 | ||||
-rw-r--r-- | arch/metag/mm/Kconfig | 3 | ||||
-rw-r--r-- | arch/metag/oprofile/Makefile | 17 | ||||
-rw-r--r-- | arch/metag/oprofile/backtrace.c | 63 | ||||
-rw-r--r-- | arch/metag/oprofile/backtrace.h | 6 | ||||
-rw-r--r-- | arch/metag/oprofile/common.c | 66 | ||||
-rw-r--r-- | arch/microblaze/Kconfig | 3 |
22 files changed, 406 insertions, 40 deletions
diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig index afc8973d1488..b06b41861aac 100644 --- a/arch/metag/Kconfig +++ b/arch/metag/Kconfig | |||
@@ -25,6 +25,7 @@ config METAG | |||
25 | select HAVE_MEMBLOCK | 25 | select HAVE_MEMBLOCK |
26 | select HAVE_MEMBLOCK_NODE_MAP | 26 | select HAVE_MEMBLOCK_NODE_MAP |
27 | select HAVE_MOD_ARCH_SPECIFIC | 27 | select HAVE_MOD_ARCH_SPECIFIC |
28 | select HAVE_OPROFILE | ||
28 | select HAVE_PERF_EVENTS | 29 | select HAVE_PERF_EVENTS |
29 | select HAVE_SYSCALL_TRACEPOINTS | 30 | select HAVE_SYSCALL_TRACEPOINTS |
30 | select IRQ_DOMAIN | 31 | select IRQ_DOMAIN |
@@ -209,6 +210,9 @@ config METAG_PERFCOUNTER_IRQS | |||
209 | When disabled, Performance Counters information will be collected | 210 | When disabled, Performance Counters information will be collected |
210 | based on Timer Interrupt. | 211 | based on Timer Interrupt. |
211 | 212 | ||
213 | config HW_PERF_EVENTS | ||
214 | def_bool METAG_PERFCOUNTER_IRQS && PERF_EVENTS | ||
215 | |||
212 | config METAG_DA | 216 | config METAG_DA |
213 | bool "DA support" | 217 | bool "DA support" |
214 | help | 218 | help |
diff --git a/arch/metag/Makefile b/arch/metag/Makefile index 81bd6a1c7483..b566116b171b 100644 --- a/arch/metag/Makefile +++ b/arch/metag/Makefile | |||
@@ -49,6 +49,8 @@ core-y += arch/metag/mm/ | |||
49 | libs-y += arch/metag/lib/ | 49 | libs-y += arch/metag/lib/ |
50 | libs-y += arch/metag/tbx/ | 50 | libs-y += arch/metag/tbx/ |
51 | 51 | ||
52 | drivers-$(CONFIG_OPROFILE) += arch/metag/oprofile/ | ||
53 | |||
52 | boot := arch/metag/boot | 54 | boot := arch/metag/boot |
53 | 55 | ||
54 | boot_targets += uImage | 56 | boot_targets += uImage |
diff --git a/arch/metag/boot/dts/Makefile b/arch/metag/boot/dts/Makefile index e0b5afd8bde8..dbd95217733a 100644 --- a/arch/metag/boot/dts/Makefile +++ b/arch/metag/boot/dts/Makefile | |||
@@ -4,13 +4,17 @@ dtb-y += skeleton.dtb | |||
4 | builtindtb-y := skeleton | 4 | builtindtb-y := skeleton |
5 | 5 | ||
6 | ifneq ($(CONFIG_METAG_BUILTIN_DTB_NAME),"") | 6 | ifneq ($(CONFIG_METAG_BUILTIN_DTB_NAME),"") |
7 | builtindtb-y := $(CONFIG_METAG_BUILTIN_DTB_NAME) | 7 | builtindtb-y := $(patsubst "%",%,$(CONFIG_METAG_BUILTIN_DTB_NAME)) |
8 | endif | 8 | endif |
9 | obj-$(CONFIG_METAG_BUILTIN_DTB) += $(patsubst "%",%,$(builtindtb-y)).dtb.o | 9 | |
10 | dtb-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb | ||
11 | obj-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb.o | ||
10 | 12 | ||
11 | targets += dtbs | 13 | targets += dtbs |
12 | targets += $(dtb-y) | 14 | targets += $(dtb-y) |
13 | 15 | ||
16 | .SECONDARY: $(obj)/$(builtindtb-y).dtb.S | ||
17 | |||
14 | dtbs: $(addprefix $(obj)/, $(dtb-y)) | 18 | dtbs: $(addprefix $(obj)/, $(dtb-y)) |
15 | 19 | ||
16 | clean-files += *.dtb | 20 | clean-files += *.dtb *.dtb.S |
diff --git a/arch/metag/configs/meta1_defconfig b/arch/metag/configs/meta1_defconfig index c35a75e8ecfe..01cd67e4403d 100644 --- a/arch/metag/configs/meta1_defconfig +++ b/arch/metag/configs/meta1_defconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | # CONFIG_LOCALVERSION_AUTO is not set | 1 | # CONFIG_LOCALVERSION_AUTO is not set |
2 | # CONFIG_SWAP is not set | 2 | # CONFIG_SWAP is not set |
3 | CONFIG_LOG_BUF_SHIFT=13 | ||
4 | CONFIG_SYSFS_DEPRECATED=y | 3 | CONFIG_SYSFS_DEPRECATED=y |
5 | CONFIG_SYSFS_DEPRECATED_V2=y | 4 | CONFIG_SYSFS_DEPRECATED_V2=y |
6 | CONFIG_KALLSYMS_ALL=y | 5 | CONFIG_KALLSYMS_ALL=y |
diff --git a/arch/metag/configs/meta2_defconfig b/arch/metag/configs/meta2_defconfig index fb3148410183..643392ba7ed5 100644 --- a/arch/metag/configs/meta2_defconfig +++ b/arch/metag/configs/meta2_defconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | # CONFIG_LOCALVERSION_AUTO is not set | 1 | # CONFIG_LOCALVERSION_AUTO is not set |
2 | # CONFIG_SWAP is not set | 2 | # CONFIG_SWAP is not set |
3 | CONFIG_SYSVIPC=y | 3 | CONFIG_SYSVIPC=y |
4 | CONFIG_LOG_BUF_SHIFT=13 | ||
5 | CONFIG_SYSFS_DEPRECATED=y | 4 | CONFIG_SYSFS_DEPRECATED=y |
6 | CONFIG_SYSFS_DEPRECATED_V2=y | 5 | CONFIG_SYSFS_DEPRECATED_V2=y |
7 | CONFIG_KALLSYMS_ALL=y | 6 | CONFIG_KALLSYMS_ALL=y |
diff --git a/arch/metag/configs/meta2_smp_defconfig b/arch/metag/configs/meta2_smp_defconfig index 6c7b777ac276..f3306737da20 100644 --- a/arch/metag/configs/meta2_smp_defconfig +++ b/arch/metag/configs/meta2_smp_defconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | # CONFIG_LOCALVERSION_AUTO is not set | 1 | # CONFIG_LOCALVERSION_AUTO is not set |
2 | # CONFIG_SWAP is not set | 2 | # CONFIG_SWAP is not set |
3 | CONFIG_SYSVIPC=y | 3 | CONFIG_SYSVIPC=y |
4 | CONFIG_LOG_BUF_SHIFT=13 | ||
5 | CONFIG_SYSFS_DEPRECATED=y | 4 | CONFIG_SYSFS_DEPRECATED=y |
6 | CONFIG_SYSFS_DEPRECATED_V2=y | 5 | CONFIG_SYSFS_DEPRECATED_V2=y |
7 | CONFIG_KALLSYMS_ALL=y | 6 | CONFIG_KALLSYMS_ALL=y |
diff --git a/arch/metag/include/asm/metag_mem.h b/arch/metag/include/asm/metag_mem.h index 3f7b54d8ccac..aa5a076df439 100644 --- a/arch/metag/include/asm/metag_mem.h +++ b/arch/metag/include/asm/metag_mem.h | |||
@@ -700,6 +700,9 @@ | |||
700 | #define SYSC_xCPARTG_AND_S 8 | 700 | #define SYSC_xCPARTG_AND_S 8 |
701 | #define SYSC_xCPARTL_OR_BITS 0x000F0000 /* Ors into top 4 bits */ | 701 | #define SYSC_xCPARTL_OR_BITS 0x000F0000 /* Ors into top 4 bits */ |
702 | #define SYSC_xCPARTL_OR_S 16 | 702 | #define SYSC_xCPARTL_OR_S 16 |
703 | #ifdef METAC_2_1 | ||
704 | #define SYSC_DCPART_GCON_BIT 0x00100000 /* Coherent shared local */ | ||
705 | #endif /* METAC_2_1 */ | ||
703 | #define SYSC_xCPARTG_OR_BITS 0x0F000000 /* Ors into top 4 bits */ | 706 | #define SYSC_xCPARTG_OR_BITS 0x0F000000 /* Ors into top 4 bits */ |
704 | #define SYSC_xCPARTG_OR_S 24 | 707 | #define SYSC_xCPARTG_OR_S 24 |
705 | #define SYSC_CWRMODE_BIT 0x80000000 /* Write cache mode bit */ | 708 | #define SYSC_CWRMODE_BIT 0x80000000 /* Write cache mode bit */ |
diff --git a/arch/metag/include/uapi/asm/Kbuild b/arch/metag/include/uapi/asm/Kbuild index 876c71f866de..84e09feb4d54 100644 --- a/arch/metag/include/uapi/asm/Kbuild +++ b/arch/metag/include/uapi/asm/Kbuild | |||
@@ -2,6 +2,7 @@ | |||
2 | include include/uapi/asm-generic/Kbuild.asm | 2 | include include/uapi/asm-generic/Kbuild.asm |
3 | 3 | ||
4 | header-y += byteorder.h | 4 | header-y += byteorder.h |
5 | header-y += ech.h | ||
5 | header-y += ptrace.h | 6 | header-y += ptrace.h |
6 | header-y += resource.h | 7 | header-y += resource.h |
7 | header-y += sigcontext.h | 8 | header-y += sigcontext.h |
diff --git a/arch/metag/include/uapi/asm/ech.h b/arch/metag/include/uapi/asm/ech.h new file mode 100644 index 000000000000..ac94d1cf9be4 --- /dev/null +++ b/arch/metag/include/uapi/asm/ech.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef _UAPI_METAG_ECH_H | ||
2 | #define _UAPI_METAG_ECH_H | ||
3 | |||
4 | /* | ||
5 | * These bits can be set in the top half of the D0.8 register when DSP context | ||
6 | * switching is enabled, in order to support partial DSP context save/restore. | ||
7 | */ | ||
8 | |||
9 | #define TBICTX_XEXT_BIT 0x1000 /* Enable extended context save */ | ||
10 | #define TBICTX_XTDP_BIT 0x0800 /* DSP accumulators/RAM/templates */ | ||
11 | #define TBICTX_XHL2_BIT 0x0400 /* Hardware loops */ | ||
12 | #define TBICTX_XAXX_BIT 0x0200 /* Extended AX registers (A*.4-7) */ | ||
13 | #define TBICTX_XDX8_BIT 0x0100 /* Extended DX registers (D*.8-15) */ | ||
14 | |||
15 | #endif /* _UAPI_METAG_ECH_H */ | ||
diff --git a/arch/metag/kernel/cachepart.c b/arch/metag/kernel/cachepart.c index 3a589dfb966b..954548b1bea8 100644 --- a/arch/metag/kernel/cachepart.c +++ b/arch/metag/kernel/cachepart.c | |||
@@ -24,15 +24,21 @@ | |||
24 | unsigned int get_dcache_size(void) | 24 | unsigned int get_dcache_size(void) |
25 | { | 25 | { |
26 | unsigned int config2 = metag_in32(METAC_CORE_CONFIG2); | 26 | unsigned int config2 = metag_in32(METAC_CORE_CONFIG2); |
27 | return 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS) | 27 | unsigned int sz = 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS) |
28 | >> METAC_CORECFG2_DCSZ_S); | 28 | >> METAC_CORECFG2_DCSZ_S); |
29 | if (config2 & METAC_CORECFG2_DCSMALL_BIT) | ||
30 | sz >>= 6; | ||
31 | return sz; | ||
29 | } | 32 | } |
30 | 33 | ||
31 | unsigned int get_icache_size(void) | 34 | unsigned int get_icache_size(void) |
32 | { | 35 | { |
33 | unsigned int config2 = metag_in32(METAC_CORE_CONFIG2); | 36 | unsigned int config2 = metag_in32(METAC_CORE_CONFIG2); |
34 | return 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS) | 37 | unsigned int sz = 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS) |
35 | >> METAC_CORE_C2ICSZ_S); | 38 | >> METAC_CORE_C2ICSZ_S); |
39 | if (config2 & METAC_CORECFG2_ICSMALL_BIT) | ||
40 | sz >>= 6; | ||
41 | return sz; | ||
36 | } | 42 | } |
37 | 43 | ||
38 | unsigned int get_global_dcache_size(void) | 44 | unsigned int get_global_dcache_size(void) |
@@ -61,7 +67,7 @@ static unsigned int get_thread_cache_size(unsigned int cache, int thread_id) | |||
61 | return 0; | 67 | return 0; |
62 | #if PAGE_OFFSET >= LINGLOBAL_BASE | 68 | #if PAGE_OFFSET >= LINGLOBAL_BASE |
63 | /* Checking for global cache */ | 69 | /* Checking for global cache */ |
64 | cache_size = (cache == DCACHE ? get_global_dache_size() : | 70 | cache_size = (cache == DCACHE ? get_global_dcache_size() : |
65 | get_global_icache_size()); | 71 | get_global_icache_size()); |
66 | offset = 8; | 72 | offset = 8; |
67 | #else | 73 | #else |
diff --git a/arch/metag/kernel/da.c b/arch/metag/kernel/da.c index 52aabb658fde..a35dbed6fffa 100644 --- a/arch/metag/kernel/da.c +++ b/arch/metag/kernel/da.c | |||
@@ -5,12 +5,14 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | 7 | ||
8 | #include <linux/export.h> | ||
8 | #include <linux/io.h> | 9 | #include <linux/io.h> |
9 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
10 | #include <asm/da.h> | 11 | #include <asm/da.h> |
11 | #include <asm/metag_mem.h> | 12 | #include <asm/metag_mem.h> |
12 | 13 | ||
13 | bool _metag_da_present; | 14 | bool _metag_da_present; |
15 | EXPORT_SYMBOL_GPL(_metag_da_present); | ||
14 | 16 | ||
15 | int __init metag_da_probe(void) | 17 | int __init metag_da_probe(void) |
16 | { | 18 | { |
diff --git a/arch/metag/kernel/head.S b/arch/metag/kernel/head.S index 969dffabc03a..713f71d1bdfe 100644 --- a/arch/metag/kernel/head.S +++ b/arch/metag/kernel/head.S | |||
@@ -1,6 +1,7 @@ | |||
1 | ! Copyright 2005,2006,2007,2009 Imagination Technologies | 1 | ! Copyright 2005,2006,2007,2009 Imagination Technologies |
2 | 2 | ||
3 | #include <linux/init.h> | 3 | #include <linux/init.h> |
4 | #include <asm/metag_mem.h> | ||
4 | #include <generated/asm-offsets.h> | 5 | #include <generated/asm-offsets.h> |
5 | #undef __exit | 6 | #undef __exit |
6 | 7 | ||
@@ -48,6 +49,13 @@ __exit: | |||
48 | .global _secondary_startup | 49 | .global _secondary_startup |
49 | .type _secondary_startup,function | 50 | .type _secondary_startup,function |
50 | _secondary_startup: | 51 | _secondary_startup: |
52 | #if CONFIG_PAGE_OFFSET < LINGLOBAL_BASE | ||
53 | ! In case GCOn has just been turned on we need to fence any writes that | ||
54 | ! the boot thread might have performed prior to coherency taking effect. | ||
55 | MOVT D0Re0,#HI(LINSYSEVENT_WR_ATOMIC_UNLOCK) | ||
56 | MOV D1Re0,#0 | ||
57 | SETD [D0Re0], D1Re0 | ||
58 | #endif | ||
51 | MOVT A0StP,#HI(_secondary_data_stack) | 59 | MOVT A0StP,#HI(_secondary_data_stack) |
52 | ADD A0StP,A0StP,#LO(_secondary_data_stack) | 60 | ADD A0StP,A0StP,#LO(_secondary_data_stack) |
53 | GETD A0StP,[A0StP] | 61 | GETD A0StP,[A0StP] |
diff --git a/arch/metag/kernel/perf/perf_event.c b/arch/metag/kernel/perf/perf_event.c index a876d5ff3897..366569425c52 100644 --- a/arch/metag/kernel/perf/perf_event.c +++ b/arch/metag/kernel/perf/perf_event.c | |||
@@ -22,9 +22,9 @@ | |||
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | 23 | ||
24 | #include <asm/core_reg.h> | 24 | #include <asm/core_reg.h> |
25 | #include <asm/hwthread.h> | ||
26 | #include <asm/io.h> | 25 | #include <asm/io.h> |
27 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | #include <asm/processor.h> | ||
28 | 28 | ||
29 | #include "perf_event.h" | 29 | #include "perf_event.h" |
30 | 30 | ||
@@ -40,10 +40,10 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); | |||
40 | /* PMU admin */ | 40 | /* PMU admin */ |
41 | const char *perf_pmu_name(void) | 41 | const char *perf_pmu_name(void) |
42 | { | 42 | { |
43 | if (metag_pmu) | 43 | if (!metag_pmu) |
44 | return metag_pmu->pmu.name; | 44 | return NULL; |
45 | 45 | ||
46 | return NULL; | 46 | return metag_pmu->name; |
47 | } | 47 | } |
48 | EXPORT_SYMBOL_GPL(perf_pmu_name); | 48 | EXPORT_SYMBOL_GPL(perf_pmu_name); |
49 | 49 | ||
@@ -171,6 +171,7 @@ static int metag_pmu_event_init(struct perf_event *event) | |||
171 | switch (event->attr.type) { | 171 | switch (event->attr.type) { |
172 | case PERF_TYPE_HARDWARE: | 172 | case PERF_TYPE_HARDWARE: |
173 | case PERF_TYPE_HW_CACHE: | 173 | case PERF_TYPE_HW_CACHE: |
174 | case PERF_TYPE_RAW: | ||
174 | err = _hw_perf_event_init(event); | 175 | err = _hw_perf_event_init(event); |
175 | break; | 176 | break; |
176 | 177 | ||
@@ -211,9 +212,10 @@ again: | |||
211 | /* | 212 | /* |
212 | * Calculate the delta and add it to the counter. | 213 | * Calculate the delta and add it to the counter. |
213 | */ | 214 | */ |
214 | delta = new_raw_count - prev_raw_count; | 215 | delta = (new_raw_count - prev_raw_count) & MAX_PERIOD; |
215 | 216 | ||
216 | local64_add(delta, &event->count); | 217 | local64_add(delta, &event->count); |
218 | local64_sub(delta, &hwc->period_left); | ||
217 | } | 219 | } |
218 | 220 | ||
219 | int metag_pmu_event_set_period(struct perf_event *event, | 221 | int metag_pmu_event_set_period(struct perf_event *event, |
@@ -223,6 +225,10 @@ int metag_pmu_event_set_period(struct perf_event *event, | |||
223 | s64 period = hwc->sample_period; | 225 | s64 period = hwc->sample_period; |
224 | int ret = 0; | 226 | int ret = 0; |
225 | 227 | ||
228 | /* The period may have been changed */ | ||
229 | if (unlikely(period != hwc->last_period)) | ||
230 | left += period - hwc->last_period; | ||
231 | |||
226 | if (unlikely(left <= -period)) { | 232 | if (unlikely(left <= -period)) { |
227 | left = period; | 233 | left = period; |
228 | local64_set(&hwc->period_left, left); | 234 | local64_set(&hwc->period_left, left); |
@@ -240,8 +246,10 @@ int metag_pmu_event_set_period(struct perf_event *event, | |||
240 | if (left > (s64)metag_pmu->max_period) | 246 | if (left > (s64)metag_pmu->max_period) |
241 | left = metag_pmu->max_period; | 247 | left = metag_pmu->max_period; |
242 | 248 | ||
243 | if (metag_pmu->write) | 249 | if (metag_pmu->write) { |
244 | metag_pmu->write(idx, (u64)(-left) & MAX_PERIOD); | 250 | local64_set(&hwc->prev_count, -(s32)left); |
251 | metag_pmu->write(idx, -left & MAX_PERIOD); | ||
252 | } | ||
245 | 253 | ||
246 | perf_event_update_userpage(event); | 254 | perf_event_update_userpage(event); |
247 | 255 | ||
@@ -549,6 +557,10 @@ static int _hw_perf_event_init(struct perf_event *event) | |||
549 | if (err) | 557 | if (err) |
550 | return err; | 558 | return err; |
551 | break; | 559 | break; |
560 | |||
561 | case PERF_TYPE_RAW: | ||
562 | mapping = attr->config; | ||
563 | break; | ||
552 | } | 564 | } |
553 | 565 | ||
554 | /* Return early if the event is unsupported */ | 566 | /* Return early if the event is unsupported */ |
@@ -610,15 +622,13 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx) | |||
610 | WARN_ONCE((config != 0x100), | 622 | WARN_ONCE((config != 0x100), |
611 | "invalid configuration (%d) for counter (%d)\n", | 623 | "invalid configuration (%d) for counter (%d)\n", |
612 | config, idx); | 624 | config, idx); |
613 | 625 | local64_set(&event->prev_count, __core_reg_get(TXTACTCYC)); | |
614 | /* Reset the cycle count */ | ||
615 | __core_reg_set(TXTACTCYC, 0); | ||
616 | goto unlock; | 626 | goto unlock; |
617 | } | 627 | } |
618 | 628 | ||
619 | /* Check for a core internal or performance channel event. */ | 629 | /* Check for a core internal or performance channel event. */ |
620 | if (tmp) { | 630 | if (tmp) { |
621 | void *perf_addr = (void *)PERF_COUNT(idx); | 631 | void *perf_addr; |
622 | 632 | ||
623 | /* | 633 | /* |
624 | * Anything other than a cycle count will write the low- | 634 | * Anything other than a cycle count will write the low- |
@@ -632,9 +642,14 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx) | |||
632 | case 0xf0: | 642 | case 0xf0: |
633 | perf_addr = (void *)PERF_CHAN(idx); | 643 | perf_addr = (void *)PERF_CHAN(idx); |
634 | break; | 644 | break; |
645 | |||
646 | default: | ||
647 | perf_addr = NULL; | ||
648 | break; | ||
635 | } | 649 | } |
636 | 650 | ||
637 | metag_out32((tmp & 0x0f), perf_addr); | 651 | if (perf_addr) |
652 | metag_out32((config & 0x0f), perf_addr); | ||
638 | 653 | ||
639 | /* | 654 | /* |
640 | * Now we use the high nibble as the performance event to | 655 | * Now we use the high nibble as the performance event to |
@@ -643,13 +658,21 @@ static void metag_pmu_enable_counter(struct hw_perf_event *event, int idx) | |||
643 | config = tmp >> 4; | 658 | config = tmp >> 4; |
644 | } | 659 | } |
645 | 660 | ||
646 | /* | ||
647 | * Enabled counters start from 0. Early cores clear the count on | ||
648 | * write but newer cores don't, so we make sure that the count is | ||
649 | * set to 0. | ||
650 | */ | ||
651 | tmp = ((config & 0xf) << 28) | | 661 | tmp = ((config & 0xf) << 28) | |
652 | ((1 << 24) << cpu_2_hwthread_id[get_cpu()]); | 662 | ((1 << 24) << hard_processor_id()); |
663 | if (metag_pmu->max_period) | ||
664 | /* | ||
665 | * Cores supporting overflow interrupts may have had the counter | ||
666 | * set to a specific value that needs preserving. | ||
667 | */ | ||
668 | tmp |= metag_in32(PERF_COUNT(idx)) & 0x00ffffff; | ||
669 | else | ||
670 | /* | ||
671 | * Older cores reset the counter on write, so prev_count needs | ||
672 | * resetting too so we can calculate a correct delta. | ||
673 | */ | ||
674 | local64_set(&event->prev_count, 0); | ||
675 | |||
653 | metag_out32(tmp, PERF_COUNT(idx)); | 676 | metag_out32(tmp, PERF_COUNT(idx)); |
654 | unlock: | 677 | unlock: |
655 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | 678 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); |
@@ -693,9 +716,8 @@ static u64 metag_pmu_read_counter(int idx) | |||
693 | { | 716 | { |
694 | u32 tmp = 0; | 717 | u32 tmp = 0; |
695 | 718 | ||
696 | /* The act of reading the cycle counter also clears it */ | ||
697 | if (METAG_INST_COUNTER == idx) { | 719 | if (METAG_INST_COUNTER == idx) { |
698 | __core_reg_swap(TXTACTCYC, tmp); | 720 | tmp = __core_reg_get(TXTACTCYC); |
699 | goto out; | 721 | goto out; |
700 | } | 722 | } |
701 | 723 | ||
@@ -764,10 +786,16 @@ static irqreturn_t metag_pmu_counter_overflow(int irq, void *dev) | |||
764 | 786 | ||
765 | /* | 787 | /* |
766 | * Enable the counter again once core overflow processing has | 788 | * Enable the counter again once core overflow processing has |
767 | * completed. | 789 | * completed. Note the counter value may have been modified while it was |
790 | * inactive to set it up ready for the next interrupt. | ||
768 | */ | 791 | */ |
769 | if (!perf_event_overflow(event, &sampledata, regs)) | 792 | if (!perf_event_overflow(event, &sampledata, regs)) { |
793 | __global_lock2(flags); | ||
794 | counter = (counter & 0xff000000) | | ||
795 | (metag_in32(PERF_COUNT(idx)) & 0x00ffffff); | ||
770 | metag_out32(counter, PERF_COUNT(idx)); | 796 | metag_out32(counter, PERF_COUNT(idx)); |
797 | __global_unlock2(flags); | ||
798 | } | ||
771 | 799 | ||
772 | return IRQ_HANDLED; | 800 | return IRQ_HANDLED; |
773 | } | 801 | } |
@@ -830,7 +858,7 @@ static int __init init_hw_perf_events(void) | |||
830 | metag_pmu->max_period = 0; | 858 | metag_pmu->max_period = 0; |
831 | } | 859 | } |
832 | 860 | ||
833 | metag_pmu->name = "Meta 2"; | 861 | metag_pmu->name = "meta2"; |
834 | metag_pmu->version = version; | 862 | metag_pmu->version = version; |
835 | metag_pmu->pmu = pmu; | 863 | metag_pmu->pmu = pmu; |
836 | } | 864 | } |
diff --git a/arch/metag/kernel/ptrace.c b/arch/metag/kernel/ptrace.c index 47a8828615a5..7563628822bd 100644 --- a/arch/metag/kernel/ptrace.c +++ b/arch/metag/kernel/ptrace.c | |||
@@ -288,10 +288,36 @@ static int metag_rp_state_set(struct task_struct *target, | |||
288 | return metag_rp_state_copyin(regs, pos, count, kbuf, ubuf); | 288 | return metag_rp_state_copyin(regs, pos, count, kbuf, ubuf); |
289 | } | 289 | } |
290 | 290 | ||
291 | static int metag_tls_get(struct task_struct *target, | ||
292 | const struct user_regset *regset, | ||
293 | unsigned int pos, unsigned int count, | ||
294 | void *kbuf, void __user *ubuf) | ||
295 | { | ||
296 | void __user *tls = target->thread.tls_ptr; | ||
297 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); | ||
298 | } | ||
299 | |||
300 | static int metag_tls_set(struct task_struct *target, | ||
301 | const struct user_regset *regset, | ||
302 | unsigned int pos, unsigned int count, | ||
303 | const void *kbuf, const void __user *ubuf) | ||
304 | { | ||
305 | int ret; | ||
306 | void __user *tls; | ||
307 | |||
308 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1); | ||
309 | if (ret) | ||
310 | return ret; | ||
311 | |||
312 | target->thread.tls_ptr = tls; | ||
313 | return ret; | ||
314 | } | ||
315 | |||
291 | enum metag_regset { | 316 | enum metag_regset { |
292 | REGSET_GENERAL, | 317 | REGSET_GENERAL, |
293 | REGSET_CBUF, | 318 | REGSET_CBUF, |
294 | REGSET_READPIPE, | 319 | REGSET_READPIPE, |
320 | REGSET_TLS, | ||
295 | }; | 321 | }; |
296 | 322 | ||
297 | static const struct user_regset metag_regsets[] = { | 323 | static const struct user_regset metag_regsets[] = { |
@@ -319,6 +345,14 @@ static const struct user_regset metag_regsets[] = { | |||
319 | .get = metag_rp_state_get, | 345 | .get = metag_rp_state_get, |
320 | .set = metag_rp_state_set, | 346 | .set = metag_rp_state_set, |
321 | }, | 347 | }, |
348 | [REGSET_TLS] = { | ||
349 | .core_note_type = NT_METAG_TLS, | ||
350 | .n = 1, | ||
351 | .size = sizeof(void *), | ||
352 | .align = sizeof(void *), | ||
353 | .get = metag_tls_get, | ||
354 | .set = metag_tls_set, | ||
355 | }, | ||
322 | }; | 356 | }; |
323 | 357 | ||
324 | static const struct user_regset_view user_metag_view = { | 358 | static const struct user_regset_view user_metag_view = { |
diff --git a/arch/metag/kernel/setup.c b/arch/metag/kernel/setup.c index 879246170aec..4f5726f1a55b 100644 --- a/arch/metag/kernel/setup.c +++ b/arch/metag/kernel/setup.c | |||
@@ -124,6 +124,7 @@ struct machine_desc *machine_desc __initdata; | |||
124 | u8 cpu_2_hwthread_id[NR_CPUS] __read_mostly = { | 124 | u8 cpu_2_hwthread_id[NR_CPUS] __read_mostly = { |
125 | [0 ... NR_CPUS-1] = BAD_HWTHREAD_ID | 125 | [0 ... NR_CPUS-1] = BAD_HWTHREAD_ID |
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(cpu_2_hwthread_id); | ||
127 | 128 | ||
128 | /* | 129 | /* |
129 | * Map a hardware thread ID to a Linux CPU number | 130 | * Map a hardware thread ID to a Linux CPU number |
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index 4de8fc8e31a5..f443ec9a7cbe 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <asm/cachepart.h> | 28 | #include <asm/cachepart.h> |
29 | #include <asm/core_reg.h> | 29 | #include <asm/core_reg.h> |
30 | #include <asm/cpu.h> | 30 | #include <asm/cpu.h> |
31 | #include <asm/global_lock.h> | ||
32 | #include <asm/metag_mem.h> | ||
31 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
32 | #include <asm/pgtable.h> | 34 | #include <asm/pgtable.h> |
33 | #include <asm/pgalloc.h> | 35 | #include <asm/pgalloc.h> |
@@ -37,6 +39,9 @@ | |||
37 | #include <asm/hwthread.h> | 39 | #include <asm/hwthread.h> |
38 | #include <asm/traps.h> | 40 | #include <asm/traps.h> |
39 | 41 | ||
42 | #define SYSC_DCPART(n) (SYSC_DCPART0 + SYSC_xCPARTn_STRIDE * (n)) | ||
43 | #define SYSC_ICPART(n) (SYSC_ICPART0 + SYSC_xCPARTn_STRIDE * (n)) | ||
44 | |||
40 | DECLARE_PER_CPU(PTBI, pTBI); | 45 | DECLARE_PER_CPU(PTBI, pTBI); |
41 | 46 | ||
42 | void *secondary_data_stack; | 47 | void *secondary_data_stack; |
@@ -99,6 +104,114 @@ int __cpuinit boot_secondary(unsigned int thread, struct task_struct *idle) | |||
99 | return 0; | 104 | return 0; |
100 | } | 105 | } |
101 | 106 | ||
107 | /** | ||
108 | * describe_cachepart_change: describe a change to cache partitions. | ||
109 | * @thread: Hardware thread number. | ||
110 | * @label: Label of cache type, e.g. "dcache" or "icache". | ||
111 | * @sz: Total size of the cache. | ||
112 | * @old: Old cache partition configuration (*CPART* register). | ||
113 | * @new: New cache partition configuration (*CPART* register). | ||
114 | * | ||
115 | * If the cache partition has changed, prints a message to the log describing | ||
116 | * those changes. | ||
117 | */ | ||
118 | static __cpuinit void describe_cachepart_change(unsigned int thread, | ||
119 | const char *label, | ||
120 | unsigned int sz, | ||
121 | unsigned int old, | ||
122 | unsigned int new) | ||
123 | { | ||
124 | unsigned int lor1, land1, gor1, gand1; | ||
125 | unsigned int lor2, land2, gor2, gand2; | ||
126 | unsigned int diff = old ^ new; | ||
127 | |||
128 | if (!diff) | ||
129 | return; | ||
130 | |||
131 | pr_info("Thread %d: %s partition changed:", thread, label); | ||
132 | if (diff & (SYSC_xCPARTL_OR_BITS | SYSC_xCPARTL_AND_BITS)) { | ||
133 | lor1 = (old & SYSC_xCPARTL_OR_BITS) >> SYSC_xCPARTL_OR_S; | ||
134 | lor2 = (new & SYSC_xCPARTL_OR_BITS) >> SYSC_xCPARTL_OR_S; | ||
135 | land1 = (old & SYSC_xCPARTL_AND_BITS) >> SYSC_xCPARTL_AND_S; | ||
136 | land2 = (new & SYSC_xCPARTL_AND_BITS) >> SYSC_xCPARTL_AND_S; | ||
137 | pr_cont(" L:%#x+%#x->%#x+%#x", | ||
138 | (lor1 * sz) >> 4, | ||
139 | ((land1 + 1) * sz) >> 4, | ||
140 | (lor2 * sz) >> 4, | ||
141 | ((land2 + 1) * sz) >> 4); | ||
142 | } | ||
143 | if (diff & (SYSC_xCPARTG_OR_BITS | SYSC_xCPARTG_AND_BITS)) { | ||
144 | gor1 = (old & SYSC_xCPARTG_OR_BITS) >> SYSC_xCPARTG_OR_S; | ||
145 | gor2 = (new & SYSC_xCPARTG_OR_BITS) >> SYSC_xCPARTG_OR_S; | ||
146 | gand1 = (old & SYSC_xCPARTG_AND_BITS) >> SYSC_xCPARTG_AND_S; | ||
147 | gand2 = (new & SYSC_xCPARTG_AND_BITS) >> SYSC_xCPARTG_AND_S; | ||
148 | pr_cont(" G:%#x+%#x->%#x+%#x", | ||
149 | (gor1 * sz) >> 4, | ||
150 | ((gand1 + 1) * sz) >> 4, | ||
151 | (gor2 * sz) >> 4, | ||
152 | ((gand2 + 1) * sz) >> 4); | ||
153 | } | ||
154 | if (diff & SYSC_CWRMODE_BIT) | ||
155 | pr_cont(" %sWR", | ||
156 | (new & SYSC_CWRMODE_BIT) ? "+" : "-"); | ||
157 | if (diff & SYSC_DCPART_GCON_BIT) | ||
158 | pr_cont(" %sGCOn", | ||
159 | (new & SYSC_DCPART_GCON_BIT) ? "+" : "-"); | ||
160 | pr_cont("\n"); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * setup_smp_cache: ensure cache coherency for new SMP thread. | ||
165 | * @thread: New hardware thread number. | ||
166 | * | ||
167 | * Ensures that coherency is enabled and that the threads share the same cache | ||
168 | * partitions. | ||
169 | */ | ||
170 | static __cpuinit void setup_smp_cache(unsigned int thread) | ||
171 | { | ||
172 | unsigned int this_thread, lflags; | ||
173 | unsigned int dcsz, dcpart_this, dcpart_old, dcpart_new; | ||
174 | unsigned int icsz, icpart_old, icpart_new; | ||
175 | |||
176 | /* | ||
177 | * Copy over the current thread's cache partition configuration to the | ||
178 | * new thread so that they share cache partitions. | ||
179 | */ | ||
180 | __global_lock2(lflags); | ||
181 | this_thread = hard_processor_id(); | ||
182 | /* Share dcache partition */ | ||
183 | dcpart_this = metag_in32(SYSC_DCPART(this_thread)); | ||
184 | dcpart_old = metag_in32(SYSC_DCPART(thread)); | ||
185 | dcpart_new = dcpart_this; | ||
186 | #if PAGE_OFFSET < LINGLOBAL_BASE | ||
187 | /* | ||
188 | * For the local data cache to be coherent the threads must also have | ||
189 | * GCOn enabled. | ||
190 | */ | ||
191 | dcpart_new |= SYSC_DCPART_GCON_BIT; | ||
192 | metag_out32(dcpart_new, SYSC_DCPART(this_thread)); | ||
193 | #endif | ||
194 | metag_out32(dcpart_new, SYSC_DCPART(thread)); | ||
195 | /* Share icache partition too */ | ||
196 | icpart_new = metag_in32(SYSC_ICPART(this_thread)); | ||
197 | icpart_old = metag_in32(SYSC_ICPART(thread)); | ||
198 | metag_out32(icpart_new, SYSC_ICPART(thread)); | ||
199 | __global_unlock2(lflags); | ||
200 | |||
201 | /* | ||
202 | * Log if the cache partitions were altered so the user is aware of any | ||
203 | * potential unintentional cache wastage. | ||
204 | */ | ||
205 | dcsz = get_dcache_size(); | ||
206 | icsz = get_dcache_size(); | ||
207 | describe_cachepart_change(this_thread, "dcache", dcsz, | ||
208 | dcpart_this, dcpart_new); | ||
209 | describe_cachepart_change(thread, "dcache", dcsz, | ||
210 | dcpart_old, dcpart_new); | ||
211 | describe_cachepart_change(thread, "icache", icsz, | ||
212 | icpart_old, icpart_new); | ||
213 | } | ||
214 | |||
102 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | 215 | int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) |
103 | { | 216 | { |
104 | unsigned int thread = cpu_2_hwthread_id[cpu]; | 217 | unsigned int thread = cpu_2_hwthread_id[cpu]; |
@@ -108,6 +221,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
108 | 221 | ||
109 | flush_tlb_all(); | 222 | flush_tlb_all(); |
110 | 223 | ||
224 | setup_smp_cache(thread); | ||
225 | |||
111 | /* | 226 | /* |
112 | * Tell the secondary CPU where to find its idle thread's stack. | 227 | * Tell the secondary CPU where to find its idle thread's stack. |
113 | */ | 228 | */ |
diff --git a/arch/metag/mm/Kconfig b/arch/metag/mm/Kconfig index 975f2f4e3ecf..794f26a187f9 100644 --- a/arch/metag/mm/Kconfig +++ b/arch/metag/mm/Kconfig | |||
@@ -98,9 +98,6 @@ config MAX_ACTIVE_REGIONS | |||
98 | default "2" if SPARSEMEM | 98 | default "2" if SPARSEMEM |
99 | default "1" | 99 | default "1" |
100 | 100 | ||
101 | config ARCH_POPULATES_NODE_MAP | ||
102 | def_bool y | ||
103 | |||
104 | config ARCH_SELECT_MEMORY_MODEL | 101 | config ARCH_SELECT_MEMORY_MODEL |
105 | def_bool y | 102 | def_bool y |
106 | 103 | ||
diff --git a/arch/metag/oprofile/Makefile b/arch/metag/oprofile/Makefile new file mode 100644 index 000000000000..c9639d4734d6 --- /dev/null +++ b/arch/metag/oprofile/Makefile | |||
@@ -0,0 +1,17 @@ | |||
1 | obj-$(CONFIG_OPROFILE) += oprofile.o | ||
2 | |||
3 | oprofile-core-y += buffer_sync.o | ||
4 | oprofile-core-y += cpu_buffer.o | ||
5 | oprofile-core-y += event_buffer.o | ||
6 | oprofile-core-y += oprof.o | ||
7 | oprofile-core-y += oprofile_files.o | ||
8 | oprofile-core-y += oprofile_stats.o | ||
9 | oprofile-core-y += oprofilefs.o | ||
10 | oprofile-core-y += timer_int.o | ||
11 | oprofile-core-$(CONFIG_HW_PERF_EVENTS) += oprofile_perf.o | ||
12 | |||
13 | oprofile-y += backtrace.o | ||
14 | oprofile-y += common.o | ||
15 | oprofile-y += $(addprefix ../../../drivers/oprofile/,$(oprofile-core-y)) | ||
16 | |||
17 | ccflags-y += -Werror | ||
diff --git a/arch/metag/oprofile/backtrace.c b/arch/metag/oprofile/backtrace.c new file mode 100644 index 000000000000..7cc3f37cb40e --- /dev/null +++ b/arch/metag/oprofile/backtrace.c | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010-2013 Imagination Technologies Ltd. | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | */ | ||
8 | |||
9 | #include <linux/oprofile.h> | ||
10 | #include <linux/uaccess.h> | ||
11 | #include <asm/processor.h> | ||
12 | #include <asm/stacktrace.h> | ||
13 | |||
14 | #include "backtrace.h" | ||
15 | |||
16 | static void user_backtrace_fp(unsigned long __user *fp, unsigned int depth) | ||
17 | { | ||
18 | while (depth-- && access_ok(VERIFY_READ, fp, 8)) { | ||
19 | unsigned long addr; | ||
20 | unsigned long __user *fpnew; | ||
21 | if (__copy_from_user_inatomic(&addr, fp + 1, sizeof(addr))) | ||
22 | break; | ||
23 | addr -= 4; | ||
24 | |||
25 | oprofile_add_trace(addr); | ||
26 | |||
27 | /* stack grows up, so frame pointers must decrease */ | ||
28 | if (__copy_from_user_inatomic(&fpnew, fp + 0, sizeof(fpnew))) | ||
29 | break; | ||
30 | if (fpnew >= fp) | ||
31 | break; | ||
32 | fp = fpnew; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static int kernel_backtrace_frame(struct stackframe *frame, void *data) | ||
37 | { | ||
38 | unsigned int *depth = data; | ||
39 | |||
40 | oprofile_add_trace(frame->pc); | ||
41 | |||
42 | /* decrement depth and stop if we reach 0 */ | ||
43 | if ((*depth)-- == 0) | ||
44 | return 1; | ||
45 | |||
46 | /* otherwise onto the next frame */ | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | void metag_backtrace(struct pt_regs * const regs, unsigned int depth) | ||
51 | { | ||
52 | if (user_mode(regs)) { | ||
53 | unsigned long *fp = (unsigned long *)regs->ctx.AX[1].U0; | ||
54 | user_backtrace_fp((unsigned long __user __force *)fp, depth); | ||
55 | } else { | ||
56 | struct stackframe frame; | ||
57 | frame.fp = regs->ctx.AX[1].U0; /* A0FrP */ | ||
58 | frame.sp = user_stack_pointer(regs); /* A0StP */ | ||
59 | frame.lr = 0; /* from stack */ | ||
60 | frame.pc = regs->ctx.CurrPC; /* PC */ | ||
61 | walk_stackframe(&frame, &kernel_backtrace_frame, &depth); | ||
62 | } | ||
63 | } | ||
diff --git a/arch/metag/oprofile/backtrace.h b/arch/metag/oprofile/backtrace.h new file mode 100644 index 000000000000..c0fcc4265abb --- /dev/null +++ b/arch/metag/oprofile/backtrace.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef _METAG_OPROFILE_BACKTRACE_H | ||
2 | #define _METAG_OPROFILE_BACKTRACE_H | ||
3 | |||
4 | void metag_backtrace(struct pt_regs * const regs, unsigned int depth); | ||
5 | |||
6 | #endif | ||
diff --git a/arch/metag/oprofile/common.c b/arch/metag/oprofile/common.c new file mode 100644 index 000000000000..ba26152b3c00 --- /dev/null +++ b/arch/metag/oprofile/common.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * arch/metag/oprofile/common.c | ||
3 | * | ||
4 | * Copyright (C) 2013 Imagination Technologies Ltd. | ||
5 | * | ||
6 | * Based on arch/sh/oprofile/common.c: | ||
7 | * | ||
8 | * Copyright (C) 2003 - 2010 Paul Mundt | ||
9 | * | ||
10 | * Based on arch/mips/oprofile/common.c: | ||
11 | * | ||
12 | * Copyright (C) 2004, 2005 Ralf Baechle | ||
13 | * Copyright (C) 2005 MIPS Technologies, Inc. | ||
14 | * | ||
15 | * This file is subject to the terms and conditions of the GNU General Public | ||
16 | * License. See the file "COPYING" in the main directory of this archive | ||
17 | * for more details. | ||
18 | */ | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/oprofile.h> | ||
22 | #include <linux/perf_event.h> | ||
23 | #include <linux/slab.h> | ||
24 | |||
25 | #include "backtrace.h" | ||
26 | |||
27 | #ifdef CONFIG_HW_PERF_EVENTS | ||
28 | /* | ||
29 | * This will need to be reworked when multiple PMUs are supported. | ||
30 | */ | ||
31 | static char *metag_pmu_op_name; | ||
32 | |||
33 | char *op_name_from_perf_id(void) | ||
34 | { | ||
35 | return metag_pmu_op_name; | ||
36 | } | ||
37 | |||
38 | int __init oprofile_arch_init(struct oprofile_operations *ops) | ||
39 | { | ||
40 | ops->backtrace = metag_backtrace; | ||
41 | |||
42 | if (perf_num_counters() == 0) | ||
43 | return -ENODEV; | ||
44 | |||
45 | metag_pmu_op_name = kasprintf(GFP_KERNEL, "metag/%s", | ||
46 | perf_pmu_name()); | ||
47 | if (unlikely(!metag_pmu_op_name)) | ||
48 | return -ENOMEM; | ||
49 | |||
50 | return oprofile_perf_init(ops); | ||
51 | } | ||
52 | |||
53 | void oprofile_arch_exit(void) | ||
54 | { | ||
55 | oprofile_perf_exit(); | ||
56 | kfree(metag_pmu_op_name); | ||
57 | } | ||
58 | #else | ||
59 | int __init oprofile_arch_init(struct oprofile_operations *ops) | ||
60 | { | ||
61 | ops->backtrace = metag_backtrace; | ||
62 | /* fall back to timer interrupt PC sampling */ | ||
63 | return -ENODEV; | ||
64 | } | ||
65 | void oprofile_arch_exit(void) {} | ||
66 | #endif /* CONFIG_HW_PERF_EVENTS */ | ||
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig index a827057c7927..54237af0b07c 100644 --- a/arch/microblaze/Kconfig +++ b/arch/microblaze/Kconfig | |||
@@ -39,9 +39,6 @@ config RWSEM_GENERIC_SPINLOCK | |||
39 | config ZONE_DMA | 39 | config ZONE_DMA |
40 | def_bool y | 40 | def_bool y |
41 | 41 | ||
42 | config ARCH_POPULATES_NODE_MAP | ||
43 | def_bool y | ||
44 | |||
45 | config RWSEM_XCHGADD_ALGORITHM | 42 | config RWSEM_XCHGADD_ALGORITHM |
46 | bool | 43 | bool |
47 | 44 | ||