aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/cpu_mf.h12
-rw-r--r--arch/s390/include/asm/irq.h2
-rw-r--r--arch/s390/kernel/irq.c23
-rw-r--r--arch/s390/oprofile/hwsampler.c52
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);
45int unregister_external_interrupt(u16 code, ext_int_handler_t handler); 45int unregister_external_interrupt(u16 code, ext_int_handler_t handler);
46void service_subclass_irq_register(void); 46void service_subclass_irq_register(void);
47void service_subclass_irq_unregister(void); 47void service_subclass_irq_unregister(void);
48void measurement_alert_subclass_register(void);
49void 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}
257EXPORT_SYMBOL(service_subclass_irq_unregister); 257EXPORT_SYMBOL(service_subclass_irq_unregister);
258
259static DEFINE_SPINLOCK(ma_subclass_lock);
260static int ma_subclass_refcount;
261
262void 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}
270EXPORT_SYMBOL(measurement_alert_subclass_register);
271
272void 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}
280EXPORT_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
39DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer); 32DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
40 33
41struct hws_execute_parms { 34struct 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 */
236static void hws_ext_handler(struct ext_code ext_code, 228static 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
239static void worker(struct work_struct *work); 243static 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
676static 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
688static int check_qsi_on_setup(void) 680static 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}