* ap_dqap(): Receive message from adjunct processor queue.
  * @qid: The AP queue number
  * @psmid: Pointer to program supplied message identifier
- * @msg: The message text
- * @length: The message length
- * @reslength: Resitual length on return
- * @resgr0: input: gr0 value (only used if != 0), output: resitual gr0 content
+ * @msg: Pointer to message buffer
+ * @msglen: Message buffer size
+ * @length: Pointer to length of actually written bytes
+ * @reslength: Residual length on return
+ * @resgr0: input: gr0 value (only used if != 0), output: residual gr0 content
  *
  * Returns AP queue status structure.
  * Condition code 1 on DQAP means the receive has taken place
  */
 static inline struct ap_queue_status ap_dqap(ap_qid_t qid,
                                             unsigned long *psmid,
-                                            void *msg, size_t length,
+                                            void *msg, size_t msglen,
+                                            size_t *length,
                                             size_t *reslength,
                                             unsigned long *resgr0)
 {
        rp1.even = 0UL;
        rp1.odd  = 0UL;
        rp2.even = (unsigned long)msg;
-       rp2.odd  = (unsigned long)length;
+       rp2.odd  = (unsigned long)msglen;
 
        asm volatile(
                "       lgr     0,%[reg0]\n"   /* qid param into gr0 */
                        *resgr0 = 0;
        }
 
+       /* update *length with the nr of bytes stored into the msg buffer */
+       if (length)
+               *length = msglen - rp2.odd;
+
        return reg1.status;
 }
 
 
        struct list_head list;          /* Request queueing. */
        unsigned long psmid;            /* Message id. */
        void *msg;                      /* Pointer to message buffer. */
-       unsigned int len;               /* actual msg len in msg buffer */
-       unsigned int bufsize;           /* allocated msg buffer size */
+       size_t len;                     /* actual msg len in msg buffer */
+       size_t bufsize;                 /* allocated msg buffer size */
        u16 flags;                      /* Flags, see AP_MSG_FLAG_xxx */
        struct ap_fi fi;                /* Failure Injection cmd */
        int rc;                         /* Return code for this message */
  * for the first time. Otherwise the ap message queue will get
  * confused.
  */
-int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t length);
-int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t length);
+int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen);
+int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t msglen);
 
 enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
 enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event);
 
  * @qid: The AP queue number
  * @psmid: The program supplied message identifier
  * @msg: The message text
- * @length: The message length
+ * @msglen: The message length
  * @special: Special Bit
  *
  * Returns AP queue status structure.
  * because a segment boundary was reached. The NQAP is repeated.
  */
 static inline struct ap_queue_status
-__ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t length,
+__ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen,
          int special)
 {
        if (special)
                qid |= 0x400000UL;
-       return ap_nqap(qid, psmid, msg, length);
+       return ap_nqap(qid, psmid, msg, msglen);
 }
 
-int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t length)
+int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen)
 {
        struct ap_queue_status status;
 
-       status = __ap_send(qid, psmid, msg, length, 0);
+       status = __ap_send(qid, psmid, msg, msglen, 0);
        switch (status.response_code) {
        case AP_RESPONSE_NORMAL:
                return 0;
 }
 EXPORT_SYMBOL(ap_send);
 
-int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t length)
+int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t msglen)
 {
        struct ap_queue_status status;
 
        if (!msg)
                return -EINVAL;
-       status = ap_dqap(qid, psmid, msg, length, NULL, NULL);
+       status = ap_dqap(qid, psmid, msg, msglen, NULL, NULL, NULL);
        switch (status.response_code) {
        case AP_RESPONSE_NORMAL:
                return 0;
        do {
                status = ap_dqap(aq->qid, &aq->reply->psmid,
                                 aq->reply->msg, aq->reply->bufsize,
-                                &reslen, &resgr0);
+                                &aq->reply->len, &reslen, &resgr0);
                parts++;
        } while (status.response_code == 0xFF && resgr0 != 0);
 
 
        ap_msg.msg = (void *)get_zeroed_page(GFP_KERNEL);
        if (!ap_msg.msg)
                return -ENOMEM;
+       ap_msg.bufsize = PAGE_SIZE;
 
        rng_type6cprb_msgx(&ap_msg, 4, &domain);
 
        /* Wait for the test message to complete. */
        for (i = 0; i < 2 * HZ; i++) {
                msleep(1000 / HZ);
-               rc = ap_recv(aq->qid, &psmid, ap_msg.msg, 4096);
+               rc = ap_recv(aq->qid, &psmid, ap_msg.msg, ap_msg.bufsize);
                if (rc == 0 && psmid == 0x0102030405060708UL)
                        break;
        }
 
        t80h = reply->msg;
        if (t80h->type == TYPE80_RSP_CODE) {
                len = t80h->len;
-               if (len > reply->bufsize || len > msg->bufsize) {
+               if (len > reply->bufsize || len > msg->bufsize ||
+                   len != reply->len) {
+                       ZCRYPT_DBF_DBG("%s len mismatch => EMSGSIZE\n", __func__);
                        msg->rc = -EMSGSIZE;
-               } else {
-                       memcpy(msg->msg, reply->msg, len);
-                       msg->len = len;
+                       goto out;
                }
+               memcpy(msg->msg, reply->msg, len);
+               msg->len = len;
        } else {
                memcpy(msg->msg, reply->msg, sizeof(error_reply));
+               msg->len = sizeof(error_reply);
        }
 out:
        complete((struct completion *)msg->private);
 
            t86r->cprbx.cprb_ver_id == 0x02) {
                switch (resp_type->type) {
                case CEXXC_RESPONSE_TYPE_ICA:
-                       len = sizeof(struct type86x_reply) + t86r->length - 2;
-                       if (len > reply->bufsize || len > msg->bufsize) {
+                       len = sizeof(struct type86x_reply) + t86r->length;
+                       if (len > reply->bufsize || len > msg->bufsize ||
+                           len != reply->len) {
+                               ZCRYPT_DBF_DBG("%s len mismatch => EMSGSIZE\n", __func__);
                                msg->rc = -EMSGSIZE;
-                       } else {
-                               memcpy(msg->msg, reply->msg, len);
-                               msg->len = len;
+                               goto out;
                        }
+                       memcpy(msg->msg, reply->msg, len);
+                       msg->len = len;
                        break;
                case CEXXC_RESPONSE_TYPE_XCRB:
-                       len = t86r->fmt2.offset2 + t86r->fmt2.count2;
-                       if (len > reply->bufsize || len > msg->bufsize) {
+                       if (t86r->fmt2.count2)
+                               len = t86r->fmt2.offset2 + t86r->fmt2.count2;
+                       else
+                               len = t86r->fmt2.offset1 + t86r->fmt2.count1;
+                       if (len > reply->bufsize || len > msg->bufsize ||
+                           len != reply->len) {
+                               ZCRYPT_DBF_DBG("%s len mismatch => EMSGSIZE\n", __func__);
                                msg->rc = -EMSGSIZE;
-                       } else {
-                               memcpy(msg->msg, reply->msg, len);
-                               msg->len = len;
+                               goto out;
                        }
+                       memcpy(msg->msg, reply->msg, len);
+                       msg->len = len;
                        break;
                default:
                        memcpy(msg->msg, &error_reply, sizeof(error_reply));
+                       msg->len = sizeof(error_reply);
                }
        } else {
                memcpy(msg->msg, reply->msg, sizeof(error_reply));
+               msg->len = sizeof(error_reply);
        }
 out:
        complete(&resp_type->work);
                switch (resp_type->type) {
                case CEXXC_RESPONSE_TYPE_EP11:
                        len = t86r->fmt2.offset1 + t86r->fmt2.count1;
-                       if (len > reply->bufsize || len > msg->bufsize) {
+                       if (len > reply->bufsize || len > msg->bufsize ||
+                           len != reply->len) {
+                               ZCRYPT_DBF_DBG("%s len mismatch => EMSGSIZE\n", __func__);
                                msg->rc = -EMSGSIZE;
-                       } else {
-                               memcpy(msg->msg, reply->msg, len);
-                               msg->len = len;
+                               goto out;
                        }
+                       memcpy(msg->msg, reply->msg, len);
+                       msg->len = len;
                        break;
                default:
                        memcpy(msg->msg, &error_reply, sizeof(error_reply));
+                       msg->len = sizeof(error_reply);
                }
        } else {
                memcpy(msg->msg, reply->msg, sizeof(error_reply));
+               msg->len = sizeof(error_reply);
        }
 out:
        complete(&resp_type->work);