diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-11 05:49:34 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-11 05:49:34 -0400 |
commit | d95c3578120e5bc4784069439f00ccb1b5f87717 (patch) | |
tree | c819de31de3983f3d69f223ede07667ff23bf7da /arch/sparc | |
parent | ba1d755a36f66101aa88ac9ebb54694def6ec38d (diff) | |
parent | 78b020d035074fc3aa4d017353bb2c32e2aff56f (diff) |
Merge branch 'x86/core' into cpus4096
Diffstat (limited to 'arch/sparc')
49 files changed, 704 insertions, 479 deletions
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index de58c02633b4..c3ea215334f6 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -36,6 +36,7 @@ config SPARC64 | |||
36 | select HAVE_KRETPROBES | 36 | select HAVE_KRETPROBES |
37 | select HAVE_KPROBES | 37 | select HAVE_KPROBES |
38 | select HAVE_LMB | 38 | select HAVE_LMB |
39 | select HAVE_SYSCALL_WRAPPERS | ||
39 | select USE_GENERIC_SMP_HELPERS if SMP | 40 | select USE_GENERIC_SMP_HELPERS if SMP |
40 | select RTC_DRV_CMOS | 41 | select RTC_DRV_CMOS |
41 | select RTC_DRV_BQ4802 | 42 | select RTC_DRV_BQ4802 |
diff --git a/arch/sparc/configs/sparc64_defconfig b/arch/sparc/configs/sparc64_defconfig index cde19ae78f5a..ade49941def2 100644 --- a/arch/sparc/configs/sparc64_defconfig +++ b/arch/sparc/configs/sparc64_defconfig | |||
@@ -867,8 +867,8 @@ CONFIG_I2C_ALGOBIT=y | |||
867 | # Miscellaneous I2C Chip support | 867 | # Miscellaneous I2C Chip support |
868 | # | 868 | # |
869 | # CONFIG_DS1682 is not set | 869 | # CONFIG_DS1682 is not set |
870 | # CONFIG_AT24 is not set | 870 | # CONFIG_EEPROM_AT24 is not set |
871 | # CONFIG_SENSORS_EEPROM is not set | 871 | # CONFIG_EEPROM_LEGACY is not set |
872 | # CONFIG_SENSORS_PCF8574 is not set | 872 | # CONFIG_SENSORS_PCF8574 is not set |
873 | # CONFIG_PCF8575 is not set | 873 | # CONFIG_PCF8575 is not set |
874 | # CONFIG_SENSORS_PCA9539 is not set | 874 | # CONFIG_SENSORS_PCA9539 is not set |
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 95e38a43dff0..deeb0fba8029 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -17,4 +17,3 @@ header-y += traps.h | |||
17 | header-y += uctx.h | 17 | header-y += uctx.h |
18 | header-y += utrap.h | 18 | header-y += utrap.h |
19 | header-y += watchdog.h | 19 | header-y += watchdog.h |
20 | header-y += swab.h | ||
diff --git a/arch/sparc/include/asm/byteorder.h b/arch/sparc/include/asm/byteorder.h index 48a047cd6fa9..ccc1b6b7de6c 100644 --- a/arch/sparc/include/asm/byteorder.h +++ b/arch/sparc/include/asm/byteorder.h | |||
@@ -1,7 +1,6 @@ | |||
1 | #ifndef _SPARC_BYTEORDER_H | 1 | #ifndef _SPARC_BYTEORDER_H |
2 | #define _SPARC_BYTEORDER_H | 2 | #define _SPARC_BYTEORDER_H |
3 | 3 | ||
4 | #include <asm/swab.h> | ||
5 | #include <linux/byteorder/big_endian.h> | 4 | #include <linux/byteorder/big_endian.h> |
6 | 5 | ||
7 | #endif /* _SPARC_BYTEORDER_H */ | 6 | #endif /* _SPARC_BYTEORDER_H */ |
diff --git a/arch/sparc/include/asm/compat.h b/arch/sparc/include/asm/compat.h index f260b58f5ce9..0e706257918f 100644 --- a/arch/sparc/include/asm/compat.h +++ b/arch/sparc/include/asm/compat.h | |||
@@ -240,4 +240,9 @@ struct compat_shmid64_ds { | |||
240 | unsigned int __unused2; | 240 | unsigned int __unused2; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | static inline int is_compat_task(void) | ||
244 | { | ||
245 | return test_thread_flag(TIF_32BIT); | ||
246 | } | ||
247 | |||
243 | #endif /* _ASM_SPARC64_COMPAT_H */ | 248 | #endif /* _ASM_SPARC64_COMPAT_H */ |
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 7da7c13d23c4..a11b89ee9ef8 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h | |||
@@ -17,7 +17,7 @@ | |||
17 | typedef struct { | 17 | typedef struct { |
18 | /* Dcache line 1 */ | 18 | /* Dcache line 1 */ |
19 | unsigned int __softirq_pending; /* must be 1st, see rtrap.S */ | 19 | unsigned int __softirq_pending; /* must be 1st, see rtrap.S */ |
20 | unsigned int __pad0; | 20 | unsigned int __nmi_count; |
21 | unsigned long clock_tick; /* %tick's per second */ | 21 | unsigned long clock_tick; /* %tick's per second */ |
22 | unsigned long __pad; | 22 | unsigned long __pad; |
23 | unsigned int __pad1; | 23 | unsigned int __pad1; |
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index d47d4a1955a9..1934f2cbf513 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h | |||
@@ -66,9 +66,6 @@ extern void virt_irq_free(unsigned int virt_irq); | |||
66 | extern void __init init_IRQ(void); | 66 | extern void __init init_IRQ(void); |
67 | extern void fixup_irqs(void); | 67 | extern void fixup_irqs(void); |
68 | 68 | ||
69 | extern int register_perfctr_intr(void (*handler)(struct pt_regs *)); | ||
70 | extern void release_perfctr_intr(void (*handler)(struct pt_regs *)); | ||
71 | |||
72 | static inline void set_softint(unsigned long bits) | 69 | static inline void set_softint(unsigned long bits) |
73 | { | 70 | { |
74 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" | 71 | __asm__ __volatile__("wr %0, 0x0, %%set_softint" |
@@ -98,5 +95,6 @@ void __trigger_all_cpu_backtrace(void); | |||
98 | extern void *hardirq_stack[NR_CPUS]; | 95 | extern void *hardirq_stack[NR_CPUS]; |
99 | extern void *softirq_stack[NR_CPUS]; | 96 | extern void *softirq_stack[NR_CPUS]; |
100 | #define __ARCH_HAS_DO_SOFTIRQ | 97 | #define __ARCH_HAS_DO_SOFTIRQ |
98 | #define ARCH_HAS_NMI_WATCHDOG | ||
101 | 99 | ||
102 | #endif | 100 | #endif |
diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h index f905b773235a..feb3578e12c4 100644 --- a/arch/sparc/include/asm/kdebug_64.h +++ b/arch/sparc/include/asm/kdebug_64.h | |||
@@ -14,6 +14,8 @@ enum die_val { | |||
14 | DIE_TRAP, | 14 | DIE_TRAP, |
15 | DIE_TRAP_TL1, | 15 | DIE_TRAP_TL1, |
16 | DIE_CALL, | 16 | DIE_CALL, |
17 | DIE_NMI, | ||
18 | DIE_NMIWATCHDOG, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | #endif | 21 | #endif |
diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h new file mode 100644 index 000000000000..fbd546dd4feb --- /dev/null +++ b/arch/sparc/include/asm/nmi.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef __NMI_H | ||
2 | #define __NMI_H | ||
3 | |||
4 | extern int __init nmi_init(void); | ||
5 | extern void perfctr_irq(int irq, struct pt_regs *regs); | ||
6 | extern void nmi_adjust_hz(unsigned int new_hz); | ||
7 | |||
8 | extern int nmi_usable; | ||
9 | |||
10 | #endif /* __NMI_H */ | ||
diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h new file mode 100644 index 000000000000..a2f5c61f924e --- /dev/null +++ b/arch/sparc/include/asm/pcr.h | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifndef __PCR_H | ||
2 | #define __PCR_H | ||
3 | |||
4 | struct pcr_ops { | ||
5 | u64 (*read)(void); | ||
6 | void (*write)(u64); | ||
7 | }; | ||
8 | extern const struct pcr_ops *pcr_ops; | ||
9 | |||
10 | extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs); | ||
11 | extern void schedule_deferred_pcr_work(void); | ||
12 | |||
13 | #define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ | ||
14 | #define PCR_STRACE 0x00000002 /* Trace supervisor events */ | ||
15 | #define PCR_UTRACE 0x00000004 /* Trace user events */ | ||
16 | #define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ | ||
17 | #define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ | ||
18 | #define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ | ||
19 | #define PCR_N2_MASK0 0x00003fc0 | ||
20 | #define PCR_N2_MASK0_SHIFT 6 | ||
21 | #define PCR_N2_SL0 0x0003c000 | ||
22 | #define PCR_N2_SL0_SHIFT 14 | ||
23 | #define PCR_N2_OV0 0x00040000 | ||
24 | #define PCR_N2_MASK1 0x07f80000 | ||
25 | #define PCR_N2_MASK1_SHIFT 19 | ||
26 | #define PCR_N2_SL1 0x78000000 | ||
27 | #define PCR_N2_SL1_SHIFT 27 | ||
28 | #define PCR_N2_OV1 0x80000000 | ||
29 | |||
30 | extern unsigned int picl_shift; | ||
31 | |||
32 | /* In order to commonize as much of the implementation as | ||
33 | * possible, we use PICH as our counter. Mostly this is | ||
34 | * to accomodate Niagara-1 which can only count insn cycles | ||
35 | * in PICH. | ||
36 | */ | ||
37 | static inline u64 picl_value(unsigned int nmi_hz) | ||
38 | { | ||
39 | u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift); | ||
40 | |||
41 | return ((u64)((0 - delta) & 0xffffffff)) << 32; | ||
42 | } | ||
43 | |||
44 | extern u64 pcr_enable; | ||
45 | |||
46 | #endif /* __PCR_H */ | ||
diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index d573820c0ff4..32a7efe76d00 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define PIL_SMP_CTX_NEW_VERSION 4 | 23 | #define PIL_SMP_CTX_NEW_VERSION 4 |
24 | #define PIL_DEVICE_IRQ 5 | 24 | #define PIL_DEVICE_IRQ 5 |
25 | #define PIL_SMP_CALL_FUNC_SNGL 6 | 25 | #define PIL_SMP_CALL_FUNC_SNGL 6 |
26 | #define PIL_DEFERRED_PCR_WORK 7 | ||
26 | #define PIL_NORMAL_MAX 14 | 27 | #define PIL_NORMAL_MAX 14 |
27 | #define PIL_NMI 15 | 28 | #define PIL_NMI 15 |
28 | 29 | ||
diff --git a/arch/sparc/include/asm/seccomp.h b/arch/sparc/include/asm/seccomp.h index 7fcd9968192b..adca1bce41d4 100644 --- a/arch/sparc/include/asm/seccomp.h +++ b/arch/sparc/include/asm/seccomp.h | |||
@@ -1,11 +1,5 @@ | |||
1 | #ifndef _ASM_SECCOMP_H | 1 | #ifndef _ASM_SECCOMP_H |
2 | 2 | ||
3 | #include <linux/thread_info.h> /* already defines TIF_32BIT */ | ||
4 | |||
5 | #ifndef TIF_32BIT | ||
6 | #error "unexpected TIF_32BIT on sparc64" | ||
7 | #endif | ||
8 | |||
9 | #include <linux/unistd.h> | 3 | #include <linux/unistd.h> |
10 | 4 | ||
11 | #define __NR_seccomp_read __NR_read | 5 | #define __NR_seccomp_read __NR_read |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 53adcaa0348b..54742e58831c 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
@@ -52,6 +52,8 @@ obj-$(CONFIG_SPARC64) += visemul.o | |||
52 | obj-$(CONFIG_SPARC64) += hvapi.o | 52 | obj-$(CONFIG_SPARC64) += hvapi.o |
53 | obj-$(CONFIG_SPARC64) += sstate.o | 53 | obj-$(CONFIG_SPARC64) += sstate.o |
54 | obj-$(CONFIG_SPARC64) += mdesc.o | 54 | obj-$(CONFIG_SPARC64) += mdesc.o |
55 | obj-$(CONFIG_SPARC64) += pcr.o | ||
56 | obj-$(CONFIG_SPARC64) += nmi.o | ||
55 | 57 | ||
56 | # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation | 58 | # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation |
57 | obj-$(CONFIG_SPARC32) += devres.o | 59 | obj-$(CONFIG_SPARC32) += devres.o |
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index 05f1c916db06..f3b5466c389c 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c | |||
@@ -103,6 +103,7 @@ static int __devinit clock_board_probe(struct of_device *op, | |||
103 | p->leds_resource.name = "leds"; | 103 | p->leds_resource.name = "leds"; |
104 | 104 | ||
105 | p->leds_pdev.name = "sunfire-clockboard-leds"; | 105 | p->leds_pdev.name = "sunfire-clockboard-leds"; |
106 | p->leds_pdev.id = -1; | ||
106 | p->leds_pdev.resource = &p->leds_resource; | 107 | p->leds_pdev.resource = &p->leds_resource; |
107 | p->leds_pdev.num_resources = 1; | 108 | p->leds_pdev.num_resources = 1; |
108 | p->leds_pdev.dev.parent = &op->dev; | 109 | p->leds_pdev.dev.parent = &op->dev; |
@@ -197,6 +198,7 @@ static int __devinit fhc_probe(struct of_device *op, | |||
197 | p->leds_resource.name = "leds"; | 198 | p->leds_resource.name = "leds"; |
198 | 199 | ||
199 | p->leds_pdev.name = "sunfire-fhc-leds"; | 200 | p->leds_pdev.name = "sunfire-fhc-leds"; |
201 | p->leds_pdev.id = p->board_num; | ||
200 | p->leds_pdev.resource = &p->leds_resource; | 202 | p->leds_pdev.resource = &p->leds_resource; |
201 | p->leds_pdev.num_resources = 1; | 203 | p->leds_pdev.num_resources = 1; |
202 | p->leds_pdev.dev.parent = &op->dev; | 204 | p->leds_pdev.dev.parent = &op->dev; |
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c index 3b9f4d6e14a9..e1a9598e2a4d 100644 --- a/arch/sparc/kernel/chmc.c +++ b/arch/sparc/kernel/chmc.c | |||
@@ -306,6 +306,7 @@ static int jbusmc_print_dimm(int syndrome_code, | |||
306 | buf[1] = '?'; | 306 | buf[1] = '?'; |
307 | buf[2] = '?'; | 307 | buf[2] = '?'; |
308 | buf[3] = '\0'; | 308 | buf[3] = '\0'; |
309 | return 0; | ||
309 | } | 310 | } |
310 | p = dp->controller; | 311 | p = dp->controller; |
311 | prop = &p->layout; | 312 | prop = &p->layout; |
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index f0b825505da5..d85c3dc4953a 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c | |||
@@ -26,6 +26,7 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data); | |||
26 | struct cpu_info { | 26 | struct cpu_info { |
27 | int psr_vers; | 27 | int psr_vers; |
28 | const char *name; | 28 | const char *name; |
29 | const char *pmu_name; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | struct fpu_info { | 32 | struct fpu_info { |
@@ -45,6 +46,9 @@ struct manufacturer_info { | |||
45 | #define CPU(ver, _name) \ | 46 | #define CPU(ver, _name) \ |
46 | { .psr_vers = ver, .name = _name } | 47 | { .psr_vers = ver, .name = _name } |
47 | 48 | ||
49 | #define CPU_PMU(ver, _name, _pmu_name) \ | ||
50 | { .psr_vers = ver, .name = _name, .pmu_name = _pmu_name } | ||
51 | |||
48 | #define FPU(ver, _name) \ | 52 | #define FPU(ver, _name) \ |
49 | { .fp_vers = ver, .name = _name } | 53 | { .fp_vers = ver, .name = _name } |
50 | 54 | ||
@@ -183,10 +187,10 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { | |||
183 | },{ | 187 | },{ |
184 | 0x17, | 188 | 0x17, |
185 | .cpu_info = { | 189 | .cpu_info = { |
186 | CPU(0x10, "TI UltraSparc I (SpitFire)"), | 190 | CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), |
187 | CPU(0x11, "TI UltraSparc II (BlackBird)"), | 191 | CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"), |
188 | CPU(0x12, "TI UltraSparc IIi (Sabre)"), | 192 | CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"), |
189 | CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), | 193 | CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"), |
190 | CPU(-1, NULL) | 194 | CPU(-1, NULL) |
191 | }, | 195 | }, |
192 | .fpu_info = { | 196 | .fpu_info = { |
@@ -199,7 +203,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { | |||
199 | },{ | 203 | },{ |
200 | 0x22, | 204 | 0x22, |
201 | .cpu_info = { | 205 | .cpu_info = { |
202 | CPU(0x10, "TI UltraSparc I (SpitFire)"), | 206 | CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), |
203 | CPU(-1, NULL) | 207 | CPU(-1, NULL) |
204 | }, | 208 | }, |
205 | .fpu_info = { | 209 | .fpu_info = { |
@@ -209,12 +213,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { | |||
209 | },{ | 213 | },{ |
210 | 0x3e, | 214 | 0x3e, |
211 | .cpu_info = { | 215 | .cpu_info = { |
212 | CPU(0x14, "TI UltraSparc III (Cheetah)"), | 216 | CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"), |
213 | CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), | 217 | CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"), |
214 | CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), | 218 | CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"), |
215 | CPU(0x18, "TI UltraSparc IV (Jaguar)"), | 219 | CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"), |
216 | CPU(0x19, "TI UltraSparc IV+ (Panther)"), | 220 | CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"), |
217 | CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), | 221 | CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"), |
218 | CPU(-1, NULL) | 222 | CPU(-1, NULL) |
219 | }, | 223 | }, |
220 | .fpu_info = { | 224 | .fpu_info = { |
@@ -234,29 +238,44 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { | |||
234 | 238 | ||
235 | const char *sparc_cpu_type; | 239 | const char *sparc_cpu_type; |
236 | const char *sparc_fpu_type; | 240 | const char *sparc_fpu_type; |
241 | const char *sparc_pmu_type; | ||
237 | 242 | ||
238 | unsigned int fsr_storage; | 243 | unsigned int fsr_storage; |
239 | 244 | ||
240 | static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) | 245 | static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) |
241 | { | 246 | { |
247 | const struct manufacturer_info *manuf; | ||
248 | int i; | ||
249 | |||
242 | sparc_cpu_type = NULL; | 250 | sparc_cpu_type = NULL; |
243 | sparc_fpu_type = NULL; | 251 | sparc_fpu_type = NULL; |
244 | if (psr_impl < ARRAY_SIZE(manufacturer_info)) | 252 | sparc_pmu_type = NULL; |
253 | manuf = NULL; | ||
254 | |||
255 | for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) | ||
256 | { | ||
257 | if (psr_impl == manufacturer_info[i].psr_impl) { | ||
258 | manuf = &manufacturer_info[i]; | ||
259 | break; | ||
260 | } | ||
261 | } | ||
262 | if (manuf != NULL) | ||
245 | { | 263 | { |
246 | const struct cpu_info *cpu; | 264 | const struct cpu_info *cpu; |
247 | const struct fpu_info *fpu; | 265 | const struct fpu_info *fpu; |
248 | 266 | ||
249 | cpu = &manufacturer_info[psr_impl].cpu_info[0]; | 267 | cpu = &manuf->cpu_info[0]; |
250 | while (cpu->psr_vers != -1) | 268 | while (cpu->psr_vers != -1) |
251 | { | 269 | { |
252 | if (cpu->psr_vers == psr_vers) { | 270 | if (cpu->psr_vers == psr_vers) { |
253 | sparc_cpu_type = cpu->name; | 271 | sparc_cpu_type = cpu->name; |
272 | sparc_pmu_type = cpu->pmu_name; | ||
254 | sparc_fpu_type = "No FPU"; | 273 | sparc_fpu_type = "No FPU"; |
255 | break; | 274 | break; |
256 | } | 275 | } |
257 | cpu++; | 276 | cpu++; |
258 | } | 277 | } |
259 | fpu = &manufacturer_info[psr_impl].fpu_info[0]; | 278 | fpu = &manuf->fpu_info[0]; |
260 | while (fpu->fp_vers != -1) | 279 | while (fpu->fp_vers != -1) |
261 | { | 280 | { |
262 | if (fpu->fp_vers == fpu_vers) { | 281 | if (fpu->fp_vers == fpu_vers) { |
@@ -278,6 +297,8 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) | |||
278 | psr_impl, fpu_vers); | 297 | psr_impl, fpu_vers); |
279 | sparc_fpu_type = "Unknown FPU"; | 298 | sparc_fpu_type = "Unknown FPU"; |
280 | } | 299 | } |
300 | if (sparc_pmu_type == NULL) | ||
301 | sparc_pmu_type = "Unknown PMU"; | ||
281 | } | 302 | } |
282 | 303 | ||
283 | #ifdef CONFIG_SPARC32 | 304 | #ifdef CONFIG_SPARC32 |
@@ -303,11 +324,13 @@ static void __init sun4v_cpu_probe(void) | |||
303 | case SUN4V_CHIP_NIAGARA1: | 324 | case SUN4V_CHIP_NIAGARA1: |
304 | sparc_cpu_type = "UltraSparc T1 (Niagara)"; | 325 | sparc_cpu_type = "UltraSparc T1 (Niagara)"; |
305 | sparc_fpu_type = "UltraSparc T1 integrated FPU"; | 326 | sparc_fpu_type = "UltraSparc T1 integrated FPU"; |
327 | sparc_pmu_type = "niagara"; | ||
306 | break; | 328 | break; |
307 | 329 | ||
308 | case SUN4V_CHIP_NIAGARA2: | 330 | case SUN4V_CHIP_NIAGARA2: |
309 | sparc_cpu_type = "UltraSparc T2 (Niagara2)"; | 331 | sparc_cpu_type = "UltraSparc T2 (Niagara2)"; |
310 | sparc_fpu_type = "UltraSparc T2 integrated FPU"; | 332 | sparc_fpu_type = "UltraSparc T2 integrated FPU"; |
333 | sparc_pmu_type = "niagara2"; | ||
311 | break; | 334 | break; |
312 | 335 | ||
313 | default: | 336 | default: |
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index faf9ccd9ef5d..f41ecc5ac0b4 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -1088,8 +1088,8 @@ sunos_execv: | |||
1088 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 | 1088 | ld [%sp + STACKFRAME_SZ + PT_I0], %o0 |
1089 | 1089 | ||
1090 | .align 4 | 1090 | .align 4 |
1091 | .globl sys_pipe | 1091 | .globl sys_sparc_pipe |
1092 | sys_pipe: | 1092 | sys_sparc_pipe: |
1093 | mov %o7, %l5 | 1093 | mov %o7, %l5 |
1094 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg | 1094 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg |
1095 | call sparc_pipe | 1095 | call sparc_pipe |
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S index 8ffee714f932..a46c3a21e26d 100644 --- a/arch/sparc/kernel/head_64.S +++ b/arch/sparc/kernel/head_64.S | |||
@@ -891,10 +891,35 @@ prom_tba: .xword 0 | |||
891 | tlb_type: .word 0 /* Must NOT end up in BSS */ | 891 | tlb_type: .word 0 /* Must NOT end up in BSS */ |
892 | .section ".fixup",#alloc,#execinstr | 892 | .section ".fixup",#alloc,#execinstr |
893 | 893 | ||
894 | .globl __ret_efault, __retl_efault | 894 | .globl __ret_efault, __retl_efault, __ret_one, __retl_one |
895 | __ret_efault: | 895 | ENTRY(__ret_efault) |
896 | ret | 896 | ret |
897 | restore %g0, -EFAULT, %o0 | 897 | restore %g0, -EFAULT, %o0 |
898 | __retl_efault: | 898 | ENDPROC(__ret_efault) |
899 | |||
900 | ENTRY(__retl_efault) | ||
899 | retl | 901 | retl |
900 | mov -EFAULT, %o0 | 902 | mov -EFAULT, %o0 |
903 | ENDPROC(__retl_efault) | ||
904 | |||
905 | ENTRY(__retl_one) | ||
906 | retl | ||
907 | mov 1, %o0 | ||
908 | ENDPROC(__retl_one) | ||
909 | |||
910 | ENTRY(__ret_one_asi) | ||
911 | wr %g0, ASI_AIUS, %asi | ||
912 | ret | ||
913 | restore %g0, 1, %o0 | ||
914 | ENDPROC(__ret_one_asi) | ||
915 | |||
916 | ENTRY(__retl_one_asi) | ||
917 | wr %g0, ASI_AIUS, %asi | ||
918 | retl | ||
919 | mov 1, %o0 | ||
920 | ENDPROC(__retl_one_asi) | ||
921 | |||
922 | ENTRY(__retl_o1) | ||
923 | retl | ||
924 | mov %o1, %o0 | ||
925 | ENDPROC(__retl_o1) | ||
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index 4ac5c651e00d..3d2c6baae96b 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
@@ -196,6 +196,11 @@ int show_interrupts(struct seq_file *p, void *v) | |||
196 | seq_putc(p, '\n'); | 196 | seq_putc(p, '\n'); |
197 | skip: | 197 | skip: |
198 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | 198 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
199 | } else if (i == NR_IRQS) { | ||
200 | seq_printf(p, "NMI: "); | ||
201 | for_each_online_cpu(j) | ||
202 | seq_printf(p, "%10u ", cpu_data(j).__nmi_count); | ||
203 | seq_printf(p, " Non-maskable interrupts\n"); | ||
199 | } | 204 | } |
200 | return 0; | 205 | return 0; |
201 | } | 206 | } |
@@ -779,69 +784,6 @@ void do_softirq(void) | |||
779 | local_irq_restore(flags); | 784 | local_irq_restore(flags); |
780 | } | 785 | } |
781 | 786 | ||
782 | static void unhandled_perf_irq(struct pt_regs *regs) | ||
783 | { | ||
784 | unsigned long pcr, pic; | ||
785 | |||
786 | read_pcr(pcr); | ||
787 | read_pic(pic); | ||
788 | |||
789 | write_pcr(0); | ||
790 | |||
791 | printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n", | ||
792 | smp_processor_id()); | ||
793 | printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n", | ||
794 | smp_processor_id(), pcr, pic); | ||
795 | } | ||
796 | |||
797 | /* Almost a direct copy of the powerpc PMC code. */ | ||
798 | static DEFINE_SPINLOCK(perf_irq_lock); | ||
799 | static void *perf_irq_owner_caller; /* mostly for debugging */ | ||
800 | static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq; | ||
801 | |||
802 | /* Invoked from level 15 PIL handler in trap table. */ | ||
803 | void perfctr_irq(int irq, struct pt_regs *regs) | ||
804 | { | ||
805 | clear_softint(1 << irq); | ||
806 | perf_irq(regs); | ||
807 | } | ||
808 | |||
809 | int register_perfctr_intr(void (*handler)(struct pt_regs *)) | ||
810 | { | ||
811 | int ret; | ||
812 | |||
813 | if (!handler) | ||
814 | return -EINVAL; | ||
815 | |||
816 | spin_lock(&perf_irq_lock); | ||
817 | if (perf_irq != unhandled_perf_irq) { | ||
818 | printk(KERN_WARNING "register_perfctr_intr: " | ||
819 | "perf IRQ busy (reserved by caller %p)\n", | ||
820 | perf_irq_owner_caller); | ||
821 | ret = -EBUSY; | ||
822 | goto out; | ||
823 | } | ||
824 | |||
825 | perf_irq_owner_caller = __builtin_return_address(0); | ||
826 | perf_irq = handler; | ||
827 | |||
828 | ret = 0; | ||
829 | out: | ||
830 | spin_unlock(&perf_irq_lock); | ||
831 | |||
832 | return ret; | ||
833 | } | ||
834 | EXPORT_SYMBOL_GPL(register_perfctr_intr); | ||
835 | |||
836 | void release_perfctr_intr(void (*handler)(struct pt_regs *)) | ||
837 | { | ||
838 | spin_lock(&perf_irq_lock); | ||
839 | perf_irq_owner_caller = NULL; | ||
840 | perf_irq = unhandled_perf_irq; | ||
841 | spin_unlock(&perf_irq_lock); | ||
842 | } | ||
843 | EXPORT_SYMBOL_GPL(release_perfctr_intr); | ||
844 | |||
845 | #ifdef CONFIG_HOTPLUG_CPU | 787 | #ifdef CONFIG_HOTPLUG_CPU |
846 | void fixup_irqs(void) | 788 | void fixup_irqs(void) |
847 | { | 789 | { |
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 81a972e8d8ea..15d8a3f645c9 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | /* cpu.c */ | 6 | /* cpu.c */ |
7 | extern const char *sparc_cpu_type; | 7 | extern const char *sparc_cpu_type; |
8 | extern const char *sparc_pmu_type; | ||
8 | extern const char *sparc_fpu_type; | 9 | extern const char *sparc_fpu_type; |
9 | 10 | ||
10 | extern unsigned int fsr_storage; | 11 | extern unsigned int fsr_storage; |
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c new file mode 100644 index 000000000000..f3577223c863 --- /dev/null +++ b/arch/sparc/kernel/nmi.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* Pseudo NMI support on sparc64 systems. | ||
2 | * | ||
3 | * Copyright (C) 2009 David S. Miller <davem@davemloft.net> | ||
4 | * | ||
5 | * The NMI watchdog support and infrastructure is based almost | ||
6 | * entirely upon the x86 NMI support code. | ||
7 | */ | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/param.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/percpu.h> | ||
12 | #include <linux/nmi.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kprobes.h> | ||
15 | #include <linux/kernel_stat.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/kdebug.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/smp.h> | ||
20 | |||
21 | #include <asm/ptrace.h> | ||
22 | #include <asm/local.h> | ||
23 | #include <asm/pcr.h> | ||
24 | |||
25 | /* We don't have a real NMI on sparc64, but we can fake one | ||
26 | * up using profiling counter overflow interrupts and interrupt | ||
27 | * levels. | ||
28 | * | ||
29 | * The profile overflow interrupts at level 15, so we use | ||
30 | * level 14 as our IRQ off level. | ||
31 | */ | ||
32 | |||
33 | static int nmi_watchdog_active; | ||
34 | static int panic_on_timeout; | ||
35 | |||
36 | int nmi_usable; | ||
37 | EXPORT_SYMBOL_GPL(nmi_usable); | ||
38 | |||
39 | static unsigned int nmi_hz = HZ; | ||
40 | |||
41 | static DEFINE_PER_CPU(unsigned int, last_irq_sum); | ||
42 | static DEFINE_PER_CPU(local_t, alert_counter); | ||
43 | static DEFINE_PER_CPU(int, nmi_touch); | ||
44 | |||
45 | void touch_nmi_watchdog(void) | ||
46 | { | ||
47 | if (nmi_watchdog_active) { | ||
48 | int cpu; | ||
49 | |||
50 | for_each_present_cpu(cpu) { | ||
51 | if (per_cpu(nmi_touch, cpu) != 1) | ||
52 | per_cpu(nmi_touch, cpu) = 1; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | touch_softlockup_watchdog(); | ||
57 | } | ||
58 | EXPORT_SYMBOL(touch_nmi_watchdog); | ||
59 | |||
60 | static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) | ||
61 | { | ||
62 | if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, | ||
63 | pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) | ||
64 | return; | ||
65 | |||
66 | console_verbose(); | ||
67 | bust_spinlocks(1); | ||
68 | |||
69 | printk(KERN_EMERG "%s", str); | ||
70 | printk(" on CPU%d, ip %08lx, registers:\n", | ||
71 | smp_processor_id(), regs->tpc); | ||
72 | show_regs(regs); | ||
73 | dump_stack(); | ||
74 | |||
75 | bust_spinlocks(0); | ||
76 | |||
77 | if (do_panic || panic_on_oops) | ||
78 | panic("Non maskable interrupt"); | ||
79 | |||
80 | local_irq_enable(); | ||
81 | do_exit(SIGBUS); | ||
82 | } | ||
83 | |||
84 | notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) | ||
85 | { | ||
86 | unsigned int sum, touched = 0; | ||
87 | int cpu = smp_processor_id(); | ||
88 | |||
89 | clear_softint(1 << irq); | ||
90 | pcr_ops->write(PCR_PIC_PRIV); | ||
91 | |||
92 | local_cpu_data().__nmi_count++; | ||
93 | |||
94 | if (notify_die(DIE_NMI, "nmi", regs, 0, | ||
95 | pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) | ||
96 | touched = 1; | ||
97 | |||
98 | sum = kstat_irqs_cpu(0, cpu); | ||
99 | if (__get_cpu_var(nmi_touch)) { | ||
100 | __get_cpu_var(nmi_touch) = 0; | ||
101 | touched = 1; | ||
102 | } | ||
103 | if (!touched && __get_cpu_var(last_irq_sum) == sum) { | ||
104 | local_inc(&__get_cpu_var(alert_counter)); | ||
105 | if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) | ||
106 | die_nmi("BUG: NMI Watchdog detected LOCKUP", | ||
107 | regs, panic_on_timeout); | ||
108 | } else { | ||
109 | __get_cpu_var(last_irq_sum) = sum; | ||
110 | local_set(&__get_cpu_var(alert_counter), 0); | ||
111 | } | ||
112 | if (nmi_usable) { | ||
113 | write_pic(picl_value(nmi_hz)); | ||
114 | pcr_ops->write(pcr_enable); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | static inline unsigned int get_nmi_count(int cpu) | ||
119 | { | ||
120 | return cpu_data(cpu).__nmi_count; | ||
121 | } | ||
122 | |||
123 | static int endflag __initdata; | ||
124 | |||
125 | static __init void nmi_cpu_busy(void *data) | ||
126 | { | ||
127 | local_irq_enable_in_hardirq(); | ||
128 | while (endflag == 0) | ||
129 | mb(); | ||
130 | } | ||
131 | |||
132 | static void report_broken_nmi(int cpu, int *prev_nmi_count) | ||
133 | { | ||
134 | printk(KERN_CONT "\n"); | ||
135 | |||
136 | printk(KERN_WARNING | ||
137 | "WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n", | ||
138 | cpu, prev_nmi_count[cpu], get_nmi_count(cpu)); | ||
139 | |||
140 | printk(KERN_WARNING | ||
141 | "Please report this to bugzilla.kernel.org,\n"); | ||
142 | printk(KERN_WARNING | ||
143 | "and attach the output of the 'dmesg' command.\n"); | ||
144 | |||
145 | nmi_usable = 0; | ||
146 | } | ||
147 | |||
148 | static void stop_watchdog(void *unused) | ||
149 | { | ||
150 | pcr_ops->write(PCR_PIC_PRIV); | ||
151 | } | ||
152 | |||
153 | static int __init check_nmi_watchdog(void) | ||
154 | { | ||
155 | unsigned int *prev_nmi_count; | ||
156 | int cpu, err; | ||
157 | |||
158 | prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL); | ||
159 | if (!prev_nmi_count) { | ||
160 | err = -ENOMEM; | ||
161 | goto error; | ||
162 | } | ||
163 | |||
164 | printk(KERN_INFO "Testing NMI watchdog ... "); | ||
165 | |||
166 | smp_call_function(nmi_cpu_busy, (void *)&endflag, 0); | ||
167 | |||
168 | for_each_possible_cpu(cpu) | ||
169 | prev_nmi_count[cpu] = get_nmi_count(cpu); | ||
170 | local_irq_enable(); | ||
171 | mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */ | ||
172 | |||
173 | for_each_online_cpu(cpu) { | ||
174 | if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5) | ||
175 | report_broken_nmi(cpu, prev_nmi_count); | ||
176 | } | ||
177 | endflag = 1; | ||
178 | if (!nmi_usable) { | ||
179 | kfree(prev_nmi_count); | ||
180 | err = -ENODEV; | ||
181 | goto error; | ||
182 | } | ||
183 | printk("OK.\n"); | ||
184 | |||
185 | nmi_hz = 1; | ||
186 | |||
187 | kfree(prev_nmi_count); | ||
188 | return 0; | ||
189 | error: | ||
190 | on_each_cpu(stop_watchdog, NULL, 1); | ||
191 | return err; | ||
192 | } | ||
193 | |||
194 | static void start_watchdog(void *unused) | ||
195 | { | ||
196 | pcr_ops->write(PCR_PIC_PRIV); | ||
197 | write_pic(picl_value(nmi_hz)); | ||
198 | |||
199 | pcr_ops->write(pcr_enable); | ||
200 | } | ||
201 | |||
202 | void nmi_adjust_hz(unsigned int new_hz) | ||
203 | { | ||
204 | nmi_hz = new_hz; | ||
205 | on_each_cpu(start_watchdog, NULL, 1); | ||
206 | } | ||
207 | EXPORT_SYMBOL_GPL(nmi_adjust_hz); | ||
208 | |||
209 | int __init nmi_init(void) | ||
210 | { | ||
211 | nmi_usable = 1; | ||
212 | |||
213 | on_each_cpu(start_watchdog, NULL, 1); | ||
214 | |||
215 | return check_nmi_watchdog(); | ||
216 | } | ||
217 | |||
218 | static int __init setup_nmi_watchdog(char *str) | ||
219 | { | ||
220 | if (!strncmp(str, "panic", 5)) | ||
221 | panic_on_timeout = 1; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | __setup("nmi_watchdog=", setup_nmi_watchdog); | ||
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c new file mode 100644 index 000000000000..1ae8cdd7e703 --- /dev/null +++ b/arch/sparc/kernel/pcr.c | |||
@@ -0,0 +1,158 @@ | |||
1 | /* pcr.c: Generic sparc64 performance counter infrastructure. | ||
2 | * | ||
3 | * Copyright (C) 2009 David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/irq.h> | ||
9 | |||
10 | #include <asm/pil.h> | ||
11 | #include <asm/pcr.h> | ||
12 | #include <asm/nmi.h> | ||
13 | |||
14 | /* This code is shared between various users of the performance | ||
15 | * counters. Users will be oprofile, pseudo-NMI watchdog, and the | ||
16 | * perf_counter support layer. | ||
17 | */ | ||
18 | |||
19 | #define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) | ||
20 | #define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ | ||
21 | PCR_N2_TOE_OV1 | \ | ||
22 | (2 << PCR_N2_SL1_SHIFT) | \ | ||
23 | (0xff << PCR_N2_MASK1_SHIFT)) | ||
24 | |||
25 | u64 pcr_enable; | ||
26 | unsigned int picl_shift; | ||
27 | |||
28 | /* Performance counter interrupts run unmasked at PIL level 15. | ||
29 | * Therefore we can't do things like wakeups and other work | ||
30 | * that expects IRQ disabling to be adhered to in locking etc. | ||
31 | * | ||
32 | * Therefore in such situations we defer the work by signalling | ||
33 | * a lower level cpu IRQ. | ||
34 | */ | ||
35 | void deferred_pcr_work_irq(int irq, struct pt_regs *regs) | ||
36 | { | ||
37 | clear_softint(1 << PIL_DEFERRED_PCR_WORK); | ||
38 | } | ||
39 | |||
40 | void schedule_deferred_pcr_work(void) | ||
41 | { | ||
42 | set_softint(1 << PIL_DEFERRED_PCR_WORK); | ||
43 | } | ||
44 | |||
45 | const struct pcr_ops *pcr_ops; | ||
46 | EXPORT_SYMBOL_GPL(pcr_ops); | ||
47 | |||
48 | static u64 direct_pcr_read(void) | ||
49 | { | ||
50 | u64 val; | ||
51 | |||
52 | read_pcr(val); | ||
53 | return val; | ||
54 | } | ||
55 | |||
56 | static void direct_pcr_write(u64 val) | ||
57 | { | ||
58 | write_pcr(val); | ||
59 | } | ||
60 | |||
61 | static const struct pcr_ops direct_pcr_ops = { | ||
62 | .read = direct_pcr_read, | ||
63 | .write = direct_pcr_write, | ||
64 | }; | ||
65 | |||
66 | static void n2_pcr_write(u64 val) | ||
67 | { | ||
68 | unsigned long ret; | ||
69 | |||
70 | ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); | ||
71 | if (val != HV_EOK) | ||
72 | write_pcr(val); | ||
73 | } | ||
74 | |||
75 | static const struct pcr_ops n2_pcr_ops = { | ||
76 | .read = direct_pcr_read, | ||
77 | .write = n2_pcr_write, | ||
78 | }; | ||
79 | |||
80 | static unsigned long perf_hsvc_group; | ||
81 | static unsigned long perf_hsvc_major; | ||
82 | static unsigned long perf_hsvc_minor; | ||
83 | |||
84 | static int __init register_perf_hsvc(void) | ||
85 | { | ||
86 | if (tlb_type == hypervisor) { | ||
87 | switch (sun4v_chip_type) { | ||
88 | case SUN4V_CHIP_NIAGARA1: | ||
89 | perf_hsvc_group = HV_GRP_NIAG_PERF; | ||
90 | break; | ||
91 | |||
92 | case SUN4V_CHIP_NIAGARA2: | ||
93 | perf_hsvc_group = HV_GRP_N2_CPU; | ||
94 | break; | ||
95 | |||
96 | default: | ||
97 | return -ENODEV; | ||
98 | } | ||
99 | |||
100 | |||
101 | perf_hsvc_major = 1; | ||
102 | perf_hsvc_minor = 0; | ||
103 | if (sun4v_hvapi_register(perf_hsvc_group, | ||
104 | perf_hsvc_major, | ||
105 | &perf_hsvc_minor)) { | ||
106 | printk("perfmon: Could not register hvapi.\n"); | ||
107 | return -ENODEV; | ||
108 | } | ||
109 | } | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static void __init unregister_perf_hsvc(void) | ||
114 | { | ||
115 | if (tlb_type != hypervisor) | ||
116 | return; | ||
117 | sun4v_hvapi_unregister(perf_hsvc_group); | ||
118 | } | ||
119 | |||
120 | int __init pcr_arch_init(void) | ||
121 | { | ||
122 | int err = register_perf_hsvc(); | ||
123 | |||
124 | if (err) | ||
125 | return err; | ||
126 | |||
127 | switch (tlb_type) { | ||
128 | case hypervisor: | ||
129 | pcr_ops = &n2_pcr_ops; | ||
130 | pcr_enable = PCR_N2_ENABLE; | ||
131 | picl_shift = 2; | ||
132 | break; | ||
133 | |||
134 | case cheetah: | ||
135 | case cheetah_plus: | ||
136 | pcr_ops = &direct_pcr_ops; | ||
137 | pcr_enable = PCR_SUN4U_ENABLE; | ||
138 | break; | ||
139 | |||
140 | case spitfire: | ||
141 | /* UltraSPARC-I/II and derivatives lack a profile | ||
142 | * counter overflow interrupt so we can't make use of | ||
143 | * their hardware currently. | ||
144 | */ | ||
145 | /* fallthrough */ | ||
146 | default: | ||
147 | err = -ENODEV; | ||
148 | goto out_unregister; | ||
149 | } | ||
150 | |||
151 | return nmi_init(); | ||
152 | |||
153 | out_unregister: | ||
154 | unregister_perf_hsvc(); | ||
155 | return err; | ||
156 | } | ||
157 | |||
158 | arch_initcall(pcr_arch_init); | ||
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index cc8b5604442c..a73954b87f0a 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/cpu.h> | 29 | #include <linux/cpu.h> |
30 | #include <linux/elfcore.h> | 30 | #include <linux/elfcore.h> |
31 | #include <linux/sysrq.h> | 31 | #include <linux/sysrq.h> |
32 | #include <linux/nmi.h> | ||
32 | 33 | ||
33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
@@ -52,8 +53,10 @@ | |||
52 | 53 | ||
53 | static void sparc64_yield(int cpu) | 54 | static void sparc64_yield(int cpu) |
54 | { | 55 | { |
55 | if (tlb_type != hypervisor) | 56 | if (tlb_type != hypervisor) { |
57 | touch_nmi_watchdog(); | ||
56 | return; | 58 | return; |
59 | } | ||
57 | 60 | ||
58 | clear_thread_flag(TIF_POLLING_NRFLAG); | 61 | clear_thread_flag(TIF_POLLING_NRFLAG); |
59 | smp_mb__after_clear_bit(); | 62 | smp_mb__after_clear_bit(); |
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 49d061f4ae9d..f2bcfd2967d7 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c | |||
@@ -354,6 +354,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) | |||
354 | seq_printf(m, | 354 | seq_printf(m, |
355 | "cpu\t\t: %s\n" | 355 | "cpu\t\t: %s\n" |
356 | "fpu\t\t: %s\n" | 356 | "fpu\t\t: %s\n" |
357 | "pmu\t\t: %s\n" | ||
357 | "prom\t\t: %s\n" | 358 | "prom\t\t: %s\n" |
358 | "type\t\t: %s\n" | 359 | "type\t\t: %s\n" |
359 | "ncpus probed\t: %d\n" | 360 | "ncpus probed\t: %d\n" |
@@ -366,6 +367,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) | |||
366 | , | 367 | , |
367 | sparc_cpu_type, | 368 | sparc_cpu_type, |
368 | sparc_fpu_type, | 369 | sparc_fpu_type, |
370 | sparc_pmu_type, | ||
369 | prom_version, | 371 | prom_version, |
370 | ((tlb_type == hypervisor) ? | 372 | ((tlb_type == hypervisor) ? |
371 | "sun4v" : | 373 | "sun4v" : |
diff --git a/arch/sparc/kernel/sparc_ksyms_64.c b/arch/sparc/kernel/sparc_ksyms_64.c index da8f804feb49..0f26066a08d9 100644 --- a/arch/sparc/kernel/sparc_ksyms_64.c +++ b/arch/sparc/kernel/sparc_ksyms_64.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/pci.h> | 9 | #include <linux/pci.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | 11 | ||
12 | #include <asm/spinlock.h> | ||
13 | #include <asm/system.h> | 12 | #include <asm/system.h> |
14 | #include <asm/cpudata.h> | 13 | #include <asm/cpudata.h> |
15 | #include <asm/uaccess.h> | 14 | #include <asm/uaccess.h> |
@@ -23,16 +22,6 @@ struct poll { | |||
23 | short revents; | 22 | short revents; |
24 | }; | 23 | }; |
25 | 24 | ||
26 | /* used by various drivers */ | ||
27 | #ifdef CONFIG_SMP | ||
28 | /* Out of line rw-locking implementation. */ | ||
29 | EXPORT_SYMBOL(__read_lock); | ||
30 | EXPORT_SYMBOL(__read_unlock); | ||
31 | EXPORT_SYMBOL(__write_lock); | ||
32 | EXPORT_SYMBOL(__write_unlock); | ||
33 | EXPORT_SYMBOL(__write_trylock); | ||
34 | #endif /* CONFIG_SMP */ | ||
35 | |||
36 | /* from helpers.S */ | 25 | /* from helpers.S */ |
37 | EXPORT_SYMBOL(__flushw_user); | 26 | EXPORT_SYMBOL(__flushw_user); |
38 | EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); | 27 | EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); |
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 09058fc39e73..e2d102447a43 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c | |||
@@ -399,7 +399,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm) | |||
399 | } | 399 | } |
400 | } | 400 | } |
401 | 401 | ||
402 | asmlinkage unsigned long sparc_brk(unsigned long brk) | 402 | SYSCALL_DEFINE1(sparc_brk, unsigned long, brk) |
403 | { | 403 | { |
404 | /* People could try to be nasty and use ta 0x6d in 32bit programs */ | 404 | /* People could try to be nasty and use ta 0x6d in 32bit programs */ |
405 | if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32) | 405 | if (test_thread_flag(TIF_32BIT) && brk >= STACK_TOP32) |
@@ -415,7 +415,7 @@ asmlinkage unsigned long sparc_brk(unsigned long brk) | |||
415 | * sys_pipe() is the normal C calling standard for creating | 415 | * sys_pipe() is the normal C calling standard for creating |
416 | * a pipe. It's not the way unix traditionally does this, though. | 416 | * a pipe. It's not the way unix traditionally does this, though. |
417 | */ | 417 | */ |
418 | asmlinkage long sparc_pipe(struct pt_regs *regs) | 418 | SYSCALL_DEFINE1(sparc_pipe_real, struct pt_regs *, regs) |
419 | { | 419 | { |
420 | int fd[2]; | 420 | int fd[2]; |
421 | int error; | 421 | int error; |
@@ -435,8 +435,8 @@ out: | |||
435 | * This is really horribly ugly. | 435 | * This is really horribly ugly. |
436 | */ | 436 | */ |
437 | 437 | ||
438 | asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, | 438 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, |
439 | unsigned long third, void __user *ptr, long fifth) | 439 | unsigned long, third, void __user *, ptr, long, fifth) |
440 | { | 440 | { |
441 | long err; | 441 | long err; |
442 | 442 | ||
@@ -519,7 +519,7 @@ out: | |||
519 | return err; | 519 | return err; |
520 | } | 520 | } |
521 | 521 | ||
522 | asmlinkage long sparc64_newuname(struct new_utsname __user *name) | 522 | SYSCALL_DEFINE1(sparc64_newuname, struct new_utsname __user *, name) |
523 | { | 523 | { |
524 | int ret = sys_newuname(name); | 524 | int ret = sys_newuname(name); |
525 | 525 | ||
@@ -530,7 +530,7 @@ asmlinkage long sparc64_newuname(struct new_utsname __user *name) | |||
530 | return ret; | 530 | return ret; |
531 | } | 531 | } |
532 | 532 | ||
533 | asmlinkage long sparc64_personality(unsigned long personality) | 533 | SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) |
534 | { | 534 | { |
535 | int ret; | 535 | int ret; |
536 | 536 | ||
@@ -564,9 +564,9 @@ int sparc_mmap_check(unsigned long addr, unsigned long len) | |||
564 | } | 564 | } |
565 | 565 | ||
566 | /* Linux version of mmap */ | 566 | /* Linux version of mmap */ |
567 | asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, | 567 | SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, |
568 | unsigned long prot, unsigned long flags, unsigned long fd, | 568 | unsigned long, prot, unsigned long, flags, unsigned long, fd, |
569 | unsigned long off) | 569 | unsigned long, off) |
570 | { | 570 | { |
571 | struct file * file = NULL; | 571 | struct file * file = NULL; |
572 | unsigned long retval = -EBADF; | 572 | unsigned long retval = -EBADF; |
@@ -589,7 +589,7 @@ out: | |||
589 | return retval; | 589 | return retval; |
590 | } | 590 | } |
591 | 591 | ||
592 | asmlinkage long sys64_munmap(unsigned long addr, size_t len) | 592 | SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len) |
593 | { | 593 | { |
594 | long ret; | 594 | long ret; |
595 | 595 | ||
@@ -606,9 +606,9 @@ extern unsigned long do_mremap(unsigned long addr, | |||
606 | unsigned long old_len, unsigned long new_len, | 606 | unsigned long old_len, unsigned long new_len, |
607 | unsigned long flags, unsigned long new_addr); | 607 | unsigned long flags, unsigned long new_addr); |
608 | 608 | ||
609 | asmlinkage unsigned long sys64_mremap(unsigned long addr, | 609 | SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len, |
610 | unsigned long old_len, unsigned long new_len, | 610 | unsigned long, new_len, unsigned long, flags, |
611 | unsigned long flags, unsigned long new_addr) | 611 | unsigned long, new_addr) |
612 | { | 612 | { |
613 | unsigned long ret = -EINVAL; | 613 | unsigned long ret = -EINVAL; |
614 | 614 | ||
@@ -671,7 +671,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs) | |||
671 | 671 | ||
672 | extern void check_pending(int signum); | 672 | extern void check_pending(int signum); |
673 | 673 | ||
674 | asmlinkage long sys_getdomainname(char __user *name, int len) | 674 | SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) |
675 | { | 675 | { |
676 | int nlen, err; | 676 | int nlen, err; |
677 | 677 | ||
@@ -694,11 +694,10 @@ out: | |||
694 | return err; | 694 | return err; |
695 | } | 695 | } |
696 | 696 | ||
697 | asmlinkage long sys_utrap_install(utrap_entry_t type, | 697 | SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type, |
698 | utrap_handler_t new_p, | 698 | utrap_handler_t, new_p, utrap_handler_t, new_d, |
699 | utrap_handler_t new_d, | 699 | utrap_handler_t __user *, old_p, |
700 | utrap_handler_t __user *old_p, | 700 | utrap_handler_t __user *, old_d) |
701 | utrap_handler_t __user *old_d) | ||
702 | { | 701 | { |
703 | if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31) | 702 | if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31) |
704 | return -EINVAL; | 703 | return -EINVAL; |
@@ -764,11 +763,9 @@ asmlinkage long sparc_memory_ordering(unsigned long model, | |||
764 | return 0; | 763 | return 0; |
765 | } | 764 | } |
766 | 765 | ||
767 | asmlinkage long sys_rt_sigaction(int sig, | 766 | SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act, |
768 | const struct sigaction __user *act, | 767 | struct sigaction __user *, oact, void __user *, restorer, |
769 | struct sigaction __user *oact, | 768 | size_t, sigsetsize) |
770 | void __user *restorer, | ||
771 | size_t sigsetsize) | ||
772 | { | 769 | { |
773 | struct k_sigaction new_ka, old_ka; | 770 | struct k_sigaction new_ka, old_ka; |
774 | int ret; | 771 | int ret; |
@@ -808,7 +805,8 @@ asmlinkage void update_perfctrs(void) | |||
808 | reset_pic(); | 805 | reset_pic(); |
809 | } | 806 | } |
810 | 807 | ||
811 | asmlinkage long sys_perfctr(int opcode, unsigned long arg0, unsigned long arg1, unsigned long arg2) | 808 | SYSCALL_DEFINE4(perfctr, int, opcode, unsigned long, arg0, |
809 | unsigned long, arg1, unsigned long, arg2) | ||
812 | { | 810 | { |
813 | int err = 0; | 811 | int err = 0; |
814 | 812 | ||
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 7a6786a71363..d150c2aa98d2 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S | |||
@@ -20,8 +20,8 @@ execve_merge: | |||
20 | add %sp, PTREGS_OFF, %o0 | 20 | add %sp, PTREGS_OFF, %o0 |
21 | 21 | ||
22 | .align 32 | 22 | .align 32 |
23 | sys_pipe: | 23 | sys_sparc_pipe: |
24 | ba,pt %xcc, sparc_pipe | 24 | ba,pt %xcc, sys_sparc_pipe_real |
25 | add %sp, PTREGS_OFF, %o0 | 25 | add %sp, PTREGS_OFF, %o0 |
26 | sys_nis_syscall: | 26 | sys_nis_syscall: |
27 | ba,pt %xcc, c_sys_nis_syscall | 27 | ba,pt %xcc, c_sys_nis_syscall |
diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index bc9f5dac4069..15c2d752b2bc 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h | |||
@@ -16,9 +16,6 @@ extern asmlinkage long sys_ipc(unsigned int call, int first, | |||
16 | void __user *ptr, long fifth); | 16 | void __user *ptr, long fifth); |
17 | extern asmlinkage long sparc64_newuname(struct new_utsname __user *name); | 17 | extern asmlinkage long sparc64_newuname(struct new_utsname __user *name); |
18 | extern asmlinkage long sparc64_personality(unsigned long personality); | 18 | extern asmlinkage long sparc64_personality(unsigned long personality); |
19 | extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, | ||
20 | unsigned long prot, unsigned long flags, | ||
21 | unsigned long fd, unsigned long off); | ||
22 | extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); | 19 | extern asmlinkage long sys64_munmap(unsigned long addr, size_t len); |
23 | extern asmlinkage unsigned long sys64_mremap(unsigned long addr, | 20 | extern asmlinkage unsigned long sys64_mremap(unsigned long addr, |
24 | unsigned long old_len, | 21 | unsigned long old_len, |
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 7d0807586442..dccc95df0c7f 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S | |||
@@ -24,7 +24,7 @@ sys_call_table: | |||
24 | /*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause | 24 | /*25*/ .long sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause |
25 | /*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice | 25 | /*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice |
26 | /*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile | 26 | /*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile |
27 | /*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid | 27 | /*40*/ .long sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_getuid |
28 | /*45*/ .long sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16 | 28 | /*45*/ .long sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16 |
29 | /*50*/ .long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl | 29 | /*50*/ .long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl |
30 | /*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve | 30 | /*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve |
@@ -56,7 +56,7 @@ sys_call_table: | |||
56 | /*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname | 56 | /*185*/ .long sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname |
57 | /*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_epoll_create, sys_epoll_ctl | 57 | /*190*/ .long sys_init_module, sys_personality, sparc_remap_file_pages, sys_epoll_create, sys_epoll_ctl |
58 | /*195*/ .long sys_epoll_wait, sys_ioprio_set, sys_getppid, sparc_sigaction, sys_sgetmask | 58 | /*195*/ .long sys_epoll_wait, sys_ioprio_set, sys_getppid, sparc_sigaction, sys_sgetmask |
59 | /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir | 59 | /*200*/ .long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, sys_old_readdir |
60 | /*205*/ .long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 | 60 | /*205*/ .long sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 |
61 | /*210*/ .long sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo | 61 | /*210*/ .long sys_fadvise64_64, sys_tgkill, sys_waitpid, sys_swapoff, sys_sysinfo |
62 | /*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex | 62 | /*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_ioprio_get, sys_adjtimex |
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index 9fc78cf354bd..f93c42a2b522 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S | |||
@@ -21,12 +21,12 @@ sys_call_table32: | |||
21 | /*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write | 21 | /*0*/ .word sys_restart_syscall, sys32_exit, sys_fork, sys_read, sys_write |
22 | /*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link | 22 | /*5*/ .word sys32_open, sys_close, sys32_wait4, sys32_creat, sys_link |
23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod | 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod |
24 | /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek | 24 | /*15*/ .word sys_chmod, sys_lchown16, sys_sparc_brk, sys32_perfctr, sys32_lseek |
25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 | 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 |
26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause | 26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause |
27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice | 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice |
28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile | 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile |
29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid | 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_sparc_pipe, compat_sys_times, sys_getuid |
30 | .word sys32_umount, sys_setgid16, sys_getgid16, sys32_signal, sys_geteuid16 | 30 | .word sys32_umount, sys_setgid16, sys_getgid16, sys32_signal, sys_geteuid16 |
31 | /*50*/ .word sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl | 31 | /*50*/ .word sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, compat_sys_ioctl |
32 | .word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve | 32 | .word sys32_reboot, sys32_mmap2, sys_symlink, sys32_readlink, sys32_execve |
@@ -55,8 +55,8 @@ sys_call_table32: | |||
55 | /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents | 55 | /*170*/ .word sys32_lsetxattr, sys32_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents |
56 | .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr | 56 | .word sys_setsid, sys_fchdir, sys32_fgetxattr, sys_listxattr, sys_llistxattr |
57 | /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall | 57 | /*180*/ .word sys32_flistxattr, sys_removexattr, sys_lremovexattr, compat_sys_sigpending, sys_ni_syscall |
58 | .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sparc64_newuname | 58 | .word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sys_sparc64_newuname |
59 | /*190*/ .word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl | 59 | /*190*/ .word sys32_init_module, sys_sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl |
60 | .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask | 60 | .word sys32_epoll_wait, sys32_ioprio_set, sys_getppid, sys32_sigaction, sys_sgetmask |
61 | /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir | 61 | /*200*/ .word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir |
62 | .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 | 62 | .word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64 |
@@ -95,18 +95,18 @@ sys_call_table: | |||
95 | /*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write | 95 | /*0*/ .word sys_restart_syscall, sparc_exit, sys_fork, sys_read, sys_write |
96 | /*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link | 96 | /*5*/ .word sys_open, sys_close, sys_wait4, sys_creat, sys_link |
97 | /*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod | 97 | /*10*/ .word sys_unlink, sys_nis_syscall, sys_chdir, sys_chown, sys_mknod |
98 | /*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek | 98 | /*15*/ .word sys_chmod, sys_lchown, sys_sparc_brk, sys_perfctr, sys_lseek |
99 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid | 99 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid |
100 | /*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall | 100 | /*25*/ .word sys_vmsplice, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall |
101 | /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice | 101 | /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice |
102 | .word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64 | 102 | .word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile64 |
103 | /*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall | 103 | /*40*/ .word sys_newlstat, sys_dup, sys_sparc_pipe, sys_times, sys_nis_syscall |
104 | .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid | 104 | .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid |
105 | /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl | 105 | /*50*/ .word sys_getegid, sys_acct, sys_memory_ordering, sys_nis_syscall, sys_ioctl |
106 | .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve | 106 | .word sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve |
107 | /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize | 107 | /*60*/ .word sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize |
108 | .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall | 108 | .word sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_nis_syscall |
109 | /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys64_munmap, sys_mprotect | 109 | /*70*/ .word sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_64_munmap, sys_mprotect |
110 | .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups | 110 | .word sys_madvise, sys_vhangup, sys_nis_syscall, sys_mincore, sys_getgroups |
111 | /*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall | 111 | /*80*/ .word sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall |
112 | .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall | 112 | .word sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall |
@@ -129,8 +129,8 @@ sys_call_table: | |||
129 | /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents | 129 | /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents |
130 | .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr | 130 | .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr |
131 | /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall | 131 | /*180*/ .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall |
132 | .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sparc64_newuname | 132 | .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_sparc64_newuname |
133 | /*190*/ .word sys_init_module, sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl | 133 | /*190*/ .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl |
134 | .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask | 134 | .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask |
135 | /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall | 135 | /*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall |
136 | .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 | 136 | .word sys_readahead, sys_socketcall, sys_syslog, sys_lookup_dcookie, sys_fadvise64 |
@@ -142,7 +142,7 @@ sys_call_table: | |||
142 | .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall | 142 | .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall |
143 | /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler | 143 | /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler |
144 | .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep | 144 | .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep |
145 | /*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl | 145 | /*250*/ .word sys_64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl |
146 | .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep | 146 | .word sys_sync_file_range, sys_clock_settime, sys_clock_gettime, sys_clock_getres, sys_clock_nanosleep |
147 | /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun | 147 | /*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun |
148 | .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy | 148 | .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy |
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index c2d153d46586..d809c4ebb48f 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* arch/sparc64/kernel/traps.c | 1 | /* arch/sparc64/kernel/traps.c |
2 | * | 2 | * |
3 | * Copyright (C) 1995,1997,2008 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1995,1997,2008,2009 David S. Miller (davem@davemloft.net) |
4 | * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com) | 4 | * Copyright (C) 1997,1999,2000 Jakub Jelinek (jakub@redhat.com) |
5 | */ | 5 | */ |
6 | 6 | ||
@@ -314,6 +314,21 @@ void sun4v_data_access_exception(struct pt_regs *regs, unsigned long addr, unsig | |||
314 | return; | 314 | return; |
315 | 315 | ||
316 | if (regs->tstate & TSTATE_PRIV) { | 316 | if (regs->tstate & TSTATE_PRIV) { |
317 | /* Test if this comes from uaccess places. */ | ||
318 | const struct exception_table_entry *entry; | ||
319 | |||
320 | entry = search_exception_tables(regs->tpc); | ||
321 | if (entry) { | ||
322 | /* Ouch, somebody is trying VM hole tricks on us... */ | ||
323 | #ifdef DEBUG_EXCEPTIONS | ||
324 | printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc); | ||
325 | printk("EX_TABLE: insn<%016lx> fixup<%016lx>\n", | ||
326 | regs->tpc, entry->fixup); | ||
327 | #endif | ||
328 | regs->tpc = entry->fixup; | ||
329 | regs->tnpc = regs->tpc + 4; | ||
330 | return; | ||
331 | } | ||
317 | printk("sun4v_data_access_exception: ADDR[%016lx] " | 332 | printk("sun4v_data_access_exception: ADDR[%016lx] " |
318 | "CTX[%04x] TYPE[%04x], going.\n", | 333 | "CTX[%04x] TYPE[%04x], going.\n", |
319 | addr, ctx, type); | 334 | addr, ctx, type); |
diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S index ea925503b42e..d9bdfb9d5c18 100644 --- a/arch/sparc/kernel/ttable.S +++ b/arch/sparc/kernel/ttable.S | |||
@@ -63,7 +63,8 @@ tl0_irq6: TRAP_IRQ(smp_call_function_single_client, 6) | |||
63 | #else | 63 | #else |
64 | tl0_irq6: BTRAP(0x46) | 64 | tl0_irq6: BTRAP(0x46) |
65 | #endif | 65 | #endif |
66 | tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) | 66 | tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7) |
67 | tl0_irq8: BTRAP(0x48) BTRAP(0x49) | ||
67 | tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) | 68 | tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) |
68 | tl0_irq14: TRAP_IRQ(timer_interrupt, 14) | 69 | tl0_irq14: TRAP_IRQ(timer_interrupt, 14) |
69 | tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) | 70 | tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) |
diff --git a/arch/sparc/lib/GENbzero.S b/arch/sparc/lib/GENbzero.S index 6a4f956a2f7a..8e7a843ddd88 100644 --- a/arch/sparc/lib/GENbzero.S +++ b/arch/sparc/lib/GENbzero.S | |||
@@ -6,13 +6,9 @@ | |||
6 | 6 | ||
7 | #define EX_ST(x,y) \ | 7 | #define EX_ST(x,y) \ |
8 | 98: x,y; \ | 8 | 98: x,y; \ |
9 | .section .fixup; \ | ||
10 | .align 4; \ | ||
11 | 99: retl; \ | ||
12 | mov %o1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 9 | .section __ex_table,"a";\ |
14 | .align 4; \ | 10 | .align 4; \ |
15 | .word 98b, 99b; \ | 11 | .word 98b, __retl_o1; \ |
16 | .text; \ | 12 | .text; \ |
17 | .align 4; | 13 | .align 4; |
18 | 14 | ||
diff --git a/arch/sparc/lib/GENcopy_from_user.S b/arch/sparc/lib/GENcopy_from_user.S index 2b9df99e87f9..b7d0bd6b1406 100644 --- a/arch/sparc/lib/GENcopy_from_user.S +++ b/arch/sparc/lib/GENcopy_from_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
@@ -27,7 +23,7 @@ | |||
27 | #define PREAMBLE \ | 23 | #define PREAMBLE \ |
28 | rd %asi, %g1; \ | 24 | rd %asi, %g1; \ |
29 | cmp %g1, ASI_AIUS; \ | 25 | cmp %g1, ASI_AIUS; \ |
30 | bne,pn %icc, memcpy_user_stub; \ | 26 | bne,pn %icc, ___copy_in_user; \ |
31 | nop | 27 | nop |
32 | #endif | 28 | #endif |
33 | 29 | ||
diff --git a/arch/sparc/lib/GENcopy_to_user.S b/arch/sparc/lib/GENcopy_to_user.S index bb3f7084daf9..780550e1afc7 100644 --- a/arch/sparc/lib/GENcopy_to_user.S +++ b/arch/sparc/lib/GENcopy_to_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
@@ -31,7 +27,7 @@ | |||
31 | #define PREAMBLE \ | 27 | #define PREAMBLE \ |
32 | rd %asi, %g1; \ | 28 | rd %asi, %g1; \ |
33 | cmp %g1, ASI_AIUS; \ | 29 | cmp %g1, ASI_AIUS; \ |
34 | bne,pn %icc, memcpy_user_stub; \ | 30 | bne,pn %icc, ___copy_in_user; \ |
35 | nop | 31 | nop |
36 | #endif | 32 | #endif |
37 | 33 | ||
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 273fc85269fc..e75faf0e59ae 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile | |||
@@ -18,7 +18,7 @@ lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o | |||
18 | lib-y += rwsem_$(BITS).o | 18 | lib-y += rwsem_$(BITS).o |
19 | lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o | 19 | lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o |
20 | 20 | ||
21 | lib-$(CONFIG_SPARC64) += PeeCeeI.o copy_page.o clear_page.o bzero.o | 21 | lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o |
22 | lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o | 22 | lib-$(CONFIG_SPARC64) += csum_copy.o csum_copy_from_user.o csum_copy_to_user.o |
23 | lib-$(CONFIG_SPARC64) += VISsave.o | 23 | lib-$(CONFIG_SPARC64) += VISsave.o |
24 | lib-$(CONFIG_SPARC64) += bitops.o | 24 | lib-$(CONFIG_SPARC64) += bitops.o |
@@ -43,3 +43,4 @@ lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o | |||
43 | obj-y += iomap.o | 43 | obj-y += iomap.o |
44 | obj-$(CONFIG_SPARC32) += atomic32.o | 44 | obj-$(CONFIG_SPARC32) += atomic32.o |
45 | obj-y += ksyms.o | 45 | obj-y += ksyms.o |
46 | obj-$(CONFIG_SPARC64) += PeeCeeI.o | ||
diff --git a/arch/sparc/lib/NG2copy_from_user.S b/arch/sparc/lib/NG2copy_from_user.S index c77ef5f22102..119ccb9a54f4 100644 --- a/arch/sparc/lib/NG2copy_from_user.S +++ b/arch/sparc/lib/NG2copy_from_user.S | |||
@@ -5,14 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: wr %g0, ASI_AIUS, %asi;\ | ||
11 | retl; \ | ||
12 | mov 1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
14 | .align 4; \ | 9 | .align 4; \ |
15 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one_asi;\ |
16 | .text; \ | 11 | .text; \ |
17 | .align 4; | 12 | .align 4; |
18 | 13 | ||
@@ -33,7 +28,7 @@ | |||
33 | #define PREAMBLE \ | 28 | #define PREAMBLE \ |
34 | rd %asi, %g1; \ | 29 | rd %asi, %g1; \ |
35 | cmp %g1, ASI_AIUS; \ | 30 | cmp %g1, ASI_AIUS; \ |
36 | bne,pn %icc, memcpy_user_stub; \ | 31 | bne,pn %icc, ___copy_in_user; \ |
37 | nop | 32 | nop |
38 | #endif | 33 | #endif |
39 | 34 | ||
diff --git a/arch/sparc/lib/NG2copy_to_user.S b/arch/sparc/lib/NG2copy_to_user.S index 4bd4093acbbd..7fe1ccefd9d0 100644 --- a/arch/sparc/lib/NG2copy_to_user.S +++ b/arch/sparc/lib/NG2copy_to_user.S | |||
@@ -5,14 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: wr %g0, ASI_AIUS, %asi;\ | ||
11 | retl; \ | ||
12 | mov 1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
14 | .align 4; \ | 9 | .align 4; \ |
15 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one_asi;\ |
16 | .text; \ | 11 | .text; \ |
17 | .align 4; | 12 | .align 4; |
18 | 13 | ||
@@ -42,7 +37,7 @@ | |||
42 | #define PREAMBLE \ | 37 | #define PREAMBLE \ |
43 | rd %asi, %g1; \ | 38 | rd %asi, %g1; \ |
44 | cmp %g1, ASI_AIUS; \ | 39 | cmp %g1, ASI_AIUS; \ |
45 | bne,pn %icc, memcpy_user_stub; \ | 40 | bne,pn %icc, ___copy_in_user; \ |
46 | nop | 41 | nop |
47 | #endif | 42 | #endif |
48 | 43 | ||
diff --git a/arch/sparc/lib/NGbzero.S b/arch/sparc/lib/NGbzero.S index 814d5f7a45e1..beab29bf419b 100644 --- a/arch/sparc/lib/NGbzero.S +++ b/arch/sparc/lib/NGbzero.S | |||
@@ -6,13 +6,9 @@ | |||
6 | 6 | ||
7 | #define EX_ST(x,y) \ | 7 | #define EX_ST(x,y) \ |
8 | 98: x,y; \ | 8 | 98: x,y; \ |
9 | .section .fixup; \ | ||
10 | .align 4; \ | ||
11 | 99: retl; \ | ||
12 | mov %o1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 9 | .section __ex_table,"a";\ |
14 | .align 4; \ | 10 | .align 4; \ |
15 | .word 98b, 99b; \ | 11 | .word 98b, __retl_o1; \ |
16 | .text; \ | 12 | .text; \ |
17 | .align 4; | 13 | .align 4; |
18 | 14 | ||
diff --git a/arch/sparc/lib/NGcopy_from_user.S b/arch/sparc/lib/NGcopy_from_user.S index e7f433f71b42..5d1e4d1ac21e 100644 --- a/arch/sparc/lib/NGcopy_from_user.S +++ b/arch/sparc/lib/NGcopy_from_user.S | |||
@@ -5,14 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: wr %g0, ASI_AIUS, %asi;\ | ||
11 | ret; \ | ||
12 | restore %g0, 1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
14 | .align 4; \ | 9 | .align 4; \ |
15 | .word 98b, 99b; \ | 10 | .word 98b, __ret_one_asi;\ |
16 | .text; \ | 11 | .text; \ |
17 | .align 4; | 12 | .align 4; |
18 | 13 | ||
@@ -30,7 +25,7 @@ | |||
30 | #define PREAMBLE \ | 25 | #define PREAMBLE \ |
31 | rd %asi, %g1; \ | 26 | rd %asi, %g1; \ |
32 | cmp %g1, ASI_AIUS; \ | 27 | cmp %g1, ASI_AIUS; \ |
33 | bne,pn %icc, memcpy_user_stub; \ | 28 | bne,pn %icc, ___copy_in_user; \ |
34 | nop | 29 | nop |
35 | #endif | 30 | #endif |
36 | 31 | ||
diff --git a/arch/sparc/lib/NGcopy_to_user.S b/arch/sparc/lib/NGcopy_to_user.S index 6ea01c5532a0..ff630dcb273c 100644 --- a/arch/sparc/lib/NGcopy_to_user.S +++ b/arch/sparc/lib/NGcopy_to_user.S | |||
@@ -5,14 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: wr %g0, ASI_AIUS, %asi;\ | ||
11 | ret; \ | ||
12 | restore %g0, 1, %o0; \ | ||
13 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
14 | .align 4; \ | 9 | .align 4; \ |
15 | .word 98b, 99b; \ | 10 | .word 98b, __ret_one_asi;\ |
16 | .text; \ | 11 | .text; \ |
17 | .align 4; | 12 | .align 4; |
18 | 13 | ||
@@ -33,7 +28,7 @@ | |||
33 | #define PREAMBLE \ | 28 | #define PREAMBLE \ |
34 | rd %asi, %g1; \ | 29 | rd %asi, %g1; \ |
35 | cmp %g1, ASI_AIUS; \ | 30 | cmp %g1, ASI_AIUS; \ |
36 | bne,pn %icc, memcpy_user_stub; \ | 31 | bne,pn %icc, ___copy_in_user; \ |
37 | nop | 32 | nop |
38 | #endif | 33 | #endif |
39 | 34 | ||
diff --git a/arch/sparc/lib/U1copy_from_user.S b/arch/sparc/lib/U1copy_from_user.S index 3192b0bf4fab..a6ae2ea04bf5 100644 --- a/arch/sparc/lib/U1copy_from_user.S +++ b/arch/sparc/lib/U1copy_from_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
@@ -27,7 +23,7 @@ | |||
27 | #define PREAMBLE \ | 23 | #define PREAMBLE \ |
28 | rd %asi, %g1; \ | 24 | rd %asi, %g1; \ |
29 | cmp %g1, ASI_AIUS; \ | 25 | cmp %g1, ASI_AIUS; \ |
30 | bne,pn %icc, memcpy_user_stub; \ | 26 | bne,pn %icc, ___copy_in_user; \ |
31 | nop; \ | 27 | nop; \ |
32 | 28 | ||
33 | #include "U1memcpy.S" | 29 | #include "U1memcpy.S" |
diff --git a/arch/sparc/lib/U1copy_to_user.S b/arch/sparc/lib/U1copy_to_user.S index d1210ffb0b82..f4b970eeb485 100644 --- a/arch/sparc/lib/U1copy_to_user.S +++ b/arch/sparc/lib/U1copy_to_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
@@ -27,7 +23,7 @@ | |||
27 | #define PREAMBLE \ | 23 | #define PREAMBLE \ |
28 | rd %asi, %g1; \ | 24 | rd %asi, %g1; \ |
29 | cmp %g1, ASI_AIUS; \ | 25 | cmp %g1, ASI_AIUS; \ |
30 | bne,pn %icc, memcpy_user_stub; \ | 26 | bne,pn %icc, ___copy_in_user; \ |
31 | nop; \ | 27 | nop; \ |
32 | 28 | ||
33 | #include "U1memcpy.S" | 29 | #include "U1memcpy.S" |
diff --git a/arch/sparc/lib/U3copy_from_user.S b/arch/sparc/lib/U3copy_from_user.S index f5bfc8d9d216..b1acd1331c33 100644 --- a/arch/sparc/lib/U3copy_from_user.S +++ b/arch/sparc/lib/U3copy_from_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_LD(x) \ | 6 | #define EX_LD(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
diff --git a/arch/sparc/lib/U3copy_to_user.S b/arch/sparc/lib/U3copy_to_user.S index 2334f111bb0c..ef1e493afdfa 100644 --- a/arch/sparc/lib/U3copy_to_user.S +++ b/arch/sparc/lib/U3copy_to_user.S | |||
@@ -5,13 +5,9 @@ | |||
5 | 5 | ||
6 | #define EX_ST(x) \ | 6 | #define EX_ST(x) \ |
7 | 98: x; \ | 7 | 98: x; \ |
8 | .section .fixup; \ | ||
9 | .align 4; \ | ||
10 | 99: retl; \ | ||
11 | mov 1, %o0; \ | ||
12 | .section __ex_table,"a";\ | 8 | .section __ex_table,"a";\ |
13 | .align 4; \ | 9 | .align 4; \ |
14 | .word 98b, 99b; \ | 10 | .word 98b, __retl_one; \ |
15 | .text; \ | 11 | .text; \ |
16 | .align 4; | 12 | .align 4; |
17 | 13 | ||
@@ -27,7 +23,7 @@ | |||
27 | #define PREAMBLE \ | 23 | #define PREAMBLE \ |
28 | rd %asi, %g1; \ | 24 | rd %asi, %g1; \ |
29 | cmp %g1, ASI_AIUS; \ | 25 | cmp %g1, ASI_AIUS; \ |
30 | bne,pn %icc, memcpy_user_stub; \ | 26 | bne,pn %icc, ___copy_in_user; \ |
31 | nop; \ | 27 | nop; \ |
32 | 28 | ||
33 | #include "U3memcpy.S" | 29 | #include "U3memcpy.S" |
diff --git a/arch/sparc/lib/bzero.S b/arch/sparc/lib/bzero.S index c7bbae8c590f..b6557297440f 100644 --- a/arch/sparc/lib/bzero.S +++ b/arch/sparc/lib/bzero.S | |||
@@ -88,13 +88,9 @@ __bzero_done: | |||
88 | 88 | ||
89 | #define EX_ST(x,y) \ | 89 | #define EX_ST(x,y) \ |
90 | 98: x,y; \ | 90 | 98: x,y; \ |
91 | .section .fixup; \ | ||
92 | .align 4; \ | ||
93 | 99: retl; \ | ||
94 | mov %o1, %o0; \ | ||
95 | .section __ex_table,"a";\ | 91 | .section __ex_table,"a";\ |
96 | .align 4; \ | 92 | .align 4; \ |
97 | .word 98b, 99b; \ | 93 | .word 98b, __retl_o1; \ |
98 | .text; \ | 94 | .text; \ |
99 | .align 4; | 95 | .align 4; |
100 | 96 | ||
diff --git a/arch/sparc/lib/copy_in_user.S b/arch/sparc/lib/copy_in_user.S index 650af3f21f78..302c0e60dc2c 100644 --- a/arch/sparc/lib/copy_in_user.S +++ b/arch/sparc/lib/copy_in_user.S | |||
@@ -3,19 +3,16 @@ | |||
3 | * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/linkage.h> | ||
6 | #include <asm/asi.h> | 7 | #include <asm/asi.h> |
7 | 8 | ||
8 | #define XCC xcc | 9 | #define XCC xcc |
9 | 10 | ||
10 | #define EX(x,y) \ | 11 | #define EX(x,y) \ |
11 | 98: x,y; \ | 12 | 98: x,y; \ |
12 | .section .fixup; \ | ||
13 | .align 4; \ | ||
14 | 99: retl; \ | ||
15 | mov 1, %o0; \ | ||
16 | .section __ex_table,"a";\ | 13 | .section __ex_table,"a";\ |
17 | .align 4; \ | 14 | .align 4; \ |
18 | .word 98b, 99b; \ | 15 | .word 98b, __retl_one; \ |
19 | .text; \ | 16 | .text; \ |
20 | .align 4; | 17 | .align 4; |
21 | 18 | ||
@@ -31,18 +28,7 @@ | |||
31 | * to copy register windows around during thread cloning. | 28 | * to copy register windows around during thread cloning. |
32 | */ | 29 | */ |
33 | 30 | ||
34 | .globl ___copy_in_user | 31 | ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */ |
35 | .type ___copy_in_user,#function | ||
36 | ___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ | ||
37 | /* Writing to %asi is _expensive_ so we hardcode it. | ||
38 | * Reading %asi to check for KERNEL_DS is comparatively | ||
39 | * cheap. | ||
40 | */ | ||
41 | rd %asi, %g1 | ||
42 | cmp %g1, ASI_AIUS | ||
43 | bne,pn %icc, memcpy_user_stub | ||
44 | nop | ||
45 | |||
46 | cmp %o2, 0 | 32 | cmp %o2, 0 |
47 | be,pn %XCC, 85f | 33 | be,pn %XCC, 85f |
48 | or %o0, %o1, %o3 | 34 | or %o0, %o1, %o3 |
@@ -53,22 +39,24 @@ ___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ | |||
53 | /* 16 < len <= 64 */ | 39 | /* 16 < len <= 64 */ |
54 | andcc %o3, 0x7, %g0 | 40 | andcc %o3, 0x7, %g0 |
55 | bne,pn %XCC, 90f | 41 | bne,pn %XCC, 90f |
56 | sub %o0, %o1, %o3 | 42 | nop |
57 | 43 | ||
58 | andn %o2, 0x7, %o4 | 44 | andn %o2, 0x7, %o4 |
59 | and %o2, 0x7, %o2 | 45 | and %o2, 0x7, %o2 |
60 | 1: subcc %o4, 0x8, %o4 | 46 | 1: subcc %o4, 0x8, %o4 |
61 | EX(ldxa [%o1] %asi, %o5) | 47 | EX(ldxa [%o1] %asi, %o5) |
62 | EX(stxa %o5, [%o1 + %o3] ASI_AIUS) | 48 | EX(stxa %o5, [%o0] %asi) |
49 | add %o1, 0x8, %o1 | ||
63 | bgu,pt %XCC, 1b | 50 | bgu,pt %XCC, 1b |
64 | add %o1, 0x8, %o1 | 51 | add %o0, 0x8, %o0 |
65 | andcc %o2, 0x4, %g0 | 52 | andcc %o2, 0x4, %g0 |
66 | be,pt %XCC, 1f | 53 | be,pt %XCC, 1f |
67 | nop | 54 | nop |
68 | sub %o2, 0x4, %o2 | 55 | sub %o2, 0x4, %o2 |
69 | EX(lduwa [%o1] %asi, %o5) | 56 | EX(lduwa [%o1] %asi, %o5) |
70 | EX(stwa %o5, [%o1 + %o3] ASI_AIUS) | 57 | EX(stwa %o5, [%o0] %asi) |
71 | add %o1, 0x4, %o1 | 58 | add %o1, 0x4, %o1 |
59 | add %o0, 0x4, %o0 | ||
72 | 1: cmp %o2, 0 | 60 | 1: cmp %o2, 0 |
73 | be,pt %XCC, 85f | 61 | be,pt %XCC, 85f |
74 | nop | 62 | nop |
@@ -78,14 +66,15 @@ ___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ | |||
78 | 80: /* 0 < len <= 16 */ | 66 | 80: /* 0 < len <= 16 */ |
79 | andcc %o3, 0x3, %g0 | 67 | andcc %o3, 0x3, %g0 |
80 | bne,pn %XCC, 90f | 68 | bne,pn %XCC, 90f |
81 | sub %o0, %o1, %o3 | 69 | nop |
82 | 70 | ||
83 | 82: | 71 | 82: |
84 | subcc %o2, 4, %o2 | 72 | subcc %o2, 4, %o2 |
85 | EX(lduwa [%o1] %asi, %g1) | 73 | EX(lduwa [%o1] %asi, %g1) |
86 | EX(stwa %g1, [%o1 + %o3] ASI_AIUS) | 74 | EX(stwa %g1, [%o0] %asi) |
75 | add %o1, 4, %o1 | ||
87 | bgu,pt %XCC, 82b | 76 | bgu,pt %XCC, 82b |
88 | add %o1, 4, %o1 | 77 | add %o0, 4, %o0 |
89 | 78 | ||
90 | 85: retl | 79 | 85: retl |
91 | clr %o0 | 80 | clr %o0 |
@@ -94,26 +83,10 @@ ___copy_in_user: /* %o0=dst, %o1=src, %o2=len */ | |||
94 | 90: | 83 | 90: |
95 | subcc %o2, 1, %o2 | 84 | subcc %o2, 1, %o2 |
96 | EX(lduba [%o1] %asi, %g1) | 85 | EX(lduba [%o1] %asi, %g1) |
97 | EX(stba %g1, [%o1 + %o3] ASI_AIUS) | 86 | EX(stba %g1, [%o0] %asi) |
87 | add %o1, 1, %o1 | ||
98 | bgu,pt %XCC, 90b | 88 | bgu,pt %XCC, 90b |
99 | add %o1, 1, %o1 | 89 | add %o0, 1, %o0 |
100 | retl | 90 | retl |
101 | clr %o0 | 91 | clr %o0 |
102 | 92 | ENDPROC(___copy_in_user) | |
103 | .size ___copy_in_user, .-___copy_in_user | ||
104 | |||
105 | /* Act like copy_{to,in}_user(), ie. return zero instead | ||
106 | * of original destination pointer. This is invoked when | ||
107 | * copy_{to,in}_user() finds that %asi is kernel space. | ||
108 | */ | ||
109 | .globl memcpy_user_stub | ||
110 | .type memcpy_user_stub,#function | ||
111 | memcpy_user_stub: | ||
112 | save %sp, -192, %sp | ||
113 | mov %i0, %o0 | ||
114 | mov %i1, %o1 | ||
115 | call memcpy | ||
116 | mov %i2, %o2 | ||
117 | ret | ||
118 | restore %g0, %g0, %o0 | ||
119 | .size memcpy_user_stub, .-memcpy_user_stub | ||
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a9e474bf6385..4ab8993b0863 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/kprobes.h> | 20 | #include <linux/kprobes.h> |
21 | #include <linux/kdebug.h> | 21 | #include <linux/kdebug.h> |
22 | #include <linux/percpu.h> | ||
22 | 23 | ||
23 | #include <asm/page.h> | 24 | #include <asm/page.h> |
24 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
@@ -224,6 +225,30 @@ cannot_handle: | |||
224 | unhandled_fault (address, current, regs); | 225 | unhandled_fault (address, current, regs); |
225 | } | 226 | } |
226 | 227 | ||
228 | static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) | ||
229 | { | ||
230 | static int times; | ||
231 | |||
232 | if (times++ < 10) | ||
233 | printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " | ||
234 | "64-bit TPC [%lx]\n", | ||
235 | current->comm, current->pid, | ||
236 | regs->tpc); | ||
237 | show_regs(regs); | ||
238 | } | ||
239 | |||
240 | static void noinline bogus_32bit_fault_address(struct pt_regs *regs, | ||
241 | unsigned long addr) | ||
242 | { | ||
243 | static int times; | ||
244 | |||
245 | if (times++ < 10) | ||
246 | printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " | ||
247 | "reports 64-bit fault address [%lx]\n", | ||
248 | current->comm, current->pid, addr); | ||
249 | show_regs(regs); | ||
250 | } | ||
251 | |||
227 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | 252 | asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) |
228 | { | 253 | { |
229 | struct mm_struct *mm = current->mm; | 254 | struct mm_struct *mm = current->mm; |
@@ -244,6 +269,19 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
244 | (fault_code & FAULT_CODE_DTLB)) | 269 | (fault_code & FAULT_CODE_DTLB)) |
245 | BUG(); | 270 | BUG(); |
246 | 271 | ||
272 | if (test_thread_flag(TIF_32BIT)) { | ||
273 | if (!(regs->tstate & TSTATE_PRIV)) { | ||
274 | if (unlikely((regs->tpc >> 32) != 0)) { | ||
275 | bogus_32bit_fault_tpc(regs); | ||
276 | goto intr_or_no_mm; | ||
277 | } | ||
278 | } | ||
279 | if (unlikely((address >> 32) != 0)) { | ||
280 | bogus_32bit_fault_address(regs, address); | ||
281 | goto intr_or_no_mm; | ||
282 | } | ||
283 | } | ||
284 | |||
247 | if (regs->tstate & TSTATE_PRIV) { | 285 | if (regs->tstate & TSTATE_PRIV) { |
248 | unsigned long tpc = regs->tpc; | 286 | unsigned long tpc = regs->tpc; |
249 | 287 | ||
@@ -264,12 +302,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) | |||
264 | if (in_atomic() || !mm) | 302 | if (in_atomic() || !mm) |
265 | goto intr_or_no_mm; | 303 | goto intr_or_no_mm; |
266 | 304 | ||
267 | if (test_thread_flag(TIF_32BIT)) { | ||
268 | if (!(regs->tstate & TSTATE_PRIV)) | ||
269 | regs->tpc &= 0xffffffff; | ||
270 | address &= 0xffffffff; | ||
271 | } | ||
272 | |||
273 | if (!down_read_trylock(&mm->mmap_sem)) { | 305 | if (!down_read_trylock(&mm->mmap_sem)) { |
274 | if ((regs->tstate & TSTATE_PRIV) && | 306 | if ((regs->tstate & TSTATE_PRIV) && |
275 | !search_exception_tables(regs->tpc)) { | 307 | !search_exception_tables(regs->tpc)) { |
diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c index d6e170c074fc..d172f86439b1 100644 --- a/arch/sparc/oprofile/init.c +++ b/arch/sparc/oprofile/init.c | |||
@@ -13,217 +13,57 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | 14 | ||
15 | #ifdef CONFIG_SPARC64 | 15 | #ifdef CONFIG_SPARC64 |
16 | #include <asm/hypervisor.h> | 16 | #include <linux/notifier.h> |
17 | #include <asm/spitfire.h> | 17 | #include <linux/rcupdate.h> |
18 | #include <asm/cpudata.h> | 18 | #include <linux/kdebug.h> |
19 | #include <asm/irq.h> | 19 | #include <asm/nmi.h> |
20 | 20 | ||
21 | static int nmi_enabled; | 21 | static int profile_timer_exceptions_notify(struct notifier_block *self, |
22 | 22 | unsigned long val, void *data) | |
23 | struct pcr_ops { | ||
24 | u64 (*read)(void); | ||
25 | void (*write)(u64); | ||
26 | }; | ||
27 | static const struct pcr_ops *pcr_ops; | ||
28 | |||
29 | static u64 direct_pcr_read(void) | ||
30 | { | ||
31 | u64 val; | ||
32 | |||
33 | read_pcr(val); | ||
34 | return val; | ||
35 | } | ||
36 | |||
37 | static void direct_pcr_write(u64 val) | ||
38 | { | ||
39 | write_pcr(val); | ||
40 | } | ||
41 | |||
42 | static const struct pcr_ops direct_pcr_ops = { | ||
43 | .read = direct_pcr_read, | ||
44 | .write = direct_pcr_write, | ||
45 | }; | ||
46 | |||
47 | static void n2_pcr_write(u64 val) | ||
48 | { | 23 | { |
49 | unsigned long ret; | 24 | struct die_args *args = (struct die_args *)data; |
50 | 25 | int ret = NOTIFY_DONE; | |
51 | ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); | ||
52 | if (val != HV_EOK) | ||
53 | write_pcr(val); | ||
54 | } | ||
55 | |||
56 | static const struct pcr_ops n2_pcr_ops = { | ||
57 | .read = direct_pcr_read, | ||
58 | .write = n2_pcr_write, | ||
59 | }; | ||
60 | |||
61 | /* In order to commonize as much of the implementation as | ||
62 | * possible, we use PICH as our counter. Mostly this is | ||
63 | * to accomodate Niagara-1 which can only count insn cycles | ||
64 | * in PICH. | ||
65 | */ | ||
66 | static u64 picl_value(void) | ||
67 | { | ||
68 | u32 delta = local_cpu_data().clock_tick / HZ; | ||
69 | |||
70 | return ((u64)((0 - delta) & 0xffffffff)) << 32; | ||
71 | } | ||
72 | |||
73 | #define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ | ||
74 | #define PCR_STRACE 0x00000002 /* Trace supervisor events */ | ||
75 | #define PCR_UTRACE 0x00000004 /* Trace user events */ | ||
76 | #define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ | ||
77 | #define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ | ||
78 | #define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ | ||
79 | #define PCR_N2_MASK0 0x00003fc0 | ||
80 | #define PCR_N2_MASK0_SHIFT 6 | ||
81 | #define PCR_N2_SL0 0x0003c000 | ||
82 | #define PCR_N2_SL0_SHIFT 14 | ||
83 | #define PCR_N2_OV0 0x00040000 | ||
84 | #define PCR_N2_MASK1 0x07f80000 | ||
85 | #define PCR_N2_MASK1_SHIFT 19 | ||
86 | #define PCR_N2_SL1 0x78000000 | ||
87 | #define PCR_N2_SL1_SHIFT 27 | ||
88 | #define PCR_N2_OV1 0x80000000 | ||
89 | |||
90 | #define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) | ||
91 | #define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ | ||
92 | PCR_N2_TOE_OV1 | \ | ||
93 | (2 << PCR_N2_SL1_SHIFT) | \ | ||
94 | (0xff << PCR_N2_MASK1_SHIFT)) | ||
95 | |||
96 | static u64 pcr_enable = PCR_SUN4U_ENABLE; | ||
97 | |||
98 | static void nmi_handler(struct pt_regs *regs) | ||
99 | { | ||
100 | pcr_ops->write(PCR_PIC_PRIV); | ||
101 | |||
102 | if (nmi_enabled) { | ||
103 | oprofile_add_sample(regs, 0); | ||
104 | |||
105 | write_pic(picl_value()); | ||
106 | pcr_ops->write(pcr_enable); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | /* We count "clock cycle" events in the lower 32-bit PIC. | ||
111 | * Then configure it such that it overflows every HZ, and thus | ||
112 | * generates a level 15 interrupt at that frequency. | ||
113 | */ | ||
114 | static void cpu_nmi_start(void *_unused) | ||
115 | { | ||
116 | pcr_ops->write(PCR_PIC_PRIV); | ||
117 | write_pic(picl_value()); | ||
118 | |||
119 | pcr_ops->write(pcr_enable); | ||
120 | } | ||
121 | 26 | ||
122 | static void cpu_nmi_stop(void *_unused) | 27 | switch (val) { |
123 | { | 28 | case DIE_NMI: |
124 | pcr_ops->write(PCR_PIC_PRIV); | 29 | oprofile_add_sample(args->regs, 0); |
125 | } | 30 | ret = NOTIFY_STOP; |
126 | 31 | break; | |
127 | static int nmi_start(void) | 32 | default: |
128 | { | 33 | break; |
129 | int err = register_perfctr_intr(nmi_handler); | ||
130 | |||
131 | if (!err) { | ||
132 | nmi_enabled = 1; | ||
133 | wmb(); | ||
134 | err = on_each_cpu(cpu_nmi_start, NULL, 1); | ||
135 | if (err) { | ||
136 | nmi_enabled = 0; | ||
137 | wmb(); | ||
138 | on_each_cpu(cpu_nmi_stop, NULL, 1); | ||
139 | release_perfctr_intr(nmi_handler); | ||
140 | } | ||
141 | } | 34 | } |
142 | 35 | return ret; | |
143 | return err; | ||
144 | } | ||
145 | |||
146 | static void nmi_stop(void) | ||
147 | { | ||
148 | nmi_enabled = 0; | ||
149 | wmb(); | ||
150 | |||
151 | on_each_cpu(cpu_nmi_stop, NULL, 1); | ||
152 | release_perfctr_intr(nmi_handler); | ||
153 | synchronize_sched(); | ||
154 | } | 36 | } |
155 | 37 | ||
156 | static unsigned long perf_hsvc_group; | 38 | static struct notifier_block profile_timer_exceptions_nb = { |
157 | static unsigned long perf_hsvc_major; | 39 | .notifier_call = profile_timer_exceptions_notify, |
158 | static unsigned long perf_hsvc_minor; | 40 | }; |
159 | 41 | ||
160 | static int __init register_perf_hsvc(void) | 42 | static int timer_start(void) |
161 | { | 43 | { |
162 | if (tlb_type == hypervisor) { | 44 | if (register_die_notifier(&profile_timer_exceptions_nb)) |
163 | switch (sun4v_chip_type) { | 45 | return 1; |
164 | case SUN4V_CHIP_NIAGARA1: | 46 | nmi_adjust_hz(HZ); |
165 | perf_hsvc_group = HV_GRP_NIAG_PERF; | ||
166 | break; | ||
167 | |||
168 | case SUN4V_CHIP_NIAGARA2: | ||
169 | perf_hsvc_group = HV_GRP_N2_CPU; | ||
170 | break; | ||
171 | |||
172 | default: | ||
173 | return -ENODEV; | ||
174 | } | ||
175 | |||
176 | |||
177 | perf_hsvc_major = 1; | ||
178 | perf_hsvc_minor = 0; | ||
179 | if (sun4v_hvapi_register(perf_hsvc_group, | ||
180 | perf_hsvc_major, | ||
181 | &perf_hsvc_minor)) { | ||
182 | printk("perfmon: Could not register N2 hvapi.\n"); | ||
183 | return -ENODEV; | ||
184 | } | ||
185 | } | ||
186 | return 0; | 47 | return 0; |
187 | } | 48 | } |
188 | 49 | ||
189 | static void unregister_perf_hsvc(void) | 50 | |
51 | static void timer_stop(void) | ||
190 | { | 52 | { |
191 | if (tlb_type != hypervisor) | 53 | nmi_adjust_hz(1); |
192 | return; | 54 | unregister_die_notifier(&profile_timer_exceptions_nb); |
193 | sun4v_hvapi_unregister(perf_hsvc_group); | 55 | synchronize_sched(); /* Allow already-started NMIs to complete. */ |
194 | } | 56 | } |
195 | 57 | ||
196 | static int oprofile_nmi_init(struct oprofile_operations *ops) | 58 | static int op_nmi_timer_init(struct oprofile_operations *ops) |
197 | { | 59 | { |
198 | int err = register_perf_hsvc(); | 60 | if (!nmi_usable) |
199 | |||
200 | if (err) | ||
201 | return err; | ||
202 | |||
203 | switch (tlb_type) { | ||
204 | case hypervisor: | ||
205 | pcr_ops = &n2_pcr_ops; | ||
206 | pcr_enable = PCR_N2_ENABLE; | ||
207 | break; | ||
208 | |||
209 | case cheetah: | ||
210 | case cheetah_plus: | ||
211 | pcr_ops = &direct_pcr_ops; | ||
212 | break; | ||
213 | |||
214 | default: | ||
215 | return -ENODEV; | 61 | return -ENODEV; |
216 | } | ||
217 | 62 | ||
218 | ops->create_files = NULL; | 63 | ops->start = timer_start; |
219 | ops->setup = NULL; | 64 | ops->stop = timer_stop; |
220 | ops->shutdown = NULL; | ||
221 | ops->start = nmi_start; | ||
222 | ops->stop = nmi_stop; | ||
223 | ops->cpu_type = "timer"; | 65 | ops->cpu_type = "timer"; |
224 | 66 | printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n"); | |
225 | printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n"); | ||
226 | |||
227 | return 0; | 67 | return 0; |
228 | } | 68 | } |
229 | #endif | 69 | #endif |
@@ -233,7 +73,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
233 | int ret = -ENODEV; | 73 | int ret = -ENODEV; |
234 | 74 | ||
235 | #ifdef CONFIG_SPARC64 | 75 | #ifdef CONFIG_SPARC64 |
236 | ret = oprofile_nmi_init(ops); | 76 | ret = op_nmi_timer_init(ops); |
237 | if (!ret) | 77 | if (!ret) |
238 | return ret; | 78 | return ret; |
239 | #endif | 79 | #endif |
@@ -241,10 +81,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
241 | return ret; | 81 | return ret; |
242 | } | 82 | } |
243 | 83 | ||
244 | |||
245 | void oprofile_arch_exit(void) | 84 | void oprofile_arch_exit(void) |
246 | { | 85 | { |
247 | #ifdef CONFIG_SPARC64 | ||
248 | unregister_perf_hsvc(); | ||
249 | #endif | ||
250 | } | 86 | } |