On Fri, 5 Jun 2015, Jan Beulich wrote:
> Particularly the maskall bit has to be under exclusive hypervisor
> control (and since they live in the same config space field, the
> enable bit has to follow suit). Use the replacement hypercall
> interfaces.

>From this commit message, I expect a patch that simply substitutes
maskall and enable writings with hypercalls and nothing else.


> Signed-off-by: Jan Beulich <jbeul...@suse.com>
> 
> --- a/qemu/upstream/hw/xen/xen_pt.h
> +++ b/qemu/upstream/hw/xen/xen_pt.h
> @@ -181,6 +181,7 @@ typedef struct XenPTMSIXEntry {
>  typedef struct XenPTMSIX {
>      uint32_t ctrl_offset;
>      bool enabled;
> +    bool maskall;
>      int total_entries;
>      int bar_index;
>      uint64_t table_base;
> @@ -293,7 +294,9 @@ int xen_pt_msix_init(XenPCIPassthroughSt
>  void xen_pt_msix_delete(XenPCIPassthroughState *s);
>  int xen_pt_msix_update(XenPCIPassthroughState *s);
>  int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
> +void xen_pt_msix_enable(XenPCIPassthroughState *s);
>  void xen_pt_msix_disable(XenPCIPassthroughState *s);
> +int xen_pt_msix_maskall(XenPCIPassthroughState *s, bool mask);
>  
>  static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int 
> bar)
>  {
> --- a/qemu/upstream/hw/xen/xen_pt_config_init.c
> +++ b/qemu/upstream/hw/xen/xen_pt_config_init.c
> @@ -1436,32 +1436,58 @@ static int xen_pt_msixctrl_reg_write(Xen
>                                       uint16_t dev_value, uint16_t valid_mask)
>  {
>      XenPTRegInfo *reg = cfg_entry->reg;
> -    uint16_t writable_mask = 0;
> +    uint16_t writable_mask, value;
>      uint16_t throughable_mask = get_throughable_mask(s, reg, valid_mask);
>      int debug_msix_enabled_old;
>  
>      /* modify emulate register */
>      writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask;
> -    cfg_entry->data = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, 
> writable_mask);
> +    value = XEN_PT_MERGE_VALUE(*val, cfg_entry->data, writable_mask);
> +    cfg_entry->data = value;
>
>      /* create value for writing to I/O device register */
>      *val = XEN_PT_MERGE_VALUE(*val, dev_value, throughable_mask);
>  
> +    debug_msix_enabled_old = s->msix->enabled;
> +
>      /* update MSI-X */
> -    if ((*val & PCI_MSIX_FLAGS_ENABLE)

Please explain in the commit message the reason of the *val/value
change.


> -        && !(*val & PCI_MSIX_FLAGS_MASKALL)) {
> +    if ((value & PCI_MSIX_FLAGS_ENABLE)
> +        && !(value & PCI_MSIX_FLAGS_MASKALL)) {
> +        if (!s->msix->enabled) {
> +            if (!s->msix->maskall) {
> +                xen_pt_msix_maskall(s, true);
> +            }
> +            xen_pt_msix_enable(s);
> +        }
>          xen_pt_msix_update(s);
> -    } else if (!(*val & PCI_MSIX_FLAGS_ENABLE) && s->msix->enabled) {
> -        xen_pt_msix_disable(s);
> +        s->msix->enabled = true;
> +        s->msix->maskall = false;
> +        xen_pt_msix_maskall(s, false);

Please explain in the commit message the reason behind the
maskall->enable->update->un_maskall logic, that wasn't present before.


> +    } else if (s->msix->enabled) {
> +        if (!(value & PCI_MSIX_FLAGS_ENABLE)) {
> +            xen_pt_msix_disable(s);
> +            s->msix->enabled = false;
> +        } else if (!s->msix->maskall) {

Why are you changing the state of s->msix->maskall here?
This is the value & PCI_MSIX_FLAGS_ENABLE case, nothing to do with
maskall, right?


> +            s->msix->maskall = true;
> +            xen_pt_msix_maskall(s, true);
> +        }
>      }
>  
> -    debug_msix_enabled_old = s->msix->enabled;
> -    s->msix->enabled = !!(*val & PCI_MSIX_FLAGS_ENABLE);
>      if (s->msix->enabled != debug_msix_enabled_old) {
>          XEN_PT_LOG(&s->dev, "%s MSI-X\n",
>                     s->msix->enabled ? "enable" : "disable");
>      }
>  
> +    xen_host_pci_get_word(&s->real_device, s->msix->ctrl_offset, &dev_value);

I have to say that I don't like the asymmetry between reading and
writing PCI config registers. If writes go via hypercalls, reads should
go via hypercalls too.


> +    if (s->msix->enabled && !(dev_value & PCI_MSIX_FLAGS_ENABLE)) {
> +        XEN_PT_ERR(&s->dev, "MSI-X unexpectedly disabled\n");
> +    } else if ((dev_value & PCI_MSIX_FLAGS_ENABLE) &&
> +               s->msix->maskall &&
> +               !(dev_value & PCI_MSIX_FLAGS_MASKALL)) {
> +        XEN_PT_ERR(&s->dev, "MSI-X unexpectedly unmasked\n");
> +    }
> +
>      return 0;
>  }
>  
> @@ -1483,9 +1509,12 @@ static XenPTRegInfo xen_pt_emu_reg_msix[
>          .offset     = PCI_MSI_FLAGS,
>          .size       = 2,
>          .init_val   = 0x0000,
> -        .res_mask   = 0x3800,
> -        .ro_mask    = 0x07FF,
> -        .emu_mask   = 0x0000,
> +        /* This must not be split into res_mask (0x3800) and ro_mask (0x07FF)
> +         * because even in permissive mode there must not be any write back
> +         * to this register.
> +         */
> +        .ro_mask    = 0x3FFF,
> +        .emu_mask   = 0xC000,
>          .init       = xen_pt_msixctrl_reg_init,
>          .u.w.read   = xen_pt_word_reg_read,
>          .u.w.write  = xen_pt_msixctrl_reg_write,
> --- a/qemu/upstream/hw/xen/xen_pt_msi.c
> +++ b/qemu/upstream/hw/xen/xen_pt_msi.c
> @@ -301,8 +301,11 @@ static int msix_set_enable(XenPCIPassthr
>          return -1;
>      }
>  
> -    return msi_msix_enable(s, s->msix->ctrl_offset, PCI_MSIX_FLAGS_ENABLE,
> -                           enabled);

Would it make sense to remove msi_msix_enable completely to avoid any
further mistakes?


> +    return xc_physdev_msix_enable(xen_xc, s->real_device.domain,
> +                                  s->real_device.bus,
> +                                  PCI_DEVFN(s->real_device.dev,
> +                                            s->real_device.func),
> +                                  enabled);
>  }
>  
>  static int xen_pt_msix_update_one(XenPCIPassthroughState *s, int entry_nr)
> @@ -361,6 +364,11 @@ int xen_pt_msix_update(XenPCIPassthrough
>      return 0;
>  }
>  
> +void xen_pt_msix_enable(XenPCIPassthroughState *s)
> +{
> +    msix_set_enable(s, true);
> +}
> +
>  void xen_pt_msix_disable(XenPCIPassthroughState *s)
>  {
>      int i = 0;
> @@ -378,6 +386,15 @@ void xen_pt_msix_disable(XenPCIPassthrou
>      }
>  }
>  
> +int xen_pt_msix_maskall(XenPCIPassthroughState *s, bool mask)
> +{
> +    return xc_physdev_msix_mask_all(xen_xc, s->real_device.domain,
> +                                    s->real_device.bus,
> +                                    PCI_DEVFN(s->real_device.dev,
> +                                              s->real_device.func),
> +                                    mask);
> +}
> +
>  int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index)
>  {
>      XenPTMSIXEntry *entry;
> 
> 
> 

Reply via email to