Commit 87c1f0f8c9442c86cbb343b9324bef8312029d7d

Authored by Linus Torvalds

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

Showing 23 changed files Side-by-side Diff

... ... @@ -25,6 +25,7 @@
25 25 select HAVE_MEMBLOCK
26 26 select HAVE_MEMBLOCK_NODE_MAP
27 27 select HAVE_MOD_ARCH_SPECIFIC
  28 + select HAVE_OPROFILE
28 29 select HAVE_PERF_EVENTS
29 30 select HAVE_SYSCALL_TRACEPOINTS
30 31 select IRQ_DOMAIN
... ... @@ -208,6 +209,9 @@
208 209  
209 210 When disabled, Performance Counters information will be collected
210 211 based on Timer Interrupt.
  212 +
  213 +config HW_PERF_EVENTS
  214 + def_bool METAG_PERFCOUNTER_IRQS && PERF_EVENTS
211 215  
212 216 config METAG_DA
213 217 bool "DA support"
... ... @@ -49,6 +49,8 @@
49 49 libs-y += arch/metag/lib/
50 50 libs-y += arch/metag/tbx/
51 51  
  52 +drivers-$(CONFIG_OPROFILE) += arch/metag/oprofile/
  53 +
52 54 boot := arch/metag/boot
53 55  
54 56 boot_targets += uImage
arch/metag/boot/dts/Makefile
... ... @@ -4,14 +4,18 @@
4 4 builtindtb-y := skeleton
5 5  
6 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 8 endif
9   -obj-$(CONFIG_METAG_BUILTIN_DTB) += $(patsubst "%",%,$(builtindtb-y)).dtb.o
10 9  
  10 +dtb-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb
  11 +obj-$(CONFIG_METAG_BUILTIN_DTB) += $(builtindtb-y).dtb.o
  12 +
11 13 targets += dtbs
12 14 targets += $(dtb-y)
13 15  
  16 +.SECONDARY: $(obj)/$(builtindtb-y).dtb.S
  17 +
14 18 dtbs: $(addprefix $(obj)/, $(dtb-y))
15 19  
16   -clean-files += *.dtb
  20 +clean-files += *.dtb *.dtb.S
arch/metag/configs/meta1_defconfig
1 1 # CONFIG_LOCALVERSION_AUTO is not set
2 2 # CONFIG_SWAP is not set
3   -CONFIG_LOG_BUF_SHIFT=13
4 3 CONFIG_SYSFS_DEPRECATED=y
5 4 CONFIG_SYSFS_DEPRECATED_V2=y
6 5 CONFIG_KALLSYMS_ALL=y
arch/metag/configs/meta2_defconfig
1 1 # CONFIG_LOCALVERSION_AUTO is not set
2 2 # CONFIG_SWAP is not set
3 3 CONFIG_SYSVIPC=y
4   -CONFIG_LOG_BUF_SHIFT=13
5 4 CONFIG_SYSFS_DEPRECATED=y
6 5 CONFIG_SYSFS_DEPRECATED_V2=y
7 6 CONFIG_KALLSYMS_ALL=y
arch/metag/configs/meta2_smp_defconfig
1 1 # CONFIG_LOCALVERSION_AUTO is not set
2 2 # CONFIG_SWAP is not set
3 3 CONFIG_SYSVIPC=y
4   -CONFIG_LOG_BUF_SHIFT=13
5 4 CONFIG_SYSFS_DEPRECATED=y
6 5 CONFIG_SYSFS_DEPRECATED_V2=y
7 6 CONFIG_KALLSYMS_ALL=y
arch/metag/include/asm/metag_mem.h
... ... @@ -700,6 +700,9 @@
700 700 #define SYSC_xCPARTG_AND_S 8
701 701 #define SYSC_xCPARTL_OR_BITS 0x000F0000 /* Ors into top 4 bits */
702 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 706 #define SYSC_xCPARTG_OR_BITS 0x0F000000 /* Ors into top 4 bits */
704 707 #define SYSC_xCPARTG_OR_S 24
705 708 #define SYSC_CWRMODE_BIT 0x80000000 /* Write cache mode bit */
arch/metag/include/uapi/asm/Kbuild
... ... @@ -2,6 +2,7 @@
2 2 include include/uapi/asm-generic/Kbuild.asm
3 3  
4 4 header-y += byteorder.h
  5 +header-y += ech.h
5 6 header-y += ptrace.h
6 7 header-y += resource.h
7 8 header-y += sigcontext.h
arch/metag/include/uapi/asm/ech.h
  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 */
arch/metag/kernel/cachepart.c
... ... @@ -24,15 +24,21 @@
24 24 unsigned int get_dcache_size(void)
25 25 {
26 26 unsigned int config2 = metag_in32(METAC_CORE_CONFIG2);
27   - return 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS)
28   - >> METAC_CORECFG2_DCSZ_S);
  27 + unsigned int sz = 0x1000 << ((config2 & METAC_CORECFG2_DCSZ_BITS)
  28 + >> METAC_CORECFG2_DCSZ_S);
  29 + if (config2 & METAC_CORECFG2_DCSMALL_BIT)
  30 + sz >>= 6;
  31 + return sz;
29 32 }
30 33  
31 34 unsigned int get_icache_size(void)
32 35 {
33 36 unsigned int config2 = metag_in32(METAC_CORE_CONFIG2);
34   - return 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS)
35   - >> METAC_CORE_C2ICSZ_S);
  37 + unsigned int sz = 0x1000 << ((config2 & METAC_CORE_C2ICSZ_BITS)
  38 + >> METAC_CORE_C2ICSZ_S);
  39 + if (config2 & METAC_CORECFG2_ICSMALL_BIT)
  40 + sz >>= 6;
  41 + return sz;
36 42 }
37 43  
38 44 unsigned int get_global_dcache_size(void)
... ... @@ -61,7 +67,7 @@
61 67 return 0;
62 68 #if PAGE_OFFSET >= LINGLOBAL_BASE
63 69 /* Checking for global cache */
64   - cache_size = (cache == DCACHE ? get_global_dache_size() :
  70 + cache_size = (cache == DCACHE ? get_global_dcache_size() :
65 71 get_global_icache_size());
66 72 offset = 8;
67 73 #else
arch/metag/kernel/da.c
... ... @@ -5,12 +5,14 @@
5 5 */
6 6  
7 7  
  8 +#include <linux/export.h>
8 9 #include <linux/io.h>
9 10 #include <linux/kernel.h>
10 11 #include <asm/da.h>
11 12 #include <asm/metag_mem.h>
12 13  
13 14 bool _metag_da_present;
  15 +EXPORT_SYMBOL_GPL(_metag_da_present);
14 16  
15 17 int __init metag_da_probe(void)
16 18 {
arch/metag/kernel/head.S
1 1 ! Copyright 2005,2006,2007,2009 Imagination Technologies
2 2  
3 3 #include <linux/init.h>
  4 +#include <asm/metag_mem.h>
4 5 #include <generated/asm-offsets.h>
5 6 #undef __exit
6 7  
... ... @@ -48,6 +49,13 @@
48 49 .global _secondary_startup
49 50 .type _secondary_startup,function
50 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 59 MOVT A0StP,#HI(_secondary_data_stack)
52 60 ADD A0StP,A0StP,#LO(_secondary_data_stack)
53 61 GETD A0StP,[A0StP]
arch/metag/kernel/perf/perf_event.c
... ... @@ -22,9 +22,9 @@
22 22 #include <linux/slab.h>
23 23  
24 24 #include <asm/core_reg.h>
25   -#include <asm/hwthread.h>
26 25 #include <asm/io.h>
27 26 #include <asm/irq.h>
  27 +#include <asm/processor.h>
28 28  
29 29 #include "perf_event.h"
30 30  
31 31  
... ... @@ -40,10 +40,10 @@
40 40 /* PMU admin */
41 41 const char *perf_pmu_name(void)
42 42 {
43   - if (metag_pmu)
44   - return metag_pmu->pmu.name;
  43 + if (!metag_pmu)
  44 + return NULL;
45 45  
46   - return NULL;
  46 + return metag_pmu->name;
47 47 }
48 48 EXPORT_SYMBOL_GPL(perf_pmu_name);
49 49  
... ... @@ -171,6 +171,7 @@
171 171 switch (event->attr.type) {
172 172 case PERF_TYPE_HARDWARE:
173 173 case PERF_TYPE_HW_CACHE:
  174 + case PERF_TYPE_RAW:
174 175 err = _hw_perf_event_init(event);
175 176 break;
176 177  
177 178  
... ... @@ -211,9 +212,10 @@
211 212 /*
212 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 217 local64_add(delta, &event->count);
  218 + local64_sub(delta, &hwc->period_left);
217 219 }
218 220  
219 221 int metag_pmu_event_set_period(struct perf_event *event,
... ... @@ -223,6 +225,10 @@
223 225 s64 period = hwc->sample_period;
224 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 232 if (unlikely(left <= -period)) {
227 233 left = period;
228 234 local64_set(&hwc->period_left, left);
... ... @@ -240,8 +246,10 @@
240 246 if (left > (s64)metag_pmu->max_period)
241 247 left = metag_pmu->max_period;
242 248  
243   - if (metag_pmu->write)
244   - metag_pmu->write(idx, (u64)(-left) & MAX_PERIOD);
  249 + if (metag_pmu->write) {
  250 + local64_set(&hwc->prev_count, -(s32)left);
  251 + metag_pmu->write(idx, -left & MAX_PERIOD);
  252 + }
245 253  
246 254 perf_event_update_userpage(event);
247 255  
... ... @@ -549,6 +557,10 @@
549 557 if (err)
550 558 return err;
551 559 break;
  560 +
  561 + case PERF_TYPE_RAW:
  562 + mapping = attr->config;
  563 + break;
552 564 }
553 565  
554 566 /* Return early if the event is unsupported */
555 567  
... ... @@ -610,15 +622,13 @@
610 622 WARN_ONCE((config != 0x100),
611 623 "invalid configuration (%d) for counter (%d)\n",
612 624 config, idx);
613   -
614   - /* Reset the cycle count */
615   - __core_reg_set(TXTACTCYC, 0);
  625 + local64_set(&event->prev_count, __core_reg_get(TXTACTCYC));
616 626 goto unlock;
617 627 }
618 628  
619 629 /* Check for a core internal or performance channel event. */
620 630 if (tmp) {
621   - void *perf_addr = (void *)PERF_COUNT(idx);
  631 + void *perf_addr;
622 632  
623 633 /*
624 634 * Anything other than a cycle count will write the low-
625 635  
... ... @@ -632,9 +642,14 @@
632 642 case 0xf0:
633 643 perf_addr = (void *)PERF_CHAN(idx);
634 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 655 * Now we use the high nibble as the performance event to
641 656  
... ... @@ -643,13 +658,21 @@
643 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 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 676 metag_out32(tmp, PERF_COUNT(idx));
654 677 unlock:
655 678 raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
656 679  
... ... @@ -693,9 +716,8 @@
693 716 {
694 717 u32 tmp = 0;
695 718  
696   - /* The act of reading the cycle counter also clears it */
697 719 if (METAG_INST_COUNTER == idx) {
698   - __core_reg_swap(TXTACTCYC, tmp);
  720 + tmp = __core_reg_get(TXTACTCYC);
699 721 goto out;
700 722 }
701 723  
702 724  
703 725  
... ... @@ -764,10 +786,16 @@
764 786  
765 787 /*
766 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 796 metag_out32(counter, PERF_COUNT(idx));
  797 + __global_unlock2(flags);
  798 + }
771 799  
772 800 return IRQ_HANDLED;
773 801 }
... ... @@ -830,7 +858,7 @@
830 858 metag_pmu->max_period = 0;
831 859 }
832 860  
833   - metag_pmu->name = "Meta 2";
  861 + metag_pmu->name = "meta2";
834 862 metag_pmu->version = version;
835 863 metag_pmu->pmu = pmu;
836 864 }
arch/metag/kernel/ptrace.c
... ... @@ -288,10 +288,36 @@
288 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 316 enum metag_regset {
292 317 REGSET_GENERAL,
293 318 REGSET_CBUF,
294 319 REGSET_READPIPE,
  320 + REGSET_TLS,
295 321 };
296 322  
297 323 static const struct user_regset metag_regsets[] = {
... ... @@ -318,6 +344,14 @@
318 344 .align = sizeof(long long),
319 345 .get = metag_rp_state_get,
320 346 .set = metag_rp_state_set,
  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,
321 355 },
322 356 };
323 357  
arch/metag/kernel/setup.c
... ... @@ -124,6 +124,7 @@
124 124 u8 cpu_2_hwthread_id[NR_CPUS] __read_mostly = {
125 125 [0 ... NR_CPUS-1] = BAD_HWTHREAD_ID
126 126 };
  127 +EXPORT_SYMBOL_GPL(cpu_2_hwthread_id);
127 128  
128 129 /*
129 130 * Map a hardware thread ID to a Linux CPU number
arch/metag/kernel/smp.c
... ... @@ -28,6 +28,8 @@
28 28 #include <asm/cachepart.h>
29 29 #include <asm/core_reg.h>
30 30 #include <asm/cpu.h>
  31 +#include <asm/global_lock.h>
  32 +#include <asm/metag_mem.h>
31 33 #include <asm/mmu_context.h>
32 34 #include <asm/pgtable.h>
33 35 #include <asm/pgalloc.h>
... ... @@ -37,6 +39,9 @@
37 39 #include <asm/hwthread.h>
38 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 45 DECLARE_PER_CPU(PTBI, pTBI);
41 46  
42 47 void *secondary_data_stack;
... ... @@ -99,6 +104,114 @@
99 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 215 int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle)
103 216 {
104 217 unsigned int thread = cpu_2_hwthread_id[cpu];
... ... @@ -107,6 +220,8 @@
107 220 load_pgd(swapper_pg_dir, thread);
108 221  
109 222 flush_tlb_all();
  223 +
  224 + setup_smp_cache(thread);
110 225  
111 226 /*
112 227 * Tell the secondary CPU where to find its idle thread's stack.
arch/metag/mm/Kconfig
... ... @@ -98,9 +98,6 @@
98 98 default "2" if SPARSEMEM
99 99 default "1"
100 100  
101   -config ARCH_POPULATES_NODE_MAP
102   - def_bool y
103   -
104 101 config ARCH_SELECT_MEMORY_MODEL
105 102 def_bool y
106 103  
arch/metag/oprofile/Makefile
  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
arch/metag/oprofile/backtrace.c
  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 +}
arch/metag/oprofile/backtrace.h
  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
arch/metag/oprofile/common.c
  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 */
arch/microblaze/Kconfig
... ... @@ -39,9 +39,6 @@
39 39 config ZONE_DMA
40 40 def_bool y
41 41  
42   -config ARCH_POPULATES_NODE_MAP
43   - def_bool y
44   -
45 42 config RWSEM_XCHGADD_ALGORITHM
46 43 bool
47 44  
include/uapi/linux/elf.h
... ... @@ -397,6 +397,7 @@
397 397 #define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
398 398 #define NT_METAG_CBUF 0x500 /* Metag catch buffer registers */
399 399 #define NT_METAG_RPIPE 0x501 /* Metag read pipeline state */
  400 +#define NT_METAG_TLS 0x502 /* Metag TLS pointer */
400 401  
401 402  
402 403 /* Note header in a PT_NOTE section */