s390/zcrypt: externalize AP queue interrupt control
authorHarald Freudenberger <freude@linux.vnet.ibm.com>
Wed, 9 Nov 2016 14:00:23 +0000 (15:00 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 6 Sep 2017 07:24:42 +0000 (09:24 +0200)
KVM has a need to control the interrupts on real and virtualized
AP queue devices. This fix provides a new function to control
the interrupt facilities of an AP queue device.

Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/ap.h
drivers/s390/crypto/ap_asm.h
drivers/s390/crypto/ap_queue.c

index 8cefd6ed981da76c5a27637238c12dbd1d8b11bf..c02f4aba88a6220bfc1bc7714632d52676aa5bef 100644 (file)
@@ -87,4 +87,40 @@ struct ap_config_info {
  */
 int ap_query_configuration(struct ap_config_info *info);
 
+/*
+ * struct ap_qirq_ctrl - convenient struct for easy invocation
+ * of the ap_queue_irq_ctrl() function. This struct is passed
+ * as GR1 parameter to the PQAP(AQIC) instruction. For details
+ * please see the AR documentation.
+ */
+struct ap_qirq_ctrl {
+       unsigned int _res1 : 8;
+       unsigned int zone  : 8;  /* zone info */
+       unsigned int ir    : 1;  /* ir flag: enable (1) or disable (0) irq */
+       unsigned int _res2 : 4;
+       unsigned int gisc  : 3;  /* guest isc field */
+       unsigned int _res3 : 6;
+       unsigned int gf    : 2;  /* gisa format */
+       unsigned int _res4 : 1;
+       unsigned int gisa  : 27; /* gisa origin */
+       unsigned int _res5 : 1;
+       unsigned int isc   : 3;  /* irq sub class */
+};
+
+/**
+ * ap_queue_irq_ctrl(): Control interruption on a AP queue.
+ * @qid: The AP queue number
+ * @qirqctrl: struct ap_qirq_ctrl, see above
+ * @ind: The notification indicator byte
+ *
+ * Returns AP queue status.
+ *
+ * Control interruption on the given AP queue.
+ * Just a simple wrapper function for the low level PQAP(AQIC)
+ * instruction available for other kernel modules.
+ */
+struct ap_queue_status ap_queue_irq_ctrl(ap_qid_t qid,
+                                        struct ap_qirq_ctrl qirqctrl,
+                                        void *ind);
+
 #endif /* _ASM_S390_AP_H_ */
index 287b4ad0999e412c5ef618a52dd681064bbebc5e..cd350345b3d25885c6cce02d8f357f387bdfbcc1 100644 (file)
@@ -69,16 +69,19 @@ static inline struct ap_queue_status ap_rapq(ap_qid_t qid)
 }
 
 /**
- * ap_aqic(): Enable interruption for a specific AP.
+ * ap_aqic(): Control interruption for a specific AP.
  * @qid: The AP queue number
+ * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
  * @ind: The notification indicator byte
  *
  * Returns AP queue status.
  */
-static inline struct ap_queue_status ap_aqic(ap_qid_t qid, void *ind)
+static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
+                                            struct ap_qirq_ctrl qirqctrl,
+                                            void *ind)
 {
        register unsigned long reg0 asm ("0") = qid | (3UL << 24);
-       register unsigned long reg1_in asm ("1") = (8UL << 44) | AP_ISC;
+       register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl;
        register struct ap_queue_status reg1_out asm ("1");
        register void *reg2 asm ("2") = ind;
 
index c906fb73a215955908bfad769f1267ba9f27e7af..56b96edffd5be897f8773d76944032de74a85e4d 100644 (file)
 #include "ap_bus.h"
 #include "ap_asm.h"
 
+/**
+ * ap_queue_irq_ctrl(): Control interruption on a AP queue.
+ * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
+ * @ind: The notification indicator byte
+ *
+ * Returns AP queue status.
+ *
+ * Control interruption on the given AP queue.
+ * Just a simple wrapper function for the low level PQAP(AQIC)
+ * instruction available for other kernel modules.
+ */
+struct ap_queue_status ap_queue_irq_ctrl(ap_qid_t qid,
+                                        struct ap_qirq_ctrl qirqctrl,
+                                        void *ind)
+{
+       return ap_aqic(qid, qirqctrl, ind);
+}
+EXPORT_SYMBOL(ap_queue_irq_ctrl);
+
 /**
  * ap_queue_enable_interruption(): Enable interruption on an AP queue.
  * @qid: The AP queue number
 static int ap_queue_enable_interruption(struct ap_queue *aq, void *ind)
 {
        struct ap_queue_status status;
+       struct ap_qirq_ctrl qirqctrl = { 0 };
 
-       status = ap_aqic(aq->qid, ind);
+       qirqctrl.ir = 1;
+       qirqctrl.isc = AP_ISC;
+       status = ap_aqic(aq->qid, qirqctrl, ind);
        switch (status.response_code) {
        case AP_RESPONSE_NORMAL:
        case AP_RESPONSE_OTHERWISE_CHANGED: