Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/vfio-ap: add s390dbf logging to the handle_pqap function

This patch adds s390dbf logging to the function that handles interception
of the PQAP(AQIC) instruction. Several items of data are validated before
ultimately calling the functions that execute the PQAP(AQIC) instruction on
behalf of the guest to which the queue for which interrupts are being
enabled or disabled is attached.

Currently, the handle_pqap function sets status response code 01 (queue not
available) in the status word that is normally returned from the
PQAP(AQIC) instruction under the following conditions:

* Set when the function pointer to the handler is not set in the
kvm_s390_crypto object (i.e., the PQAP hook is not registered).

* Set when the KVM pointer is not set in the ap_matrix_mdev object
(i.e., the matrix mdev is not passed through to a guest).

* Set when the queue for which interrupts are being enabled or
disabled is either not bound to the vfio_ap device driver or not assigned
to the matrix mdev.

Setting the response code returned to userspace without also logging a
message in the kernel makes it impossible to determine whether the response
was due to an error detected by the vfio_ap device driver or because the
response code was returned by the firmware in response to the PQAP(AQIC)
instruction, so this patch logs a message to the s390dbf log for the
vfio_ap device driver for each of the situations described above.

Signed-off-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>

authored by

Tony Krowiak and committed by
Vasily Gorbik
68f554b7 d5c49db2

+70 -8
+70 -8
drivers/s390/crypto/vfio_ap_ops.c
··· 16 16 #include <linux/bitops.h> 17 17 #include <linux/kvm_host.h> 18 18 #include <linux/module.h> 19 + #include <linux/uuid.h> 19 20 #include <asm/kvm.h> 20 21 #include <asm/zcrypt.h> 21 22 22 23 #include "vfio_ap_private.h" 24 + #include "vfio_ap_debug.h" 23 25 24 26 #define VFIO_AP_MDEV_TYPE_HWVIRT "passthrough" 25 27 #define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device" ··· 259 257 } 260 258 261 259 /** 260 + * vfio_ap_le_guid_to_be_uuid - convert a little endian guid array into an array 261 + * of big endian elements that can be passed by 262 + * value to an s390dbf sprintf event function to 263 + * format a UUID string. 264 + * 265 + * @guid: the object containing the little endian guid 266 + * @uuid: a six-element array of long values that can be passed by value as 267 + * arguments for a formatting string specifying a UUID. 268 + * 269 + * The S390 Debug Feature (s390dbf) allows the use of "%s" in the sprintf 270 + * event functions if the memory for the passed string is available as long as 271 + * the debug feature exists. Since a mediated device can be removed at any 272 + * time, it's name can not be used because %s passes the reference to the string 273 + * in memory and the reference will go stale once the device is removed . 274 + * 275 + * The s390dbf string formatting function allows a maximum of 9 arguments for a 276 + * message to be displayed in the 'sprintf' view. In order to use the bytes 277 + * comprising the mediated device's UUID to display the mediated device name, 278 + * they will have to be converted into an array whose elements can be passed by 279 + * value to sprintf. For example: 280 + * 281 + * guid array: { 83, 78, 17, 62, bb, f1, f0, 47, 91, 4d, 32, a2, 2e, 3a, 88, 04 } 282 + * mdev name: 62177883-f1bb-47f0-914d-32a22e3a8804 283 + * array returned: { 62177883, f1bb, 47f0, 914d, 32a2, 2e3a8804 } 284 + * formatting string: "%08lx-%04lx-%04lx-%04lx-%02lx%04lx" 285 + */ 286 + static void vfio_ap_le_guid_to_be_uuid(guid_t *guid, unsigned long *uuid) 287 + { 288 + /* 289 + * The input guid is ordered in little endian, so it needs to be 290 + * reordered for displaying a UUID as a string. This specifies the 291 + * guid indices in proper order. 292 + */ 293 + uuid[0] = le32_to_cpup((__le32 *)guid); 294 + uuid[1] = le16_to_cpup((__le16 *)&guid->b[4]); 295 + uuid[2] = le16_to_cpup((__le16 *)&guid->b[6]); 296 + uuid[3] = *((__u16 *)&guid->b[8]); 297 + uuid[4] = *((__u16 *)&guid->b[10]); 298 + uuid[5] = *((__u32 *)&guid->b[12]); 299 + } 300 + 301 + /** 262 302 * handle_pqap - PQAP instruction callback 263 303 * 264 304 * @vcpu: The vcpu on which we received the PQAP instruction ··· 325 281 { 326 282 uint64_t status; 327 283 uint16_t apqn; 284 + unsigned long uuid[6]; 328 285 struct vfio_ap_queue *q; 329 286 struct ap_queue_status qstatus = { 330 287 .response_code = AP_RESPONSE_Q_NOT_AVAIL, }; 331 288 struct ap_matrix_mdev *matrix_mdev; 332 289 333 - /* If we do not use the AIV facility just go to userland */ 334 - if (!(vcpu->arch.sie_block->eca & ECA_AIV)) 335 - return -EOPNOTSUPP; 336 - 337 290 apqn = vcpu->run->s.regs.gprs[0] & 0xffff; 338 - mutex_lock(&matrix_dev->lock); 339 291 340 - if (!vcpu->kvm->arch.crypto.pqap_hook) 292 + /* If we do not use the AIV facility just go to userland */ 293 + if (!(vcpu->arch.sie_block->eca & ECA_AIV)) { 294 + VFIO_AP_DBF_WARN("%s: AIV facility not installed: apqn=0x%04x, eca=0x%04x\n", 295 + __func__, apqn, vcpu->arch.sie_block->eca); 296 + 297 + return -EOPNOTSUPP; 298 + } 299 + 300 + mutex_lock(&matrix_dev->lock); 301 + if (!vcpu->kvm->arch.crypto.pqap_hook) { 302 + VFIO_AP_DBF_WARN("%s: PQAP(AQIC) hook not registered with the vfio_ap driver: apqn=0x%04x\n", 303 + __func__, apqn); 341 304 goto out_unlock; 305 + } 306 + 342 307 matrix_mdev = container_of(vcpu->kvm->arch.crypto.pqap_hook, 343 308 struct ap_matrix_mdev, pqap_hook); 344 309 345 310 /* If the there is no guest using the mdev, there is nothing to do */ 346 - if (!matrix_mdev->kvm) 311 + if (!matrix_mdev->kvm) { 312 + vfio_ap_le_guid_to_be_uuid(&matrix_mdev->mdev->uuid, uuid); 313 + VFIO_AP_DBF_WARN("%s: mdev %08lx-%04lx-%04lx-%04lx-%04lx%08lx not in use: apqn=0x%04x\n", 314 + __func__, uuid[0], uuid[1], uuid[2], 315 + uuid[3], uuid[4], uuid[5], apqn); 347 316 goto out_unlock; 317 + } 348 318 349 319 q = vfio_ap_get_queue(matrix_mdev, apqn); 350 - if (!q) 320 + if (!q) { 321 + VFIO_AP_DBF_WARN("%s: Queue %02x.%04x not bound to the vfio_ap driver\n", 322 + __func__, AP_QID_CARD(apqn), 323 + AP_QID_QUEUE(apqn)); 351 324 goto out_unlock; 325 + } 352 326 353 327 status = vcpu->run->s.regs.gprs[1]; 354 328