qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v1 3/5] s390x/intc: Emulate Adapter Interrupt Su


From: Cornelia Huck
Subject: Re: [Qemu-devel] [PATCH v1 3/5] s390x/intc: Emulate Adapter Interrupt Suppression
Date: Mon, 9 Oct 2017 10:42:44 +0200

On Wed,  4 Oct 2017 15:49:37 +0200
Pierre Morel <address@hidden> wrote:

> Emulate the Adapter Interrupt Suppression in the KVM FLIC interface when
> the kernel does not support AIS.
> 
> When the kernel KVM does not support AIS, we can not support VFIO PCI
> devices but we still can support emulated devices if we emulate AIS
> inside QEMU.
> Let's emulate AIS, allowing to use emulated PCI devices without KVM AIS
> support.
> 
> Signed-off-by: Pierre Morel <address@hidden>
> ---
>  hw/intc/s390_flic.c     |  3 +-
>  hw/intc/s390_flic_kvm.c | 76 
> ++++++++++++++++++++++++++++++++++++++++---------
>  2 files changed, 64 insertions(+), 15 deletions(-)
> 
> diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
> index 6eaf178..33a7cde 100644
> --- a/hw/intc/s390_flic.c
> +++ b/hw/intc/s390_flic.c
> @@ -185,8 +185,7 @@ static void s390_flic_common_realize(DeviceState *dev, 
> Error **errp)
>                     " (%d > %d)", max_batch, ADAPTER_ROUTES_MAX_GSI);
>          return;
>      }
> -
> -    fs->ais_supported = s390_has_feat(S390_FEAT_ADAPTER_INT_SUPPRESSION);
> +    fs->ais_supported = false;
>  }
>  
>  static void s390_flic_class_init(ObjectClass *oc, void *data)
> diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
> index 7ead17a..fd1aa22 100644
> --- a/hw/intc/s390_flic_kvm.c
> +++ b/hw/intc/s390_flic_kvm.c
> @@ -33,6 +33,8 @@ typedef struct KVMS390FLICState {
>  
>      uint32_t fd;
>      bool clear_io_supported;
> +    uint8_t simm;
> +    uint8_t nimm;
>  } KVMS390FLICState;

Instead of duplicating this, move simm/nimm into the common flic state?

>  
>  DeviceState *s390_flic_kvm_create(void)
> @@ -164,11 +166,24 @@ static int kvm_s390_modify_ais_mode(S390FLICState *fs, 
> uint8_t isc,
>          .addr = (uint64_t)&req,
>      };
>  
> -    if (!fs->ais_supported) {
> -        return -ENOSYS;
> +    if (fs->ais_supported) {
> +        return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
>      }
>  
> -    return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
> +    /* Kernel does not support AIS, emulate it here */
> +    switch (mode) {
> +    case SIC_IRQ_MODE_ALL:
> +        flic->simm &= ~AIS_MODE_MASK(isc);
> +        flic->nimm &= ~AIS_MODE_MASK(isc);
> +        break;
> +    case SIC_IRQ_MODE_SINGLE:
> +        flic->simm |= AIS_MODE_MASK(isc);
> +        flic->nimm &= ~AIS_MODE_MASK(isc);
> +        break;
> +    default:
> +        return -EINVAL;
> +    }

That's just the same as for the qemu flic. What about creating a
wrapper (to be called from css.c) in the common flic code that calls a
specific callback (only needed for kvm) and falls back to emulating if
it was not successful?

> +    return 0;
>  }
>  
>  static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
> @@ -180,12 +195,23 @@ static int kvm_s390_inject_airq(S390FLICState *fs, 
> uint8_t type,
>          .group = KVM_DEV_FLIC_AIRQ_INJECT,
>          .attr = id,
>      };
> +    uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
>  
> -    if (!fs->ais_supported) {
> -        return -ENOSYS;
> +    if (fs->ais_supported) {
> +        return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
>      }
>  
> -    return ioctl(flic->fd, KVM_SET_DEVICE_ATTR, &attr) ? -errno : 0;
> +    /* Kernel does not support AIS, emulate it here */
> +    if (flags && (flic->nimm & AIS_MODE_MASK(isc))) {
> +        return 0;
> +    }
> +
> +    s390_io_interrupt(0, 0, 0, io_int_word);
> +
> +    if (flags && (flic->simm & AIS_MODE_MASK(isc))) {
> +        flic->nimm |= AIS_MODE_MASK(isc);
> +    }

Same here: I think doing this in the generic flic would make sense.

> +    return 0;
>  }
>  
>  /**
> @@ -557,6 +583,32 @@ static void kvm_s390_flic_realize(DeviceState *dev, 
> Error **errp)
>      test_attr.group = KVM_DEV_FLIC_CLEAR_IO_IRQ;
>      flic_state->clear_io_supported = !ioctl(flic_state->fd,
>                                              KVM_HAS_DEVICE_ATTR, test_attr);
> +    /* To support ais we need all these three FLIC attributes */
> +    test_attr.group = KVM_DEV_FLIC_AISM;
> +    ret = !ioctl(flic_state->fd, KVM_HAS_DEVICE_ATTR, test_attr);
> +    flic_state->parent_obj.ais_supported &= ret;
> +
> +    test_attr.group = KVM_DEV_FLIC_AIRQ_INJECT;
> +    ret = !ioctl(flic_state->fd, KVM_HAS_DEVICE_ATTR, test_attr);
> +    flic_state->parent_obj.ais_supported &= ret;
> +
> +    test_attr.group = KVM_DEV_FLIC_AISM_ALL;
> +    ret &= !ioctl(flic_state->fd, KVM_HAS_DEVICE_ATTR, test_attr);
> +    flic_state->parent_obj.ais_supported &= ret;
> +
> +    /* For buggy kernels we need to really test that the attribute is 
> supported */

Ugh.

> +    {
> +        struct kvm_s390_ais_req req = {
> +            .mode = SIC_IRQ_MODE_ALL,
> +        };
> +        struct kvm_device_attr attr = {
> +            .group = KVM_DEV_FLIC_AISM,
> +            .addr = (uint64_t)&req,
> +        };
> +        ret = !ioctl(flic_state->fd, KVM_SET_DEVICE_ATTR, &attr);
> +    }
> +    flic_state->parent_obj.ais_supported &= ret;
> +
>      return;
>  fail:
>      error_propagate(errp, errp_local);
> @@ -578,13 +630,11 @@ static void kvm_s390_flic_reset(DeviceState *dev)
>  
>      flic_disable_wait_pfault(flic);
>  
> -    if (fs->ais_supported) {
> -        for (isc = 0; isc <= MAX_ISC; isc++) {
> -            rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL);
> -            if (rc) {
> -                error_report("Failed to reset ais mode for isc %d: %s",
> -                             isc, strerror(-rc));
> -            }
> +    for (isc = 0; isc <= MAX_ISC; isc++) {
> +        rc = kvm_s390_modify_ais_mode(fs, isc, SIC_IRQ_MODE_ALL);
> +        if (rc) {
> +            error_report("Failed to reset ais mode for isc %d: %s",
> +                         isc, strerror(-rc));
>          }
>      }
>  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]