From: Pierre Morel <pmorel@linux.ibm.com>
To: Cornelia Huck <cohuck@redhat.com>
Cc: borntraeger@de.ibm.com, agraf@suse.de, rth@twiddle.net,
david@redhat.com, qemu-s390x@nongnu.org, qemu-devel@nongnu.org,
peter.maydell@linaro.org, pbonzini@redhat.com, mst@redhat.com,
eric.auger@redhat.com, akrowiak@linux.ibm.com,
pasic@linux.ibm.com
Subject: Re: [Qemu-devel] [PATCH v1 5/5] s390x/vfio: ap: Implementing AP Queue Interrupt Control
Date: Thu, 8 Nov 2018 00:02:13 +0100 [thread overview]
Message-ID: <29a2919c-908c-0ef8-9e04-63d9e9284700@linux.ibm.com> (raw)
In-Reply-To: <20181107143944.69cad7ef.cohuck@redhat.com>
On 07/11/2018 14:39, Cornelia Huck wrote:
> On Fri, 2 Nov 2018 11:30:21 +0100
> Pierre Morel <pmorel@linux.ibm.com> wrote:
>
>> We intercept the PQAP(AQIC) instruction and transform
>> the guest's AQIC command parameters for the host AQIC
>> parameters.
>>
>> Doing this we use the standard adapter interface to provide
>> the adapter NIB, indicator and ISC.
>>
>> We define a new structure, APQueue to keep track of
>> the route and indicator address and we add an array of
>> AP Queues in the VFIOAPDevice.
>>
>> We call the VFIO ioctl to set or clear the interruption
>> according to the "i" bit of the parameter.
>>
>> Signed-off-by: Pierre Morel <pmorel@linux.ibm.com>
>> ---
>> hw/vfio/ap.c | 92 +++++++++++++++++++++++++++++++++++-
>> include/hw/s390x/ap-device.h | 46 ++++++++++++++++++
>> 2 files changed, 137 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c
>> index d8d9cadc46..67a46e163e 100644
>> --- a/hw/vfio/ap.c
>> +++ b/hw/vfio/ap.c
>> @@ -27,17 +27,90 @@
>> #include "sysemu/sysemu.h"
>> #include "hw/s390x/ap-bridge.h"
>> #include "exec/address-spaces.h"
>> +#include "hw/s390x/s390_flic.h"
>> +#include "hw/s390x/css.h"
>>
>> #define VFIO_AP_DEVICE_TYPE "vfio-ap"
>>
>> typedef struct VFIOAPDevice {
>> APDevice apdev;
>> VFIODevice vdev;
>> + QTAILQ_ENTRY(VFIOAPDevice) sibling;
>> + APQueue apq[MAX_AP][MAX_DOMAIN];
>> } VFIOAPDevice;
>>
>> #define VFIO_AP_DEVICE(obj) \
>> OBJECT_CHECK(VFIOAPDevice, (obj), VFIO_AP_DEVICE_TYPE)
>>
>> +VFIOAPDevice *vfio_apdev;
>> +static APDevice *matrix;
>
> Why do you need those variables? Can't you get the target device in a
> different way?
>
>> +
>> +static int ap_aqic(CPUS390XState *env)
>
> <bikeshed>I think ap_pqap_aqic would be slightly better.</bikeshed>
agreed.
>
>> +{
>> + struct pqap_cmd cmd = reg2cmd(env->regs[0]);
>> + struct ap_status status = reg2status(env->regs[1]);
>
> I don't really like those reg2<whatever> helpers; they obfuscate things
> IMO.
>
I agree, I will use masks and uint64_t/uint32_t.
> Also: These are internal structs and not copied from Linux, right? Then
> they should be CamelCase.
>
>> + uint64_t guest_nib = env->regs[2];
>
> Another point: What about endianness? Even though this is kvm-only, I
> would like an emulation of an instruction to be endian-clean. (Maybe it
> also needs a different split?)
OK, I will look at this
>
>> + struct vfio_ap_aqic param = {};
>> + int retval;
>> + VFIODevice *vdev;
>> + VFIOAPDevice *ap_vdev;
>> + APQueue *apq;
>> +
>> + ap_vdev = DO_UPCAST(VFIOAPDevice, apdev, matrix);
>> + apq = &ap_vdev->apq[cmd.apid][cmd.apqi];
>> + vdev = &ap_vdev->vdev;
>> +
>> + if (status.irq) {
>> + if (apq->nib) {
>> + status.rc = AP_RC_BAD_STATE;
>> + goto error;
>> + }
>> + } else {
>> + if (!apq->nib) {
>> + status.rc = AP_RC_BAD_STATE;
>> + goto error;
>> + }
>> + }
>
> Maybe
> if (!!status.irq == !!apq->nib) {
> status.rc = AP_RC_BAD_STATE;
> goto error;
> }
> ?
:)
>
>> + if (!guest_nib) {
>> + status.rc = AP_RC_INVALID_ADDR;
>> + goto error;
>> + }
>> +
>> + apq->routes.adapter.adapter_id = css_get_adapter_id(
>> + CSS_IO_ADAPTER_AP, status.isc);
>> +
>> + apq->nib = get_indicator(ldq_p(&guest_nib), 8);
>> +
>> + retval = map_indicator(&apq->routes.adapter, apq->nib);
>> + if (retval) {
>> + status.rc = AP_RC_INVALID_ADDR;
>> + env->regs[1] = status2reg(status);
>
> I do not like the backwards conversion macros, either :(
>
>> + goto error;
>> + }
>> +
>> + param.cmd = env->regs[0];
>> + param.status = env->regs[1];
>> + param.nib = env->regs[2];
>> + param.adapter_id = apq->routes.adapter.adapter_id;
>> + param.argsz = sizeof(param);
>> +
>> + retval = ioctl(vdev->fd, VFIO_AP_SET_IRQ, ¶m);
>> + status = reg2status(param.status);
>> + if (retval) {
>> + goto err_ioctl;
>> + }
>> +
>> + env->regs[1] = param.status;
>> +
>> + return 0;
>> +err_ioctl:
>> + release_indicator(&apq->routes.adapter, apq->nib);
>> + apq->nib = NULL;
>> +error:
>> + env->regs[1] = status2reg(status);
>> + return 0;
>> +}
>> +
>> /*
>> * ap_pqap
>> * @env: environment pointing to registers
>> @@ -45,7 +118,20 @@ typedef struct VFIOAPDevice {
>> */
>> int ap_pqap(CPUS390XState *env)
>> {
>> - return -PGM_OPERATION;
>> + struct pqap_cmd cmd = reg2cmd(env->regs[0]);
>
> Dito on the macro.
>
>> + int cc = 0;
>> +
>> + switch (cmd.fc) {
>
> This probably needs some endian handling as well.
>
>> + case AQIC:
>
> What about calling this PQAP_AQCI?
I can use it , however the function itself is called ap_pqap()
so we already know it is about PQAP...
>
>> + if (!s390_has_feat(S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL)) {
>> + return -PGM_OPERATION;
>> + }
>> + cc = ap_aqic(env);
>> + break;
>> + default:
>> + return -PGM_OPERATION;
>> + }
>> + return cc;
>> }
>>
>> static void vfio_ap_compute_needs_reset(VFIODevice *vdev)
>> @@ -119,6 +205,9 @@ static void vfio_ap_realize(DeviceState *dev, Error **errp)
>> goto out_get_dev_err;
>> }
>>
>> + matrix = apdev;
>
> Huh?
OK, sorry, I can do better. (I hope)
>
>> + css_register_io_adapters(CSS_IO_ADAPTER_AP, true, false,
>> + 0, &error_abort);
>> return;
>>
>> out_get_dev_err:
>> @@ -135,6 +224,7 @@ static void vfio_ap_unrealize(DeviceState *dev, Error **errp)
>> VFIOGroup *group = vapdev->vdev.group;
>>
>> vfio_ap_put_device(vapdev);
>> + matrix = NULL;
>> vfio_put_group(group);
>> }
>>
>> diff --git a/include/hw/s390x/ap-device.h b/include/hw/s390x/ap-device.h
>> index a83ea096c7..bc2b7bcd8e 100644
>> --- a/include/hw/s390x/ap-device.h
>> +++ b/include/hw/s390x/ap-device.h
>> @@ -28,4 +28,50 @@ typedef struct APDevice {
>> #include "cpu.h"
>> int ap_pqap(CPUS390XState *env);
>>
>> +#define MAX_AP 256
>> +#define MAX_DOMAIN 256
>> +
>> +#include "hw/s390x/s390_flic.h"
>> +#include "hw/s390x/css.h"
>> +typedef struct APQueue {
>> + uint32_t apid;
>> + uint32_t apqi;
>> + AdapterRoutes routes;
>> + IndAddr *nib;
>> +} APQueue;
>> +
>> +/* AP PQAP commands definitions */
>> +#define AQIC 0x03
>> +
>> +struct pqap_cmd {
>> + uint32_t unused;
>> + uint8_t fc;
>> + unsigned t:1;
>> + unsigned reserved:7;
>
> It is better to make this an uint8_t and define an accessor for the 't'
> bit.
OK
>
>> + uint8_t apid;
>> + uint8_t apqi;
>> +};
>
> Also, please use typedef and CamelCase :)
right, more camels
>
>> +/* AP status returned by the AP PQAP commands */
>> +#define AP_RC_APQN_INVALID 0x01
>> +#define AP_RC_INVALID_ADDR 0x06
>> +#define AP_RC_BAD_STATE 0x07
>> +
>> +struct ap_status {
>> + uint16_t pad;
>> + unsigned irq:1;
>> + unsigned pad2:15;
>> + unsigned e:1;
>> + unsigned r:1;
>> + unsigned f:1;
>> + unsigned unused:4;
>> + unsigned i:1;
>> + unsigned char rc;
>> + unsigned reserved:13;
>> + unsigned isc:3;
>> +};
>
> Dito on bitfields and CamelCase :)
OK again, even more Camels
Thanks,
Pierre
>
>> +
>> +#define reg2cmd(reg) (*(struct pqap_cmd *)&(reg))
>> +#define status2reg(status) (*((uint64_t *)&status))
>> +#define reg2status(reg) (*(struct ap_status *)&(reg))
>> +
>> #endif /* HW_S390X_AP_DEVICE_H */
>
--
Pierre Morel
Linux/KVM/QEMU in Böblingen - Germany
next prev parent reply other threads:[~2018-11-07 23:02 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-02 10:30 [Qemu-devel] [PATCH v1 0/5] s390x/vfio: VFIO-AP interrupt control interception Pierre Morel
2018-11-02 10:30 ` [Qemu-devel] [PATCH v1 1/5] s390x/vfio: ap: Linux uapi VFIO place holder Pierre Morel
2018-11-02 10:30 ` [Qemu-devel] [PATCH v1 2/5] s390x/cpumodel: Set up CPU model for AQIC interception Pierre Morel
2018-11-02 10:30 ` [Qemu-devel] [PATCH v1 3/5] s390x/vfio: ap: Definition for AP Adapter type Pierre Morel
2018-11-02 10:30 ` [Qemu-devel] [PATCH v1 4/5] s390x/vfio: ap: Intercepting AP Queue Interrupt Control Pierre Morel
2018-11-07 12:40 ` Cornelia Huck
2018-11-07 22:44 ` Pierre Morel
2018-11-02 10:30 ` [Qemu-devel] [PATCH v1 5/5] s390x/vfio: ap: Implementing " Pierre Morel
2018-11-07 13:39 ` Cornelia Huck
2018-11-07 23:02 ` Pierre Morel [this message]
2018-11-02 12:53 ` [Qemu-devel] [PATCH v1 0/5] s390x/vfio: VFIO-AP interrupt control interception David Hildenbrand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=29a2919c-908c-0ef8-9e04-63d9e9284700@linux.ibm.com \
--to=pmorel@linux.ibm.com \
--cc=agraf@suse.de \
--cc=akrowiak@linux.ibm.com \
--cc=borntraeger@de.ibm.com \
--cc=cohuck@redhat.com \
--cc=david@redhat.com \
--cc=eric.auger@redhat.com \
--cc=mst@redhat.com \
--cc=pasic@linux.ibm.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).