aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/Kconfig20
-rw-r--r--arch/arc/configs/nps_defconfig1
-rw-r--r--arch/arc/configs/vdk_hs38_defconfig1
-rw-r--r--arch/arc/configs/vdk_hs38_smp_defconfig2
-rw-r--r--arch/arc/include/asm/Kbuild4
-rw-r--r--arch/arc/include/asm/arcregs.h20
-rw-r--r--arch/arc/include/asm/bitops.h6
-rw-r--r--arch/arc/include/asm/cache.h11
-rw-r--r--arch/arc/include/asm/entry-arcv2.h54
-rw-r--r--arch/arc/include/asm/perf_event.h3
-rw-r--r--arch/arc/include/asm/uaccess.h8
-rw-r--r--arch/arc/kernel/entry-arcv2.S4
-rw-r--r--arch/arc/kernel/head.S16
-rw-r--r--arch/arc/kernel/intc-arcv2.c2
-rw-r--r--arch/arc/kernel/perf_event.c241
-rw-r--r--arch/arc/kernel/setup.c144
-rw-r--r--arch/arc/kernel/troubleshoot.c30
-rw-r--r--arch/arc/lib/memcpy-archs.S14
-rw-r--r--arch/arc/lib/memset-archs.S40
-rw-r--r--arch/arc/mm/fault.c13
-rw-r--r--arch/arc/mm/init.c3
-rw-r--r--arch/arc/plat-hsdk/Kconfig1
22 files changed, 463 insertions, 175 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 376366a7db81..d750b302d5ab 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -191,7 +191,6 @@ config NR_CPUS
191 191
192config ARC_SMP_HALT_ON_RESET 192config ARC_SMP_HALT_ON_RESET
193 bool "Enable Halt-on-reset boot mode" 193 bool "Enable Halt-on-reset boot mode"
194 default y if ARC_UBOOT_SUPPORT
195 help 194 help
196 In SMP configuration cores can be configured as Halt-on-reset 195 In SMP configuration cores can be configured as Halt-on-reset
197 or they could all start at same time. For Halt-on-reset, non 196 or they could all start at same time. For Halt-on-reset, non
@@ -407,6 +406,14 @@ config ARC_HAS_ACCL_REGS
407 (also referred to as r58:r59). These can also be used by gcc as GPR so 406 (also referred to as r58:r59). These can also be used by gcc as GPR so
408 kernel needs to save/restore per process 407 kernel needs to save/restore per process
409 408
409config ARC_IRQ_NO_AUTOSAVE
410 bool "Disable hardware autosave regfile on interrupts"
411 default n
412 help
413 On HS cores, taken interrupt auto saves the regfile on stack.
414 This is programmable and can be optionally disabled in which case
415 software INTERRUPT_PROLOGUE/EPILGUE do the needed work
416
410endif # ISA_ARCV2 417endif # ISA_ARCV2
411 418
412endmenu # "ARC CPU Configuration" 419endmenu # "ARC CPU Configuration"
@@ -515,17 +522,6 @@ config ARC_DBG_TLB_PARANOIA
515 522
516endif 523endif
517 524
518config ARC_UBOOT_SUPPORT
519 bool "Support uboot arg Handling"
520 help
521 ARC Linux by default checks for uboot provided args as pointers to
522 external cmdline or DTB. This however breaks in absence of uboot,
523 when booting from Metaware debugger directly, as the registers are
524 not zeroed out on reset by mdb and/or ARCv2 based cores. The bogus
525 registers look like uboot args to kernel which then chokes.
526 So only enable the uboot arg checking/processing if users are sure
527 of uboot being in play.
528
529config ARC_BUILTIN_DTB_NAME 525config ARC_BUILTIN_DTB_NAME
530 string "Built in DTB" 526 string "Built in DTB"
531 help 527 help
diff --git a/arch/arc/configs/nps_defconfig b/arch/arc/configs/nps_defconfig
index 6e84060e7c90..621f59407d76 100644
--- a/arch/arc/configs/nps_defconfig
+++ b/arch/arc/configs/nps_defconfig
@@ -31,7 +31,6 @@ CONFIG_ARC_CACHE_LINE_SHIFT=5
31# CONFIG_ARC_HAS_LLSC is not set 31# CONFIG_ARC_HAS_LLSC is not set
32CONFIG_ARC_KVADDR_SIZE=402 32CONFIG_ARC_KVADDR_SIZE=402
33CONFIG_ARC_EMUL_UNALIGNED=y 33CONFIG_ARC_EMUL_UNALIGNED=y
34CONFIG_ARC_UBOOT_SUPPORT=y
35CONFIG_PREEMPT=y 34CONFIG_PREEMPT=y
36CONFIG_NET=y 35CONFIG_NET=y
37CONFIG_UNIX=y 36CONFIG_UNIX=y
diff --git a/arch/arc/configs/vdk_hs38_defconfig b/arch/arc/configs/vdk_hs38_defconfig
index 1e59a2e9c602..e447ace6fa1c 100644
--- a/arch/arc/configs/vdk_hs38_defconfig
+++ b/arch/arc/configs/vdk_hs38_defconfig
@@ -13,7 +13,6 @@ CONFIG_PARTITION_ADVANCED=y
13CONFIG_ARC_PLAT_AXS10X=y 13CONFIG_ARC_PLAT_AXS10X=y
14CONFIG_AXS103=y 14CONFIG_AXS103=y
15CONFIG_ISA_ARCV2=y 15CONFIG_ISA_ARCV2=y
16CONFIG_ARC_UBOOT_SUPPORT=y
17CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38" 16CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38"
18CONFIG_PREEMPT=y 17CONFIG_PREEMPT=y
19CONFIG_NET=y 18CONFIG_NET=y
diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig
index b5c3f6c54b03..c82cdb10aaf4 100644
--- a/arch/arc/configs/vdk_hs38_smp_defconfig
+++ b/arch/arc/configs/vdk_hs38_smp_defconfig
@@ -15,8 +15,6 @@ CONFIG_AXS103=y
15CONFIG_ISA_ARCV2=y 15CONFIG_ISA_ARCV2=y
16CONFIG_SMP=y 16CONFIG_SMP=y
17# CONFIG_ARC_TIMERS_64BIT is not set 17# CONFIG_ARC_TIMERS_64BIT is not set
18# CONFIG_ARC_SMP_HALT_ON_RESET is not set
19CONFIG_ARC_UBOOT_SUPPORT=y
20CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp" 18CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
21CONFIG_PREEMPT=y 19CONFIG_PREEMPT=y
22CONFIG_NET=y 20CONFIG_NET=y
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index feed50ce89fa..caa270261521 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -3,23 +3,19 @@ generic-y += bugs.h
3generic-y += compat.h 3generic-y += compat.h
4generic-y += device.h 4generic-y += device.h
5generic-y += div64.h 5generic-y += div64.h
6generic-y += dma-mapping.h
7generic-y += emergency-restart.h 6generic-y += emergency-restart.h
8generic-y += extable.h 7generic-y += extable.h
9generic-y += fb.h
10generic-y += ftrace.h 8generic-y += ftrace.h
11generic-y += hardirq.h 9generic-y += hardirq.h
12generic-y += hw_irq.h 10generic-y += hw_irq.h
13generic-y += irq_regs.h 11generic-y += irq_regs.h
14generic-y += irq_work.h 12generic-y += irq_work.h
15generic-y += kmap_types.h
16generic-y += local.h 13generic-y += local.h
17generic-y += local64.h 14generic-y += local64.h
18generic-y += mcs_spinlock.h 15generic-y += mcs_spinlock.h
19generic-y += mm-arch-hooks.h 16generic-y += mm-arch-hooks.h
20generic-y += msi.h 17generic-y += msi.h
21generic-y += parport.h 18generic-y += parport.h
22generic-y += pci.h
23generic-y += percpu.h 19generic-y += percpu.h
24generic-y += preempt.h 20generic-y += preempt.h
25generic-y += topology.h 21generic-y += topology.h
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 49bfbd879caa..a27eafdc8260 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -151,6 +151,14 @@ struct bcr_isa_arcv2 {
151#endif 151#endif
152}; 152};
153 153
154struct bcr_uarch_build_arcv2 {
155#ifdef CONFIG_CPU_BIG_ENDIAN
156 unsigned int pad:8, prod:8, maj:8, min:8;
157#else
158 unsigned int min:8, maj:8, prod:8, pad:8;
159#endif
160};
161
154struct bcr_mpy { 162struct bcr_mpy {
155#ifdef CONFIG_CPU_BIG_ENDIAN 163#ifdef CONFIG_CPU_BIG_ENDIAN
156 unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8; 164 unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
@@ -216,6 +224,14 @@ struct bcr_fp_arcv2 {
216#endif 224#endif
217}; 225};
218 226
227struct bcr_actionpoint {
228#ifdef CONFIG_CPU_BIG_ENDIAN
229 unsigned int pad:21, min:1, num:2, ver:8;
230#else
231 unsigned int ver:8, num:2, min:1, pad:21;
232#endif
233};
234
219#include <soc/arc/timers.h> 235#include <soc/arc/timers.h>
220 236
221struct bcr_bpu_arcompact { 237struct bcr_bpu_arcompact {
@@ -283,7 +299,7 @@ struct cpuinfo_arc_cache {
283}; 299};
284 300
285struct cpuinfo_arc_bpu { 301struct cpuinfo_arc_bpu {
286 unsigned int ver, full, num_cache, num_pred; 302 unsigned int ver, full, num_cache, num_pred, ret_stk;
287}; 303};
288 304
289struct cpuinfo_arc_ccm { 305struct cpuinfo_arc_ccm {
@@ -302,7 +318,7 @@ struct cpuinfo_arc {
302 struct { 318 struct {
303 unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2, 319 unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
304 fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4, 320 fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4,
305 debug:1, ap:1, smart:1, rtt:1, pad3:4, 321 ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1,
306 timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4; 322 timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
307 } extn; 323 } extn;
308 struct bcr_mpy extn_mpy; 324 struct bcr_mpy extn_mpy;
diff --git a/arch/arc/include/asm/bitops.h b/arch/arc/include/asm/bitops.h
index ee9246184033..202b74c339f0 100644
--- a/arch/arc/include/asm/bitops.h
+++ b/arch/arc/include/asm/bitops.h
@@ -340,7 +340,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
340/* 340/*
341 * __ffs: Similar to ffs, but zero based (0-31) 341 * __ffs: Similar to ffs, but zero based (0-31)
342 */ 342 */
343static inline __attribute__ ((const)) int __ffs(unsigned long word) 343static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
344{ 344{
345 if (!word) 345 if (!word)
346 return word; 346 return word;
@@ -400,9 +400,9 @@ static inline __attribute__ ((const)) int ffs(unsigned long x)
400/* 400/*
401 * __ffs: Similar to ffs, but zero based (0-31) 401 * __ffs: Similar to ffs, but zero based (0-31)
402 */ 402 */
403static inline __attribute__ ((const)) int __ffs(unsigned long x) 403static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
404{ 404{
405 int n; 405 unsigned long n;
406 406
407 asm volatile( 407 asm volatile(
408 " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */ 408 " ffs.f %0, %1 \n" /* 0:31; 31(Z) if src 0 */
diff --git a/arch/arc/include/asm/cache.h b/arch/arc/include/asm/cache.h
index f393b663413e..2ad77fb43639 100644
--- a/arch/arc/include/asm/cache.h
+++ b/arch/arc/include/asm/cache.h
@@ -52,6 +52,17 @@
52#define cache_line_size() SMP_CACHE_BYTES 52#define cache_line_size() SMP_CACHE_BYTES
53#define ARCH_DMA_MINALIGN SMP_CACHE_BYTES 53#define ARCH_DMA_MINALIGN SMP_CACHE_BYTES
54 54
55/*
56 * Make sure slab-allocated buffers are 64-bit aligned when atomic64_t uses
57 * ARCv2 64-bit atomics (LLOCKD/SCONDD). This guarantess runtime 64-bit
58 * alignment for any atomic64_t embedded in buffer.
59 * Default ARCH_SLAB_MINALIGN is __alignof__(long long) which has a relaxed
60 * value of 4 (and not 8) in ARC ABI.
61 */
62#if defined(CONFIG_ARC_HAS_LL64) && defined(CONFIG_ARC_HAS_LLSC)
63#define ARCH_SLAB_MINALIGN 8
64#endif
65
55extern void arc_cache_init(void); 66extern void arc_cache_init(void);
56extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); 67extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
57extern void read_decode_cache_bcr(void); 68extern void read_decode_cache_bcr(void);
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index 309f4e6721b3..225e7df2d8ed 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -17,6 +17,33 @@
17 ; 17 ;
18 ; Now manually save: r12, sp, fp, gp, r25 18 ; Now manually save: r12, sp, fp, gp, r25
19 19
20#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
21.ifnc \called_from, exception
22 st.as r9, [sp, -10] ; save r9 in it's final stack slot
23 sub sp, sp, 12 ; skip JLI, LDI, EI
24
25 PUSH lp_count
26 PUSHAX lp_start
27 PUSHAX lp_end
28 PUSH blink
29
30 PUSH r11
31 PUSH r10
32
33 sub sp, sp, 4 ; skip r9
34
35 PUSH r8
36 PUSH r7
37 PUSH r6
38 PUSH r5
39 PUSH r4
40 PUSH r3
41 PUSH r2
42 PUSH r1
43 PUSH r0
44.endif
45#endif
46
20#ifdef CONFIG_ARC_HAS_ACCL_REGS 47#ifdef CONFIG_ARC_HAS_ACCL_REGS
21 PUSH r59 48 PUSH r59
22 PUSH r58 49 PUSH r58
@@ -86,6 +113,33 @@
86 POP r59 113 POP r59
87#endif 114#endif
88 115
116#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
117.ifnc \called_from, exception
118 POP r0
119 POP r1
120 POP r2
121 POP r3
122 POP r4
123 POP r5
124 POP r6
125 POP r7
126 POP r8
127 POP r9
128 POP r10
129 POP r11
130
131 POP blink
132 POPAX lp_end
133 POPAX lp_start
134
135 POP r9
136 mov lp_count, r9
137
138 add sp, sp, 12 ; skip JLI, LDI, EI
139 ld.as r9, [sp, -10] ; reload r9 which got clobbered
140.endif
141#endif
142
89.endm 143.endm
90 144
91/*------------------------------------------------------------------------*/ 145/*------------------------------------------------------------------------*/
diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index 9185541035cc..6958545390f0 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
103 103
104 /* counts condition */ 104 /* counts condition */
105 [PERF_COUNT_HW_INSTRUCTIONS] = "iall", 105 [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
106 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */ 106 /* All jump instructions that are taken */
107 [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
107 [PERF_COUNT_ARC_BPOK] = "bpok", /* NP-NT, PT-T, PNT-NT */ 108 [PERF_COUNT_ARC_BPOK] = "bpok", /* NP-NT, PT-T, PNT-NT */
108#ifdef CONFIG_ISA_ARCV2 109#ifdef CONFIG_ISA_ARCV2
109 [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp", 110 [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h
index c9173c02081c..eabc3efa6c6d 100644
--- a/arch/arc/include/asm/uaccess.h
+++ b/arch/arc/include/asm/uaccess.h
@@ -207,7 +207,7 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n)
207 */ 207 */
208 "=&r" (tmp), "+r" (to), "+r" (from) 208 "=&r" (tmp), "+r" (to), "+r" (from)
209 : 209 :
210 : "lp_count", "lp_start", "lp_end", "memory"); 210 : "lp_count", "memory");
211 211
212 return n; 212 return n;
213 } 213 }
@@ -433,7 +433,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
433 */ 433 */
434 "=&r" (tmp), "+r" (to), "+r" (from) 434 "=&r" (tmp), "+r" (to), "+r" (from)
435 : 435 :
436 : "lp_count", "lp_start", "lp_end", "memory"); 436 : "lp_count", "memory");
437 437
438 return n; 438 return n;
439 } 439 }
@@ -653,7 +653,7 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
653 " .previous \n" 653 " .previous \n"
654 : "+r"(d_char), "+r"(res) 654 : "+r"(d_char), "+r"(res)
655 : "i"(0) 655 : "i"(0)
656 : "lp_count", "lp_start", "lp_end", "memory"); 656 : "lp_count", "memory");
657 657
658 return res; 658 return res;
659} 659}
@@ -686,7 +686,7 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
686 " .previous \n" 686 " .previous \n"
687 : "+r"(res), "+r"(dst), "+r"(src), "=r"(val) 687 : "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
688 : "g"(-EFAULT), "r"(count) 688 : "g"(-EFAULT), "r"(count)
689 : "lp_count", "lp_start", "lp_end", "memory"); 689 : "lp_count", "memory");
690 690
691 return res; 691 return res;
692} 692}
diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S
index cc558a25b8fa..562089d62d9d 100644
--- a/arch/arc/kernel/entry-arcv2.S
+++ b/arch/arc/kernel/entry-arcv2.S
@@ -209,7 +209,9 @@ restore_regs:
209;####### Return from Intr ####### 209;####### Return from Intr #######
210 210
211debug_marker_l1: 211debug_marker_l1:
212 bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot 212 ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
213 btst r0, STATUS_DE_BIT ; Z flag set if bit clear
214 bnz .Lintr_ret_to_delay_slot ; branch if STATUS_DE_BIT set
213 215
214.Lisr_ret_fast_path: 216.Lisr_ret_fast_path:
215 ; Handle special case #1: (Entry via Exception, Return via IRQ) 217 ; Handle special case #1: (Entry via Exception, Return via IRQ)
diff --git a/arch/arc/kernel/head.S b/arch/arc/kernel/head.S
index 8b90d25a15cc..30e090625916 100644
--- a/arch/arc/kernel/head.S
+++ b/arch/arc/kernel/head.S
@@ -17,6 +17,7 @@
17#include <asm/entry.h> 17#include <asm/entry.h>
18#include <asm/arcregs.h> 18#include <asm/arcregs.h>
19#include <asm/cache.h> 19#include <asm/cache.h>
20#include <asm/irqflags.h>
20 21
21.macro CPU_EARLY_SETUP 22.macro CPU_EARLY_SETUP
22 23
@@ -47,6 +48,15 @@
47 sr r5, [ARC_REG_DC_CTRL] 48 sr r5, [ARC_REG_DC_CTRL]
48 49
491: 501:
51
52#ifdef CONFIG_ISA_ARCV2
53 ; Unaligned access is disabled at reset, so re-enable early as
54 ; gcc 7.3.1 (ARC GNU 2018.03) onwards generates unaligned access
55 ; by default
56 lr r5, [status32]
57 bset r5, r5, STATUS_AD_BIT
58 kflag r5
59#endif
50.endm 60.endm
51 61
52 .section .init.text, "ax",@progbits 62 .section .init.text, "ax",@progbits
@@ -90,15 +100,13 @@ ENTRY(stext)
90 st.ab 0, [r5, 4] 100 st.ab 0, [r5, 4]
911: 1011:
92 102
93#ifdef CONFIG_ARC_UBOOT_SUPPORT
94 ; Uboot - kernel ABI 103 ; Uboot - kernel ABI
95 ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2 104 ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
96 ; r1 = magic number (board identity, unused as of now 105 ; r1 = magic number (always zero as of now)
97 ; r2 = pointer to uboot provided cmdline or external DTB in mem 106 ; r2 = pointer to uboot provided cmdline or external DTB in mem
98 ; These are handled later in setup_arch() 107 ; These are handled later in handle_uboot_args()
99 st r0, [@uboot_tag] 108 st r0, [@uboot_tag]
100 st r2, [@uboot_arg] 109 st r2, [@uboot_arg]
101#endif
102 110
103 ; setup "current" tsk and optionally cache it in dedicated r25 111 ; setup "current" tsk and optionally cache it in dedicated r25
104 mov r9, @init_task 112 mov r9, @init_task
diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c
index 067ea362fb3e..cf18b3e5a934 100644
--- a/arch/arc/kernel/intc-arcv2.c
+++ b/arch/arc/kernel/intc-arcv2.c
@@ -49,11 +49,13 @@ void arc_init_IRQ(void)
49 49
50 *(unsigned int *)&ictrl = 0; 50 *(unsigned int *)&ictrl = 0;
51 51
52#ifndef CONFIG_ARC_IRQ_NO_AUTOSAVE
52 ictrl.save_nr_gpr_pairs = 6; /* r0 to r11 (r12 saved manually) */ 53 ictrl.save_nr_gpr_pairs = 6; /* r0 to r11 (r12 saved manually) */
53 ictrl.save_blink = 1; 54 ictrl.save_blink = 1;
54 ictrl.save_lp_regs = 1; /* LP_COUNT, LP_START, LP_END */ 55 ictrl.save_lp_regs = 1; /* LP_COUNT, LP_START, LP_END */
55 ictrl.save_u_to_u = 0; /* user ctxt saved on kernel stack */ 56 ictrl.save_u_to_u = 0; /* user ctxt saved on kernel stack */
56 ictrl.save_idx_regs = 1; /* JLI, LDI, EI */ 57 ictrl.save_idx_regs = 1; /* JLI, LDI, EI */
58#endif
57 59
58 WRITE_AUX(AUX_IRQ_CTRL, ictrl); 60 WRITE_AUX(AUX_IRQ_CTRL, ictrl);
59 61
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 8aec462d90fb..861a8aea51f9 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -1,15 +1,10 @@
1/* 1// SPDX-License-Identifier: GPL-2.0+
2 * Linux performance counter support for ARC700 series 2//
3 * 3// Linux performance counter support for ARC CPUs.
4 * Copyright (C) 2013-2015 Synopsys, Inc. (www.synopsys.com) 4// This code is inspired by the perf support of various other architectures.
5 * 5//
6 * This code is inspired by the perf support of various other architectures. 6// Copyright (C) 2013-2018 Synopsys, Inc. (www.synopsys.com)
7 * 7
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13#include <linux/errno.h> 8#include <linux/errno.h>
14#include <linux/interrupt.h> 9#include <linux/interrupt.h>
15#include <linux/module.h> 10#include <linux/module.h>
@@ -19,12 +14,31 @@
19#include <asm/arcregs.h> 14#include <asm/arcregs.h>
20#include <asm/stacktrace.h> 15#include <asm/stacktrace.h>
21 16
17/* HW holds 8 symbols + one for null terminator */
18#define ARCPMU_EVENT_NAME_LEN 9
19
20enum arc_pmu_attr_groups {
21 ARCPMU_ATTR_GR_EVENTS,
22 ARCPMU_ATTR_GR_FORMATS,
23 ARCPMU_NR_ATTR_GR
24};
25
26struct arc_pmu_raw_event_entry {
27 char name[ARCPMU_EVENT_NAME_LEN];
28};
29
22struct arc_pmu { 30struct arc_pmu {
23 struct pmu pmu; 31 struct pmu pmu;
24 unsigned int irq; 32 unsigned int irq;
25 int n_counters; 33 int n_counters;
34 int n_events;
26 u64 max_period; 35 u64 max_period;
27 int ev_hw_idx[PERF_COUNT_ARC_HW_MAX]; 36 int ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
37
38 struct arc_pmu_raw_event_entry *raw_entry;
39 struct attribute **attrs;
40 struct perf_pmu_events_attr *attr;
41 const struct attribute_group *attr_groups[ARCPMU_NR_ATTR_GR + 1];
28}; 42};
29 43
30struct arc_pmu_cpu { 44struct arc_pmu_cpu {
@@ -49,6 +63,7 @@ static int callchain_trace(unsigned int addr, void *data)
49{ 63{
50 struct arc_callchain_trace *ctrl = data; 64 struct arc_callchain_trace *ctrl = data;
51 struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff; 65 struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;
66
52 perf_callchain_store(entry, addr); 67 perf_callchain_store(entry, addr);
53 68
54 if (ctrl->depth++ < 3) 69 if (ctrl->depth++ < 3)
@@ -57,8 +72,8 @@ static int callchain_trace(unsigned int addr, void *data)
57 return -1; 72 return -1;
58} 73}
59 74
60void 75void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
61perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) 76 struct pt_regs *regs)
62{ 77{
63 struct arc_callchain_trace ctrl = { 78 struct arc_callchain_trace ctrl = {
64 .depth = 0, 79 .depth = 0,
@@ -68,8 +83,8 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
68 arc_unwind_core(NULL, regs, callchain_trace, &ctrl); 83 arc_unwind_core(NULL, regs, callchain_trace, &ctrl);
69} 84}
70 85
71void 86void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
72perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) 87 struct pt_regs *regs)
73{ 88{
74 /* 89 /*
75 * User stack can't be unwound trivially with kernel dwarf unwinder 90 * User stack can't be unwound trivially with kernel dwarf unwinder
@@ -82,10 +97,10 @@ static struct arc_pmu *arc_pmu;
82static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu); 97static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu);
83 98
84/* read counter #idx; note that counter# != event# on ARC! */ 99/* read counter #idx; note that counter# != event# on ARC! */
85static uint64_t arc_pmu_read_counter(int idx) 100static u64 arc_pmu_read_counter(int idx)
86{ 101{
87 uint32_t tmp; 102 u32 tmp;
88 uint64_t result; 103 u64 result;
89 104
90 /* 105 /*
91 * ARC supports making 'snapshots' of the counters, so we don't 106 * ARC supports making 'snapshots' of the counters, so we don't
@@ -94,7 +109,7 @@ static uint64_t arc_pmu_read_counter(int idx)
94 write_aux_reg(ARC_REG_PCT_INDEX, idx); 109 write_aux_reg(ARC_REG_PCT_INDEX, idx);
95 tmp = read_aux_reg(ARC_REG_PCT_CONTROL); 110 tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
96 write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN); 111 write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
97 result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32; 112 result = (u64) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
98 result |= read_aux_reg(ARC_REG_PCT_SNAPL); 113 result |= read_aux_reg(ARC_REG_PCT_SNAPL);
99 114
100 return result; 115 return result;
@@ -103,9 +118,9 @@ static uint64_t arc_pmu_read_counter(int idx)
103static void arc_perf_event_update(struct perf_event *event, 118static void arc_perf_event_update(struct perf_event *event,
104 struct hw_perf_event *hwc, int idx) 119 struct hw_perf_event *hwc, int idx)
105{ 120{
106 uint64_t prev_raw_count = local64_read(&hwc->prev_count); 121 u64 prev_raw_count = local64_read(&hwc->prev_count);
107 uint64_t new_raw_count = arc_pmu_read_counter(idx); 122 u64 new_raw_count = arc_pmu_read_counter(idx);
108 int64_t delta = new_raw_count - prev_raw_count; 123 s64 delta = new_raw_count - prev_raw_count;
109 124
110 /* 125 /*
111 * We aren't afraid of hwc->prev_count changing beneath our feet 126 * We aren't afraid of hwc->prev_count changing beneath our feet
@@ -155,7 +170,7 @@ static int arc_pmu_event_init(struct perf_event *event)
155 int ret; 170 int ret;
156 171
157 if (!is_sampling_event(event)) { 172 if (!is_sampling_event(event)) {
158 hwc->sample_period = arc_pmu->max_period; 173 hwc->sample_period = arc_pmu->max_period;
159 hwc->last_period = hwc->sample_period; 174 hwc->last_period = hwc->sample_period;
160 local64_set(&hwc->period_left, hwc->sample_period); 175 local64_set(&hwc->period_left, hwc->sample_period);
161 } 176 }
@@ -192,6 +207,18 @@ static int arc_pmu_event_init(struct perf_event *event)
192 pr_debug("init cache event with h/w %08x \'%s\'\n", 207 pr_debug("init cache event with h/w %08x \'%s\'\n",
193 (int)hwc->config, arc_pmu_ev_hw_map[ret]); 208 (int)hwc->config, arc_pmu_ev_hw_map[ret]);
194 return 0; 209 return 0;
210
211 case PERF_TYPE_RAW:
212 if (event->attr.config >= arc_pmu->n_events)
213 return -ENOENT;
214
215 hwc->config |= event->attr.config;
216 pr_debug("init raw event with idx %lld \'%s\'\n",
217 event->attr.config,
218 arc_pmu->raw_entry[event->attr.config].name);
219
220 return 0;
221
195 default: 222 default:
196 return -ENOENT; 223 return -ENOENT;
197 } 224 }
@@ -200,7 +227,7 @@ static int arc_pmu_event_init(struct perf_event *event)
200/* starts all counters */ 227/* starts all counters */
201static void arc_pmu_enable(struct pmu *pmu) 228static void arc_pmu_enable(struct pmu *pmu)
202{ 229{
203 uint32_t tmp; 230 u32 tmp;
204 tmp = read_aux_reg(ARC_REG_PCT_CONTROL); 231 tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
205 write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1); 232 write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
206} 233}
@@ -208,7 +235,7 @@ static void arc_pmu_enable(struct pmu *pmu)
208/* stops all counters */ 235/* stops all counters */
209static void arc_pmu_disable(struct pmu *pmu) 236static void arc_pmu_disable(struct pmu *pmu)
210{ 237{
211 uint32_t tmp; 238 u32 tmp;
212 tmp = read_aux_reg(ARC_REG_PCT_CONTROL); 239 tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
213 write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0); 240 write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
214} 241}
@@ -228,7 +255,7 @@ static int arc_pmu_event_set_period(struct perf_event *event)
228 local64_set(&hwc->period_left, left); 255 local64_set(&hwc->period_left, left);
229 hwc->last_period = period; 256 hwc->last_period = period;
230 overflow = 1; 257 overflow = 1;
231 } else if (unlikely(left <= 0)) { 258 } else if (unlikely(left <= 0)) {
232 /* left underflowed by less than period. */ 259 /* left underflowed by less than period. */
233 left += period; 260 left += period;
234 local64_set(&hwc->period_left, left); 261 local64_set(&hwc->period_left, left);
@@ -246,8 +273,8 @@ static int arc_pmu_event_set_period(struct perf_event *event)
246 write_aux_reg(ARC_REG_PCT_INDEX, idx); 273 write_aux_reg(ARC_REG_PCT_INDEX, idx);
247 274
248 /* Write value */ 275 /* Write value */
249 write_aux_reg(ARC_REG_PCT_COUNTL, (u32)value); 276 write_aux_reg(ARC_REG_PCT_COUNTL, lower_32_bits(value));
250 write_aux_reg(ARC_REG_PCT_COUNTH, (value >> 32)); 277 write_aux_reg(ARC_REG_PCT_COUNTH, upper_32_bits(value));
251 278
252 perf_event_update_userpage(event); 279 perf_event_update_userpage(event);
253 280
@@ -277,7 +304,7 @@ static void arc_pmu_start(struct perf_event *event, int flags)
277 /* Enable interrupt for this counter */ 304 /* Enable interrupt for this counter */
278 if (is_sampling_event(event)) 305 if (is_sampling_event(event))
279 write_aux_reg(ARC_REG_PCT_INT_CTRL, 306 write_aux_reg(ARC_REG_PCT_INT_CTRL,
280 read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx)); 307 read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
281 308
282 /* enable ARC pmu here */ 309 /* enable ARC pmu here */
283 write_aux_reg(ARC_REG_PCT_INDEX, idx); /* counter # */ 310 write_aux_reg(ARC_REG_PCT_INDEX, idx); /* counter # */
@@ -295,9 +322,9 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
295 * Reset interrupt flag by writing of 1. This is required 322 * Reset interrupt flag by writing of 1. This is required
296 * to make sure pending interrupt was not left. 323 * to make sure pending interrupt was not left.
297 */ 324 */
298 write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx); 325 write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
299 write_aux_reg(ARC_REG_PCT_INT_CTRL, 326 write_aux_reg(ARC_REG_PCT_INT_CTRL,
300 read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx)); 327 read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~BIT(idx));
301 } 328 }
302 329
303 if (!(event->hw.state & PERF_HES_STOPPED)) { 330 if (!(event->hw.state & PERF_HES_STOPPED)) {
@@ -349,9 +376,10 @@ static int arc_pmu_add(struct perf_event *event, int flags)
349 376
350 if (is_sampling_event(event)) { 377 if (is_sampling_event(event)) {
351 /* Mimic full counter overflow as other arches do */ 378 /* Mimic full counter overflow as other arches do */
352 write_aux_reg(ARC_REG_PCT_INT_CNTL, (u32)arc_pmu->max_period); 379 write_aux_reg(ARC_REG_PCT_INT_CNTL,
380 lower_32_bits(arc_pmu->max_period));
353 write_aux_reg(ARC_REG_PCT_INT_CNTH, 381 write_aux_reg(ARC_REG_PCT_INT_CNTH,
354 (arc_pmu->max_period >> 32)); 382 upper_32_bits(arc_pmu->max_period));
355 } 383 }
356 384
357 write_aux_reg(ARC_REG_PCT_CONFIG, 0); 385 write_aux_reg(ARC_REG_PCT_CONFIG, 0);
@@ -392,7 +420,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
392 idx = __ffs(active_ints); 420 idx = __ffs(active_ints);
393 421
394 /* Reset interrupt flag by writing of 1 */ 422 /* Reset interrupt flag by writing of 1 */
395 write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx); 423 write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
396 424
397 /* 425 /*
398 * On reset of "interrupt active" bit corresponding 426 * On reset of "interrupt active" bit corresponding
@@ -400,7 +428,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
400 * Now we need to re-enable interrupt for the counter. 428 * Now we need to re-enable interrupt for the counter.
401 */ 429 */
402 write_aux_reg(ARC_REG_PCT_INT_CTRL, 430 write_aux_reg(ARC_REG_PCT_INT_CTRL,
403 read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx)); 431 read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
404 432
405 event = pmu_cpu->act_counter[idx]; 433 event = pmu_cpu->act_counter[idx];
406 hwc = &event->hw; 434 hwc = &event->hw;
@@ -414,7 +442,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
414 arc_pmu_stop(event, 0); 442 arc_pmu_stop(event, 0);
415 } 443 }
416 444
417 active_ints &= ~(1U << idx); 445 active_ints &= ~BIT(idx);
418 } while (active_ints); 446 } while (active_ints);
419 447
420done: 448done:
@@ -441,19 +469,108 @@ static void arc_cpu_pmu_irq_init(void *data)
441 write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff); 469 write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
442} 470}
443 471
472/* Event field occupies the bottom 15 bits of our config field */
473PMU_FORMAT_ATTR(event, "config:0-14");
474static struct attribute *arc_pmu_format_attrs[] = {
475 &format_attr_event.attr,
476 NULL,
477};
478
479static struct attribute_group arc_pmu_format_attr_gr = {
480 .name = "format",
481 .attrs = arc_pmu_format_attrs,
482};
483
484static ssize_t arc_pmu_events_sysfs_show(struct device *dev,
485 struct device_attribute *attr,
486 char *page)
487{
488 struct perf_pmu_events_attr *pmu_attr;
489
490 pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
491 return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
492}
493
494/*
495 * We don't add attrs here as we don't have pre-defined list of perf events.
496 * We will generate and add attrs dynamically in probe() after we read HW
497 * configuration.
498 */
499static struct attribute_group arc_pmu_events_attr_gr = {
500 .name = "events",
501};
502
503static void arc_pmu_add_raw_event_attr(int j, char *str)
504{
505 memmove(arc_pmu->raw_entry[j].name, str, ARCPMU_EVENT_NAME_LEN - 1);
506 arc_pmu->attr[j].attr.attr.name = arc_pmu->raw_entry[j].name;
507 arc_pmu->attr[j].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0444);
508 arc_pmu->attr[j].attr.show = arc_pmu_events_sysfs_show;
509 arc_pmu->attr[j].id = j;
510 arc_pmu->attrs[j] = &(arc_pmu->attr[j].attr.attr);
511}
512
513static int arc_pmu_raw_alloc(struct device *dev)
514{
515 arc_pmu->attr = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
516 sizeof(*arc_pmu->attr), GFP_KERNEL | __GFP_ZERO);
517 if (!arc_pmu->attr)
518 return -ENOMEM;
519
520 arc_pmu->attrs = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
521 sizeof(*arc_pmu->attrs), GFP_KERNEL | __GFP_ZERO);
522 if (!arc_pmu->attrs)
523 return -ENOMEM;
524
525 arc_pmu->raw_entry = devm_kmalloc_array(dev, arc_pmu->n_events,
526 sizeof(*arc_pmu->raw_entry), GFP_KERNEL | __GFP_ZERO);
527 if (!arc_pmu->raw_entry)
528 return -ENOMEM;
529
530 return 0;
531}
532
533static inline bool event_in_hw_event_map(int i, char *name)
534{
535 if (!arc_pmu_ev_hw_map[i])
536 return false;
537
538 if (!strlen(arc_pmu_ev_hw_map[i]))
539 return false;
540
541 if (strcmp(arc_pmu_ev_hw_map[i], name))
542 return false;
543
544 return true;
545}
546
547static void arc_pmu_map_hw_event(int j, char *str)
548{
549 int i;
550
551 /* See if HW condition has been mapped to a perf event_id */
552 for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
553 if (event_in_hw_event_map(i, str)) {
554 pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
555 i, str, j);
556 arc_pmu->ev_hw_idx[i] = j;
557 }
558 }
559}
560
444static int arc_pmu_device_probe(struct platform_device *pdev) 561static int arc_pmu_device_probe(struct platform_device *pdev)
445{ 562{
446 struct arc_reg_pct_build pct_bcr; 563 struct arc_reg_pct_build pct_bcr;
447 struct arc_reg_cc_build cc_bcr; 564 struct arc_reg_cc_build cc_bcr;
448 int i, j, has_interrupts; 565 int i, has_interrupts;
449 int counter_size; /* in bits */ 566 int counter_size; /* in bits */
450 567
451 union cc_name { 568 union cc_name {
452 struct { 569 struct {
453 uint32_t word0, word1; 570 u32 word0, word1;
454 char sentinel; 571 char sentinel;
455 } indiv; 572 } indiv;
456 char str[9]; 573 char str[ARCPMU_EVENT_NAME_LEN];
457 } cc_name; 574 } cc_name;
458 575
459 576
@@ -463,15 +580,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
463 return -ENODEV; 580 return -ENODEV;
464 } 581 }
465 BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32); 582 BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32);
466 BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS); 583 if (WARN_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS))
584 return -EINVAL;
467 585
468 READ_BCR(ARC_REG_CC_BUILD, cc_bcr); 586 READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
469 BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */ 587 if (WARN(!cc_bcr.v, "Counters exist but No countable conditions?"))
588 return -EINVAL;
470 589
471 arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL); 590 arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
472 if (!arc_pmu) 591 if (!arc_pmu)
473 return -ENOMEM; 592 return -ENOMEM;
474 593
594 arc_pmu->n_events = cc_bcr.c;
595
596 if (arc_pmu_raw_alloc(&pdev->dev))
597 return -ENOMEM;
598
475 has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0; 599 has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0;
476 600
477 arc_pmu->n_counters = pct_bcr.c; 601 arc_pmu->n_counters = pct_bcr.c;
@@ -481,30 +605,26 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
481 605
482 pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n", 606 pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
483 arc_pmu->n_counters, counter_size, cc_bcr.c, 607 arc_pmu->n_counters, counter_size, cc_bcr.c,
484 has_interrupts ? ", [overflow IRQ support]":""); 608 has_interrupts ? ", [overflow IRQ support]" : "");
485 609
486 cc_name.str[8] = 0; 610 cc_name.str[ARCPMU_EVENT_NAME_LEN - 1] = 0;
487 for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++) 611 for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
488 arc_pmu->ev_hw_idx[i] = -1; 612 arc_pmu->ev_hw_idx[i] = -1;
489 613
490 /* loop thru all available h/w condition indexes */ 614 /* loop thru all available h/w condition indexes */
491 for (j = 0; j < cc_bcr.c; j++) { 615 for (i = 0; i < cc_bcr.c; i++) {
492 write_aux_reg(ARC_REG_CC_INDEX, j); 616 write_aux_reg(ARC_REG_CC_INDEX, i);
493 cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0); 617 cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
494 cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1); 618 cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
495 619
496 /* See if it has been mapped to a perf event_id */ 620 arc_pmu_map_hw_event(i, cc_name.str);
497 for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) { 621 arc_pmu_add_raw_event_attr(i, cc_name.str);
498 if (arc_pmu_ev_hw_map[i] &&
499 !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
500 strlen(arc_pmu_ev_hw_map[i])) {
501 pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
502 i, cc_name.str, j);
503 arc_pmu->ev_hw_idx[i] = j;
504 }
505 }
506 } 622 }
507 623
624 arc_pmu_events_attr_gr.attrs = arc_pmu->attrs;
625 arc_pmu->attr_groups[ARCPMU_ATTR_GR_EVENTS] = &arc_pmu_events_attr_gr;
626 arc_pmu->attr_groups[ARCPMU_ATTR_GR_FORMATS] = &arc_pmu_format_attr_gr;
627
508 arc_pmu->pmu = (struct pmu) { 628 arc_pmu->pmu = (struct pmu) {
509 .pmu_enable = arc_pmu_enable, 629 .pmu_enable = arc_pmu_enable,
510 .pmu_disable = arc_pmu_disable, 630 .pmu_disable = arc_pmu_disable,
@@ -514,6 +634,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
514 .start = arc_pmu_start, 634 .start = arc_pmu_start,
515 .stop = arc_pmu_stop, 635 .stop = arc_pmu_stop,
516 .read = arc_pmu_read, 636 .read = arc_pmu_read,
637 .attr_groups = arc_pmu->attr_groups,
517 }; 638 };
518 639
519 if (has_interrupts) { 640 if (has_interrupts) {
@@ -535,17 +656,19 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
535 } else 656 } else
536 arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT; 657 arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
537 658
538 return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW); 659 /*
660 * perf parser doesn't really like '-' symbol in events name, so let's
661 * use '_' in arc pct name as it goes to kernel PMU event prefix.
662 */
663 return perf_pmu_register(&arc_pmu->pmu, "arc_pct", PERF_TYPE_RAW);
539} 664}
540 665
541#ifdef CONFIG_OF
542static const struct of_device_id arc_pmu_match[] = { 666static const struct of_device_id arc_pmu_match[] = {
543 { .compatible = "snps,arc700-pct" }, 667 { .compatible = "snps,arc700-pct" },
544 { .compatible = "snps,archs-pct" }, 668 { .compatible = "snps,archs-pct" },
545 {}, 669 {},
546}; 670};
547MODULE_DEVICE_TABLE(of, arc_pmu_match); 671MODULE_DEVICE_TABLE(of, arc_pmu_match);
548#endif
549 672
550static struct platform_driver arc_pmu_driver = { 673static struct platform_driver arc_pmu_driver = {
551 .driver = { 674 .driver = {
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 2e018b8c2e19..7b2340996cf8 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -123,6 +123,7 @@ static void read_arc_build_cfg_regs(void)
123 struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; 123 struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
124 const struct id_to_str *tbl; 124 const struct id_to_str *tbl;
125 struct bcr_isa_arcv2 isa; 125 struct bcr_isa_arcv2 isa;
126 struct bcr_actionpoint ap;
126 127
127 FIX_PTR(cpu); 128 FIX_PTR(cpu);
128 129
@@ -195,20 +196,40 @@ static void read_arc_build_cfg_regs(void)
195 cpu->bpu.full = bpu.ft; 196 cpu->bpu.full = bpu.ft;
196 cpu->bpu.num_cache = 256 << bpu.bce; 197 cpu->bpu.num_cache = 256 << bpu.bce;
197 cpu->bpu.num_pred = 2048 << bpu.pte; 198 cpu->bpu.num_pred = 2048 << bpu.pte;
199 cpu->bpu.ret_stk = 4 << bpu.rse;
198 200
199 if (cpu->core.family >= 0x54) { 201 if (cpu->core.family >= 0x54) {
200 unsigned int exec_ctrl;
201 202
202 READ_BCR(AUX_EXEC_CTRL, exec_ctrl); 203 struct bcr_uarch_build_arcv2 uarch;
203 cpu->extn.dual_enb = !(exec_ctrl & 1);
204 204
205 /* dual issue always present for this core */ 205 /*
206 cpu->extn.dual = 1; 206 * The first 0x54 core (uarch maj:min 0:1 or 0:2) was
207 * dual issue only (HS4x). But next uarch rev (1:0)
208 * allows it be configured for single issue (HS3x)
209 * Ensure we fiddle with dual issue only on HS4x
210 */
211 READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch);
212
213 if (uarch.prod == 4) {
214 unsigned int exec_ctrl;
215
216 /* dual issue hardware always present */
217 cpu->extn.dual = 1;
218
219 READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
220
221 /* dual issue hardware enabled ? */
222 cpu->extn.dual_enb = !(exec_ctrl & 1);
223
224 }
207 } 225 }
208 } 226 }
209 227
210 READ_BCR(ARC_REG_AP_BCR, bcr); 228 READ_BCR(ARC_REG_AP_BCR, ap);
211 cpu->extn.ap = bcr.ver ? 1 : 0; 229 if (ap.ver) {
230 cpu->extn.ap_num = 2 << ap.num;
231 cpu->extn.ap_full = !ap.min;
232 }
212 233
213 READ_BCR(ARC_REG_SMART_BCR, bcr); 234 READ_BCR(ARC_REG_SMART_BCR, bcr);
214 cpu->extn.smart = bcr.ver ? 1 : 0; 235 cpu->extn.smart = bcr.ver ? 1 : 0;
@@ -216,8 +237,6 @@ static void read_arc_build_cfg_regs(void)
216 READ_BCR(ARC_REG_RTT_BCR, bcr); 237 READ_BCR(ARC_REG_RTT_BCR, bcr);
217 cpu->extn.rtt = bcr.ver ? 1 : 0; 238 cpu->extn.rtt = bcr.ver ? 1 : 0;
218 239
219 cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
220
221 READ_BCR(ARC_REG_ISA_CFG_BCR, isa); 240 READ_BCR(ARC_REG_ISA_CFG_BCR, isa);
222 241
223 /* some hacks for lack of feature BCR info in old ARC700 cores */ 242 /* some hacks for lack of feature BCR info in old ARC700 cores */
@@ -299,10 +318,10 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
299 318
300 if (cpu->bpu.ver) 319 if (cpu->bpu.ver)
301 n += scnprintf(buf + n, len - n, 320 n += scnprintf(buf + n, len - n,
302 "BPU\t\t: %s%s match, cache:%d, Predict Table:%d", 321 "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d",
303 IS_AVAIL1(cpu->bpu.full, "full"), 322 IS_AVAIL1(cpu->bpu.full, "full"),
304 IS_AVAIL1(!cpu->bpu.full, "partial"), 323 IS_AVAIL1(!cpu->bpu.full, "partial"),
305 cpu->bpu.num_cache, cpu->bpu.num_pred); 324 cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk);
306 325
307 if (is_isa_arcv2()) { 326 if (is_isa_arcv2()) {
308 struct bcr_lpb lpb; 327 struct bcr_lpb lpb;
@@ -336,11 +355,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
336 IS_AVAIL1(cpu->extn.fpu_sp, "SP "), 355 IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
337 IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); 356 IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
338 357
339 if (cpu->extn.debug) 358 if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) {
340 n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n", 359 n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s",
341 IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
342 IS_AVAIL1(cpu->extn.smart, "smaRT "), 360 IS_AVAIL1(cpu->extn.smart, "smaRT "),
343 IS_AVAIL1(cpu->extn.rtt, "RTT ")); 361 IS_AVAIL1(cpu->extn.rtt, "RTT "));
362 if (cpu->extn.ap_num) {
363 n += scnprintf(buf + n, len - n, "ActionPoint %d/%s",
364 cpu->extn.ap_num,
365 cpu->extn.ap_full ? "full":"min");
366 }
367 n += scnprintf(buf + n, len - n, "\n");
368 }
344 369
345 if (cpu->dccm.sz || cpu->iccm.sz) 370 if (cpu->dccm.sz || cpu->iccm.sz)
346 n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n", 371 n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
@@ -453,43 +478,78 @@ void setup_processor(void)
453 arc_chk_core_config(); 478 arc_chk_core_config();
454} 479}
455 480
456static inline int is_kernel(unsigned long addr) 481static inline bool uboot_arg_invalid(unsigned long addr)
457{ 482{
458 if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) 483 /*
459 return 1; 484 * Check that it is a untranslated address (although MMU is not enabled
460 return 0; 485 * yet, it being a high address ensures this is not by fluke)
486 */
487 if (addr < PAGE_OFFSET)
488 return true;
489
490 /* Check that address doesn't clobber resident kernel image */
491 return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;
461} 492}
462 493
463void __init setup_arch(char **cmdline_p) 494#define IGNORE_ARGS "Ignore U-boot args: "
495
496/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */
497#define UBOOT_TAG_NONE 0
498#define UBOOT_TAG_CMDLINE 1
499#define UBOOT_TAG_DTB 2
500
501void __init handle_uboot_args(void)
464{ 502{
465#ifdef CONFIG_ARC_UBOOT_SUPPORT 503 bool use_embedded_dtb = true;
466 /* make sure that uboot passed pointer to cmdline/dtb is valid */ 504 bool append_cmdline = false;
467 if (uboot_tag && is_kernel((unsigned long)uboot_arg)) 505
468 panic("Invalid uboot arg\n"); 506 /* check that we know this tag */
469 507 if (uboot_tag != UBOOT_TAG_NONE &&
470 /* See if u-boot passed an external Device Tree blob */ 508 uboot_tag != UBOOT_TAG_CMDLINE &&
471 machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */ 509 uboot_tag != UBOOT_TAG_DTB) {
472 if (!machine_desc) 510 pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag);
473#endif 511 goto ignore_uboot_args;
474 { 512 }
475 /* No, so try the embedded one */ 513
514 if (uboot_tag != UBOOT_TAG_NONE &&
515 uboot_arg_invalid((unsigned long)uboot_arg)) {
516 pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg);
517 goto ignore_uboot_args;
518 }
519
520 /* see if U-boot passed an external Device Tree blob */
521 if (uboot_tag == UBOOT_TAG_DTB) {
522 machine_desc = setup_machine_fdt((void *)uboot_arg);
523
524 /* external Device Tree blob is invalid - use embedded one */
525 use_embedded_dtb = !machine_desc;
526 }
527
528 if (uboot_tag == UBOOT_TAG_CMDLINE)
529 append_cmdline = true;
530
531ignore_uboot_args:
532
533 if (use_embedded_dtb) {
476 machine_desc = setup_machine_fdt(__dtb_start); 534 machine_desc = setup_machine_fdt(__dtb_start);
477 if (!machine_desc) 535 if (!machine_desc)
478 panic("Embedded DT invalid\n"); 536 panic("Embedded DT invalid\n");
537 }
479 538
480 /* 539 /*
481 * If we are here, it is established that @uboot_arg didn't 540 * NOTE: @boot_command_line is populated by setup_machine_fdt() so this
482 * point to DT blob. Instead if u-boot says it is cmdline, 541 * append processing can only happen after.
483 * append to embedded DT cmdline. 542 */
484 * setup_machine_fdt() would have populated @boot_command_line 543 if (append_cmdline) {
485 */ 544 /* Ensure a whitespace between the 2 cmdlines */
486 if (uboot_tag == 1) { 545 strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
487 /* Ensure a whitespace between the 2 cmdlines */ 546 strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);
488 strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
489 strlcat(boot_command_line, uboot_arg,
490 COMMAND_LINE_SIZE);
491 }
492 } 547 }
548}
549
550void __init setup_arch(char **cmdline_p)
551{
552 handle_uboot_args();
493 553
494 /* Save unparsed command line copy for /proc/cmdline */ 554 /* Save unparsed command line copy for /proc/cmdline */
495 *cmdline_p = boot_command_line; 555 *cmdline_p = boot_command_line;
diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c
index e8d9fb452346..215f515442e0 100644
--- a/arch/arc/kernel/troubleshoot.c
+++ b/arch/arc/kernel/troubleshoot.c
@@ -18,6 +18,8 @@
18#include <asm/arcregs.h> 18#include <asm/arcregs.h>
19#include <asm/irqflags.h> 19#include <asm/irqflags.h>
20 20
21#define ARC_PATH_MAX 256
22
21/* 23/*
22 * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25) 24 * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
23 * -Prints 3 regs per line and a CR. 25 * -Prints 3 regs per line and a CR.
@@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
58 print_reg_file(&(cregs->r13), 13); 60 print_reg_file(&(cregs->r13), 13);
59} 61}
60 62
61static void print_task_path_n_nm(struct task_struct *tsk, char *buf) 63static void print_task_path_n_nm(struct task_struct *tsk)
62{ 64{
63 char *path_nm = NULL; 65 char *path_nm = NULL;
64 struct mm_struct *mm; 66 struct mm_struct *mm;
65 struct file *exe_file; 67 struct file *exe_file;
68 char buf[ARC_PATH_MAX];
66 69
67 mm = get_task_mm(tsk); 70 mm = get_task_mm(tsk);
68 if (!mm) 71 if (!mm)
@@ -72,7 +75,7 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
72 mmput(mm); 75 mmput(mm);
73 76
74 if (exe_file) { 77 if (exe_file) {
75 path_nm = file_path(exe_file, buf, 255); 78 path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
76 fput(exe_file); 79 fput(exe_file);
77 } 80 }
78 81
@@ -80,10 +83,9 @@ done:
80 pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?"); 83 pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
81} 84}
82 85
83static void show_faulting_vma(unsigned long address, char *buf) 86static void show_faulting_vma(unsigned long address)
84{ 87{
85 struct vm_area_struct *vma; 88 struct vm_area_struct *vma;
86 char *nm = buf;
87 struct mm_struct *active_mm = current->active_mm; 89 struct mm_struct *active_mm = current->active_mm;
88 90
89 /* can't use print_vma_addr() yet as it doesn't check for 91 /* can't use print_vma_addr() yet as it doesn't check for
@@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
96 * if the container VMA is not found 98 * if the container VMA is not found
97 */ 99 */
98 if (vma && (vma->vm_start <= address)) { 100 if (vma && (vma->vm_start <= address)) {
101 char buf[ARC_PATH_MAX];
102 char *nm = "?";
103
99 if (vma->vm_file) { 104 if (vma->vm_file) {
100 nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1); 105 nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
101 if (IS_ERR(nm)) 106 if (IS_ERR(nm))
102 nm = "?"; 107 nm = "?";
103 } 108 }
@@ -173,13 +178,14 @@ void show_regs(struct pt_regs *regs)
173{ 178{
174 struct task_struct *tsk = current; 179 struct task_struct *tsk = current;
175 struct callee_regs *cregs; 180 struct callee_regs *cregs;
176 char *buf;
177 181
178 buf = (char *)__get_free_page(GFP_KERNEL); 182 /*
179 if (!buf) 183 * generic code calls us with preemption disabled, but some calls
180 return; 184 * here could sleep, so re-enable to avoid lockdep splat
185 */
186 preempt_enable();
181 187
182 print_task_path_n_nm(tsk, buf); 188 print_task_path_n_nm(tsk);
183 show_regs_print_info(KERN_INFO); 189 show_regs_print_info(KERN_INFO);
184 190
185 show_ecr_verbose(regs); 191 show_ecr_verbose(regs);
@@ -189,7 +195,7 @@ void show_regs(struct pt_regs *regs)
189 (void *)regs->blink, (void *)regs->ret); 195 (void *)regs->blink, (void *)regs->ret);
190 196
191 if (user_mode(regs)) 197 if (user_mode(regs))
192 show_faulting_vma(regs->ret, buf); /* faulting code, not data */ 198 show_faulting_vma(regs->ret); /* faulting code, not data */
193 199
194 pr_info("[STAT32]: 0x%08lx", regs->status32); 200 pr_info("[STAT32]: 0x%08lx", regs->status32);
195 201
@@ -222,7 +228,7 @@ void show_regs(struct pt_regs *regs)
222 if (cregs) 228 if (cregs)
223 show_callee_regs(cregs); 229 show_callee_regs(cregs);
224 230
225 free_page((unsigned long)buf); 231 preempt_disable();
226} 232}
227 233
228void show_kernel_fault_diag(const char *str, struct pt_regs *regs, 234void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
diff --git a/arch/arc/lib/memcpy-archs.S b/arch/arc/lib/memcpy-archs.S
index d61044dd8b58..ea14b0bf3116 100644
--- a/arch/arc/lib/memcpy-archs.S
+++ b/arch/arc/lib/memcpy-archs.S
@@ -25,15 +25,11 @@
25#endif 25#endif
26 26
27#ifdef CONFIG_ARC_HAS_LL64 27#ifdef CONFIG_ARC_HAS_LL64
28# define PREFETCH_READ(RX) prefetch [RX, 56]
29# define PREFETCH_WRITE(RX) prefetchw [RX, 64]
30# define LOADX(DST,RX) ldd.ab DST, [RX, 8] 28# define LOADX(DST,RX) ldd.ab DST, [RX, 8]
31# define STOREX(SRC,RX) std.ab SRC, [RX, 8] 29# define STOREX(SRC,RX) std.ab SRC, [RX, 8]
32# define ZOLSHFT 5 30# define ZOLSHFT 5
33# define ZOLAND 0x1F 31# define ZOLAND 0x1F
34#else 32#else
35# define PREFETCH_READ(RX) prefetch [RX, 28]
36# define PREFETCH_WRITE(RX) prefetchw [RX, 32]
37# define LOADX(DST,RX) ld.ab DST, [RX, 4] 33# define LOADX(DST,RX) ld.ab DST, [RX, 4]
38# define STOREX(SRC,RX) st.ab SRC, [RX, 4] 34# define STOREX(SRC,RX) st.ab SRC, [RX, 4]
39# define ZOLSHFT 4 35# define ZOLSHFT 4
@@ -41,8 +37,6 @@
41#endif 37#endif
42 38
43ENTRY_CFI(memcpy) 39ENTRY_CFI(memcpy)
44 prefetch [r1] ; Prefetch the read location
45 prefetchw [r0] ; Prefetch the write location
46 mov.f 0, r2 40 mov.f 0, r2
47;;; if size is zero 41;;; if size is zero
48 jz.d [blink] 42 jz.d [blink]
@@ -72,8 +66,6 @@ ENTRY_CFI(memcpy)
72 lpnz @.Lcopy32_64bytes 66 lpnz @.Lcopy32_64bytes
73 ;; LOOP START 67 ;; LOOP START
74 LOADX (r6, r1) 68 LOADX (r6, r1)
75 PREFETCH_READ (r1)
76 PREFETCH_WRITE (r3)
77 LOADX (r8, r1) 69 LOADX (r8, r1)
78 LOADX (r10, r1) 70 LOADX (r10, r1)
79 LOADX (r4, r1) 71 LOADX (r4, r1)
@@ -117,9 +109,7 @@ ENTRY_CFI(memcpy)
117 lpnz @.Lcopy8bytes_1 109 lpnz @.Lcopy8bytes_1
118 ;; LOOP START 110 ;; LOOP START
119 ld.ab r6, [r1, 4] 111 ld.ab r6, [r1, 4]
120 prefetch [r1, 28] ;Prefetch the next read location
121 ld.ab r8, [r1,4] 112 ld.ab r8, [r1,4]
122 prefetchw [r3, 32] ;Prefetch the next write location
123 113
124 SHIFT_1 (r7, r6, 24) 114 SHIFT_1 (r7, r6, 24)
125 or r7, r7, r5 115 or r7, r7, r5
@@ -162,9 +152,7 @@ ENTRY_CFI(memcpy)
162 lpnz @.Lcopy8bytes_2 152 lpnz @.Lcopy8bytes_2
163 ;; LOOP START 153 ;; LOOP START
164 ld.ab r6, [r1, 4] 154 ld.ab r6, [r1, 4]
165 prefetch [r1, 28] ;Prefetch the next read location
166 ld.ab r8, [r1,4] 155 ld.ab r8, [r1,4]
167 prefetchw [r3, 32] ;Prefetch the next write location
168 156
169 SHIFT_1 (r7, r6, 16) 157 SHIFT_1 (r7, r6, 16)
170 or r7, r7, r5 158 or r7, r7, r5
@@ -204,9 +192,7 @@ ENTRY_CFI(memcpy)
204 lpnz @.Lcopy8bytes_3 192 lpnz @.Lcopy8bytes_3
205 ;; LOOP START 193 ;; LOOP START
206 ld.ab r6, [r1, 4] 194 ld.ab r6, [r1, 4]
207 prefetch [r1, 28] ;Prefetch the next read location
208 ld.ab r8, [r1,4] 195 ld.ab r8, [r1,4]
209 prefetchw [r3, 32] ;Prefetch the next write location
210 196
211 SHIFT_1 (r7, r6, 8) 197 SHIFT_1 (r7, r6, 8)
212 or r7, r7, r5 198 or r7, r7, r5
diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S
index 62ad4bcb841a..f230bb7092fd 100644
--- a/arch/arc/lib/memset-archs.S
+++ b/arch/arc/lib/memset-archs.S
@@ -7,11 +7,39 @@
7 */ 7 */
8 8
9#include <linux/linkage.h> 9#include <linux/linkage.h>
10#include <asm/cache.h>
10 11
11#undef PREALLOC_NOT_AVAIL 12/*
13 * The memset implementation below is optimized to use prefetchw and prealloc
14 * instruction in case of CPU with 64B L1 data cache line (L1_CACHE_SHIFT == 6)
15 * If you want to implement optimized memset for other possible L1 data cache
16 * line lengths (32B and 128B) you should rewrite code carefully checking
17 * we don't call any prefetchw/prealloc instruction for L1 cache lines which
18 * don't belongs to memset area.
19 */
20
21#if L1_CACHE_SHIFT == 6
22
23.macro PREALLOC_INSTR reg, off
24 prealloc [\reg, \off]
25.endm
26
27.macro PREFETCHW_INSTR reg, off
28 prefetchw [\reg, \off]
29.endm
30
31#else
32
33.macro PREALLOC_INSTR
34.endm
35
36.macro PREFETCHW_INSTR
37.endm
38
39#endif
12 40
13ENTRY_CFI(memset) 41ENTRY_CFI(memset)
14 prefetchw [r0] ; Prefetch the write location 42 PREFETCHW_INSTR r0, 0 ; Prefetch the first write location
15 mov.f 0, r2 43 mov.f 0, r2
16;;; if size is zero 44;;; if size is zero
17 jz.d [blink] 45 jz.d [blink]
@@ -48,11 +76,8 @@ ENTRY_CFI(memset)
48 76
49 lpnz @.Lset64bytes 77 lpnz @.Lset64bytes
50 ;; LOOP START 78 ;; LOOP START
51#ifdef PREALLOC_NOT_AVAIL 79 PREALLOC_INSTR r3, 64 ; alloc next line w/o fetching
52 prefetchw [r3, 64] ;Prefetch the next write location 80
53#else
54 prealloc [r3, 64]
55#endif
56#ifdef CONFIG_ARC_HAS_LL64 81#ifdef CONFIG_ARC_HAS_LL64
57 std.ab r4, [r3, 8] 82 std.ab r4, [r3, 8]
58 std.ab r4, [r3, 8] 83 std.ab r4, [r3, 8]
@@ -85,7 +110,6 @@ ENTRY_CFI(memset)
85 lsr.f lp_count, r2, 5 ;Last remaining max 124 bytes 110 lsr.f lp_count, r2, 5 ;Last remaining max 124 bytes
86 lpnz .Lset32bytes 111 lpnz .Lset32bytes
87 ;; LOOP START 112 ;; LOOP START
88 prefetchw [r3, 32] ;Prefetch the next write location
89#ifdef CONFIG_ARC_HAS_LL64 113#ifdef CONFIG_ARC_HAS_LL64
90 std.ab r4, [r3, 8] 114 std.ab r4, [r3, 8]
91 std.ab r4, [r3, 8] 115 std.ab r4, [r3, 8]
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index a1d723197084..8df1638259f3 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -141,12 +141,17 @@ good_area:
141 */ 141 */
142 fault = handle_mm_fault(vma, address, flags); 142 fault = handle_mm_fault(vma, address, flags);
143 143
144 /* If Pagefault was interrupted by SIGKILL, exit page fault "early" */
145 if (fatal_signal_pending(current)) { 144 if (fatal_signal_pending(current)) {
146 if ((fault & VM_FAULT_ERROR) && !(fault & VM_FAULT_RETRY)) 145
147 up_read(&mm->mmap_sem); 146 /*
148 if (user_mode(regs)) 147 * if fault retry, mmap_sem already relinquished by core mm
148 * so OK to return to user mode (with signal handled first)
149 */
150 if (fault & VM_FAULT_RETRY) {
151 if (!user_mode(regs))
152 goto no_context;
149 return; 153 return;
154 }
150 } 155 }
151 156
152 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); 157 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
index 43bf4c3a1290..e1ab2d7f1d64 100644
--- a/arch/arc/mm/init.c
+++ b/arch/arc/mm/init.c
@@ -119,7 +119,8 @@ void __init setup_arch_memory(void)
119 */ 119 */
120 120
121 memblock_add_node(low_mem_start, low_mem_sz, 0); 121 memblock_add_node(low_mem_start, low_mem_sz, 0);
122 memblock_reserve(low_mem_start, __pa(_end) - low_mem_start); 122 memblock_reserve(CONFIG_LINUX_LINK_BASE,
123 __pa(_end) - CONFIG_LINUX_LINK_BASE);
123 124
124#ifdef CONFIG_BLK_DEV_INITRD 125#ifdef CONFIG_BLK_DEV_INITRD
125 if (phys_initrd_size) { 126 if (phys_initrd_size) {
diff --git a/arch/arc/plat-hsdk/Kconfig b/arch/arc/plat-hsdk/Kconfig
index f25c085b9874..23e00216e5a5 100644
--- a/arch/arc/plat-hsdk/Kconfig
+++ b/arch/arc/plat-hsdk/Kconfig
@@ -9,6 +9,7 @@ menuconfig ARC_SOC_HSDK
9 bool "ARC HS Development Kit SOC" 9 bool "ARC HS Development Kit SOC"
10 depends on ISA_ARCV2 10 depends on ISA_ARCV2
11 select ARC_HAS_ACCL_REGS 11 select ARC_HAS_ACCL_REGS
12 select ARC_IRQ_NO_AUTOSAVE
12 select CLK_HSDK 13 select CLK_HSDK
13 select RESET_HSDK 14 select RESET_HSDK
14 select HAVE_PCI 15 select HAVE_PCI