diff options
-rw-r--r-- | arch/s390/include/asm/cpu_mf.h | 12 | ||||
-rw-r--r-- | arch/s390/include/asm/irq.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 23 | ||||
-rw-r--r-- | arch/s390/oprofile/hwsampler.c | 52 |
4 files changed, 59 insertions, 30 deletions
diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h new file mode 100644 index 000000000000..d91dd38112de --- /dev/null +++ b/arch/s390/include/asm/cpu_mf.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef _ASM_S390_CPU_MF_H | ||
2 | #define _ASM_S390_CPU_MF_H | ||
3 | |||
4 | #define CPU_MF_INT_SF_MASK 0xffc00000 | ||
5 | |||
6 | #define CPU_MF_INT_SF_IAE (1 << 31) /* invalid entry address */ | ||
7 | #define CPU_MF_INT_SF_ISE (1 << 30) /* incorrect SDBT entry */ | ||
8 | #define CPU_MF_INT_SF_PRA (1 << 29) /* program request alert */ | ||
9 | #define CPU_MF_INT_SF_SACA (1 << 23) /* sampler auth. change alert */ | ||
10 | #define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */ | ||
11 | |||
12 | #endif | ||
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index acee1806f61e..5289cacd4861 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -45,5 +45,7 @@ int register_external_interrupt(u16 code, ext_int_handler_t handler); | |||
45 | int unregister_external_interrupt(u16 code, ext_int_handler_t handler); | 45 | int unregister_external_interrupt(u16 code, ext_int_handler_t handler); |
46 | void service_subclass_irq_register(void); | 46 | void service_subclass_irq_register(void); |
47 | void service_subclass_irq_unregister(void); | 47 | void service_subclass_irq_unregister(void); |
48 | void measurement_alert_subclass_register(void); | ||
49 | void measurement_alert_subclass_unregister(void); | ||
48 | 50 | ||
49 | #endif /* _ASM_IRQ_H */ | 51 | #endif /* _ASM_IRQ_H */ |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 2429ecd68872..1c2cdd59ccd0 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -255,3 +255,26 @@ void service_subclass_irq_unregister(void) | |||
255 | spin_unlock(&sc_irq_lock); | 255 | spin_unlock(&sc_irq_lock); |
256 | } | 256 | } |
257 | EXPORT_SYMBOL(service_subclass_irq_unregister); | 257 | EXPORT_SYMBOL(service_subclass_irq_unregister); |
258 | |||
259 | static DEFINE_SPINLOCK(ma_subclass_lock); | ||
260 | static int ma_subclass_refcount; | ||
261 | |||
262 | void measurement_alert_subclass_register(void) | ||
263 | { | ||
264 | spin_lock(&ma_subclass_lock); | ||
265 | if (!ma_subclass_refcount) | ||
266 | ctl_set_bit(0, 5); | ||
267 | ma_subclass_refcount++; | ||
268 | spin_unlock(&ma_subclass_lock); | ||
269 | } | ||
270 | EXPORT_SYMBOL(measurement_alert_subclass_register); | ||
271 | |||
272 | void measurement_alert_subclass_unregister(void) | ||
273 | { | ||
274 | spin_lock(&ma_subclass_lock); | ||
275 | ma_subclass_refcount--; | ||
276 | if (!ma_subclass_refcount) | ||
277 | ctl_clear_bit(0, 5); | ||
278 | spin_unlock(&ma_subclass_lock); | ||
279 | } | ||
280 | EXPORT_SYMBOL(measurement_alert_subclass_unregister); | ||
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 12bea05a0fc1..f097d516d8c5 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c | |||
@@ -17,8 +17,7 @@ | |||
17 | #include <linux/semaphore.h> | 17 | #include <linux/semaphore.h> |
18 | #include <linux/oom.h> | 18 | #include <linux/oom.h> |
19 | #include <linux/oprofile.h> | 19 | #include <linux/oprofile.h> |
20 | 20 | #include <asm/cpu_mf.h> | |
21 | #include <asm/lowcore.h> | ||
22 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
23 | 22 | ||
24 | #include "hwsampler.h" | 23 | #include "hwsampler.h" |
@@ -30,12 +29,6 @@ | |||
30 | #define ALERT_REQ_MASK 0x4000000000000000ul | 29 | #define ALERT_REQ_MASK 0x4000000000000000ul |
31 | #define BUFFER_FULL_MASK 0x8000000000000000ul | 30 | #define BUFFER_FULL_MASK 0x8000000000000000ul |
32 | 31 | ||
33 | #define EI_IEA (1 << 31) /* invalid entry address */ | ||
34 | #define EI_ISE (1 << 30) /* incorrect SDBT entry */ | ||
35 | #define EI_PRA (1 << 29) /* program request alert */ | ||
36 | #define EI_SACA (1 << 23) /* sampler authorization change alert */ | ||
37 | #define EI_LSDA (1 << 22) /* loss of sample data alert */ | ||
38 | |||
39 | DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); | 32 | DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); |
40 | 33 | ||
41 | struct hws_execute_parms { | 34 | struct hws_execute_parms { |
@@ -232,9 +225,20 @@ static inline unsigned long *trailer_entry_ptr(unsigned long v) | |||
232 | return (unsigned long *) ret; | 225 | return (unsigned long *) ret; |
233 | } | 226 | } |
234 | 227 | ||
235 | /* prototypes for external interrupt handler and worker */ | ||
236 | static void hws_ext_handler(struct ext_code ext_code, | 228 | static void hws_ext_handler(struct ext_code ext_code, |
237 | unsigned int param32, unsigned long param64); | 229 | unsigned int param32, unsigned long param64) |
230 | { | ||
231 | struct hws_cpu_buffer *cb = &__get_cpu_var(sampler_cpu_buffer); | ||
232 | |||
233 | if (!(param32 & CPU_MF_INT_SF_MASK)) | ||
234 | return; | ||
235 | |||
236 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CPM]++; | ||
237 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); | ||
238 | |||
239 | if (hws_wq) | ||
240 | queue_work(hws_wq, &cb->worker); | ||
241 | } | ||
238 | 242 | ||
239 | static void worker(struct work_struct *work); | 243 | static void worker(struct work_struct *work); |
240 | 244 | ||
@@ -673,18 +677,6 @@ int hwsampler_activate(unsigned int cpu) | |||
673 | return rc; | 677 | return rc; |
674 | } | 678 | } |
675 | 679 | ||
676 | static void hws_ext_handler(struct ext_code ext_code, | ||
677 | unsigned int param32, unsigned long param64) | ||
678 | { | ||
679 | struct hws_cpu_buffer *cb; | ||
680 | |||
681 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CPM]++; | ||
682 | cb = &__get_cpu_var(sampler_cpu_buffer); | ||
683 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); | ||
684 | if (hws_wq) | ||
685 | queue_work(hws_wq, &cb->worker); | ||
686 | } | ||
687 | |||
688 | static int check_qsi_on_setup(void) | 680 | static int check_qsi_on_setup(void) |
689 | { | 681 | { |
690 | int rc; | 682 | int rc; |
@@ -760,23 +752,23 @@ static int worker_check_error(unsigned int cpu, int ext_params) | |||
760 | if (!sdbt || !*sdbt) | 752 | if (!sdbt || !*sdbt) |
761 | return -EINVAL; | 753 | return -EINVAL; |
762 | 754 | ||
763 | if (ext_params & EI_PRA) | 755 | if (ext_params & CPU_MF_INT_SF_PRA) |
764 | cb->req_alert++; | 756 | cb->req_alert++; |
765 | 757 | ||
766 | if (ext_params & EI_LSDA) | 758 | if (ext_params & CPU_MF_INT_SF_LSDA) |
767 | cb->loss_of_sample_data++; | 759 | cb->loss_of_sample_data++; |
768 | 760 | ||
769 | if (ext_params & EI_IEA) { | 761 | if (ext_params & CPU_MF_INT_SF_IAE) { |
770 | cb->invalid_entry_address++; | 762 | cb->invalid_entry_address++; |
771 | rc = -EINVAL; | 763 | rc = -EINVAL; |
772 | } | 764 | } |
773 | 765 | ||
774 | if (ext_params & EI_ISE) { | 766 | if (ext_params & CPU_MF_INT_SF_ISE) { |
775 | cb->incorrect_sdbt_entry++; | 767 | cb->incorrect_sdbt_entry++; |
776 | rc = -EINVAL; | 768 | rc = -EINVAL; |
777 | } | 769 | } |
778 | 770 | ||
779 | if (ext_params & EI_SACA) { | 771 | if (ext_params & CPU_MF_INT_SF_SACA) { |
780 | cb->sample_auth_change_alert++; | 772 | cb->sample_auth_change_alert++; |
781 | rc = -EINVAL; | 773 | rc = -EINVAL; |
782 | } | 774 | } |
@@ -1009,7 +1001,7 @@ int hwsampler_deallocate(void) | |||
1009 | if (hws_state != HWS_STOPPED) | 1001 | if (hws_state != HWS_STOPPED) |
1010 | goto deallocate_exit; | 1002 | goto deallocate_exit; |
1011 | 1003 | ||
1012 | ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ | 1004 | measurement_alert_subclass_unregister(); |
1013 | deallocate_sdbt(); | 1005 | deallocate_sdbt(); |
1014 | 1006 | ||
1015 | hws_state = HWS_DEALLOCATED; | 1007 | hws_state = HWS_DEALLOCATED; |
@@ -1123,7 +1115,7 @@ int hwsampler_shutdown(void) | |||
1123 | mutex_lock(&hws_sem); | 1115 | mutex_lock(&hws_sem); |
1124 | 1116 | ||
1125 | if (hws_state == HWS_STOPPED) { | 1117 | if (hws_state == HWS_STOPPED) { |
1126 | ctl_clear_bit(0, 5); /* set bit 58 CR0 off */ | 1118 | measurement_alert_subclass_unregister(); |
1127 | deallocate_sdbt(); | 1119 | deallocate_sdbt(); |
1128 | } | 1120 | } |
1129 | if (hws_wq) { | 1121 | if (hws_wq) { |
@@ -1198,7 +1190,7 @@ start_all_exit: | |||
1198 | hws_oom = 1; | 1190 | hws_oom = 1; |
1199 | hws_flush_all = 0; | 1191 | hws_flush_all = 0; |
1200 | /* now let them in, 1407 CPUMF external interrupts */ | 1192 | /* now let them in, 1407 CPUMF external interrupts */ |
1201 | ctl_set_bit(0, 5); /* set CR0 bit 58 */ | 1193 | measurement_alert_subclass_register(); |
1202 | 1194 | ||
1203 | return 0; | 1195 | return 0; |
1204 | } | 1196 | } |