vfio_ap_ops.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Adjunct processor matrix VFIO device driver callbacks.
  4. *
  5. * Copyright IBM Corp. 2018
  6. *
  7. * Author(s): Tony Krowiak <akrowiak@linux.ibm.com>
  8. * Halil Pasic <pasic@linux.ibm.com>
  9. * Pierre Morel <pmorel@linux.ibm.com>
  10. */
  11. #include <linux/string.h>
  12. #include <linux/vfio.h>
  13. #include <linux/device.h>
  14. #include <linux/list.h>
  15. #include <linux/ctype.h>
  16. #include <asm/zcrypt.h>
  17. #include "vfio_ap_private.h"
  18. #define VFIO_AP_MDEV_TYPE_HWVIRT "passthrough"
  19. #define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
  20. static void vfio_ap_matrix_init(struct ap_config_info *info,
  21. struct ap_matrix *matrix)
  22. {
  23. matrix->apm_max = info->apxa ? info->Na : 63;
  24. matrix->aqm_max = info->apxa ? info->Nd : 15;
  25. matrix->adm_max = info->apxa ? info->Nd : 15;
  26. }
  27. static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
  28. {
  29. struct ap_matrix_mdev *matrix_mdev;
  30. if ((atomic_dec_if_positive(&matrix_dev->available_instances) < 0))
  31. return -EPERM;
  32. matrix_mdev = kzalloc(sizeof(*matrix_mdev), GFP_KERNEL);
  33. if (!matrix_mdev) {
  34. atomic_inc(&matrix_dev->available_instances);
  35. return -ENOMEM;
  36. }
  37. vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
  38. mdev_set_drvdata(mdev, matrix_mdev);
  39. mutex_lock(&matrix_dev->lock);
  40. list_add(&matrix_mdev->node, &matrix_dev->mdev_list);
  41. mutex_unlock(&matrix_dev->lock);
  42. return 0;
  43. }
  44. static int vfio_ap_mdev_remove(struct mdev_device *mdev)
  45. {
  46. struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
  47. mutex_lock(&matrix_dev->lock);
  48. list_del(&matrix_mdev->node);
  49. mutex_unlock(&matrix_dev->lock);
  50. kfree(matrix_mdev);
  51. mdev_set_drvdata(mdev, NULL);
  52. atomic_inc(&matrix_dev->available_instances);
  53. return 0;
  54. }
  55. static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
  56. {
  57. return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
  58. }
  59. MDEV_TYPE_ATTR_RO(name);
  60. static ssize_t available_instances_show(struct kobject *kobj,
  61. struct device *dev, char *buf)
  62. {
  63. return sprintf(buf, "%d\n",
  64. atomic_read(&matrix_dev->available_instances));
  65. }
  66. MDEV_TYPE_ATTR_RO(available_instances);
  67. static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
  68. char *buf)
  69. {
  70. return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
  71. }
  72. MDEV_TYPE_ATTR_RO(device_api);
  73. static struct attribute *vfio_ap_mdev_type_attrs[] = {
  74. &mdev_type_attr_name.attr,
  75. &mdev_type_attr_device_api.attr,
  76. &mdev_type_attr_available_instances.attr,
  77. NULL,
  78. };
  79. static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
  80. .name = VFIO_AP_MDEV_TYPE_HWVIRT,
  81. .attrs = vfio_ap_mdev_type_attrs,
  82. };
  83. static struct attribute_group *vfio_ap_mdev_type_groups[] = {
  84. &vfio_ap_mdev_hwvirt_type_group,
  85. NULL,
  86. };
  87. static const struct mdev_parent_ops vfio_ap_matrix_ops = {
  88. .owner = THIS_MODULE,
  89. .supported_type_groups = vfio_ap_mdev_type_groups,
  90. .create = vfio_ap_mdev_create,
  91. .remove = vfio_ap_mdev_remove,
  92. };
  93. int vfio_ap_mdev_register(void)
  94. {
  95. atomic_set(&matrix_dev->available_instances, MAX_ZDEV_ENTRIES_EXT);
  96. return mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_ops);
  97. }
  98. void vfio_ap_mdev_unregister(void)
  99. {
  100. mdev_unregister_device(&matrix_dev->device);
  101. }