aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/csky/Kconfig7
-rw-r--r--arch/csky/Makefile2
-rw-r--r--arch/csky/abiv1/inc/abi/ckmmu.h24
-rw-r--r--arch/csky/abiv1/inc/abi/entry.h41
-rw-r--r--arch/csky/abiv1/inc/abi/regdef.h5
-rw-r--r--arch/csky/abiv2/cacheflush.c13
-rw-r--r--arch/csky/abiv2/inc/abi/ckmmu.h34
-rw-r--r--arch/csky/abiv2/inc/abi/entry.h87
-rw-r--r--arch/csky/abiv2/inc/abi/regdef.h5
-rw-r--r--arch/csky/abiv2/mcount.S39
-rw-r--r--arch/csky/abiv2/memmove.S6
-rw-r--r--arch/csky/include/asm/Kbuild1
-rw-r--r--arch/csky/include/asm/ftrace.h18
-rw-r--r--arch/csky/include/asm/mmu_context.h17
-rw-r--r--arch/csky/include/asm/page.h39
-rw-r--r--arch/csky/include/asm/perf_event.h8
-rw-r--r--arch/csky/include/asm/ptrace.h41
-rw-r--r--arch/csky/include/asm/syscall.h9
-rw-r--r--arch/csky/include/asm/thread_info.h27
-rw-r--r--arch/csky/include/asm/unistd.h2
-rw-r--r--arch/csky/include/uapi/asm/perf_regs.h51
-rw-r--r--arch/csky/include/uapi/asm/ptrace.h15
-rw-r--r--arch/csky/kernel/Makefile2
-rw-r--r--arch/csky/kernel/atomic.S26
-rw-r--r--arch/csky/kernel/entry.S77
-rw-r--r--arch/csky/kernel/ftrace.c148
-rw-r--r--arch/csky/kernel/head.S60
-rw-r--r--arch/csky/kernel/perf_callchain.c119
-rw-r--r--arch/csky/kernel/perf_regs.c40
-rw-r--r--arch/csky/kernel/ptrace.c51
-rw-r--r--arch/csky/kernel/setup.c12
-rw-r--r--arch/csky/kernel/signal.c348
-rw-r--r--arch/csky/mm/fault.c15
-rwxr-xr-xscripts/recordmcount.pl3
34 files changed, 890 insertions, 502 deletions
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 6555d1781132..941e3e2adf41 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -29,15 +29,20 @@ config CSKY
29 select GENERIC_SCHED_CLOCK 29 select GENERIC_SCHED_CLOCK
30 select GENERIC_SMP_IDLE_THREAD 30 select GENERIC_SMP_IDLE_THREAD
31 select HAVE_ARCH_TRACEHOOK 31 select HAVE_ARCH_TRACEHOOK
32 select HAVE_ARCH_AUDITSYSCALL
33 select HAVE_DYNAMIC_FTRACE
32 select HAVE_FUNCTION_TRACER 34 select HAVE_FUNCTION_TRACER
33 select HAVE_FUNCTION_GRAPH_TRACER 35 select HAVE_FUNCTION_GRAPH_TRACER
36 select HAVE_FTRACE_MCOUNT_RECORD
34 select HAVE_KERNEL_GZIP 37 select HAVE_KERNEL_GZIP
35 select HAVE_KERNEL_LZO 38 select HAVE_KERNEL_LZO
36 select HAVE_KERNEL_LZMA 39 select HAVE_KERNEL_LZMA
37 select HAVE_PERF_EVENTS 40 select HAVE_PERF_EVENTS
38 select HAVE_C_RECORDMCOUNT 41 select HAVE_PERF_REGS
42 select HAVE_PERF_USER_STACK_DUMP
39 select HAVE_DMA_API_DEBUG 43 select HAVE_DMA_API_DEBUG
40 select HAVE_DMA_CONTIGUOUS 44 select HAVE_DMA_CONTIGUOUS
45 select HAVE_SYSCALL_TRACEPOINTS
41 select MAY_HAVE_SPARSE_IRQ 46 select MAY_HAVE_SPARSE_IRQ
42 select MODULES_USE_ELF_RELA if MODULES 47 select MODULES_USE_ELF_RELA if MODULES
43 select OF 48 select OF
diff --git a/arch/csky/Makefile b/arch/csky/Makefile
index 3607a6e8f66c..6b87f6c22ad6 100644
--- a/arch/csky/Makefile
+++ b/arch/csky/Makefile
@@ -36,7 +36,7 @@ endif
36 36
37ifneq ($(CSKYABI),) 37ifneq ($(CSKYABI),)
38MCPU_STR = $(CPUTYPE)$(FPUEXT)$(VDSPEXT)$(TEEEXT) 38MCPU_STR = $(CPUTYPE)$(FPUEXT)$(VDSPEXT)$(TEEEXT)
39KBUILD_CFLAGS += -mcpu=$(MCPU_STR) 39KBUILD_CFLAGS += -mcpu=$(CPUTYPE) -Wa,-mcpu=$(MCPU_STR)
40KBUILD_CFLAGS += -DCSKYCPU_DEF_NAME=\"$(MCPU_STR)\" 40KBUILD_CFLAGS += -DCSKYCPU_DEF_NAME=\"$(MCPU_STR)\"
41KBUILD_CFLAGS += -msoft-float -mdiv 41KBUILD_CFLAGS += -msoft-float -mdiv
42KBUILD_CFLAGS += -fno-tree-vectorize 42KBUILD_CFLAGS += -fno-tree-vectorize
diff --git a/arch/csky/abiv1/inc/abi/ckmmu.h b/arch/csky/abiv1/inc/abi/ckmmu.h
index 3a002017bebe..81f37715c0d2 100644
--- a/arch/csky/abiv1/inc/abi/ckmmu.h
+++ b/arch/csky/abiv1/inc/abi/ckmmu.h
@@ -40,6 +40,26 @@ static inline void write_mmu_entryhi(int value)
40 cpwcr("cpcr4", value); 40 cpwcr("cpcr4", value);
41} 41}
42 42
43static inline unsigned long read_mmu_msa0(void)
44{
45 return cprcr("cpcr30");
46}
47
48static inline void write_mmu_msa0(unsigned long value)
49{
50 cpwcr("cpcr30", value);
51}
52
53static inline unsigned long read_mmu_msa1(void)
54{
55 return cprcr("cpcr31");
56}
57
58static inline void write_mmu_msa1(unsigned long value)
59{
60 cpwcr("cpcr31", value);
61}
62
43/* 63/*
44 * TLB operations. 64 * TLB operations.
45 */ 65 */
@@ -65,11 +85,11 @@ static inline void tlb_invalid_indexed(void)
65 85
66static inline void setup_pgd(unsigned long pgd, bool kernel) 86static inline void setup_pgd(unsigned long pgd, bool kernel)
67{ 87{
68 cpwcr("cpcr29", pgd); 88 cpwcr("cpcr29", pgd | BIT(0));
69} 89}
70 90
71static inline unsigned long get_pgd(void) 91static inline unsigned long get_pgd(void)
72{ 92{
73 return cprcr("cpcr29"); 93 return cprcr("cpcr29") & ~BIT(0);
74} 94}
75#endif /* __ASM_CSKY_CKMMUV1_H */ 95#endif /* __ASM_CSKY_CKMMUV1_H */
diff --git a/arch/csky/abiv1/inc/abi/entry.h b/arch/csky/abiv1/inc/abi/entry.h
index 3f3faab3d747..7ab78bd0f3b1 100644
--- a/arch/csky/abiv1/inc/abi/entry.h
+++ b/arch/csky/abiv1/inc/abi/entry.h
@@ -16,9 +16,6 @@
16#define LSAVE_A4 40 16#define LSAVE_A4 40
17#define LSAVE_A5 44 17#define LSAVE_A5 44
18 18
19#define EPC_INCREASE 2
20#define EPC_KEEP 0
21
22.macro USPTOKSP 19.macro USPTOKSP
23 mtcr sp, ss1 20 mtcr sp, ss1
24 mfcr sp, ss0 21 mfcr sp, ss0
@@ -29,10 +26,6 @@
29 mfcr sp, ss1 26 mfcr sp, ss1
30.endm 27.endm
31 28
32.macro INCTRAP rx
33 addi \rx, EPC_INCREASE
34.endm
35
36.macro SAVE_ALL epc_inc 29.macro SAVE_ALL epc_inc
37 mtcr r13, ss2 30 mtcr r13, ss2
38 mfcr r13, epsr 31 mfcr r13, epsr
@@ -150,11 +143,35 @@
150 cpwcr \rx, cpcr8 143 cpwcr \rx, cpcr8
151.endm 144.endm
152 145
153.macro SETUP_MMU rx 146.macro SETUP_MMU
154 lrw \rx, PHYS_OFFSET | 0xe 147 /* Init psr and enable ee */
155 cpwcr \rx, cpcr30 148 lrw r6, DEFAULT_PSR_VALUE
156 lrw \rx, (PHYS_OFFSET + 0x20000000) | 0xe 149 mtcr r6, psr
157 cpwcr \rx, cpcr31 150 psrset ee
151
152 /* Select MMU as co-processor */
153 cpseti cp15
154
155 /*
156 * cpcr30 format:
157 * 31 - 29 | 28 - 4 | 3 | 2 | 1 | 0
158 * BA Reserved C D V
159 */
160 cprcr r6, cpcr30
161 lsri r6, 28
162 lsli r6, 28
163 addi r6, 0xe
164 cpwcr r6, cpcr30
165
166 lsri r6, 28
167 addi r6, 2
168 lsli r6, 28
169 addi r6, 0xe
170 cpwcr r6, cpcr31
158.endm 171.endm
159 172
173.macro ANDI_R3 rx, imm
174 lsri \rx, 3
175 andi \rx, (\imm >> 3)
176.endm
160#endif /* __ASM_CSKY_ENTRY_H */ 177#endif /* __ASM_CSKY_ENTRY_H */
diff --git a/arch/csky/abiv1/inc/abi/regdef.h b/arch/csky/abiv1/inc/abi/regdef.h
index 876689291b71..104707fbdcc1 100644
--- a/arch/csky/abiv1/inc/abi/regdef.h
+++ b/arch/csky/abiv1/inc/abi/regdef.h
@@ -5,9 +5,8 @@
5#define __ASM_CSKY_REGDEF_H 5#define __ASM_CSKY_REGDEF_H
6 6
7#define syscallid r1 7#define syscallid r1
8#define r11_sig r11
9
10#define regs_syscallid(regs) regs->regs[9] 8#define regs_syscallid(regs) regs->regs[9]
9#define regs_fp(regs) regs->regs[2]
11 10
12/* 11/*
13 * PSR format: 12 * PSR format:
@@ -23,4 +22,6 @@
23 22
24#define SYSTRACE_SAVENUM 2 23#define SYSTRACE_SAVENUM 2
25 24
25#define TRAP0_SIZE 2
26
26#endif /* __ASM_CSKY_REGDEF_H */ 27#endif /* __ASM_CSKY_REGDEF_H */
diff --git a/arch/csky/abiv2/cacheflush.c b/arch/csky/abiv2/cacheflush.c
index d22c95ffc74d..5bb887b275e1 100644
--- a/arch/csky/abiv2/cacheflush.c
+++ b/arch/csky/abiv2/cacheflush.c
@@ -34,10 +34,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
34{ 34{
35 unsigned long addr, pfn; 35 unsigned long addr, pfn;
36 struct page *page; 36 struct page *page;
37 void *va;
38
39 if (!(vma->vm_flags & VM_EXEC))
40 return;
41 37
42 pfn = pte_pfn(*pte); 38 pfn = pte_pfn(*pte);
43 if (unlikely(!pfn_valid(pfn))) 39 if (unlikely(!pfn_valid(pfn)))
@@ -47,14 +43,9 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
47 if (page == ZERO_PAGE(0)) 43 if (page == ZERO_PAGE(0))
48 return; 44 return;
49 45
50 va = page_address(page); 46 addr = (unsigned long) kmap_atomic(page);
51 addr = (unsigned long) va;
52
53 if (va == NULL && PageHighMem(page))
54 addr = (unsigned long) kmap_atomic(page);
55 47
56 cache_wbinv_range(addr, addr + PAGE_SIZE); 48 cache_wbinv_range(addr, addr + PAGE_SIZE);
57 49
58 if (va == NULL && PageHighMem(page)) 50 kunmap_atomic((void *) addr);
59 kunmap_atomic((void *) addr);
60} 51}
diff --git a/arch/csky/abiv2/inc/abi/ckmmu.h b/arch/csky/abiv2/inc/abi/ckmmu.h
index 97230ad9427c..e4480e6bc3b3 100644
--- a/arch/csky/abiv2/inc/abi/ckmmu.h
+++ b/arch/csky/abiv2/inc/abi/ckmmu.h
@@ -42,6 +42,26 @@ static inline void write_mmu_entryhi(int value)
42 mtcr("cr<4, 15>", value); 42 mtcr("cr<4, 15>", value);
43} 43}
44 44
45static inline unsigned long read_mmu_msa0(void)
46{
47 return mfcr("cr<30, 15>");
48}
49
50static inline void write_mmu_msa0(unsigned long value)
51{
52 mtcr("cr<30, 15>", value);
53}
54
55static inline unsigned long read_mmu_msa1(void)
56{
57 return mfcr("cr<31, 15>");
58}
59
60static inline void write_mmu_msa1(unsigned long value)
61{
62 mtcr("cr<31, 15>", value);
63}
64
45/* 65/*
46 * TLB operations. 66 * TLB operations.
47 */ 67 */
@@ -70,18 +90,16 @@ static inline void tlb_invalid_indexed(void)
70 mtcr("cr<8, 15>", 0x02000000); 90 mtcr("cr<8, 15>", 0x02000000);
71} 91}
72 92
73/* setup hardrefil pgd */
74static inline unsigned long get_pgd(void)
75{
76 return mfcr("cr<29, 15>");
77}
78
79static inline void setup_pgd(unsigned long pgd, bool kernel) 93static inline void setup_pgd(unsigned long pgd, bool kernel)
80{ 94{
81 if (kernel) 95 if (kernel)
82 mtcr("cr<28, 15>", pgd); 96 mtcr("cr<28, 15>", pgd | BIT(0));
83 else 97 else
84 mtcr("cr<29, 15>", pgd); 98 mtcr("cr<29, 15>", pgd | BIT(0));
85} 99}
86 100
101static inline unsigned long get_pgd(void)
102{
103 return mfcr("cr<29, 15>") & ~BIT(0);
104}
87#endif /* __ASM_CSKY_CKMMUV2_H */ 105#endif /* __ASM_CSKY_CKMMUV2_H */
diff --git a/arch/csky/abiv2/inc/abi/entry.h b/arch/csky/abiv2/inc/abi/entry.h
index edc5cc04c4de..9897a16b45e5 100644
--- a/arch/csky/abiv2/inc/abi/entry.h
+++ b/arch/csky/abiv2/inc/abi/entry.h
@@ -14,18 +14,11 @@
14#define LSAVE_A2 32 14#define LSAVE_A2 32
15#define LSAVE_A3 36 15#define LSAVE_A3 36
16 16
17#define EPC_INCREASE 4
18#define EPC_KEEP 0
19
20#define KSPTOUSP 17#define KSPTOUSP
21#define USPTOKSP 18#define USPTOKSP
22 19
23#define usp cr<14, 1> 20#define usp cr<14, 1>
24 21
25.macro INCTRAP rx
26 addi \rx, EPC_INCREASE
27.endm
28
29.macro SAVE_ALL epc_inc 22.macro SAVE_ALL epc_inc
30 subi sp, 152 23 subi sp, 152
31 stw tls, (sp, 0) 24 stw tls, (sp, 0)
@@ -169,10 +162,80 @@
169 mtcr \rx, cr<8, 15> 162 mtcr \rx, cr<8, 15>
170.endm 163.endm
171 164
172.macro SETUP_MMU rx 165.macro SETUP_MMU
173 lrw \rx, PHYS_OFFSET | 0xe 166 /* Init psr and enable ee */
174 mtcr \rx, cr<30, 15> 167 lrw r6, DEFAULT_PSR_VALUE
175 lrw \rx, (PHYS_OFFSET + 0x20000000) | 0xe 168 mtcr r6, psr
176 mtcr \rx, cr<31, 15> 169 psrset ee
170
171 /* Invalid I/Dcache BTB BHT */
172 movi r6, 7
173 lsli r6, 16
174 addi r6, (1<<4) | 3
175 mtcr r6, cr17
176
177 /* Invalid all TLB */
178 bgeni r6, 26
179 mtcr r6, cr<8, 15> /* Set MCIR */
180
181 /* Check MMU on/off */
182 mfcr r6, cr18
183 btsti r6, 0
184 bt 1f
185
186 /* MMU off: setup mapping tlb entry */
187 movi r6, 0
188 mtcr r6, cr<6, 15> /* Set MPR with 4K page size */
189
190 grs r6, 1f /* Get current pa by PC */
191 bmaski r7, (PAGE_SHIFT + 1) /* r7 = 0x1fff */
192 andn r6, r7
193 mtcr r6, cr<4, 15> /* Set MEH */
194
195 mov r8, r6
196 movi r7, 0x00000006
197 or r8, r7
198 mtcr r8, cr<2, 15> /* Set MEL0 */
199 movi r7, 0x00001006
200 or r8, r7
201 mtcr r8, cr<3, 15> /* Set MEL1 */
202
203 bgeni r8, 28
204 mtcr r8, cr<8, 15> /* Set MCIR to write TLB */
205
206 br 2f
2071:
208 /*
209 * MMU on: use origin MSA value from bootloader
210 *
211 * cr<30/31, 15> MSA register format:
212 * 31 - 29 | 28 - 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
213 * BA Reserved SH WA B SO SEC C D V
214 */
215 mfcr r6, cr<30, 15> /* Get MSA0 */
2162:
217 lsri r6, 28
218 lsli r6, 28
219 addi r6, 0x1ce
220 mtcr r6, cr<30, 15> /* Set MSA0 */
221
222 lsri r6, 28
223 addi r6, 2
224 lsli r6, 28
225 addi r6, 0x1ce
226 mtcr r6, cr<31, 15> /* Set MSA1 */
227
228 /* enable MMU */
229 mfcr r6, cr18
230 bseti r6, 0
231 mtcr r6, cr18
232
233 jmpi 3f /* jump to va */
2343:
235.endm
236
237.macro ANDI_R3 rx, imm
238 lsri \rx, 3
239 andi \rx, (\imm >> 3)
177.endm 240.endm
178#endif /* __ASM_CSKY_ENTRY_H */ 241#endif /* __ASM_CSKY_ENTRY_H */
diff --git a/arch/csky/abiv2/inc/abi/regdef.h b/arch/csky/abiv2/inc/abi/regdef.h
index c72abb781bdc..d7328bbc1ce7 100644
--- a/arch/csky/abiv2/inc/abi/regdef.h
+++ b/arch/csky/abiv2/inc/abi/regdef.h
@@ -5,9 +5,8 @@
5#define __ASM_CSKY_REGDEF_H 5#define __ASM_CSKY_REGDEF_H
6 6
7#define syscallid r7 7#define syscallid r7
8#define r11_sig r11
9
10#define regs_syscallid(regs) regs->regs[3] 8#define regs_syscallid(regs) regs->regs[3]
9#define regs_fp(regs) regs->regs[4]
11 10
12/* 11/*
13 * PSR format: 12 * PSR format:
@@ -23,4 +22,6 @@
23 22
24#define SYSTRACE_SAVENUM 5 23#define SYSTRACE_SAVENUM 5
25 24
25#define TRAP0_SIZE 4
26
26#endif /* __ASM_CSKY_REGDEF_H */ 27#endif /* __ASM_CSKY_REGDEF_H */
diff --git a/arch/csky/abiv2/mcount.S b/arch/csky/abiv2/mcount.S
index c633379956f5..326402e65f9e 100644
--- a/arch/csky/abiv2/mcount.S
+++ b/arch/csky/abiv2/mcount.S
@@ -61,10 +61,17 @@
61 addi sp, 16 61 addi sp, 16
62.endm 62.endm
63 63
64.macro nop32_stub
65 nop32
66 nop32
67 nop32
68.endm
69
64ENTRY(ftrace_stub) 70ENTRY(ftrace_stub)
65 jmp lr 71 jmp lr
66END(ftrace_stub) 72END(ftrace_stub)
67 73
74#ifndef CONFIG_DYNAMIC_FTRACE
68ENTRY(_mcount) 75ENTRY(_mcount)
69 mcount_enter 76 mcount_enter
70 77
@@ -76,7 +83,7 @@ ENTRY(_mcount)
76 bf skip_ftrace 83 bf skip_ftrace
77 84
78 mov a0, lr 85 mov a0, lr
79 subi a0, MCOUNT_INSN_SIZE 86 subi a0, 4
80 ldw a1, (sp, 24) 87 ldw a1, (sp, 24)
81 88
82 jsr r26 89 jsr r26
@@ -101,13 +108,41 @@ skip_ftrace:
101 mcount_exit 108 mcount_exit
102#endif 109#endif
103END(_mcount) 110END(_mcount)
111#else /* CONFIG_DYNAMIC_FTRACE */
112ENTRY(_mcount)
113 mov t1, lr
114 ldw lr, (sp, 0)
115 addi sp, 4
116 jmp t1
117ENDPROC(_mcount)
118
119ENTRY(ftrace_caller)
120 mcount_enter
121
122 ldw a0, (sp, 16)
123 subi a0, 4
124 ldw a1, (sp, 24)
125
126 nop
127GLOBAL(ftrace_call)
128 nop32_stub
129
130#ifdef CONFIG_FUNCTION_GRAPH_TRACER
131 nop
132GLOBAL(ftrace_graph_call)
133 nop32_stub
134#endif
135
136 mcount_exit
137ENDPROC(ftrace_caller)
138#endif /* CONFIG_DYNAMIC_FTRACE */
104 139
105#ifdef CONFIG_FUNCTION_GRAPH_TRACER 140#ifdef CONFIG_FUNCTION_GRAPH_TRACER
106ENTRY(ftrace_graph_caller) 141ENTRY(ftrace_graph_caller)
107 mov a0, sp 142 mov a0, sp
108 addi a0, 24 143 addi a0, 24
109 ldw a1, (sp, 16) 144 ldw a1, (sp, 16)
110 subi a1, MCOUNT_INSN_SIZE 145 subi a1, 4
111 mov a2, r8 146 mov a2, r8
112 lrw r26, prepare_ftrace_return 147 lrw r26, prepare_ftrace_return
113 jsr r26 148 jsr r26
diff --git a/arch/csky/abiv2/memmove.S b/arch/csky/abiv2/memmove.S
index b0c42ecf1889..5721e73ad3d8 100644
--- a/arch/csky/abiv2/memmove.S
+++ b/arch/csky/abiv2/memmove.S
@@ -35,11 +35,7 @@ ENTRY(memmove)
35.L_len_larger_16bytes: 35.L_len_larger_16bytes:
36 subi r1, 16 36 subi r1, 16
37 subi r0, 16 37 subi r0, 16
38#if defined(__CSKY_VDSPV2__) 38#if defined(__CK860__)
39 vldx.8 vr0, (r1), r19
40 PRE_BNEZAD (r18)
41 vstx.8 vr0, (r0), r19
42#elif defined(__CK860__)
43 ldw r3, (r1, 12) 39 ldw r3, (r1, 12)
44 stw r3, (r0, 12) 40 stw r3, (r0, 12)
45 ldw r3, (r1, 8) 41 ldw r3, (r1, 8)
diff --git a/arch/csky/include/asm/Kbuild b/arch/csky/include/asm/Kbuild
index 95f4e550db8a..a9b63efef416 100644
--- a/arch/csky/include/asm/Kbuild
+++ b/arch/csky/include/asm/Kbuild
@@ -12,7 +12,6 @@ generic-y += dma-mapping.h
12generic-y += emergency-restart.h 12generic-y += emergency-restart.h
13generic-y += exec.h 13generic-y += exec.h
14generic-y += fb.h 14generic-y += fb.h
15generic-y += ftrace.h
16generic-y += futex.h 15generic-y += futex.h
17generic-y += gpio.h 16generic-y += gpio.h
18generic-y += hardirq.h 17generic-y += hardirq.h
diff --git a/arch/csky/include/asm/ftrace.h b/arch/csky/include/asm/ftrace.h
index 7547c45312a8..ba35d93ecda2 100644
--- a/arch/csky/include/asm/ftrace.h
+++ b/arch/csky/include/asm/ftrace.h
@@ -4,10 +4,26 @@
4#ifndef __ASM_CSKY_FTRACE_H 4#ifndef __ASM_CSKY_FTRACE_H
5#define __ASM_CSKY_FTRACE_H 5#define __ASM_CSKY_FTRACE_H
6 6
7#define MCOUNT_INSN_SIZE 4 7#define MCOUNT_INSN_SIZE 14
8 8
9#define HAVE_FUNCTION_GRAPH_FP_TEST 9#define HAVE_FUNCTION_GRAPH_FP_TEST
10 10
11#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR 11#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
12 12
13#define MCOUNT_ADDR ((unsigned long)_mcount)
14
15#ifndef __ASSEMBLY__
16
17extern void _mcount(unsigned long);
18
19extern void ftrace_graph_call(void);
20
21static inline unsigned long ftrace_call_adjust(unsigned long addr)
22{
23 return addr;
24}
25
26struct dyn_arch_ftrace {
27};
28#endif /* !__ASSEMBLY__ */
13#endif /* __ASM_CSKY_FTRACE_H */ 29#endif /* __ASM_CSKY_FTRACE_H */
diff --git a/arch/csky/include/asm/mmu_context.h b/arch/csky/include/asm/mmu_context.h
index b2905c0485a7..734db3a122e1 100644
--- a/arch/csky/include/asm/mmu_context.h
+++ b/arch/csky/include/asm/mmu_context.h
@@ -14,23 +14,10 @@
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <abi/ckmmu.h> 15#include <abi/ckmmu.h>
16 16
17static inline void tlbmiss_handler_setup_pgd(unsigned long pgd, bool kernel)
18{
19 pgd -= PAGE_OFFSET;
20 pgd += PHYS_OFFSET;
21 pgd |= 1;
22 setup_pgd(pgd, kernel);
23}
24
25#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ 17#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
26 tlbmiss_handler_setup_pgd((unsigned long)pgd, 0) 18 setup_pgd(__pa(pgd), false)
27#define TLBMISS_HANDLER_SETUP_PGD_KERNEL(pgd) \ 19#define TLBMISS_HANDLER_SETUP_PGD_KERNEL(pgd) \
28 tlbmiss_handler_setup_pgd((unsigned long)pgd, 1) 20 setup_pgd(__pa(pgd), true)
29
30static inline unsigned long tlb_get_pgd(void)
31{
32 return ((get_pgd() - PHYS_OFFSET) & ~1) + PAGE_OFFSET;
33}
34 21
35#define cpu_context(cpu, mm) ((mm)->context.asid[cpu]) 22#define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
36#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) 23#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h
index 73cf2bd66a13..9738eacefdc7 100644
--- a/arch/csky/include/asm/page.h
+++ b/arch/csky/include/asm/page.h
@@ -8,7 +8,7 @@
8#include <linux/const.h> 8#include <linux/const.h>
9 9
10/* 10/*
11 * PAGE_SHIFT determines the page size 11 * PAGE_SHIFT determines the page size: 4KB
12 */ 12 */
13#define PAGE_SHIFT 12 13#define PAGE_SHIFT 12
14#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) 14#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
@@ -17,12 +17,18 @@
17#define THREAD_MASK (~(THREAD_SIZE - 1)) 17#define THREAD_MASK (~(THREAD_SIZE - 1))
18#define THREAD_SHIFT (PAGE_SHIFT + 1) 18#define THREAD_SHIFT (PAGE_SHIFT + 1)
19 19
20
20/* 21/*
21 * NOTE: virtual isn't really correct, actually it should be the offset into the 22 * For C-SKY "User-space:Kernel-space" is "2GB:2GB" fixed by hardware and there
22 * memory node, but we have no highmem, so that works for now. 23 * are two segment registers (MSA0 + MSA1) to mapping 512MB + 512MB physical
23 * TODO: implement (fast) pfn<->pgdat_idx conversion functions, this makes lots 24 * address region. We use them mapping kernel 1GB direct-map address area and
24 * of the shifts unnecessary. 25 * for more than 1GB of memory we use highmem.
25 */ 26 */
27#define PAGE_OFFSET 0x80000000
28#define SSEG_SIZE 0x20000000
29#define LOWMEM_LIMIT (SSEG_SIZE * 2)
30
31#define PHYS_OFFSET_OFFSET (CONFIG_RAM_BASE & (SSEG_SIZE - 1))
26 32
27#ifndef __ASSEMBLY__ 33#ifndef __ASSEMBLY__
28 34
@@ -50,9 +56,6 @@ struct page;
50 56
51struct vm_area_struct; 57struct vm_area_struct;
52 58
53/*
54 * These are used to make use of C type-checking..
55 */
56typedef struct { unsigned long pte_low; } pte_t; 59typedef struct { unsigned long pte_low; } pte_t;
57#define pte_val(x) ((x).pte_low) 60#define pte_val(x) ((x).pte_low)
58 61
@@ -69,18 +72,13 @@ typedef struct page *pgtable_t;
69#define __pgd(x) ((pgd_t) { (x) }) 72#define __pgd(x) ((pgd_t) { (x) })
70#define __pgprot(x) ((pgprot_t) { (x) }) 73#define __pgprot(x) ((pgprot_t) { (x) })
71 74
72#endif /* !__ASSEMBLY__ */ 75extern unsigned long va_pa_offset;
73 76
74#define PHYS_OFFSET (CONFIG_RAM_BASE & ~(LOWMEM_LIMIT - 1)) 77#define ARCH_PFN_OFFSET PFN_DOWN(va_pa_offset + PHYS_OFFSET_OFFSET)
75#define PHYS_OFFSET_OFFSET (CONFIG_RAM_BASE & (LOWMEM_LIMIT - 1))
76#define ARCH_PFN_OFFSET PFN_DOWN(CONFIG_RAM_BASE)
77 78
78#define PAGE_OFFSET 0x80000000 79#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + va_pa_offset)
79#define LOWMEM_LIMIT 0x40000000 80#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - va_pa_offset))
80 81
81#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
82#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - \
83 PHYS_OFFSET))
84#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0)) 82#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
85 83
86#define MAP_NR(x) PFN_DOWN((unsigned long)(x) - PAGE_OFFSET - \ 84#define MAP_NR(x) PFN_DOWN((unsigned long)(x) - PAGE_OFFSET - \
@@ -90,15 +88,10 @@ typedef struct page *pgtable_t;
90#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ 88#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
91 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) 89 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
92 90
93/*
94 * main RAM and kernel working space are coincident at 0x80000000, but to make
95 * life more interesting, there's also an uncached virtual shadow at 0xb0000000
96 * - these mappings are fixed in the MMU
97 */
98
99#define pfn_to_kaddr(x) __va(PFN_PHYS(x)) 91#define pfn_to_kaddr(x) __va(PFN_PHYS(x))
100 92
101#include <asm-generic/memory_model.h> 93#include <asm-generic/memory_model.h>
102#include <asm-generic/getorder.h> 94#include <asm-generic/getorder.h>
103 95
96#endif /* !__ASSEMBLY__ */
104#endif /* __ASM_CSKY_PAGE_H */ 97#endif /* __ASM_CSKY_PAGE_H */
diff --git a/arch/csky/include/asm/perf_event.h b/arch/csky/include/asm/perf_event.h
index ea8193122294..572093e11001 100644
--- a/arch/csky/include/asm/perf_event.h
+++ b/arch/csky/include/asm/perf_event.h
@@ -4,4 +4,12 @@
4#ifndef __ASM_CSKY_PERF_EVENT_H 4#ifndef __ASM_CSKY_PERF_EVENT_H
5#define __ASM_CSKY_PERF_EVENT_H 5#define __ASM_CSKY_PERF_EVENT_H
6 6
7#include <abi/regdef.h>
8
9#define perf_arch_fetch_caller_regs(regs, __ip) { \
10 (regs)->pc = (__ip); \
11 regs_fp(regs) = (unsigned long) __builtin_frame_address(0); \
12 asm volatile("mov %0, sp\n":"=r"((regs)->usp)); \
13}
14
7#endif /* __ASM_PERF_EVENT_ELF_H */ 15#endif /* __ASM_PERF_EVENT_ELF_H */
diff --git a/arch/csky/include/asm/ptrace.h b/arch/csky/include/asm/ptrace.h
new file mode 100644
index 000000000000..d0aba7b32417
--- /dev/null
+++ b/arch/csky/include/asm/ptrace.h
@@ -0,0 +1,41 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4#ifndef __ASM_CSKY_PTRACE_H
5#define __ASM_CSKY_PTRACE_H
6
7#include <uapi/asm/ptrace.h>
8#include <asm/traps.h>
9#include <linux/types.h>
10
11#ifndef __ASSEMBLY__
12
13#define PS_S 0x80000000 /* Supervisor Mode */
14
15#define arch_has_single_step() (1)
16#define current_pt_regs() \
17({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; })
18
19#define user_stack_pointer(regs) ((regs)->usp)
20
21#define user_mode(regs) (!((regs)->sr & PS_S))
22#define instruction_pointer(regs) ((regs)->pc)
23#define profile_pc(regs) instruction_pointer(regs)
24
25static inline bool in_syscall(struct pt_regs const *regs)
26{
27 return ((regs->sr >> 16) & 0xff) == VEC_TRAP0;
28}
29
30static inline void forget_syscall(struct pt_regs *regs)
31{
32 regs->sr &= ~(0xff << 16);
33}
34
35static inline unsigned long regs_return_value(struct pt_regs *regs)
36{
37 return regs->a0;
38}
39
40#endif /* __ASSEMBLY__ */
41#endif /* __ASM_CSKY_PTRACE_H */
diff --git a/arch/csky/include/asm/syscall.h b/arch/csky/include/asm/syscall.h
index bc0d8717d28b..f624fa3bbc22 100644
--- a/arch/csky/include/asm/syscall.h
+++ b/arch/csky/include/asm/syscall.h
@@ -8,6 +8,8 @@
8#include <abi/regdef.h> 8#include <abi/regdef.h>
9#include <uapi/linux/audit.h> 9#include <uapi/linux/audit.h>
10 10
11extern void *sys_call_table[];
12
11static inline int 13static inline int
12syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 14syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
13{ 15{
@@ -15,6 +17,13 @@ syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
15} 17}
16 18
17static inline void 19static inline void
20syscall_set_nr(struct task_struct *task, struct pt_regs *regs,
21 int sysno)
22{
23 regs_syscallid(regs) = sysno;
24}
25
26static inline void
18syscall_rollback(struct task_struct *task, struct pt_regs *regs) 27syscall_rollback(struct task_struct *task, struct pt_regs *regs)
19{ 28{
20 regs->a0 = regs->orig_a0; 29 regs->a0 = regs->orig_a0;
diff --git a/arch/csky/include/asm/thread_info.h b/arch/csky/include/asm/thread_info.h
index 0e9d035d712b..0b546a55a8bf 100644
--- a/arch/csky/include/asm/thread_info.h
+++ b/arch/csky/include/asm/thread_info.h
@@ -51,29 +51,26 @@ static inline struct thread_info *current_thread_info(void)
51 51
52#endif /* !__ASSEMBLY__ */ 52#endif /* !__ASSEMBLY__ */
53 53
54/* entry.S relies on these definitions!
55 * bits 0-5 are tested at every exception exit
56 */
57#define TIF_SIGPENDING 0 /* signal pending */ 54#define TIF_SIGPENDING 0 /* signal pending */
58#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ 55#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
59#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ 56#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
60#define TIF_SYSCALL_TRACE 5 /* syscall trace active */ 57#define TIF_SYSCALL_TRACE 3 /* syscall trace active */
61#define TIF_DELAYED_TRACE 14 /* single step a syscall */ 58#define TIF_SYSCALL_TRACEPOINT 4 /* syscall tracepoint instrumentation */
59#define TIF_SYSCALL_AUDIT 5 /* syscall auditing */
62#define TIF_POLLING_NRFLAG 16 /* poll_idle() is TIF_NEED_RESCHED */ 60#define TIF_POLLING_NRFLAG 16 /* poll_idle() is TIF_NEED_RESCHED */
63#define TIF_MEMDIE 18 /* is terminating due to OOM killer */ 61#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
64#define TIF_FREEZE 19 /* thread is freezing for suspend */
65#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */ 62#define TIF_RESTORE_SIGMASK 20 /* restore signal mask in do_signal() */
66#define TIF_SECCOMP 21 /* secure computing */ 63#define TIF_SECCOMP 21 /* secure computing */
67 64
68#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) 65#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
69#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) 66#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
70#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) 67#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
71#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 68#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
72#define _TIF_DELAYED_TRACE (1 << TIF_DELAYED_TRACE) 69#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
73#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) 70#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
71#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
74#define _TIF_MEMDIE (1 << TIF_MEMDIE) 72#define _TIF_MEMDIE (1 << TIF_MEMDIE)
75#define _TIF_FREEZE (1 << TIF_FREEZE) 73#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
76#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) 74#define _TIF_SECCOMP (1 << TIF_SECCOMP)
77#define _TIF_SECCOMP (1 << TIF_SECCOMP)
78 75
79#endif /* _ASM_CSKY_THREAD_INFO_H */ 76#endif /* _ASM_CSKY_THREAD_INFO_H */
diff --git a/arch/csky/include/asm/unistd.h b/arch/csky/include/asm/unistd.h
index 284487477a61..da7a18295615 100644
--- a/arch/csky/include/asm/unistd.h
+++ b/arch/csky/include/asm/unistd.h
@@ -2,3 +2,5 @@
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3 3
4#include <uapi/asm/unistd.h> 4#include <uapi/asm/unistd.h>
5
6#define NR_syscalls (__NR_syscalls)
diff --git a/arch/csky/include/uapi/asm/perf_regs.h b/arch/csky/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..ee323d818592
--- /dev/null
+++ b/arch/csky/include/uapi/asm/perf_regs.h
@@ -0,0 +1,51 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
3
4#ifndef _ASM_CSKY_PERF_REGS_H
5#define _ASM_CSKY_PERF_REGS_H
6
7/* Index of struct pt_regs */
8enum perf_event_csky_regs {
9 PERF_REG_CSKY_TLS,
10 PERF_REG_CSKY_LR,
11 PERF_REG_CSKY_PC,
12 PERF_REG_CSKY_SR,
13 PERF_REG_CSKY_SP,
14 PERF_REG_CSKY_ORIG_A0,
15 PERF_REG_CSKY_A0,
16 PERF_REG_CSKY_A1,
17 PERF_REG_CSKY_A2,
18 PERF_REG_CSKY_A3,
19 PERF_REG_CSKY_REGS0,
20 PERF_REG_CSKY_REGS1,
21 PERF_REG_CSKY_REGS2,
22 PERF_REG_CSKY_REGS3,
23 PERF_REG_CSKY_REGS4,
24 PERF_REG_CSKY_REGS5,
25 PERF_REG_CSKY_REGS6,
26 PERF_REG_CSKY_REGS7,
27 PERF_REG_CSKY_REGS8,
28 PERF_REG_CSKY_REGS9,
29#if defined(__CSKYABIV2__)
30 PERF_REG_CSKY_EXREGS0,
31 PERF_REG_CSKY_EXREGS1,
32 PERF_REG_CSKY_EXREGS2,
33 PERF_REG_CSKY_EXREGS3,
34 PERF_REG_CSKY_EXREGS4,
35 PERF_REG_CSKY_EXREGS5,
36 PERF_REG_CSKY_EXREGS6,
37 PERF_REG_CSKY_EXREGS7,
38 PERF_REG_CSKY_EXREGS8,
39 PERF_REG_CSKY_EXREGS9,
40 PERF_REG_CSKY_EXREGS10,
41 PERF_REG_CSKY_EXREGS11,
42 PERF_REG_CSKY_EXREGS12,
43 PERF_REG_CSKY_EXREGS13,
44 PERF_REG_CSKY_EXREGS14,
45 PERF_REG_CSKY_HI,
46 PERF_REG_CSKY_LO,
47 PERF_REG_CSKY_DCSR,
48#endif
49 PERF_REG_CSKY_MAX,
50};
51#endif /* _ASM_CSKY_PERF_REGS_H */
diff --git a/arch/csky/include/uapi/asm/ptrace.h b/arch/csky/include/uapi/asm/ptrace.h
index a4eaa8ddf0b1..4e248d5b86ef 100644
--- a/arch/csky/include/uapi/asm/ptrace.h
+++ b/arch/csky/include/uapi/asm/ptrace.h
@@ -48,20 +48,5 @@ struct user_fp {
48 unsigned long reserved; 48 unsigned long reserved;
49}; 49};
50 50
51#ifdef __KERNEL__
52
53#define PS_S 0x80000000 /* Supervisor Mode */
54
55#define arch_has_single_step() (1)
56#define current_pt_regs() \
57({ (struct pt_regs *)((char *)current_thread_info() + THREAD_SIZE) - 1; })
58
59#define user_stack_pointer(regs) ((regs)->usp)
60
61#define user_mode(regs) (!((regs)->sr & PS_S))
62#define instruction_pointer(regs) ((regs)->pc)
63#define profile_pc(regs) instruction_pointer(regs)
64
65#endif /* __KERNEL__ */
66#endif /* __ASSEMBLY__ */ 51#endif /* __ASSEMBLY__ */
67#endif /* _CSKY_PTRACE_H */ 52#endif /* _CSKY_PTRACE_H */
diff --git a/arch/csky/kernel/Makefile b/arch/csky/kernel/Makefile
index 484e6d3a3647..1624b04bffb5 100644
--- a/arch/csky/kernel/Makefile
+++ b/arch/csky/kernel/Makefile
@@ -9,6 +9,8 @@ obj-$(CONFIG_SMP) += smp.o
9obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o 9obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o
10obj-$(CONFIG_STACKTRACE) += stacktrace.o 10obj-$(CONFIG_STACKTRACE) += stacktrace.o
11obj-$(CONFIG_CSKY_PMU_V1) += perf_event.o 11obj-$(CONFIG_CSKY_PMU_V1) += perf_event.o
12obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
13obj-$(CONFIG_HAVE_PERF_REGS) += perf_regs.o
12 14
13ifdef CONFIG_FUNCTION_TRACER 15ifdef CONFIG_FUNCTION_TRACER
14CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) 16CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
diff --git a/arch/csky/kernel/atomic.S b/arch/csky/kernel/atomic.S
index d2357c8f85bd..5b84f11485ae 100644
--- a/arch/csky/kernel/atomic.S
+++ b/arch/csky/kernel/atomic.S
@@ -12,11 +12,10 @@
12 * If *ptr != oldval && return 1, 12 * If *ptr != oldval && return 1,
13 * else *ptr = newval return 0. 13 * else *ptr = newval return 0.
14 */ 14 */
15#ifdef CONFIG_CPU_HAS_LDSTEX
16ENTRY(csky_cmpxchg) 15ENTRY(csky_cmpxchg)
17 USPTOKSP 16 USPTOKSP
18 mfcr a3, epc 17 mfcr a3, epc
19 INCTRAP a3 18 addi a3, TRAP0_SIZE
20 19
21 subi sp, 8 20 subi sp, 8
22 stw a3, (sp, 0) 21 stw a3, (sp, 0)
@@ -24,6 +23,7 @@ ENTRY(csky_cmpxchg)
24 stw a3, (sp, 4) 23 stw a3, (sp, 4)
25 24
26 psrset ee 25 psrset ee
26#ifdef CONFIG_CPU_HAS_LDSTEX
271: 271:
28 ldex a3, (a2) 28 ldex a3, (a2)
29 cmpne a0, a3 29 cmpne a0, a3
@@ -33,27 +33,7 @@ ENTRY(csky_cmpxchg)
33 bez a3, 1b 33 bez a3, 1b
342: 342:
35 sync.is 35 sync.is
36 mvc a0
37 ldw a3, (sp, 0)
38 mtcr a3, epc
39 ldw a3, (sp, 4)
40 mtcr a3, epsr
41 addi sp, 8
42 KSPTOUSP
43 rte
44END(csky_cmpxchg)
45#else 36#else
46ENTRY(csky_cmpxchg)
47 USPTOKSP
48 mfcr a3, epc
49 INCTRAP a3
50
51 subi sp, 8
52 stw a3, (sp, 0)
53 mfcr a3, epsr
54 stw a3, (sp, 4)
55
56 psrset ee
571: 371:
58 ldw a3, (a2) 38 ldw a3, (a2)
59 cmpne a0, a3 39 cmpne a0, a3
@@ -61,6 +41,7 @@ ENTRY(csky_cmpxchg)
612: 412:
62 stw a1, (a2) 42 stw a1, (a2)
633: 433:
44#endif
64 mvc a0 45 mvc a0
65 ldw a3, (sp, 0) 46 ldw a3, (sp, 0)
66 mtcr a3, epc 47 mtcr a3, epc
@@ -71,6 +52,7 @@ ENTRY(csky_cmpxchg)
71 rte 52 rte
72END(csky_cmpxchg) 53END(csky_cmpxchg)
73 54
55#ifndef CONFIG_CPU_HAS_LDSTEX
74/* 56/*
75 * Called from tlbmodified exception 57 * Called from tlbmodified exception
76 */ 58 */
diff --git a/arch/csky/kernel/entry.S b/arch/csky/kernel/entry.S
index 5137ed9062bd..a7e84ccccbd8 100644
--- a/arch/csky/kernel/entry.S
+++ b/arch/csky/kernel/entry.S
@@ -40,7 +40,8 @@ ENTRY(csky_\name)
40 WR_MCIR a2 40 WR_MCIR a2
41#endif 41#endif
42 bclri r6, 0 42 bclri r6, 0
43 lrw a2, PHYS_OFFSET 43 lrw a2, va_pa_offset
44 ld.w a2, (a2, 0)
44 subu r6, a2 45 subu r6, a2
45 bseti r6, 31 46 bseti r6, 31
46 47
@@ -50,7 +51,8 @@ ENTRY(csky_\name)
50 addu r6, a2 51 addu r6, a2
51 ldw r6, (r6) 52 ldw r6, (r6)
52 53
53 lrw a2, PHYS_OFFSET 54 lrw a2, va_pa_offset
55 ld.w a2, (a2, 0)
54 subu r6, a2 56 subu r6, a2
55 bseti r6, 31 57 bseti r6, 31
56 58
@@ -91,7 +93,7 @@ ENTRY(csky_\name)
91 mfcr a3, ss2 93 mfcr a3, ss2
92 mfcr r6, ss3 94 mfcr r6, ss3
93 mfcr a2, ss4 95 mfcr a2, ss4
94 SAVE_ALL EPC_KEEP 96 SAVE_ALL 0
95.endm 97.endm
96.macro tlbop_end is_write 98.macro tlbop_end is_write
97 RD_MEH a2 99 RD_MEH a2
@@ -99,7 +101,6 @@ ENTRY(csky_\name)
99 mov a0, sp 101 mov a0, sp
100 movi a1, \is_write 102 movi a1, \is_write
101 jbsr do_page_fault 103 jbsr do_page_fault
102 movi r11_sig, 0 /* r11 = 0, Not a syscall. */
103 jmpi ret_from_exception 104 jmpi ret_from_exception
104.endm 105.endm
105 106
@@ -118,7 +119,7 @@ jbsr csky_cmpxchg_fixup
118tlbop_end 1 119tlbop_end 1
119 120
120ENTRY(csky_systemcall) 121ENTRY(csky_systemcall)
121 SAVE_ALL EPC_INCREASE 122 SAVE_ALL TRAP0_SIZE
122 123
123 psrset ee, ie 124 psrset ee, ie
124 125
@@ -136,8 +137,9 @@ ENTRY(csky_systemcall)
136 bmaski r10, THREAD_SHIFT 137 bmaski r10, THREAD_SHIFT
137 andn r9, r10 138 andn r9, r10
138 ldw r8, (r9, TINFO_FLAGS) 139 ldw r8, (r9, TINFO_FLAGS)
139 btsti r8, TIF_SYSCALL_TRACE 140 ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
140 bt 1f 141 cmpnei r8, 0
142 bt csky_syscall_trace
141#if defined(__CSKYABIV2__) 143#if defined(__CSKYABIV2__)
142 subi sp, 8 144 subi sp, 8
143 stw r5, (sp, 0x4) 145 stw r5, (sp, 0x4)
@@ -150,10 +152,9 @@ ENTRY(csky_systemcall)
150 stw a0, (sp, LSAVE_A0) /* Save return value */ 152 stw a0, (sp, LSAVE_A0) /* Save return value */
151 jmpi ret_from_exception 153 jmpi ret_from_exception
152 154
1531: 155csky_syscall_trace:
154 movi a0, 0 /* enter system call */ 156 mov a0, sp /* sp = pt_regs pointer */
155 mov a1, sp /* sp = pt_regs pointer */ 157 jbsr syscall_trace_enter
156 jbsr syscall_trace
157 /* Prepare args before do system call */ 158 /* Prepare args before do system call */
158 ldw a0, (sp, LSAVE_A0) 159 ldw a0, (sp, LSAVE_A0)
159 ldw a1, (sp, LSAVE_A1) 160 ldw a1, (sp, LSAVE_A1)
@@ -173,9 +174,8 @@ ENTRY(csky_systemcall)
173#endif 174#endif
174 stw a0, (sp, LSAVE_A0) /* Save return value */ 175 stw a0, (sp, LSAVE_A0) /* Save return value */
175 176
176 movi a0, 1 /* leave system call */ 177 mov a0, sp /* right now, sp --> pt_regs */
177 mov a1, sp /* right now, sp --> pt_regs */ 178 jbsr syscall_trace_exit
178 jbsr syscall_trace
179 br ret_from_exception 179 br ret_from_exception
180 180
181ENTRY(ret_from_kernel_thread) 181ENTRY(ret_from_kernel_thread)
@@ -190,14 +190,11 @@ ENTRY(ret_from_fork)
190 bmaski r10, THREAD_SHIFT 190 bmaski r10, THREAD_SHIFT
191 andn r9, r10 191 andn r9, r10
192 ldw r8, (r9, TINFO_FLAGS) 192 ldw r8, (r9, TINFO_FLAGS)
193 movi r11_sig, 1 193 ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
194 btsti r8, TIF_SYSCALL_TRACE 194 cmpnei r8, 0
195 bf 3f 195 bf ret_from_exception
196 movi a0, 1 196 mov a0, sp /* sp = pt_regs pointer */
197 mov a1, sp /* sp = pt_regs pointer */ 197 jbsr syscall_trace_exit
198 jbsr syscall_trace
1993:
200 jbsr ret_from_exception
201 198
202ret_from_exception: 199ret_from_exception:
203 ld syscallid, (sp, LSAVE_PSR) 200 ld syscallid, (sp, LSAVE_PSR)
@@ -212,41 +209,30 @@ ret_from_exception:
212 bmaski r10, THREAD_SHIFT 209 bmaski r10, THREAD_SHIFT
213 andn r9, r10 210 andn r9, r10
214 211
215resume_userspace:
216 ldw r8, (r9, TINFO_FLAGS) 212 ldw r8, (r9, TINFO_FLAGS)
217 andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) 213 andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
218 cmpnei r8, 0 214 cmpnei r8, 0
219 bt exit_work 215 bt exit_work
2201: RESTORE_ALL 2161:
217 RESTORE_ALL
221 218
222exit_work: 219exit_work:
220 lrw syscallid, ret_from_exception
221 mov lr, syscallid
222
223 btsti r8, TIF_NEED_RESCHED 223 btsti r8, TIF_NEED_RESCHED
224 bt work_resched 224 bt work_resched
225 /* If thread_info->flag is empty, RESTORE_ALL */ 225
226 cmpnei r8, 0 226 mov a0, sp
227 bf 1b 227 mov a1, r8
228 mov a1, sp 228 jmpi do_notify_resume
229 mov a0, r8
230 mov a2, r11_sig /* syscall? */
231 btsti r8, TIF_SIGPENDING /* delivering a signal? */
232 /* prevent further restarts(set r11 = 0) */
233 clrt r11_sig
234 jbsr do_notify_resume /* do signals */
235 br resume_userspace
236 229
237work_resched: 230work_resched:
238 lrw syscallid, ret_from_exception
239 mov r15, syscallid /* Return address in link */
240 jmpi schedule 231 jmpi schedule
241 232
242ENTRY(sys_rt_sigreturn)
243 movi r11_sig, 0
244 jmpi do_rt_sigreturn
245
246ENTRY(csky_trap) 233ENTRY(csky_trap)
247 SAVE_ALL EPC_KEEP 234 SAVE_ALL 0
248 psrset ee 235 psrset ee
249 movi r11_sig, 0 /* r11 = 0, Not a syscall. */
250 mov a0, sp /* Push Stack pointer arg */ 236 mov a0, sp /* Push Stack pointer arg */
251 jbsr trap_c /* Call C-level trap handler */ 237 jbsr trap_c /* Call C-level trap handler */
252 jmpi ret_from_exception 238 jmpi ret_from_exception
@@ -261,7 +247,7 @@ ENTRY(csky_get_tls)
261 247
262 /* increase epc for continue */ 248 /* increase epc for continue */
263 mfcr a0, epc 249 mfcr a0, epc
264 INCTRAP a0 250 addi a0, TRAP0_SIZE
265 mtcr a0, epc 251 mtcr a0, epc
266 252
267 /* get current task thread_info with kernel 8K stack */ 253 /* get current task thread_info with kernel 8K stack */
@@ -278,9 +264,8 @@ ENTRY(csky_get_tls)
278 rte 264 rte
279 265
280ENTRY(csky_irq) 266ENTRY(csky_irq)
281 SAVE_ALL EPC_KEEP 267 SAVE_ALL 0
282 psrset ee 268 psrset ee
283 movi r11_sig, 0 /* r11 = 0, Not a syscall. */
284 269
285#ifdef CONFIG_PREEMPT 270#ifdef CONFIG_PREEMPT
286 mov r9, sp /* Get current stack pointer */ 271 mov r9, sp /* Get current stack pointer */
diff --git a/arch/csky/kernel/ftrace.c b/arch/csky/kernel/ftrace.c
index 274c431f1810..44f4880179b7 100644
--- a/arch/csky/kernel/ftrace.c
+++ b/arch/csky/kernel/ftrace.c
@@ -3,6 +3,137 @@
3 3
4#include <linux/ftrace.h> 4#include <linux/ftrace.h>
5#include <linux/uaccess.h> 5#include <linux/uaccess.h>
6#include <asm/cacheflush.h>
7
8#ifdef CONFIG_DYNAMIC_FTRACE
9
10#define NOP 0x4000
11#define NOP32_HI 0xc400
12#define NOP32_LO 0x4820
13#define PUSH_LR 0x14d0
14#define MOVIH_LINK 0xea3a
15#define ORI_LINK 0xef5a
16#define JSR_LINK 0xe8fa
17#define BSR_LINK 0xe000
18
19/*
20 * Gcc-csky with -pg will insert stub in function prologue:
21 * push lr
22 * jbsr _mcount
23 * nop32
24 * nop32
25 *
26 * If the (callee - current_pc) is less then 64MB, we'll use bsr:
27 * push lr
28 * bsr _mcount
29 * nop32
30 * nop32
31 * else we'll use (movih + ori + jsr):
32 * push lr
33 * movih r26, ...
34 * ori r26, ...
35 * jsr r26
36 *
37 * (r26 is our reserved link-reg)
38 *
39 */
40static inline void make_jbsr(unsigned long callee, unsigned long pc,
41 uint16_t *call, bool nolr)
42{
43 long offset;
44
45 call[0] = nolr ? NOP : PUSH_LR;
46
47 offset = (long) callee - (long) pc;
48
49 if (unlikely(offset < -67108864 || offset > 67108864)) {
50 call[1] = MOVIH_LINK;
51 call[2] = callee >> 16;
52 call[3] = ORI_LINK;
53 call[4] = callee & 0xffff;
54 call[5] = JSR_LINK;
55 call[6] = 0;
56 } else {
57 offset = offset >> 1;
58
59 call[1] = BSR_LINK |
60 ((uint16_t)((unsigned long) offset >> 16) & 0x3ff);
61 call[2] = (uint16_t)((unsigned long) offset & 0xffff);
62 call[3] = call[5] = NOP32_HI;
63 call[4] = call[6] = NOP32_LO;
64 }
65}
66
67static uint16_t nops[7] = {NOP, NOP32_HI, NOP32_LO, NOP32_HI, NOP32_LO,
68 NOP32_HI, NOP32_LO};
69static int ftrace_check_current_nop(unsigned long hook)
70{
71 uint16_t olds[7];
72 unsigned long hook_pos = hook - 2;
73
74 if (probe_kernel_read((void *)olds, (void *)hook_pos, sizeof(nops)))
75 return -EFAULT;
76
77 if (memcmp((void *)nops, (void *)olds, sizeof(nops))) {
78 pr_err("%p: nop but get (%04x %04x %04x %04x %04x %04x %04x)\n",
79 (void *)hook_pos,
80 olds[0], olds[1], olds[2], olds[3], olds[4], olds[5],
81 olds[6]);
82
83 return -EINVAL;
84 }
85
86 return 0;
87}
88
89static int ftrace_modify_code(unsigned long hook, unsigned long target,
90 bool enable, bool nolr)
91{
92 uint16_t call[7];
93
94 unsigned long hook_pos = hook - 2;
95 int ret = 0;
96
97 make_jbsr(target, hook, call, nolr);
98
99 ret = probe_kernel_write((void *)hook_pos, enable ? call : nops,
100 sizeof(nops));
101 if (ret)
102 return -EPERM;
103
104 flush_icache_range(hook_pos, hook_pos + MCOUNT_INSN_SIZE);
105
106 return 0;
107}
108
109int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
110{
111 int ret = ftrace_check_current_nop(rec->ip);
112
113 if (ret)
114 return ret;
115
116 return ftrace_modify_code(rec->ip, addr, true, false);
117}
118
119int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
120 unsigned long addr)
121{
122 return ftrace_modify_code(rec->ip, addr, false, false);
123}
124
125int ftrace_update_ftrace_func(ftrace_func_t func)
126{
127 int ret = ftrace_modify_code((unsigned long)&ftrace_call,
128 (unsigned long)func, true, true);
129 return ret;
130}
131
132int __init ftrace_dyn_arch_init(void)
133{
134 return 0;
135}
136#endif /* CONFIG_DYNAMIC_FTRACE */
6 137
7#ifdef CONFIG_FUNCTION_GRAPH_TRACER 138#ifdef CONFIG_FUNCTION_GRAPH_TRACER
8void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, 139void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
@@ -43,8 +174,21 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
43 *(unsigned long *)frame_pointer = return_hooker; 174 *(unsigned long *)frame_pointer = return_hooker;
44 } 175 }
45} 176}
46#endif 177
178#ifdef CONFIG_DYNAMIC_FTRACE
179int ftrace_enable_ftrace_graph_caller(void)
180{
181 return ftrace_modify_code((unsigned long)&ftrace_graph_call,
182 (unsigned long)&ftrace_graph_caller, true, true);
183}
184
185int ftrace_disable_ftrace_graph_caller(void)
186{
187 return ftrace_modify_code((unsigned long)&ftrace_graph_call,
188 (unsigned long)&ftrace_graph_caller, false, true);
189}
190#endif /* CONFIG_DYNAMIC_FTRACE */
191#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
47 192
48/* _mcount is defined in abi's mcount.S */ 193/* _mcount is defined in abi's mcount.S */
49extern void _mcount(void);
50EXPORT_SYMBOL(_mcount); 194EXPORT_SYMBOL(_mcount);
diff --git a/arch/csky/kernel/head.S b/arch/csky/kernel/head.S
index 9c4ec473b76b..61989f9241c0 100644
--- a/arch/csky/kernel/head.S
+++ b/arch/csky/kernel/head.S
@@ -7,16 +7,11 @@
7 7
8__HEAD 8__HEAD
9ENTRY(_start) 9ENTRY(_start)
10 /* set super user mode */ 10 SETUP_MMU
11 lrw a3, DEFAULT_PSR_VALUE
12 mtcr a3, psr
13 psrset ee
14
15 SETUP_MMU a3
16 11
17 /* set stack point */ 12 /* set stack point */
18 lrw a3, init_thread_union + THREAD_SIZE 13 lrw r6, init_thread_union + THREAD_SIZE
19 mov sp, a3 14 mov sp, r6
20 15
21 jmpi csky_start 16 jmpi csky_start
22END(_start) 17END(_start)
@@ -24,53 +19,12 @@ END(_start)
24#ifdef CONFIG_SMP 19#ifdef CONFIG_SMP
25.align 10 20.align 10
26ENTRY(_start_smp_secondary) 21ENTRY(_start_smp_secondary)
27 /* Invalid I/Dcache BTB BHT */ 22 SETUP_MMU
28 movi a3, 7
29 lsli a3, 16
30 addi a3, (1<<4) | 3
31 mtcr a3, cr17
32
33 tlbi.alls
34
35 /* setup PAGEMASK */
36 movi a3, 0
37 mtcr a3, cr<6, 15>
38
39 /* setup MEL0/MEL1 */
40 grs a0, _start_smp_pc
41_start_smp_pc:
42 bmaski a1, 13
43 andn a0, a1
44 movi a1, 0x00000006
45 movi a2, 0x00001006
46 or a1, a0
47 or a2, a0
48 mtcr a1, cr<2, 15>
49 mtcr a2, cr<3, 15>
50
51 /* setup MEH */
52 mtcr a0, cr<4, 15>
53
54 /* write TLB */
55 bgeni a3, 28
56 mtcr a3, cr<8, 15>
57
58 SETUP_MMU a3
59
60 /* enable MMU */
61 movi a3, 1
62 mtcr a3, cr18
63
64 jmpi _goto_mmu_on
65_goto_mmu_on:
66 lrw a3, DEFAULT_PSR_VALUE
67 mtcr a3, psr
68 psrset ee
69 23
70 /* set stack point */ 24 /* set stack point */
71 lrw a3, secondary_stack 25 lrw r6, secondary_stack
72 ld.w a3, (a3, 0) 26 ld.w r6, (r6, 0)
73 mov sp, a3 27 mov sp, r6
74 28
75 jmpi csky_start_secondary 29 jmpi csky_start_secondary
76END(_start_smp_secondary) 30END(_start_smp_secondary)
diff --git a/arch/csky/kernel/perf_callchain.c b/arch/csky/kernel/perf_callchain.c
new file mode 100644
index 000000000000..e68ff375c8f8
--- /dev/null
+++ b/arch/csky/kernel/perf_callchain.c
@@ -0,0 +1,119 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/perf_event.h>
5#include <linux/uaccess.h>
6
7/* Kernel callchain */
8struct stackframe {
9 unsigned long fp;
10 unsigned long lr;
11};
12
13static int unwind_frame_kernel(struct stackframe *frame)
14{
15 if (kstack_end((void *)frame->fp))
16 return -EPERM;
17 if (frame->fp & 0x3 || frame->fp < TASK_SIZE)
18 return -EPERM;
19
20 *frame = *(struct stackframe *)frame->fp;
21 if (__kernel_text_address(frame->lr)) {
22 int graph = 0;
23
24 frame->lr = ftrace_graph_ret_addr(NULL, &graph, frame->lr,
25 NULL);
26 }
27 return 0;
28}
29
30static void notrace walk_stackframe(struct stackframe *fr,
31 struct perf_callchain_entry_ctx *entry)
32{
33 do {
34 perf_callchain_store(entry, fr->lr);
35 } while (unwind_frame_kernel(fr) >= 0);
36}
37
38/*
39 * Get the return address for a single stackframe and return a pointer to the
40 * next frame tail.
41 */
42static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
43 unsigned long fp, unsigned long reg_lr)
44{
45 struct stackframe buftail;
46 unsigned long lr = 0;
47 unsigned long *user_frame_tail = (unsigned long *)fp;
48
49 /* Check accessibility of one struct frame_tail beyond */
50 if (!access_ok(user_frame_tail, sizeof(buftail)))
51 return 0;
52 if (__copy_from_user_inatomic(&buftail, user_frame_tail,
53 sizeof(buftail)))
54 return 0;
55
56 if (reg_lr != 0)
57 lr = reg_lr;
58 else
59 lr = buftail.lr;
60
61 fp = buftail.fp;
62 perf_callchain_store(entry, lr);
63
64 return fp;
65}
66
67/*
68 * This will be called when the target is in user mode
69 * This function will only be called when we use
70 * "PERF_SAMPLE_CALLCHAIN" in
71 * kernel/events/core.c:perf_prepare_sample()
72 *
73 * How to trigger perf_callchain_[user/kernel] :
74 * $ perf record -e cpu-clock --call-graph fp ./program
75 * $ perf report --call-graph
76 *
77 * On C-SKY platform, the program being sampled and the C library
78 * need to be compiled with * -mbacktrace, otherwise the user
79 * stack will not contain function frame.
80 */
81void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
82 struct pt_regs *regs)
83{
84 unsigned long fp = 0;
85
86 /* C-SKY does not support virtualization. */
87 if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
88 return;
89
90 fp = regs->regs[4];
91 perf_callchain_store(entry, regs->pc);
92
93 /*
94 * While backtrace from leaf function, lr is normally
95 * not saved inside frame on C-SKY, so get lr from pt_regs
96 * at the sample point. However, lr value can be incorrect if
97 * lr is used as temp register
98 */
99 fp = user_backtrace(entry, fp, regs->lr);
100
101 while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
102 fp = user_backtrace(entry, fp, 0);
103}
104
105void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
106 struct pt_regs *regs)
107{
108 struct stackframe fr;
109
110 /* C-SKY does not support virtualization. */
111 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
112 pr_warn("C-SKY does not support perf in guest mode!");
113 return;
114 }
115
116 fr.fp = regs->regs[4];
117 fr.lr = regs->lr;
118 walk_stackframe(&fr, entry);
119}
diff --git a/arch/csky/kernel/perf_regs.c b/arch/csky/kernel/perf_regs.c
new file mode 100644
index 000000000000..eb32838b8210
--- /dev/null
+++ b/arch/csky/kernel/perf_regs.c
@@ -0,0 +1,40 @@
1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
3
4#include <linux/errno.h>
5#include <linux/kernel.h>
6#include <linux/perf_event.h>
7#include <linux/bug.h>
8#include <asm/perf_regs.h>
9#include <asm/ptrace.h>
10
11u64 perf_reg_value(struct pt_regs *regs, int idx)
12{
13 if (WARN_ON_ONCE((u32)idx >= PERF_REG_CSKY_MAX))
14 return 0;
15
16 return (u64)*((u32 *)regs + idx);
17}
18
19#define REG_RESERVED (~((1ULL << PERF_REG_CSKY_MAX) - 1))
20
21int perf_reg_validate(u64 mask)
22{
23 if (!mask || mask & REG_RESERVED)
24 return -EINVAL;
25
26 return 0;
27}
28
29u64 perf_reg_abi(struct task_struct *task)
30{
31 return PERF_SAMPLE_REGS_ABI_32;
32}
33
34void perf_get_regs_user(struct perf_regs *regs_user,
35 struct pt_regs *regs,
36 struct pt_regs *regs_user_copy)
37{
38 regs_user->regs = task_pt_regs(current);
39 regs_user->abi = perf_reg_abi(current);
40}
diff --git a/arch/csky/kernel/ptrace.c b/arch/csky/kernel/ptrace.c
index f2f12fff36f7..313623a19ecb 100644
--- a/arch/csky/kernel/ptrace.c
+++ b/arch/csky/kernel/ptrace.c
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3 3
4#include <linux/audit.h>
4#include <linux/elf.h> 5#include <linux/elf.h>
5#include <linux/errno.h> 6#include <linux/errno.h>
6#include <linux/kernel.h> 7#include <linux/kernel.h>
@@ -11,6 +12,7 @@
11#include <linux/sched/task_stack.h> 12#include <linux/sched/task_stack.h>
12#include <linux/signal.h> 13#include <linux/signal.h>
13#include <linux/smp.h> 14#include <linux/smp.h>
15#include <linux/tracehook.h>
14#include <linux/uaccess.h> 16#include <linux/uaccess.h>
15#include <linux/user.h> 17#include <linux/user.h>
16 18
@@ -22,6 +24,9 @@
22 24
23#include <abi/regdef.h> 25#include <abi/regdef.h>
24 26
27#define CREATE_TRACE_POINTS
28#include <trace/events/syscalls.h>
29
25/* sets the trace bits. */ 30/* sets the trace bits. */
26#define TRACE_MODE_SI (1 << 14) 31#define TRACE_MODE_SI (1 << 14)
27#define TRACE_MODE_RUN 0 32#define TRACE_MODE_RUN 0
@@ -207,35 +212,27 @@ long arch_ptrace(struct task_struct *child, long request,
207 return ret; 212 return ret;
208} 213}
209 214
210/* 215asmlinkage void syscall_trace_enter(struct pt_regs *regs)
211 * If process's system calls is traces, do some corresponding handles in this
212 * function before entering system call function and after exiting system call
213 * function.
214 */
215asmlinkage void syscall_trace(int why, struct pt_regs *regs)
216{ 216{
217 long saved_why; 217 if (test_thread_flag(TIF_SYSCALL_TRACE))
218 /* 218 if (tracehook_report_syscall_entry(regs))
219 * Save saved_why, why is used to denote syscall entry/exit; 219 syscall_set_nr(current, regs, -1);
220 * why = 0:entry, why = 1: exit 220
221 */ 221 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
222 saved_why = regs->regs[SYSTRACE_SAVENUM]; 222 trace_sys_enter(regs, syscall_get_nr(current, regs));
223 regs->regs[SYSTRACE_SAVENUM] = why; 223
224 224 audit_syscall_entry(regs_syscallid(regs), regs->a0, regs->a1, regs->a2, regs->a3);
225 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 225}
226 ? 0x80 : 0)); 226
227 227asmlinkage void syscall_trace_exit(struct pt_regs *regs)
228 /* 228{
229 * this isn't the same as continuing with a signal, but it will do 229 audit_syscall_exit(regs);
230 * for normal use. strace only continues with a signal if the 230
231 * stopping signal is not SIGTRAP. -brl 231 if (test_thread_flag(TIF_SYSCALL_TRACE))
232 */ 232 tracehook_report_syscall_exit(regs, 0);
233 if (current->exit_code) {
234 send_sig(current->exit_code, current, 1);
235 current->exit_code = 0;
236 }
237 233
238 regs->regs[SYSTRACE_SAVENUM] = saved_why; 234 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
235 trace_sys_exit(regs, syscall_get_return_value(current, regs));
239} 236}
240 237
241extern void show_stack(struct task_struct *task, unsigned long *stack); 238extern void show_stack(struct task_struct *task, unsigned long *stack);
diff --git a/arch/csky/kernel/setup.c b/arch/csky/kernel/setup.c
index dff8b89444ec..23ee604aafdb 100644
--- a/arch/csky/kernel/setup.c
+++ b/arch/csky/kernel/setup.c
@@ -142,18 +142,24 @@ void __init setup_arch(char **cmdline_p)
142#endif 142#endif
143} 143}
144 144
145asmlinkage __visible void __init csky_start(unsigned int unused, void *param) 145unsigned long va_pa_offset;
146EXPORT_SYMBOL(va_pa_offset);
147
148asmlinkage __visible void __init csky_start(unsigned int unused,
149 void *dtb_start)
146{ 150{
147 /* Clean up bss section */ 151 /* Clean up bss section */
148 memset(__bss_start, 0, __bss_stop - __bss_start); 152 memset(__bss_start, 0, __bss_stop - __bss_start);
149 153
154 va_pa_offset = read_mmu_msa0() & ~(SSEG_SIZE - 1);
155
150 pre_trap_init(); 156 pre_trap_init();
151 pre_mmu_init(); 157 pre_mmu_init();
152 158
153 if (param == NULL) 159 if (dtb_start == NULL)
154 early_init_dt_scan(__dtb_start); 160 early_init_dt_scan(__dtb_start);
155 else 161 else
156 early_init_dt_scan(param); 162 early_init_dt_scan(dtb_start);
157 163
158 start_kernel(); 164 start_kernel();
159 165
diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c
index 207a891479d2..04a43cfd4e09 100644
--- a/arch/csky/kernel/signal.c
+++ b/arch/csky/kernel/signal.c
@@ -1,26 +1,10 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3 2
4#include <linux/sched.h>
5#include <linux/mm.h>
6#include <linux/kernel.h>
7#include <linux/signal.h> 3#include <linux/signal.h>
4#include <linux/uaccess.h>
8#include <linux/syscalls.h> 5#include <linux/syscalls.h>
9#include <linux/errno.h>
10#include <linux/wait.h>
11#include <linux/ptrace.h>
12#include <linux/unistd.h>
13#include <linux/stddef.h>
14#include <linux/highuid.h>
15#include <linux/personality.h>
16#include <linux/tty.h>
17#include <linux/binfmts.h>
18#include <linux/tracehook.h> 6#include <linux/tracehook.h>
19#include <linux/freezer.h>
20#include <linux/uaccess.h>
21 7
22#include <asm/setup.h>
23#include <asm/pgtable.h>
24#include <asm/traps.h> 8#include <asm/traps.h>
25#include <asm/ucontext.h> 9#include <asm/ucontext.h>
26#include <asm/vdso.h> 10#include <asm/vdso.h>
@@ -29,110 +13,117 @@
29 13
30#ifdef CONFIG_CPU_HAS_FPU 14#ifdef CONFIG_CPU_HAS_FPU
31#include <abi/fpu.h> 15#include <abi/fpu.h>
32 16static int restore_fpu_state(struct sigcontext __user *sc)
33static int restore_fpu_state(struct sigcontext *sc)
34{ 17{
35 int err = 0; 18 int err = 0;
36 struct user_fp user_fp; 19 struct user_fp user_fp;
37 20
38 err = copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp)); 21 err = __copy_from_user(&user_fp, &sc->sc_user_fp, sizeof(user_fp));
39 22
40 restore_from_user_fp(&user_fp); 23 restore_from_user_fp(&user_fp);
41 24
42 return err; 25 return err;
43} 26}
44 27
45static int save_fpu_state(struct sigcontext *sc) 28static int save_fpu_state(struct sigcontext __user *sc)
46{ 29{
47 struct user_fp user_fp; 30 struct user_fp user_fp;
48 31
49 save_to_user_fp(&user_fp); 32 save_to_user_fp(&user_fp);
50 33
51 return copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp)); 34 return __copy_to_user(&sc->sc_user_fp, &user_fp, sizeof(user_fp));
52} 35}
53#else 36#else
54static inline int restore_fpu_state(struct sigcontext *sc) { return 0; } 37#define restore_fpu_state(sigcontext) (0)
55static inline int save_fpu_state(struct sigcontext *sc) { return 0; } 38#define save_fpu_state(sigcontext) (0)
56#endif 39#endif
57 40
58struct rt_sigframe { 41struct rt_sigframe {
59 int sig;
60 struct siginfo *pinfo;
61 void *puc;
62 struct siginfo info; 42 struct siginfo info;
63 struct ucontext uc; 43 struct ucontext uc;
64}; 44};
65 45
66static int 46static long restore_sigcontext(struct pt_regs *regs,
67restore_sigframe(struct pt_regs *regs, 47 struct sigcontext __user *sc)
68 struct sigcontext *sc, int *pr2)
69{ 48{
70 int err = 0; 49 int err = 0;
71 50
72 /* Always make any pending restarted system calls return -EINTR */ 51 /* sc_pt_regs is structured the same as the start of pt_regs */
73 current_thread_info()->task->restart_block.fn = do_no_restart_syscall; 52 err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
74
75 err |= copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
76 53
54 /* Restore the floating-point state. */
77 err |= restore_fpu_state(sc); 55 err |= restore_fpu_state(sc);
78 56
79 *pr2 = regs->a0;
80 return err; 57 return err;
81} 58}
82 59
83asmlinkage int 60SYSCALL_DEFINE0(rt_sigreturn)
84do_rt_sigreturn(void)
85{ 61{
86 sigset_t set;
87 int a0;
88 struct pt_regs *regs = current_pt_regs(); 62 struct pt_regs *regs = current_pt_regs();
89 struct rt_sigframe *frame = (struct rt_sigframe *)(regs->usp); 63 struct rt_sigframe __user *frame;
64 struct task_struct *task;
65 sigset_t set;
66
67 /* Always make any pending restarted system calls return -EINTR */
68 current->restart_block.fn = do_no_restart_syscall;
69
70 frame = (struct rt_sigframe __user *)regs->usp;
90 71
91 if (!access_ok(frame, sizeof(*frame))) 72 if (!access_ok(frame, sizeof(*frame)))
92 goto badframe; 73 goto badframe;
74
93 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 75 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
94 goto badframe; 76 goto badframe;
95 77
96 sigdelsetmask(&set, (sigmask(SIGKILL) | sigmask(SIGSTOP))); 78 set_current_blocked(&set);
97 spin_lock_irq(&current->sighand->siglock);
98 current->blocked = set;
99 recalc_sigpending();
100 spin_unlock_irq(&current->sighand->siglock);
101 79
102 if (restore_sigframe(regs, &frame->uc.uc_mcontext, &a0)) 80 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
103 goto badframe; 81 goto badframe;
104 82
105 return a0; 83 if (restore_altstack(&frame->uc.uc_stack))
84 goto badframe;
85
86 return regs->a0;
106 87
107badframe: 88badframe:
108 force_sig(SIGSEGV, current); 89 task = current;
90 force_sig(SIGSEGV, task);
109 return 0; 91 return 0;
110} 92}
111 93
112static int setup_sigframe(struct sigcontext *sc, struct pt_regs *regs) 94static int setup_sigcontext(struct rt_sigframe __user *frame,
95 struct pt_regs *regs)
113{ 96{
97 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
114 int err = 0; 98 int err = 0;
115 99
116 err |= copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs)); 100 err |= __copy_to_user(&sc->sc_pt_regs, regs, sizeof(struct pt_regs));
117 err |= save_fpu_state(sc); 101 err |= save_fpu_state(sc);
118 102
119 return err; 103 return err;
120} 104}
121 105
122static inline void * 106static inline void __user *get_sigframe(struct ksignal *ksig,
123get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 107 struct pt_regs *regs, size_t framesize)
124{ 108{
125 unsigned long usp; 109 unsigned long sp;
110 /* Default to using normal stack */
111 sp = regs->usp;
112
113 /*
114 * If we are on the alternate signal stack and would overflow it, don't.
115 * Return an always-bogus address instead so we will die with SIGSEGV.
116 */
117 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize)))
118 return (void __user __force *)(-1UL);
126 119
127 /* Default to using normal stack. */ 120 /* This is the X/Open sanctioned signal stack switching. */
128 usp = regs->usp; 121 sp = sigsp(sp, ksig) - framesize;
129 122
130 /* This is the X/Open sanctioned signal stack switching. */ 123 /* Align the stack frame. */
131 if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(usp)) { 124 sp &= -8UL;
132 if (!on_sig_stack(usp)) 125
133 usp = current->sas_ss_sp + current->sas_ss_size; 126 return (void __user *)sp;
134 }
135 return (void *)((usp - frame_size) & -8UL);
136} 127}
137 128
138static int 129static int
@@ -140,205 +131,128 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
140{ 131{
141 struct rt_sigframe *frame; 132 struct rt_sigframe *frame;
142 int err = 0; 133 int err = 0;
143
144 struct csky_vdso *vdso = current->mm->context.vdso; 134 struct csky_vdso *vdso = current->mm->context.vdso;
145 135
146 frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); 136 frame = get_sigframe(ksig, regs, sizeof(*frame));
147 if (!frame) 137 if (!access_ok(frame, sizeof(*frame)))
148 return 1; 138 return -EFAULT;
149 139
150 err |= __put_user(ksig->sig, &frame->sig);
151 err |= __put_user(&frame->info, &frame->pinfo);
152 err |= __put_user(&frame->uc, &frame->puc);
153 err |= copy_siginfo_to_user(&frame->info, &ksig->info); 140 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
154 141
155 /* Create the ucontext. */ 142 /* Create the ucontext. */
156 err |= __put_user(0, &frame->uc.uc_flags); 143 err |= __put_user(0, &frame->uc.uc_flags);
157 err |= __put_user(0, &frame->uc.uc_link); 144 err |= __put_user(NULL, &frame->uc.uc_link);
158 err |= __put_user((void *)current->sas_ss_sp, 145 err |= __save_altstack(&frame->uc.uc_stack, regs->usp);
159 &frame->uc.uc_stack.ss_sp); 146 err |= setup_sigcontext(frame, regs);
160 err |= __put_user(sas_ss_flags(regs->usp), 147 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
161 &frame->uc.uc_stack.ss_flags);
162 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
163 err |= setup_sigframe(&frame->uc.uc_mcontext, regs);
164 err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
165
166 if (err) 148 if (err)
167 goto give_sigsegv; 149 return -EFAULT;
168 150
169 /* Set up registers for signal handler */ 151 /* Set up to return from userspace. */
170 regs->usp = (unsigned long)frame; 152 regs->lr = (unsigned long)(vdso->rt_signal_retcode);
171 regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
172 regs->lr = (unsigned long)vdso->rt_signal_retcode;
173 153
174adjust_stack: 154 /*
175 regs->a0 = ksig->sig; /* first arg is signo */ 155 * Set up registers for signal handler.
176 regs->a1 = (unsigned long)(&(frame->info)); 156 * Registers that we don't modify keep the value they had from
177 regs->a2 = (unsigned long)(&(frame->uc)); 157 * user-space at the time we took the signal.
178 return err; 158 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
159 * since some things rely on this (e.g. glibc's debug/segfault.c).
160 */
161 regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
162 regs->usp = (unsigned long)frame;
163 regs->a0 = ksig->sig; /* a0: signal number */
164 regs->a1 = (unsigned long)(&(frame->info)); /* a1: siginfo pointer */
165 regs->a2 = (unsigned long)(&(frame->uc)); /* a2: ucontext pointer */
179 166
180give_sigsegv: 167 return 0;
181 if (ksig->sig == SIGSEGV)
182 ksig->ka.sa.sa_handler = SIG_DFL;
183 force_sig(SIGSEGV, current);
184 goto adjust_stack;
185} 168}
186 169
187/* 170static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
188 * OK, we're invoking a handler
189 */
190static int
191handle_signal(struct ksignal *ksig, struct pt_regs *regs)
192{ 171{
193 int ret;
194 sigset_t *oldset = sigmask_to_save(); 172 sigset_t *oldset = sigmask_to_save();
173 int ret;
195 174
196 /* 175 /* Are we from a system call? */
197 * set up the stack frame, regardless of SA_SIGINFO, 176 if (in_syscall(regs)) {
198 * and pass info anyway. 177 /* Avoid additional syscall restarting via ret_from_exception */
199 */ 178 forget_syscall(regs);
200 ret = setup_rt_frame(ksig, oldset, regs); 179
180 /* If so, check system call restarting.. */
181 switch (regs->a0) {
182 case -ERESTART_RESTARTBLOCK:
183 case -ERESTARTNOHAND:
184 regs->a0 = -EINTR;
185 break;
201 186
202 if (ret != 0) { 187 case -ERESTARTSYS:
203 force_sigsegv(ksig->sig, current); 188 if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
204 return ret; 189 regs->a0 = -EINTR;
190 break;
191 }
192 /* fallthrough */
193 case -ERESTARTNOINTR:
194 regs->a0 = regs->orig_a0;
195 regs->pc -= TRAP0_SIZE;
196 break;
197 }
205 } 198 }
206 199
207 /* Block the signal if we were successful. */ 200 /* Set up the stack frame */
208 spin_lock_irq(&current->sighand->siglock); 201 ret = setup_rt_frame(ksig, oldset, regs);
209 sigorsets(&current->blocked, &current->blocked, &ksig->ka.sa.sa_mask);
210 if (!(ksig->ka.sa.sa_flags & SA_NODEFER))
211 sigaddset(&current->blocked, ksig->sig);
212 recalc_sigpending();
213 spin_unlock_irq(&current->sighand->siglock);
214 202
215 return 0; 203 signal_setup_done(ret, ksig, 0);
216} 204}
217 205
218/* 206static void do_signal(struct pt_regs *regs)
219 * Note that 'init' is a special process: it doesn't get signals it doesn't
220 * want to handle. Thus you cannot kill init even with a SIGKILL even by
221 * mistake.
222 *
223 * Note that we go through the signals twice: once to check the signals
224 * that the kernel can handle, and then we build all the user-level signal
225 * handling stack-frames in one go after that.
226 */
227static void do_signal(struct pt_regs *regs, int syscall)
228{ 207{
229 unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
230 struct ksignal ksig; 208 struct ksignal ksig;
231 209
232 /* 210 if (get_signal(&ksig)) {
233 * We want the common case to go fast, which 211 /* Actually deliver the signal */
234 * is why we may in certain cases get here from 212 handle_signal(&ksig, regs);
235 * kernel mode. Just return without doing anything
236 * if so.
237 */
238 if (!user_mode(regs))
239 return; 213 return;
214 }
240 215
241 /* 216 /* Did we come from a system call? */
242 * If we were from a system call, check for system call restarting... 217 if (in_syscall(regs)) {
243 */ 218 /* Avoid additional syscall restarting via ret_from_exception */
244 if (syscall) { 219 forget_syscall(regs);
245 continue_addr = regs->pc;
246#if defined(__CSKYABIV2__)
247 restart_addr = continue_addr - 4;
248#else
249 restart_addr = continue_addr - 2;
250#endif
251 retval = regs->a0;
252 220
253 /* 221 /* Restart the system call - no handlers present */
254 * Prepare for system call restart. We do this here so that a 222 switch (regs->a0) {
255 * debugger will see the already changed.
256 */
257 switch (retval) {
258 case -ERESTARTNOHAND: 223 case -ERESTARTNOHAND:
259 case -ERESTARTSYS: 224 case -ERESTARTSYS:
260 case -ERESTARTNOINTR: 225 case -ERESTARTNOINTR:
261 regs->a0 = regs->orig_a0; 226 regs->a0 = regs->orig_a0;
262 regs->pc = restart_addr; 227 regs->pc -= TRAP0_SIZE;
263 break; 228 break;
264 case -ERESTART_RESTARTBLOCK: 229 case -ERESTART_RESTARTBLOCK:
265 regs->a0 = -EINTR; 230 regs->a0 = regs->orig_a0;
231 regs_syscallid(regs) = __NR_restart_syscall;
232 regs->pc -= TRAP0_SIZE;
266 break; 233 break;
267 } 234 }
268 } 235 }
269 236
270 if (try_to_freeze())
271 goto no_signal;
272
273 /* 237 /*
274 * Get the signal to deliver. When running under ptrace, at this 238 * If there is no signal to deliver, we just put the saved
275 * point the debugger may change all our registers ... 239 * sigmask back.
276 */ 240 */
277 if (get_signal(&ksig)) { 241 restore_saved_sigmask();
278 /*
279 * Depending on the signal settings we may need to revert the
280 * decision to restart the system call. But skip this if a
281 * debugger has chosen to restart at a different PC.
282 */
283 if (regs->pc == restart_addr) {
284 if (retval == -ERESTARTNOHAND ||
285 (retval == -ERESTARTSYS &&
286 !(ksig.ka.sa.sa_flags & SA_RESTART))) {
287 regs->a0 = -EINTR;
288 regs->pc = continue_addr;
289 }
290 }
291
292 /* Whee! Actually deliver the signal. */
293 if (handle_signal(&ksig, regs) == 0) {
294 /*
295 * A signal was successfully delivered; the saved
296 * sigmask will have been stored in the signal frame,
297 * and will be restored by sigreturn, so we can simply
298 * clear the TIF_RESTORE_SIGMASK flag.
299 */
300 if (test_thread_flag(TIF_RESTORE_SIGMASK))
301 clear_thread_flag(TIF_RESTORE_SIGMASK);
302 }
303 return;
304 }
305
306no_signal:
307 if (syscall) {
308 /*
309 * Handle restarting a different system call. As above,
310 * if a debugger has chosen to restart at a different PC,
311 * ignore the restart.
312 */
313 if (retval == -ERESTART_RESTARTBLOCK
314 && regs->pc == continue_addr) {
315#if defined(__CSKYABIV2__)
316 regs->regs[3] = __NR_restart_syscall;
317 regs->pc -= 4;
318#else
319 regs->regs[9] = __NR_restart_syscall;
320 regs->pc -= 2;
321#endif
322 }
323
324 /*
325 * If there's no signal to deliver, we just put the saved
326 * sigmask back.
327 */
328 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
329 clear_thread_flag(TIF_RESTORE_SIGMASK);
330 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
331 }
332 }
333} 242}
334 243
335asmlinkage void 244/*
336do_notify_resume(unsigned int thread_flags, struct pt_regs *regs, int syscall) 245 * notification of userspace execution resumption
246 * - triggered by the _TIF_WORK_MASK flags
247 */
248asmlinkage void do_notify_resume(struct pt_regs *regs,
249 unsigned long thread_info_flags)
337{ 250{
338 if (thread_flags & _TIF_SIGPENDING) 251 /* Handle pending signal delivery */
339 do_signal(regs, syscall); 252 if (thread_info_flags & _TIF_SIGPENDING)
253 do_signal(regs);
340 254
341 if (thread_flags & _TIF_NOTIFY_RESUME) { 255 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
342 clear_thread_flag(TIF_NOTIFY_RESUME); 256 clear_thread_flag(TIF_NOTIFY_RESUME);
343 tracehook_notify_resume(regs); 257 tracehook_notify_resume(regs);
344 } 258 }
diff --git a/arch/csky/mm/fault.c b/arch/csky/mm/fault.c
index d6f4b66b93e2..18041f46ded1 100644
--- a/arch/csky/mm/fault.c
+++ b/arch/csky/mm/fault.c
@@ -15,9 +15,9 @@
15#include <linux/smp.h> 15#include <linux/smp.h>
16#include <linux/version.h> 16#include <linux/version.h>
17#include <linux/vt_kern.h> 17#include <linux/vt_kern.h>
18#include <linux/kernel.h>
19#include <linux/extable.h> 18#include <linux/extable.h>
20#include <linux/uaccess.h> 19#include <linux/uaccess.h>
20#include <linux/perf_event.h>
21 21
22#include <asm/hardirq.h> 22#include <asm/hardirq.h>
23#include <asm/mmu_context.h> 23#include <asm/mmu_context.h>
@@ -82,7 +82,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
82 82
83 unsigned long pgd_base; 83 unsigned long pgd_base;
84 84
85 pgd_base = tlb_get_pgd(); 85 pgd_base = (unsigned long)__va(get_pgd());
86 pgd = (pgd_t *)pgd_base + offset; 86 pgd = (pgd_t *)pgd_base + offset;
87 pgd_k = init_mm.pgd + offset; 87 pgd_k = init_mm.pgd + offset;
88 88
@@ -107,6 +107,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
107 return; 107 return;
108 } 108 }
109#endif 109#endif
110
111 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
110 /* 112 /*
111 * If we're in an interrupt or have no user 113 * If we're in an interrupt or have no user
112 * context, we must not take the fault.. 114 * context, we must not take the fault..
@@ -154,10 +156,15 @@ good_area:
154 goto bad_area; 156 goto bad_area;
155 BUG(); 157 BUG();
156 } 158 }
157 if (fault & VM_FAULT_MAJOR) 159 if (fault & VM_FAULT_MAJOR) {
158 tsk->maj_flt++; 160 tsk->maj_flt++;
159 else 161 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs,
162 address);
163 } else {
160 tsk->min_flt++; 164 tsk->min_flt++;
165 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs,
166 address);
167 }
161 168
162 up_read(&mm->mmap_sem); 169 up_read(&mm->mmap_sem);
163 return; 170 return;
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 68841d01162c..f71666899245 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -397,6 +397,9 @@ if ($arch eq "x86_64") {
397} elsif ($arch eq "nds32") { 397} elsif ($arch eq "nds32") {
398 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$"; 398 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_NDS32_HI20_RELA\\s+_mcount\$";
399 $alignment = 2; 399 $alignment = 2;
400} elsif ($arch eq "csky") {
401 $mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_CKCORE_PCREL_JSR_IMM26BY2\\s+_mcount\$";
402 $alignment = 2;
400} else { 403} else {
401 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; 404 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
402} 405}