diff mbox

[v5,05/13] s390: vfio-ap: register matrix device with VFIO mdev framework

Message ID 1525705912-12815-6-git-send-email-akrowiak@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tony Krowiak May 7, 2018, 3:11 p.m. UTC
Registers the matrix device created by the VFIO AP device
driver with the VFIO mediated device framework.
Registering the matrix device will create the sysfs
structures needed to create mediated matrix devices
each of which will be used to configure the AP matrix
for a guest and connect it to the VFIO AP device driver.

Registering the matrix device with the VFIO mediated device
framework will create the following sysfs structures:

/sys/devices/vfio_ap
... [matrix]
...... [mdev_supported_types]
......... [vfio_ap-passthrough]
............ create

To create a mediated device for the AP matrix device, write a UUID
to the create file:

	uuidgen > create

A symbolic link to the mediated device's directory will be created in the
devices subdirectory named after the generated $uuid:

/sys/devices/vfio_ap
... [matrix]
...... [mdev_supported_types]
......... [vfio_ap-passthrough]
............ [devices]
............... [$uuid]

Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
---
 MAINTAINERS                           |    1 +
 drivers/s390/crypto/Makefile          |    2 +-
 drivers/s390/crypto/vfio_ap_drv.c     |    9 +++
 drivers/s390/crypto/vfio_ap_ops.c     |  106 +++++++++++++++++++++++++++++++++
 drivers/s390/crypto/vfio_ap_private.h |   17 +++++
 5 files changed, 134 insertions(+), 1 deletions(-)
 create mode 100644 drivers/s390/crypto/vfio_ap_ops.c

Comments

Halil Pasic May 11, 2018, 5:18 p.m. UTC | #1
On 05/07/2018 05:11 PM, Tony Krowiak wrote:
> Registers the matrix device created by the VFIO AP device
> driver with the VFIO mediated device framework.
> Registering the matrix device will create the sysfs
> structures needed to create mediated matrix devices
> each of which will be used to configure the AP matrix
> for a guest and connect it to the VFIO AP device driver.
> 
[..]
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
> new file mode 100644
> index 0000000..d7d36fb
> --- /dev/null
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Adjunct processor matrix VFIO device driver callbacks.
> + *
> + * Copyright IBM Corp. 2017
> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
> + *
> + */
> +#include <linux/string.h>
> +#include <linux/vfio.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/ctype.h>
> +
> +#include "vfio_ap_private.h"
> +
> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
> +
> +static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
> +{
> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> +
> +	ap_matrix->available_instances--;
> +
> +	return 0;
> +}
> +
> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
> +{
> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> +
> +	ap_matrix->available_instances++;
> +
> +	return 0;
> +}
> +

The above functions seem to be called with the lock of this auto-generated
mdev parent device held. That's why we don't have to care about synchronization
ourselves, right?

A small comment in the code could be helpful for mdev non-experts. Hell, I would
even consider documenting it for all mdev -- took me some time to figure out.

[..]


> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
> +{
> +	int ret;
> +
> +	ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
> +	if (ret)
> +		return ret;
> +
> +	ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
> +
> +	return 0;
> +}
> +
> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
> +{
> +	ap_matrix->available_instances--;

What is this for? I don't understand.

Regards,
Halil

> +	mdev_unregister_device(&ap_matrix->device);
> +}
Tony Krowiak May 14, 2018, 7:42 p.m. UTC | #2
On 05/11/2018 01:18 PM, Halil Pasic wrote:
>
>
> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>> Registers the matrix device created by the VFIO AP device
>> driver with the VFIO mediated device framework.
>> Registering the matrix device will create the sysfs
>> structures needed to create mediated matrix devices
>> each of which will be used to configure the AP matrix
>> for a guest and connect it to the VFIO AP device driver.
>>
> [..]
>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
>> b/drivers/s390/crypto/vfio_ap_ops.c
>> new file mode 100644
>> index 0000000..d7d36fb
>> --- /dev/null
>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>> @@ -0,0 +1,106 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Adjunct processor matrix VFIO device driver callbacks.
>> + *
>> + * Copyright IBM Corp. 2017
>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>> + *
>> + */
>> +#include <linux/string.h>
>> +#include <linux/vfio.h>
>> +#include <linux/device.h>
>> +#include <linux/list.h>
>> +#include <linux/ctype.h>
>> +
>> +#include "vfio_ap_private.h"
>> +
>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>> +
>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct 
>> mdev_device *mdev)
>> +{
>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +    ap_matrix->available_instances--;
>> +
>> +    return 0;
>> +}
>> +
>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>> +{
>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +    ap_matrix->available_instances++;
>> +
>> +    return 0;
>> +}
>> +
>
> The above functions seem to be called with the lock of this 
> auto-generated
> mdev parent device held. That's why we don't have to care about 
> synchronization
> ourselves, right?

I would assume as much. The comments for the 'struct mdev_parent_ops' in
include/linux/mdev.h do not mention anything about synchronization, nor 
did I
see any locking or synchronization in the vfio_ccw implementation after 
which
I modeled my code, so frankly it is something I did not consider.

>
>
> A small comment in the code could be helpful for mdev non-experts. 
> Hell, I would
> even consider documenting it for all mdev -- took me some time to 
> figure out.

You may want to bring this up with the VFIO mdev maintainers, but I'd be 
happy to
include a comment in the functions in question if you think it important.

>
>
> [..]
>
>
>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>> +{
>> +    int ret;
>> +
>> +    ret = mdev_register_device(&ap_matrix->device, 
>> &vfio_ap_matrix_ops);
>> +    if (ret)
>> +        return ret;
>> +
>> +    ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>> +
>> +    return 0;
>> +}
>> +
>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>> +{
>> +    ap_matrix->available_instances--;
>
> What is this for? I don't understand.

To control the number of mediated devices one can create for the matrix 
device.
Once the max is reached, the mdev framework will not allow creation of 
another
mediated device until one is removed. This counter keeps track of the number
of instances that can be created. This is documented with the mediated
framework. You may want to take a look at:

Documentation/vfio-mediated-device.txt
Documentation/vfio.txt
Documentation/virtual/kvm/devices/vfio.txt

>
>
> Regards,
> Halil
>
>> + mdev_unregister_device(&ap_matrix->device);
>> +}
Pierre Morel May 15, 2018, 2:17 p.m. UTC | #3
On 14/05/2018 21:42, Tony Krowiak wrote:
> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>
>>
>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>> Registers the matrix device created by the VFIO AP device
>>> driver with the VFIO mediated device framework.
>>> Registering the matrix device will create the sysfs
>>> structures needed to create mediated matrix devices
>>> each of which will be used to configure the AP matrix
>>> for a guest and connect it to the VFIO AP device driver.
>>>
>> [..]
>>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
>>> b/drivers/s390/crypto/vfio_ap_ops.c
>>> new file mode 100644
>>> index 0000000..d7d36fb
>>> --- /dev/null
>>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>>> @@ -0,0 +1,106 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Adjunct processor matrix VFIO device driver callbacks.
>>> + *
>>> + * Copyright IBM Corp. 2017
>>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>>> + *
>>> + */
>>> +#include <linux/string.h>
>>> +#include <linux/vfio.h>
>>> +#include <linux/device.h>
>>> +#include <linux/list.h>
>>> +#include <linux/ctype.h>
>>> +
>>> +#include "vfio_ap_private.h"
>>> +
>>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>>> +
>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct 
>>> mdev_device *mdev)
>>> +{
>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>> +
>>> +    ap_matrix->available_instances--;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>> +{
>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>> +
>>> +    ap_matrix->available_instances++;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>
>> The above functions seem to be called with the lock of this 
>> auto-generated
>> mdev parent device held. That's why we don't have to care about 
>> synchronization
>> ourselves, right?
>
> I would assume as much. The comments for the 'struct mdev_parent_ops' in
> include/linux/mdev.h do not mention anything about synchronization, 
> nor did I
> see any locking or synchronization in the vfio_ccw implementation 
> after which
> I modeled my code, so frankly it is something I did not consider.
>
>>
>>
>> A small comment in the code could be helpful for mdev non-experts. 
>> Hell, I would
>> even consider documenting it for all mdev -- took me some time to 
>> figure out.
>
> You may want to bring this up with the VFIO mdev maintainers, but I'd 
> be happy to
> include a comment in the functions in question if you think it important.
>
>>
>>
>> [..]
>>
>>
>>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>>> +{
>>> +    int ret;
>>> +
>>> +    ret = mdev_register_device(&ap_matrix->device, 
>>> &vfio_ap_matrix_ops);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    ap_matrix->available_instances = 
>>> AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>>> +{
>>> +    ap_matrix->available_instances--;
>>
>> What is this for? I don't understand.
>
> To control the number of mediated devices one can create for the 
> matrix device.
> Once the max is reached, the mdev framework will not allow creation of 
> another
> mediated device until one is removed. This counter keeps track of the 
> number
> of instances that can be created. This is documented with the mediated
> framework. You may want to take a look at:
>
> Documentation/vfio-mediated-device.txt
> Documentation/vfio.txt
> Documentation/virtual/kvm/devices/vfio.txt

This is what you do in create/remove.
But here in unregister I agree with Halil, it does not seem to be usefull.

>
>>
>>
>> Regards,
>> Halil
>>
>>> + mdev_unregister_device(&ap_matrix->device);
>>> +}
>
>
Tony Krowiak May 15, 2018, 3:16 p.m. UTC | #4
On 05/15/2018 10:17 AM, Pierre Morel wrote:
> On 14/05/2018 21:42, Tony Krowiak wrote:
>> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>>
>>>
>>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>>> Registers the matrix device created by the VFIO AP device
>>>> driver with the VFIO mediated device framework.
>>>> Registering the matrix device will create the sysfs
>>>> structures needed to create mediated matrix devices
>>>> each of which will be used to configure the AP matrix
>>>> for a guest and connect it to the VFIO AP device driver.
>>>>
>>> [..]
>>>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
>>>> b/drivers/s390/crypto/vfio_ap_ops.c
>>>> new file mode 100644
>>>> index 0000000..d7d36fb
>>>> --- /dev/null
>>>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>>>> @@ -0,0 +1,106 @@
>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>> +/*
>>>> + * Adjunct processor matrix VFIO device driver callbacks.
>>>> + *
>>>> + * Copyright IBM Corp. 2017
>>>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>>>> + *
>>>> + */
>>>> +#include <linux/string.h>
>>>> +#include <linux/vfio.h>
>>>> +#include <linux/device.h>
>>>> +#include <linux/list.h>
>>>> +#include <linux/ctype.h>
>>>> +
>>>> +#include "vfio_ap_private.h"
>>>> +
>>>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>>>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>>>> +
>>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct 
>>>> mdev_device *mdev)
>>>> +{
>>>> +    struct ap_matrix *ap_matrix = 
>>>> to_ap_matrix(mdev_parent_dev(mdev));
>>>> +
>>>> +    ap_matrix->available_instances--;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>>> +{
>>>> +    struct ap_matrix *ap_matrix = 
>>>> to_ap_matrix(mdev_parent_dev(mdev));
>>>> +
>>>> +    ap_matrix->available_instances++;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>
>>> The above functions seem to be called with the lock of this 
>>> auto-generated
>>> mdev parent device held. That's why we don't have to care about 
>>> synchronization
>>> ourselves, right?
>>
>> I would assume as much. The comments for the 'struct mdev_parent_ops' in
>> include/linux/mdev.h do not mention anything about synchronization, 
>> nor did I
>> see any locking or synchronization in the vfio_ccw implementation 
>> after which
>> I modeled my code, so frankly it is something I did not consider.
>>
>>>
>>>
>>> A small comment in the code could be helpful for mdev non-experts. 
>>> Hell, I would
>>> even consider documenting it for all mdev -- took me some time to 
>>> figure out.
>>
>> You may want to bring this up with the VFIO mdev maintainers, but I'd 
>> be happy to
>> include a comment in the functions in question if you think it 
>> important.
>>
>>>
>>>
>>> [..]
>>>
>>>
>>>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>>>> +{
>>>> +    int ret;
>>>> +
>>>> +    ret = mdev_register_device(&ap_matrix->device, 
>>>> &vfio_ap_matrix_ops);
>>>> +    if (ret)
>>>> +        return ret;
>>>> +
>>>> +    ap_matrix->available_instances = 
>>>> AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>>>> +{
>>>> +    ap_matrix->available_instances--;
>>>
>>> What is this for? I don't understand.
>>
>> To control the number of mediated devices one can create for the 
>> matrix device.
>> Once the max is reached, the mdev framework will not allow creation 
>> of another
>> mediated device until one is removed. This counter keeps track of the 
>> number
>> of instances that can be created. This is documented with the mediated
>> framework. You may want to take a look at:
>>
>> Documentation/vfio-mediated-device.txt
>> Documentation/vfio.txt
>> Documentation/virtual/kvm/devices/vfio.txt
>
> This is what you do in create/remove.
> But here in unregister I agree with Halil, it does not seem to be usefull.

If that is in fact what Halil was asking, then I misinterpreted his 
question; I
thought he was asking what the available_instances was used for. You are
correct, this does not belong here although it makes little difference given
this is called only when the driver, which creates the matrix device, is 
unloaded.
It is necessary in the register function to initialize its value, but I'll
remove it from here.

>
>
>>
>>>
>>>
>>> Regards,
>>> Halil
>>>
>>>> + mdev_unregister_device(&ap_matrix->device);
>>>> +}
>>
>>
>
Halil Pasic May 15, 2018, 3:48 p.m. UTC | #5
On 05/15/2018 05:16 PM, Tony Krowiak wrote:
> On 05/15/2018 10:17 AM, Pierre Morel wrote:
>> On 14/05/2018 21:42, Tony Krowiak wrote:
>>> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>>>
>>>>
>>>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>>>> Registers the matrix device created by the VFIO AP device
>>>>> driver with the VFIO mediated device framework.
>>>>> Registering the matrix device will create the sysfs
>>>>> structures needed to create mediated matrix devices
>>>>> each of which will be used to configure the AP matrix
>>>>> for a guest and connect it to the VFIO AP device driver.
>>>>>
>>>> [..]
>>>>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
>>>>> new file mode 100644
>>>>> index 0000000..d7d36fb
>>>>> --- /dev/null
>>>>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>>>>> @@ -0,0 +1,106 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>> +/*
>>>>> + * Adjunct processor matrix VFIO device driver callbacks.
>>>>> + *
>>>>> + * Copyright IBM Corp. 2017
>>>>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>>>>> + *
>>>>> + */
>>>>> +#include <linux/string.h>
>>>>> +#include <linux/vfio.h>
>>>>> +#include <linux/device.h>
>>>>> +#include <linux/list.h>
>>>>> +#include <linux/ctype.h>
>>>>> +
>>>>> +#include "vfio_ap_private.h"
>>>>> +
>>>>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>>>>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>>>>> +
>>>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
>>>>> +{
>>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>>> +
>>>>> +    ap_matrix->available_instances--;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>>>> +{
>>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>>> +
>>>>> +    ap_matrix->available_instances++;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>
>>>> The above functions seem to be called with the lock of this auto-generated
>>>> mdev parent device held. That's why we don't have to care about synchronization
>>>> ourselves, right?
>>>
>>> I would assume as much. The comments for the 'struct mdev_parent_ops' in
>>> include/linux/mdev.h do not mention anything about synchronization, nor did I
>>> see any locking or synchronization in the vfio_ccw implementation after which
>>> I modeled my code, so frankly it is something I did not consider.
>>>
>>>>
>>>>
>>>> A small comment in the code could be helpful for mdev non-experts. Hell, I would
>>>> even consider documenting it for all mdev -- took me some time to figure out.
>>>
>>> You may want to bring this up with the VFIO mdev maintainers, but I'd be happy to
>>> include a comment in the functions in question if you think it important.
>>>
>>>>
>>>>
>>>> [..]
>>>>
>>>>
>>>>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>>>>> +{
>>>>> +    int ret;
>>>>> +
>>>>> +    ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
>>>>> +    if (ret)
>>>>> +        return ret;
>>>>> +
>>>>> +    ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>>>>> +
>>>>> +    return 0;
>>>>> +}
>>>>> +
>>>>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>>>>> +{
>>>>> +    ap_matrix->available_instances--;
>>>>
>>>> What is this for? I don't understand.
>>>
>>> To control the number of mediated devices one can create for the matrix device.
>>> Once the max is reached, the mdev framework will not allow creation of another
>>> mediated device until one is removed. This counter keeps track of the number
>>> of instances that can be created. This is documented with the mediated
>>> framework. You may want to take a look at:
>>>
>>> Documentation/vfio-mediated-device.txt
>>> Documentation/vfio.txt
>>> Documentation/virtual/kvm/devices/vfio.txt
>>
>> This is what you do in create/remove.
>> But here in unregister I agree with Halil, it does not seem to be usefull.
> 
> If that is in fact what Halil was asking, then I misinterpreted his question; I
> thought he was asking what the available_instances was used for. You are
> correct, this does not belong here although it makes little difference given
> this is called only when the driver, which creates the matrix device, is unloaded.
> It is necessary in the register function to initialize its value, but I'll
> remove it from here.
> 

I questioned the dubious usage of ap_matrix->available_instances rather than
asking what is the variable for.

If I've had this deemed damaging I would have asked if it's damaging in a way
I think it is. For example take my comment on 'KVM: s390: interfaces to manage
guest's AP matrix'.

Regards,
Halil

>>
>>
>>>
>>>>
>>>>
>>>> Regards,
>>>> Halil
>>>>
>>>>> + mdev_unregister_device(&ap_matrix->device);
>>>>> +}
>>>
>>>
>>
>
Tony Krowiak May 15, 2018, 4:11 p.m. UTC | #6
On 05/15/2018 11:48 AM, Halil Pasic wrote:
>
>
> On 05/15/2018 05:16 PM, Tony Krowiak wrote:
>> On 05/15/2018 10:17 AM, Pierre Morel wrote:
>>> On 14/05/2018 21:42, Tony Krowiak wrote:
>>>> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>>>>
>>>>>
>>>>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>>>>> Registers the matrix device created by the VFIO AP device
>>>>>> driver with the VFIO mediated device framework.
>>>>>> Registering the matrix device will create the sysfs
>>>>>> structures needed to create mediated matrix devices
>>>>>> each of which will be used to configure the AP matrix
>>>>>> for a guest and connect it to the VFIO AP device driver.
>>>>>>
>>>>> [..]
>>>>>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
>>>>>> b/drivers/s390/crypto/vfio_ap_ops.c
>>>>>> new file mode 100644
>>>>>> index 0000000..d7d36fb
>>>>>> --- /dev/null
>>>>>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>>>>>> @@ -0,0 +1,106 @@
>>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>>> +/*
>>>>>> + * Adjunct processor matrix VFIO device driver callbacks.
>>>>>> + *
>>>>>> + * Copyright IBM Corp. 2017
>>>>>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>>>>>> + *
>>>>>> + */
>>>>>> +#include <linux/string.h>
>>>>>> +#include <linux/vfio.h>
>>>>>> +#include <linux/device.h>
>>>>>> +#include <linux/list.h>
>>>>>> +#include <linux/ctype.h>
>>>>>> +
>>>>>> +#include "vfio_ap_private.h"
>>>>>> +
>>>>>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>>>>>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>>>>>> +
>>>>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct 
>>>>>> mdev_device *mdev)
>>>>>> +{
>>>>>> +    struct ap_matrix *ap_matrix = 
>>>>>> to_ap_matrix(mdev_parent_dev(mdev));
>>>>>> +
>>>>>> +    ap_matrix->available_instances--;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>>>>> +{
>>>>>> +    struct ap_matrix *ap_matrix = 
>>>>>> to_ap_matrix(mdev_parent_dev(mdev));
>>>>>> +
>>>>>> +    ap_matrix->available_instances++;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>
>>>>> The above functions seem to be called with the lock of this 
>>>>> auto-generated
>>>>> mdev parent device held. That's why we don't have to care about 
>>>>> synchronization
>>>>> ourselves, right?
>>>>
>>>> I would assume as much. The comments for the 'struct 
>>>> mdev_parent_ops' in
>>>> include/linux/mdev.h do not mention anything about synchronization, 
>>>> nor did I
>>>> see any locking or synchronization in the vfio_ccw implementation 
>>>> after which
>>>> I modeled my code, so frankly it is something I did not consider.
>>>>
>>>>>
>>>>>
>>>>> A small comment in the code could be helpful for mdev non-experts. 
>>>>> Hell, I would
>>>>> even consider documenting it for all mdev -- took me some time to 
>>>>> figure out.
>>>>
>>>> You may want to bring this up with the VFIO mdev maintainers, but 
>>>> I'd be happy to
>>>> include a comment in the functions in question if you think it 
>>>> important.
>>>>
>>>>>
>>>>>
>>>>> [..]
>>>>>
>>>>>
>>>>>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>>>>>> +{
>>>>>> +    int ret;
>>>>>> +
>>>>>> +    ret = mdev_register_device(&ap_matrix->device, 
>>>>>> &vfio_ap_matrix_ops);
>>>>>> +    if (ret)
>>>>>> +        return ret;
>>>>>> +
>>>>>> +    ap_matrix->available_instances = 
>>>>>> AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>>>>>> +{
>>>>>> +    ap_matrix->available_instances--;
>>>>>
>>>>> What is this for? I don't understand.
>>>>
>>>> To control the number of mediated devices one can create for the 
>>>> matrix device.
>>>> Once the max is reached, the mdev framework will not allow creation 
>>>> of another
>>>> mediated device until one is removed. This counter keeps track of 
>>>> the number
>>>> of instances that can be created. This is documented with the mediated
>>>> framework. You may want to take a look at:
>>>>
>>>> Documentation/vfio-mediated-device.txt
>>>> Documentation/vfio.txt
>>>> Documentation/virtual/kvm/devices/vfio.txt
>>>
>>> This is what you do in create/remove.
>>> But here in unregister I agree with Halil, it does not seem to be 
>>> usefull.
>>
>> If that is in fact what Halil was asking, then I misinterpreted his 
>> question; I
>> thought he was asking what the available_instances was used for. You are
>> correct, this does not belong here although it makes little 
>> difference given
>> this is called only when the driver, which creates the matrix device, 
>> is unloaded.
>> It is necessary in the register function to initialize its value, but 
>> I'll
>> remove it from here.
>>
>
> I questioned the dubious usage of ap_matrix->available_instances 
> rather than
> asking what is the variable for.

I said I'd remove it.

>
>
> If I've had this deemed damaging I would have asked if it's damaging 
> in a way
> I think it is. For example take my comment on 'KVM: s390: interfaces 
> to manage
> guest's AP matrix'.

I apologize for not being able to read your mind. While this is not 
necessarily
necessary, it is not damaging because this is called only when the 
driver is being
unloaded. The point is moot, however, because I am removing it.

>
>
> Regards,
> Halil
>
>>>
>>>
>>>>
>>>>>
>>>>>
>>>>> Regards,
>>>>> Halil
>>>>>
>>>>>> + mdev_unregister_device(&ap_matrix->device);
>>>>>> +}
>>>>
>>>>
>>>
>>
Cornelia Huck May 16, 2018, 10:42 a.m. UTC | #7
On Mon,  7 May 2018 11:11:44 -0400
Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:

> Registers the matrix device created by the VFIO AP device
> driver with the VFIO mediated device framework.
> Registering the matrix device will create the sysfs
> structures needed to create mediated matrix devices
> each of which will be used to configure the AP matrix
> for a guest and connect it to the VFIO AP device driver.
> 
> Registering the matrix device with the VFIO mediated device
> framework will create the following sysfs structures:
> 
> /sys/devices/vfio_ap
> ... [matrix]
> ...... [mdev_supported_types]
> ......... [vfio_ap-passthrough]
> ............ create
> 
> To create a mediated device for the AP matrix device, write a UUID
> to the create file:
> 
> 	uuidgen > create
> 
> A symbolic link to the mediated device's directory will be created in the
> devices subdirectory named after the generated $uuid:
> 
> /sys/devices/vfio_ap
> ... [matrix]
> ...... [mdev_supported_types]
> ......... [vfio_ap-passthrough]
> ............ [devices]
> ............... [$uuid]
> 
> Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
> ---
>  MAINTAINERS                           |    1 +
>  drivers/s390/crypto/Makefile          |    2 +-
>  drivers/s390/crypto/vfio_ap_drv.c     |    9 +++
>  drivers/s390/crypto/vfio_ap_ops.c     |  106 +++++++++++++++++++++++++++++++++
>  drivers/s390/crypto/vfio_ap_private.h |   17 +++++
>  5 files changed, 134 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/s390/crypto/vfio_ap_ops.c


> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
> new file mode 100644
> index 0000000..d7d36fb
> --- /dev/null
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -0,0 +1,106 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Adjunct processor matrix VFIO device driver callbacks.
> + *
> + * Copyright IBM Corp. 2017

Should be '2018' (also in some other files in this series; please
double check.)

> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
> + *
> + */
> +#include <linux/string.h>
> +#include <linux/vfio.h>
> +#include <linux/device.h>
> +#include <linux/list.h>
> +#include <linux/ctype.h>
> +
> +#include "vfio_ap_private.h"
> +
> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
> +
> +static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
> +{
> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> +
> +	ap_matrix->available_instances--;

Shouldn't the code check whether available_instances is actually > 0?

> +
> +	return 0;
> +}
> +
> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
> +{
> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> +
> +	ap_matrix->available_instances++;
> +
> +	return 0;
> +}
> +
> +static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
> +{
> +	return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
> +}
> +
> +MDEV_TYPE_ATTR_RO(name);
> +
> +static ssize_t available_instances_show(struct kobject *kobj,
> +					struct device *dev, char *buf)
> +{
> +	struct ap_matrix *ap_matrix;
> +
> +	ap_matrix = to_ap_matrix(dev);

Move this with the declaration?

> +
> +	return sprintf(buf, "%d\n", ap_matrix->available_instances);
> +}
> +
> +MDEV_TYPE_ATTR_RO(available_instances);
> +
> +static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
> +			       char *buf)
> +{
> +	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
> +}
> +
> +MDEV_TYPE_ATTR_RO(device_api);
> +
> +static struct attribute *vfio_ap_mdev_type_attrs[] = {
> +	&mdev_type_attr_name.attr,
> +	&mdev_type_attr_device_api.attr,
> +	&mdev_type_attr_available_instances.attr,
> +	NULL,
> +};
> +
> +static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
> +	.name = VFOP_AP_MDEV_TYPE_HWVIRT,
> +	.attrs = vfio_ap_mdev_type_attrs,
> +};
> +
> +static struct attribute_group *vfio_ap_mdev_type_groups[] = {
> +	&vfio_ap_mdev_hwvirt_type_group,
> +	NULL,
> +};
> +
> +static const struct mdev_parent_ops vfio_ap_matrix_ops = {
> +	.owner			= THIS_MODULE,
> +	.supported_type_groups	= vfio_ap_mdev_type_groups,
> +	.create			= vfio_ap_mdev_create,
> +	.remove			= vfio_ap_mdev_remove,
> +};
> +
> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
> +{
> +	int ret;
> +
> +	ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
> +	if (ret)
> +		return ret;
> +
> +	ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
> +
> +	return 0;
> +}
> +
> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
> +{
> +	ap_matrix->available_instances--;
> +	mdev_unregister_device(&ap_matrix->device);
> +}
> diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
> index cf23675..afd8dbc 100644
> --- a/drivers/s390/crypto/vfio_ap_private.h
> +++ b/drivers/s390/crypto/vfio_ap_private.h
> @@ -10,14 +10,31 @@
>  #define _VFIO_AP_PRIVATE_H_
>  
>  #include <linux/types.h>
> +#include <linux/device.h>
> +#include <linux/mdev.h>
>  
>  #include "ap_bus.h"
>  
>  #define VFIO_AP_MODULE_NAME "vfio_ap"
>  #define VFIO_AP_DRV_NAME "vfio_ap"
> +/**
> + * There must be one mediated matrix device per guest. If every APQN is assigned

One, or at most one? Or one for every guest using ap devices?

> + * to a guest, then the maximum number of guests with a unique APQN assigned
> + * would be 255 adapters x 255 domains = 72351 guests.
> + */
> +#define AP_MATRIX_MAX_AVAILABLE_INSTANCES 72351
>  
>  struct ap_matrix {
>  	struct device device;
> +	int available_instances;
>  };
>  
> +static inline struct ap_matrix *to_ap_matrix(struct device *dev)
> +{
> +	return container_of(dev, struct ap_matrix, device);
> +}
> +
> +extern int vfio_ap_mdev_register(struct ap_matrix *ap_matrix);
> +extern void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix);
> +
>  #endif /* _VFIO_AP_PRIVATE_H_ */
Tony Krowiak May 16, 2018, 12:48 p.m. UTC | #8
On 05/16/2018 06:42 AM, Cornelia Huck wrote:
> On Mon,  7 May 2018 11:11:44 -0400
> Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
>
>> Registers the matrix device created by the VFIO AP device
>> driver with the VFIO mediated device framework.
>> Registering the matrix device will create the sysfs
>> structures needed to create mediated matrix devices
>> each of which will be used to configure the AP matrix
>> for a guest and connect it to the VFIO AP device driver.
>>
>> Registering the matrix device with the VFIO mediated device
>> framework will create the following sysfs structures:
>>
>> /sys/devices/vfio_ap
>> ... [matrix]
>> ...... [mdev_supported_types]
>> ......... [vfio_ap-passthrough]
>> ............ create
>>
>> To create a mediated device for the AP matrix device, write a UUID
>> to the create file:
>>
>> 	uuidgen > create
>>
>> A symbolic link to the mediated device's directory will be created in the
>> devices subdirectory named after the generated $uuid:
>>
>> /sys/devices/vfio_ap
>> ... [matrix]
>> ...... [mdev_supported_types]
>> ......... [vfio_ap-passthrough]
>> ............ [devices]
>> ............... [$uuid]
>>
>> Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>> ---
>>   MAINTAINERS                           |    1 +
>>   drivers/s390/crypto/Makefile          |    2 +-
>>   drivers/s390/crypto/vfio_ap_drv.c     |    9 +++
>>   drivers/s390/crypto/vfio_ap_ops.c     |  106 +++++++++++++++++++++++++++++++++
>>   drivers/s390/crypto/vfio_ap_private.h |   17 +++++
>>   5 files changed, 134 insertions(+), 1 deletions(-)
>>   create mode 100644 drivers/s390/crypto/vfio_ap_ops.c
>
>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
>> new file mode 100644
>> index 0000000..d7d36fb
>> --- /dev/null
>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>> @@ -0,0 +1,106 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Adjunct processor matrix VFIO device driver callbacks.
>> + *
>> + * Copyright IBM Corp. 2017
> Should be '2018' (also in some other files in this series; please
> double check.)

Gee, I thought I got all of these fixed. I must have a gremlin in my
laptop.

>
>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>> + *
>> + */
>> +#include <linux/string.h>
>> +#include <linux/vfio.h>
>> +#include <linux/device.h>
>> +#include <linux/list.h>
>> +#include <linux/ctype.h>
>> +
>> +#include "vfio_ap_private.h"
>> +
>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>> +
>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
>> +{
>> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +	ap_matrix->available_instances--;
> Shouldn't the code check whether available_instances is actually > 0?

It is my understanding that once the available_instances hits zero, the 
mdev
framework will not allow any more mediated devices to be created, so the
value should always be greater than zero when this function is invoked.

I did an experiment to verify my understanding. I initialized the 
available_instances
to 1. I was able to create 2 mediated devices. It seems that the 
framework refuses to
create a mediated device only after the available_instances sysfs 
attribute is a negative
number, so I have two choices: Initialize available_instances to one 
less than desires;
add the check you suggested. I think I'll go with the latter.

>
>> +
>> +	return 0;
>> +}
>> +
>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>> +{
>> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +	ap_matrix->available_instances++;
>> +
>> +	return 0;
>> +}
>> +
>> +static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
>> +{
>> +	return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(name);
>> +
>> +static ssize_t available_instances_show(struct kobject *kobj,
>> +					struct device *dev, char *buf)
>> +{
>> +	struct ap_matrix *ap_matrix;
>> +
>> +	ap_matrix = to_ap_matrix(dev);
> Move this with the declaration?
>
>> +
>> +	return sprintf(buf, "%d\n", ap_matrix->available_instances);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(available_instances);
>> +
>> +static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
>> +			       char *buf)
>> +{
>> +	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(device_api);
>> +
>> +static struct attribute *vfio_ap_mdev_type_attrs[] = {
>> +	&mdev_type_attr_name.attr,
>> +	&mdev_type_attr_device_api.attr,
>> +	&mdev_type_attr_available_instances.attr,
>> +	NULL,
>> +};
>> +
>> +static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
>> +	.name = VFOP_AP_MDEV_TYPE_HWVIRT,
>> +	.attrs = vfio_ap_mdev_type_attrs,
>> +};
>> +
>> +static struct attribute_group *vfio_ap_mdev_type_groups[] = {
>> +	&vfio_ap_mdev_hwvirt_type_group,
>> +	NULL,
>> +};
>> +
>> +static const struct mdev_parent_ops vfio_ap_matrix_ops = {
>> +	.owner			= THIS_MODULE,
>> +	.supported_type_groups	= vfio_ap_mdev_type_groups,
>> +	.create			= vfio_ap_mdev_create,
>> +	.remove			= vfio_ap_mdev_remove,
>> +};
>> +
>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>> +{
>> +	int ret;
>> +
>> +	ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>> +
>> +	return 0;
>> +}
>> +
>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>> +{
>> +	ap_matrix->available_instances--;
>> +	mdev_unregister_device(&ap_matrix->device);
>> +}
>> diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
>> index cf23675..afd8dbc 100644
>> --- a/drivers/s390/crypto/vfio_ap_private.h
>> +++ b/drivers/s390/crypto/vfio_ap_private.h
>> @@ -10,14 +10,31 @@
>>   #define _VFIO_AP_PRIVATE_H_
>>   
>>   #include <linux/types.h>
>> +#include <linux/device.h>
>> +#include <linux/mdev.h>
>>   
>>   #include "ap_bus.h"
>>   
>>   #define VFIO_AP_MODULE_NAME "vfio_ap"
>>   #define VFIO_AP_DRV_NAME "vfio_ap"
>> +/**
>> + * There must be one mediated matrix device per guest. If every APQN is assigned
> One, or at most one? Or one for every guest using ap devices?
>
>> + * to a guest, then the maximum number of guests with a unique APQN assigned
>> + * would be 255 adapters x 255 domains = 72351 guests.
>> + */
>> +#define AP_MATRIX_MAX_AVAILABLE_INSTANCES 72351
>>   
>>   struct ap_matrix {
>>   	struct device device;
>> +	int available_instances;
>>   };
>>   
>> +static inline struct ap_matrix *to_ap_matrix(struct device *dev)
>> +{
>> +	return container_of(dev, struct ap_matrix, device);
>> +}
>> +
>> +extern int vfio_ap_mdev_register(struct ap_matrix *ap_matrix);
>> +extern void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix);
>> +
>>   #endif /* _VFIO_AP_PRIVATE_H_ */
Tony Krowiak May 16, 2018, 12:58 p.m. UTC | #9
On 05/16/2018 06:42 AM, Cornelia Huck wrote:
> On Mon,  7 May 2018 11:11:44 -0400
> Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
>
>> Registers the matrix device created by the VFIO AP device
>> driver with the VFIO mediated device framework.
>> Registering the matrix device will create the sysfs
>> structures needed to create mediated matrix devices
>> each of which will be used to configure the AP matrix
>> for a guest and connect it to the VFIO AP device driver.
>>
>> Registering the matrix device with the VFIO mediated device
>> framework will create the following sysfs structures:
>>
>> /sys/devices/vfio_ap
>> ... [matrix]
>> ...... [mdev_supported_types]
>> ......... [vfio_ap-passthrough]
>> ............ create
>>
>> To create a mediated device for the AP matrix device, write a UUID
>> to the create file:
>>
>> 	uuidgen > create
>>
>> A symbolic link to the mediated device's directory will be created in the
>> devices subdirectory named after the generated $uuid:
>>
>> /sys/devices/vfio_ap
>> ... [matrix]
>> ...... [mdev_supported_types]
>> ......... [vfio_ap-passthrough]
>> ............ [devices]
>> ............... [$uuid]
>>
>> Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>> ---
>>   MAINTAINERS                           |    1 +
>>   drivers/s390/crypto/Makefile          |    2 +-
>>   drivers/s390/crypto/vfio_ap_drv.c     |    9 +++
>>   drivers/s390/crypto/vfio_ap_ops.c     |  106 +++++++++++++++++++++++++++++++++
>>   drivers/s390/crypto/vfio_ap_private.h |   17 +++++
>>   5 files changed, 134 insertions(+), 1 deletions(-)
>>   create mode 100644 drivers/s390/crypto/vfio_ap_ops.c
>
>> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
>> new file mode 100644
>> index 0000000..d7d36fb
>> --- /dev/null
>> +++ b/drivers/s390/crypto/vfio_ap_ops.c
>> @@ -0,0 +1,106 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Adjunct processor matrix VFIO device driver callbacks.
>> + *
>> + * Copyright IBM Corp. 2017
> Should be '2018' (also in some other files in this series; please
> double check.)
>
>> + * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
>> + *
>> + */
>> +#include <linux/string.h>
>> +#include <linux/vfio.h>
>> +#include <linux/device.h>
>> +#include <linux/list.h>
>> +#include <linux/ctype.h>
>> +
>> +#include "vfio_ap_private.h"
>> +
>> +#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
>> +#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
>> +
>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
>> +{
>> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +	ap_matrix->available_instances--;
> Shouldn't the code check whether available_instances is actually > 0?

Disregard my last response to this, I'm an idiot; it is the return of a
negative number from this function that causes the create to fail.

>
>> +
>> +	return 0;
>> +}
>> +
>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>> +{
>> +	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>> +
>> +	ap_matrix->available_instances++;
>> +
>> +	return 0;
>> +}
>> +
>> +static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
>> +{
>> +	return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(name);
>> +
>> +static ssize_t available_instances_show(struct kobject *kobj,
>> +					struct device *dev, char *buf)
>> +{
>> +	struct ap_matrix *ap_matrix;
>> +
>> +	ap_matrix = to_ap_matrix(dev);
> Move this with the declaration?

Okay, will do.

>
>> +
>> +	return sprintf(buf, "%d\n", ap_matrix->available_instances);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(available_instances);
>> +
>> +static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
>> +			       char *buf)
>> +{
>> +	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
>> +}
>> +
>> +MDEV_TYPE_ATTR_RO(device_api);
>> +
>> +static struct attribute *vfio_ap_mdev_type_attrs[] = {
>> +	&mdev_type_attr_name.attr,
>> +	&mdev_type_attr_device_api.attr,
>> +	&mdev_type_attr_available_instances.attr,
>> +	NULL,
>> +};
>> +
>> +static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
>> +	.name = VFOP_AP_MDEV_TYPE_HWVIRT,
>> +	.attrs = vfio_ap_mdev_type_attrs,
>> +};
>> +
>> +static struct attribute_group *vfio_ap_mdev_type_groups[] = {
>> +	&vfio_ap_mdev_hwvirt_type_group,
>> +	NULL,
>> +};
>> +
>> +static const struct mdev_parent_ops vfio_ap_matrix_ops = {
>> +	.owner			= THIS_MODULE,
>> +	.supported_type_groups	= vfio_ap_mdev_type_groups,
>> +	.create			= vfio_ap_mdev_create,
>> +	.remove			= vfio_ap_mdev_remove,
>> +};
>> +
>> +int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
>> +{
>> +	int ret;
>> +
>> +	ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
>> +
>> +	return 0;
>> +}
>> +
>> +void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
>> +{
>> +	ap_matrix->available_instances--;
>> +	mdev_unregister_device(&ap_matrix->device);
>> +}
>> diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
>> index cf23675..afd8dbc 100644
>> --- a/drivers/s390/crypto/vfio_ap_private.h
>> +++ b/drivers/s390/crypto/vfio_ap_private.h
>> @@ -10,14 +10,31 @@
>>   #define _VFIO_AP_PRIVATE_H_
>>   
>>   #include <linux/types.h>
>> +#include <linux/device.h>
>> +#include <linux/mdev.h>
>>   
>>   #include "ap_bus.h"
>>   
>>   #define VFIO_AP_MODULE_NAME "vfio_ap"
>>   #define VFIO_AP_DRV_NAME "vfio_ap"
>> +/**
>> + * There must be one mediated matrix device per guest. If every APQN is assigned
> One, or at most one? Or one for every guest using ap devices?

'One mediated matrix device for every guest using AP devices' is most 
accurate. I'll make the change.

>
>> + * to a guest, then the maximum number of guests with a unique APQN assigned
>> + * would be 255 adapters x 255 domains = 72351 guests.
>> + */
>> +#define AP_MATRIX_MAX_AVAILABLE_INSTANCES 72351
>>   
>>   struct ap_matrix {
>>   	struct device device;
>> +	int available_instances;
>>   };
>>   
>> +static inline struct ap_matrix *to_ap_matrix(struct device *dev)
>> +{
>> +	return container_of(dev, struct ap_matrix, device);
>> +}
>> +
>> +extern int vfio_ap_mdev_register(struct ap_matrix *ap_matrix);
>> +extern void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix);
>> +
>>   #endif /* _VFIO_AP_PRIVATE_H_ */
Cornelia Huck May 17, 2018, 7:44 a.m. UTC | #10
On Mon, 14 May 2018 15:42:18 -0400
Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:

> On 05/11/2018 01:18 PM, Halil Pasic wrote:
> >
> >
> > On 05/07/2018 05:11 PM, Tony Krowiak wrote:  
> >> Registers the matrix device created by the VFIO AP device
> >> driver with the VFIO mediated device framework.
> >> Registering the matrix device will create the sysfs
> >> structures needed to create mediated matrix devices
> >> each of which will be used to configure the AP matrix
> >> for a guest and connect it to the VFIO AP device driver.

> >> +static int vfio_ap_mdev_create(struct kobject *kobj, struct 
> >> mdev_device *mdev)
> >> +{
> >> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> >> +
> >> +    ap_matrix->available_instances--;
> >> +
> >> +    return 0;
> >> +}
> >> +
> >> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
> >> +{
> >> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> >> +
> >> +    ap_matrix->available_instances++;
> >> +
> >> +    return 0;
> >> +}
> >> +  
> >
> > The above functions seem to be called with the lock of this 
> > auto-generated
> > mdev parent device held. That's why we don't have to care about 
> > synchronization
> > ourselves, right?  
> 
> I would assume as much. The comments for the 'struct mdev_parent_ops' in
> include/linux/mdev.h do not mention anything about synchronization, nor 
> did I
> see any locking or synchronization in the vfio_ccw implementation after 
> which
> I modeled my code, so frankly it is something I did not consider.
> 
> >
> >
> > A small comment in the code could be helpful for mdev non-experts. 
> > Hell, I would
> > even consider documenting it for all mdev -- took me some time to 
> > figure out.  
> 
> You may want to bring this up with the VFIO mdev maintainers, but I'd be 
> happy to
> include a comment in the functions in question if you think it important.

Important note: There's currently a patch on list that removes the mdev
parent mutex, and it seems there was never intended to be any
serialization in that place by the mdev core. (Look for "vfio/mdev:
Check globally for duplicate devices".)
Tony Krowiak May 21, 2018, 3:13 p.m. UTC | #11
On 05/17/2018 03:44 AM, Cornelia Huck wrote:
> On Mon, 14 May 2018 15:42:18 -0400
> Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
>
>> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>>
>>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>>> Registers the matrix device created by the VFIO AP device
>>>> driver with the VFIO mediated device framework.
>>>> Registering the matrix device will create the sysfs
>>>> structures needed to create mediated matrix devices
>>>> each of which will be used to configure the AP matrix
>>>> for a guest and connect it to the VFIO AP device driver.
>>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct
>>>> mdev_device *mdev)
>>>> +{
>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>> +
>>>> +    ap_matrix->available_instances--;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>>> +{
>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>> +
>>>> +    ap_matrix->available_instances++;
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>> The above functions seem to be called with the lock of this
>>> auto-generated
>>> mdev parent device held. That's why we don't have to care about
>>> synchronization
>>> ourselves, right?
>> I would assume as much. The comments for the 'struct mdev_parent_ops' in
>> include/linux/mdev.h do not mention anything about synchronization, nor
>> did I
>> see any locking or synchronization in the vfio_ccw implementation after
>> which
>> I modeled my code, so frankly it is something I did not consider.
>>
>>>
>>> A small comment in the code could be helpful for mdev non-experts.
>>> Hell, I would
>>> even consider documenting it for all mdev -- took me some time to
>>> figure out.
>> You may want to bring this up with the VFIO mdev maintainers, but I'd be
>> happy to
>> include a comment in the functions in question if you think it important.
> Important note: There's currently a patch on list that removes the mdev
> parent mutex, and it seems there was never intended to be any
> serialization in that place by the mdev core. (Look for "vfio/mdev:
> Check globally for duplicate devices".)

The patch on the list holds the mdev_list_lock during create and remove
of an mdev device, so it looks like no synchronization is necessary on the
part of the vendor code in the create/remove callbacks; does that sound
about right?

>
Cornelia Huck May 22, 2018, 8:19 a.m. UTC | #12
On Mon, 21 May 2018 11:13:58 -0400
Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:

> On 05/17/2018 03:44 AM, Cornelia Huck wrote:
> > On Mon, 14 May 2018 15:42:18 -0400
> > Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
> >  
> >> On 05/11/2018 01:18 PM, Halil Pasic wrote:  
> >>>
> >>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:  
> >>>> Registers the matrix device created by the VFIO AP device
> >>>> driver with the VFIO mediated device framework.
> >>>> Registering the matrix device will create the sysfs
> >>>> structures needed to create mediated matrix devices
> >>>> each of which will be used to configure the AP matrix
> >>>> for a guest and connect it to the VFIO AP device driver.
> >>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct
> >>>> mdev_device *mdev)
> >>>> +{
> >>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> >>>> +
> >>>> +    ap_matrix->available_instances--;
> >>>> +
> >>>> +    return 0;
> >>>> +}
> >>>> +
> >>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
> >>>> +{
> >>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
> >>>> +
> >>>> +    ap_matrix->available_instances++;
> >>>> +
> >>>> +    return 0;
> >>>> +}
> >>>> +  
> >>> The above functions seem to be called with the lock of this
> >>> auto-generated
> >>> mdev parent device held. That's why we don't have to care about
> >>> synchronization
> >>> ourselves, right?  
> >> I would assume as much. The comments for the 'struct mdev_parent_ops' in
> >> include/linux/mdev.h do not mention anything about synchronization, nor
> >> did I
> >> see any locking or synchronization in the vfio_ccw implementation after
> >> which
> >> I modeled my code, so frankly it is something I did not consider.
> >>  
> >>>
> >>> A small comment in the code could be helpful for mdev non-experts.
> >>> Hell, I would
> >>> even consider documenting it for all mdev -- took me some time to
> >>> figure out.  
> >> You may want to bring this up with the VFIO mdev maintainers, but I'd be
> >> happy to
> >> include a comment in the functions in question if you think it important.  
> > Important note: There's currently a patch on list that removes the mdev
> > parent mutex, and it seems there was never intended to be any
> > serialization in that place by the mdev core. (Look for "vfio/mdev:
> > Check globally for duplicate devices".)  
> 
> The patch on the list holds the mdev_list_lock during create and remove
> of an mdev device, so it looks like no synchronization is necessary on the
> part of the vendor code in the create/remove callbacks; does that sound
> about right?

v1/v2 did that; v3/v4 hold the list lock only while the device is added
to the mdev list. v4 also adds a note regarding locking to the
documentation.
Tony Krowiak May 22, 2018, 9:41 p.m. UTC | #13
On 05/22/2018 04:19 AM, Cornelia Huck wrote:
> On Mon, 21 May 2018 11:13:58 -0400
> Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
>
>> On 05/17/2018 03:44 AM, Cornelia Huck wrote:
>>> On Mon, 14 May 2018 15:42:18 -0400
>>> Tony Krowiak <akrowiak@linux.vnet.ibm.com> wrote:
>>>   
>>>> On 05/11/2018 01:18 PM, Halil Pasic wrote:
>>>>> On 05/07/2018 05:11 PM, Tony Krowiak wrote:
>>>>>> Registers the matrix device created by the VFIO AP device
>>>>>> driver with the VFIO mediated device framework.
>>>>>> Registering the matrix device will create the sysfs
>>>>>> structures needed to create mediated matrix devices
>>>>>> each of which will be used to configure the AP matrix
>>>>>> for a guest and connect it to the VFIO AP device driver.
>>>>>> +static int vfio_ap_mdev_create(struct kobject *kobj, struct
>>>>>> mdev_device *mdev)
>>>>>> +{
>>>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>>>> +
>>>>>> +    ap_matrix->available_instances--;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>>> +static int vfio_ap_mdev_remove(struct mdev_device *mdev)
>>>>>> +{
>>>>>> +    struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
>>>>>> +
>>>>>> +    ap_matrix->available_instances++;
>>>>>> +
>>>>>> +    return 0;
>>>>>> +}
>>>>>> +
>>>>> The above functions seem to be called with the lock of this
>>>>> auto-generated
>>>>> mdev parent device held. That's why we don't have to care about
>>>>> synchronization
>>>>> ourselves, right?
>>>> I would assume as much. The comments for the 'struct mdev_parent_ops' in
>>>> include/linux/mdev.h do not mention anything about synchronization, nor
>>>> did I
>>>> see any locking or synchronization in the vfio_ccw implementation after
>>>> which
>>>> I modeled my code, so frankly it is something I did not consider.
>>>>   
>>>>> A small comment in the code could be helpful for mdev non-experts.
>>>>> Hell, I would
>>>>> even consider documenting it for all mdev -- took me some time to
>>>>> figure out.
>>>> You may want to bring this up with the VFIO mdev maintainers, but I'd be
>>>> happy to
>>>> include a comment in the functions in question if you think it important.
>>> Important note: There's currently a patch on list that removes the mdev
>>> parent mutex, and it seems there was never intended to be any
>>> serialization in that place by the mdev core. (Look for "vfio/mdev:
>>> Check globally for duplicate devices".)
>> The patch on the list holds the mdev_list_lock during create and remove
>> of an mdev device, so it looks like no synchronization is necessary on the
>> part of the vendor code in the create/remove callbacks; does that sound
>> about right?
> v1/v2 did that; v3/v4 hold the list lock only while the device is added
> to the mdev list. v4 also adds a note regarding locking to the
> documentation.

I'll add some synchronization to the read/update of available instances.

>
diff mbox

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 2792c81..cecadf2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12246,6 +12246,7 @@  W:	http://www.ibm.com/developerworks/linux/linux390/
 S:	Supported
 F:	drivers/s390/crypto/vfio_ap_drv.c
 F:	drivers/s390/crypto/vfio_ap_private.h
+F:	drivers/s390/crypto/vfio_ap_ops.c
 
 S390 ZFCP DRIVER
 M:	Steffen Maier <maier@linux.ibm.com>
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile
index 48e466e..8d36b05 100644
--- a/drivers/s390/crypto/Makefile
+++ b/drivers/s390/crypto/Makefile
@@ -17,5 +17,5 @@  pkey-objs := pkey_api.o
 obj-$(CONFIG_PKEY) += pkey.o
 
 # adjunct processor matrix
-vfio_ap-objs := vfio_ap_drv.o
+vfio_ap-objs := vfio_ap_drv.o vfio_ap_ops.o
 obj-$(CONFIG_VFIO_AP) += vfio_ap.o
diff --git a/drivers/s390/crypto/vfio_ap_drv.c b/drivers/s390/crypto/vfio_ap_drv.c
index 014d70f..cc7fbd7 100644
--- a/drivers/s390/crypto/vfio_ap_drv.c
+++ b/drivers/s390/crypto/vfio_ap_drv.c
@@ -121,11 +121,20 @@  int __init vfio_ap_init(void)
 		return ret;
 	}
 
+	ret = vfio_ap_mdev_register(ap_matrix);
+	if (ret) {
+		ap_driver_unregister(&vfio_ap_drv);
+		vfio_ap_matrix_dev_destroy(ap_matrix);
+
+		return ret;
+	}
+
 	return 0;
 }
 
 void __exit vfio_ap_exit(void)
 {
+	vfio_ap_mdev_unregister(ap_matrix);
 	ap_driver_unregister(&vfio_ap_drv);
 	vfio_ap_matrix_dev_destroy(ap_matrix);
 }
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
new file mode 100644
index 0000000..d7d36fb
--- /dev/null
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -0,0 +1,106 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Adjunct processor matrix VFIO device driver callbacks.
+ *
+ * Copyright IBM Corp. 2017
+ * Author(s): Tony Krowiak <akrowiak@linux.vnet.ibm.com>
+ *
+ */
+#include <linux/string.h>
+#include <linux/vfio.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+
+#include "vfio_ap_private.h"
+
+#define VFOP_AP_MDEV_TYPE_HWVIRT "passthrough"
+#define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
+
+static int vfio_ap_mdev_create(struct kobject *kobj, struct mdev_device *mdev)
+{
+	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
+
+	ap_matrix->available_instances--;
+
+	return 0;
+}
+
+static int vfio_ap_mdev_remove(struct mdev_device *mdev)
+{
+	struct ap_matrix *ap_matrix = to_ap_matrix(mdev_parent_dev(mdev));
+
+	ap_matrix->available_instances++;
+
+	return 0;
+}
+
+static ssize_t name_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+	return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
+}
+
+MDEV_TYPE_ATTR_RO(name);
+
+static ssize_t available_instances_show(struct kobject *kobj,
+					struct device *dev, char *buf)
+{
+	struct ap_matrix *ap_matrix;
+
+	ap_matrix = to_ap_matrix(dev);
+
+	return sprintf(buf, "%d\n", ap_matrix->available_instances);
+}
+
+MDEV_TYPE_ATTR_RO(available_instances);
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+			       char *buf)
+{
+	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
+}
+
+MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *vfio_ap_mdev_type_attrs[] = {
+	&mdev_type_attr_name.attr,
+	&mdev_type_attr_device_api.attr,
+	&mdev_type_attr_available_instances.attr,
+	NULL,
+};
+
+static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
+	.name = VFOP_AP_MDEV_TYPE_HWVIRT,
+	.attrs = vfio_ap_mdev_type_attrs,
+};
+
+static struct attribute_group *vfio_ap_mdev_type_groups[] = {
+	&vfio_ap_mdev_hwvirt_type_group,
+	NULL,
+};
+
+static const struct mdev_parent_ops vfio_ap_matrix_ops = {
+	.owner			= THIS_MODULE,
+	.supported_type_groups	= vfio_ap_mdev_type_groups,
+	.create			= vfio_ap_mdev_create,
+	.remove			= vfio_ap_mdev_remove,
+};
+
+int vfio_ap_mdev_register(struct ap_matrix *ap_matrix)
+{
+	int ret;
+
+	ret = mdev_register_device(&ap_matrix->device, &vfio_ap_matrix_ops);
+	if (ret)
+		return ret;
+
+	ap_matrix->available_instances = AP_MATRIX_MAX_AVAILABLE_INSTANCES;
+
+	return 0;
+}
+
+void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix)
+{
+	ap_matrix->available_instances--;
+	mdev_unregister_device(&ap_matrix->device);
+}
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index cf23675..afd8dbc 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -10,14 +10,31 @@ 
 #define _VFIO_AP_PRIVATE_H_
 
 #include <linux/types.h>
+#include <linux/device.h>
+#include <linux/mdev.h>
 
 #include "ap_bus.h"
 
 #define VFIO_AP_MODULE_NAME "vfio_ap"
 #define VFIO_AP_DRV_NAME "vfio_ap"
+/**
+ * There must be one mediated matrix device per guest. If every APQN is assigned
+ * to a guest, then the maximum number of guests with a unique APQN assigned
+ * would be 255 adapters x 255 domains = 72351 guests.
+ */
+#define AP_MATRIX_MAX_AVAILABLE_INSTANCES 72351
 
 struct ap_matrix {
 	struct device device;
+	int available_instances;
 };
 
+static inline struct ap_matrix *to_ap_matrix(struct device *dev)
+{
+	return container_of(dev, struct ap_matrix, device);
+}
+
+extern int vfio_ap_mdev_register(struct ap_matrix *ap_matrix);
+extern void vfio_ap_mdev_unregister(struct ap_matrix *ap_matrix);
+
 #endif /* _VFIO_AP_PRIVATE_H_ */