From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39680) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z0qHf-00039T-3b for qemu-devel@nongnu.org; Fri, 05 Jun 2015 07:59:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z0qHb-0002Yf-P6 for qemu-devel@nongnu.org; Fri, 05 Jun 2015 07:59:35 -0400 Received: from mail.emea.novell.com ([130.57.118.101]:41530) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z0qHb-0002YJ-6u for qemu-devel@nongnu.org; Fri, 05 Jun 2015 07:59:31 -0400 Message-Id: <5571AB41020000780008153F@mail.emea.novell.com> Date: Fri, 05 Jun 2015 12:59:29 +0100 From: "Jan Beulich" References: <5571AA3B020000780008152E@mail.emea.novell.com> In-Reply-To: <5571AA3B020000780008152E@mail.emea.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartF2C6DB31.2__=" Subject: [Qemu-devel] [PATCH 1/6] xen/MSI-X: latch MSI-X table writes List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: xen-devel , Stefano Stabellini This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartF2C6DB31.2__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline The remaining log message in pci_msix_write() is wrong, as there guest behavior may only appear to be wrong: For one, the old logic didn't take the mask-all bit into account. And then this shouldn't depend on host device state (i.e. the host may have masked the entry without the guest having done so). Plus these writes shouldn't be dropped even when an entry gets unmasked. Instead, if they can't be made take effect right away, they should take effect on the next unmasking or enabling operation - the specification explicitly describes such caching behavior. Signed-off-by: Jan Beulich --- a/qemu/upstream/hw/xen/xen_pt.h +++ b/qemu/upstream/hw/xen/xen_pt.h @@ -175,9 +175,8 @@ typedef struct XenPTMSIXEntry { int pirq; uint64_t addr; uint32_t data; - uint32_t vector_ctrl; + uint32_t latch[4]; bool updated; /* indicate whether MSI ADDR or DATA is updated */ - bool warned; /* avoid issuing (bogus) warning more than once */ } XenPTMSIXEntry; typedef struct XenPTMSIX { uint32_t ctrl_offset; --- a/qemu/upstream/hw/xen/xen_pt_msi.c +++ b/qemu/upstream/hw/xen/xen_pt_msi.c @@ -25,6 +25,7 @@ #define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12 #define XEN_PT_GFLAGSSHIFT_TRG_MODE 15 =20 +#define latch(fld) latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)] =20 /* * Helpers @@ -322,6 +323,13 @@ static int xen_pt_msix_update_one(XenPCI =20 pirq =3D entry->pirq; =20 + if (pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ || s->msix->maskall || + (entry->latch(VECTOR_CTRL) & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { + entry->addr =3D entry->latch(LOWER_ADDR) | + ((uint64_t)entry->latch(UPPER_ADDR) << 32); + entry->data =3D entry->latch(DATA); + } + rc =3D msi_msix_setup(s, entry->addr, entry->data, &pirq, true, = entry_nr, entry->pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ); if (rc) { @@ -396,35 +404,15 @@ int xen_pt_msix_update_remap(XenPCIPasst =20 static uint32_t get_entry_value(XenPTMSIXEntry *e, int offset) { - switch (offset) { - case PCI_MSIX_ENTRY_LOWER_ADDR: - return e->addr & UINT32_MAX; - case PCI_MSIX_ENTRY_UPPER_ADDR: - return e->addr >> 32; - case PCI_MSIX_ENTRY_DATA: - return e->data; - case PCI_MSIX_ENTRY_VECTOR_CTRL: - return e->vector_ctrl; - default: - return 0; - } + return !(offset % sizeof(*e->latch)) + ? e->latch[offset / sizeof(*e->latch)] : 0; } =20 static void set_entry_value(XenPTMSIXEntry *e, int offset, uint32_t val) { - switch (offset) { - case PCI_MSIX_ENTRY_LOWER_ADDR: - e->addr =3D (e->addr & ((uint64_t)UINT32_MAX << 32)) | val; - break; - case PCI_MSIX_ENTRY_UPPER_ADDR: - e->addr =3D (uint64_t)val << 32 | (e->addr & UINT32_MAX); - break; - case PCI_MSIX_ENTRY_DATA: - e->data =3D val; - break; - case PCI_MSIX_ENTRY_VECTOR_CTRL: - e->vector_ctrl =3D val; - break; + if (!(offset % sizeof(*e->latch))) + { + e->latch[offset / sizeof(*e->latch)] =3D val; } } =20 @@ -444,39 +432,28 @@ static void pci_msix_write(void *opaque, offset =3D addr % PCI_MSIX_ENTRY_SIZE; =20 if (offset !=3D PCI_MSIX_ENTRY_VECTOR_CTRL) { - const volatile uint32_t *vec_ctrl; - if (get_entry_value(entry, offset) =3D=3D val && entry->pirq !=3D XEN_PT_UNASSIGNED_PIRQ) { return; } =20 + entry->updated =3D true; + } else if (msix->enabled && entry->updated && + !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { + const volatile uint32_t *vec_ctrl; + /* * If Xen intercepts the mask bit access, entry->vec_ctrl may not = be * up-to-date. Read from hardware directly. */ vec_ctrl =3D s->msix->phys_iomem_base + entry_nr * PCI_MSIX_ENTRY_= SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; + set_entry_value(entry, offset, *vec_ctrl); =20 - if (msix->enabled && !(*vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = { - if (!entry->warned) { - entry->warned =3D true; - XEN_PT_ERR(&s->dev, "Can't update msix entry %d since = MSI-X is" - " already enabled.\n", entry_nr); - } - return; - } - - entry->updated =3D true; + xen_pt_msix_update_one(s, entry_nr); } =20 set_entry_value(entry, offset, val); - - if (offset =3D=3D PCI_MSIX_ENTRY_VECTOR_CTRL) { - if (msix->enabled && !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { - xen_pt_msix_update_one(s, entry_nr); - } - } } =20 static uint64_t pci_msix_read(void *opaque, hwaddr addr, --=__PartF2C6DB31.2__= Content-Type: text/plain; name="qemu-MSI-X-latch-writes.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="qemu-MSI-X-latch-writes.patch" xen/MSI-X: latch MSI-X table writes=0A=0AThe remaining log message in = pci_msix_write() is wrong, as there guest=0Abehavior may only appear to be = wrong: For one, the old logic didn't=0Atake the mask-all bit into account. = And then this shouldn't depend on=0Ahost device state (i.e. the host may = have masked the entry without the=0Aguest having done so). Plus these = writes shouldn't be dropped even when=0Aan entry gets unmasked. Instead, = if they can't be made take effect=0Aright away, they should take effect on = the next unmasking or enabling=0Aoperation - the specification explicitly = describes such caching=0Abehavior.=0A=0ASigned-off-by: Jan Beulich = =0A=0A--- a/qemu/upstream/hw/xen/xen_pt.h=0A+++ = b/qemu/upstream/hw/xen/xen_pt.h=0A@@ -175,9 +175,8 @@ typedef struct = XenPTMSIXEntry {=0A int pirq;=0A uint64_t addr;=0A uint32_t = data;=0A- uint32_t vector_ctrl;=0A+ uint32_t latch[4];=0A bool = updated; /* indicate whether MSI ADDR or DATA is updated */=0A- bool = warned; /* avoid issuing (bogus) warning more than once */=0A } XenPTMSIXE= ntry;=0A typedef struct XenPTMSIX {=0A uint32_t ctrl_offset;=0A--- = a/qemu/upstream/hw/xen/xen_pt_msi.c=0A+++ b/qemu/upstream/hw/xen/xen_pt_msi= .c=0A@@ -25,6 +25,7 @@=0A #define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12=0A = #define XEN_PT_GFLAGSSHIFT_TRG_MODE 15=0A =0A+#define latch(fld) = latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)]=0A =0A /*=0A * Helpers=0A@@= -322,6 +323,13 @@ static int xen_pt_msix_update_one(XenPCI=0A =0A = pirq =3D entry->pirq;=0A =0A+ if (pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ || = s->msix->maskall ||=0A+ (entry->latch(VECTOR_CTRL) & PCI_MSIX_ENTRY_= CTRL_MASKBIT)) {=0A+ entry->addr =3D entry->latch(LOWER_ADDR) |=0A+ = ((uint64_t)entry->latch(UPPER_ADDR) << 32);=0A+ = entry->data =3D entry->latch(DATA);=0A+ }=0A+=0A rc =3D msi_msix_se= tup(s, entry->addr, entry->data, &pirq, true, entry_nr,=0A = entry->pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ);=0A if (rc) {=0A@@ = -396,35 +404,15 @@ int xen_pt_msix_update_remap(XenPCIPasst=0A =0A static = uint32_t get_entry_value(XenPTMSIXEntry *e, int offset)=0A {=0A- switch = (offset) {=0A- case PCI_MSIX_ENTRY_LOWER_ADDR:=0A- return = e->addr & UINT32_MAX;=0A- case PCI_MSIX_ENTRY_UPPER_ADDR:=0A- = return e->addr >> 32;=0A- case PCI_MSIX_ENTRY_DATA:=0A- return = e->data;=0A- case PCI_MSIX_ENTRY_VECTOR_CTRL:=0A- return = e->vector_ctrl;=0A- default:=0A- return 0;=0A- }=0A+ = return !(offset % sizeof(*e->latch))=0A+ ? e->latch[offset / = sizeof(*e->latch)] : 0;=0A }=0A =0A static void set_entry_value(XenPTMSIXEn= try *e, int offset, uint32_t val)=0A {=0A- switch (offset) {=0A- = case PCI_MSIX_ENTRY_LOWER_ADDR:=0A- e->addr =3D (e->addr & = ((uint64_t)UINT32_MAX << 32)) | val;=0A- break;=0A- case = PCI_MSIX_ENTRY_UPPER_ADDR:=0A- e->addr =3D (uint64_t)val << 32 | = (e->addr & UINT32_MAX);=0A- break;=0A- case PCI_MSIX_ENTRY_DATA:= =0A- e->data =3D val;=0A- break;=0A- case PCI_MSIX_ENTRY_V= ECTOR_CTRL:=0A- e->vector_ctrl =3D val;=0A- break;=0A+ if = (!(offset % sizeof(*e->latch)))=0A+ {=0A+ e->latch[offset / = sizeof(*e->latch)] =3D val;=0A }=0A }=0A =0A@@ -444,39 +432,28 @@ = static void pci_msix_write(void *opaque,=0A offset =3D addr % = PCI_MSIX_ENTRY_SIZE;=0A =0A if (offset !=3D PCI_MSIX_ENTRY_VECTOR_CTRL)= {=0A- const volatile uint32_t *vec_ctrl;=0A-=0A if = (get_entry_value(entry, offset) =3D=3D val=0A && entry->pirq = !=3D XEN_PT_UNASSIGNED_PIRQ) {=0A return;=0A }=0A =0A+ = entry->updated =3D true;=0A+ } else if (msix->enabled && = entry->updated &&=0A+ !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = {=0A+ const volatile uint32_t *vec_ctrl;=0A+=0A /*=0A = * If Xen intercepts the mask bit access, entry->vec_ctrl may not be=0A = * up-to-date. Read from hardware directly.=0A */=0A = vec_ctrl =3D s->msix->phys_iomem_base + entry_nr * PCI_MSIX_ENTRY_SIZE=0A= + PCI_MSIX_ENTRY_VECTOR_CTRL;=0A+ set_entry_value(entry= , offset, *vec_ctrl);=0A =0A- if (msix->enabled && !(*vec_ctrl & = PCI_MSIX_ENTRY_CTRL_MASKBIT)) {=0A- if (!entry->warned) {=0A- = entry->warned =3D true;=0A- XEN_PT_ERR(&s->dev,= "Can't update msix entry %d since MSI-X is"=0A- = " already enabled.\n", entry_nr);=0A- }=0A- = return;=0A- }=0A-=0A- entry->updated =3D true;=0A+ = xen_pt_msix_update_one(s, entry_nr);=0A }=0A =0A set_entry_value(en= try, offset, val);=0A-=0A- if (offset =3D=3D PCI_MSIX_ENTRY_VECTOR_CTRL)= {=0A- if (msix->enabled && !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = {=0A- xen_pt_msix_update_one(s, entry_nr);=0A- }=0A- = }=0A }=0A =0A static uint64_t pci_msix_read(void *opaque, hwaddr addr,=0A --=__PartF2C6DB31.2__=-- From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 1/6] xen/MSI-X: latch MSI-X table writes Date: Fri, 05 Jun 2015 12:59:29 +0100 Message-ID: <5571AB41020000780008153F@mail.emea.novell.com> References: <5571AA3B020000780008152E@mail.emea.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartF2C6DB31.1__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Z0qHf-00086H-Dl for xen-devel@lists.xenproject.org; Fri, 05 Jun 2015 11:59:35 +0000 In-Reply-To: <5571AA3B020000780008152E@mail.emea.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: qemu-devel@nongnu.org Cc: xen-devel , Stefano Stabellini List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartF2C6DB31.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline The remaining log message in pci_msix_write() is wrong, as there guest behavior may only appear to be wrong: For one, the old logic didn't take the mask-all bit into account. And then this shouldn't depend on host device state (i.e. the host may have masked the entry without the guest having done so). Plus these writes shouldn't be dropped even when an entry gets unmasked. Instead, if they can't be made take effect right away, they should take effect on the next unmasking or enabling operation - the specification explicitly describes such caching behavior. Signed-off-by: Jan Beulich --- a/qemu/upstream/hw/xen/xen_pt.h +++ b/qemu/upstream/hw/xen/xen_pt.h @@ -175,9 +175,8 @@ typedef struct XenPTMSIXEntry { int pirq; uint64_t addr; uint32_t data; - uint32_t vector_ctrl; + uint32_t latch[4]; bool updated; /* indicate whether MSI ADDR or DATA is updated */ - bool warned; /* avoid issuing (bogus) warning more than once */ } XenPTMSIXEntry; typedef struct XenPTMSIX { uint32_t ctrl_offset; --- a/qemu/upstream/hw/xen/xen_pt_msi.c +++ b/qemu/upstream/hw/xen/xen_pt_msi.c @@ -25,6 +25,7 @@ #define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12 #define XEN_PT_GFLAGSSHIFT_TRG_MODE 15 =20 +#define latch(fld) latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)] =20 /* * Helpers @@ -322,6 +323,13 @@ static int xen_pt_msix_update_one(XenPCI =20 pirq =3D entry->pirq; =20 + if (pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ || s->msix->maskall || + (entry->latch(VECTOR_CTRL) & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { + entry->addr =3D entry->latch(LOWER_ADDR) | + ((uint64_t)entry->latch(UPPER_ADDR) << 32); + entry->data =3D entry->latch(DATA); + } + rc =3D msi_msix_setup(s, entry->addr, entry->data, &pirq, true, = entry_nr, entry->pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ); if (rc) { @@ -396,35 +404,15 @@ int xen_pt_msix_update_remap(XenPCIPasst =20 static uint32_t get_entry_value(XenPTMSIXEntry *e, int offset) { - switch (offset) { - case PCI_MSIX_ENTRY_LOWER_ADDR: - return e->addr & UINT32_MAX; - case PCI_MSIX_ENTRY_UPPER_ADDR: - return e->addr >> 32; - case PCI_MSIX_ENTRY_DATA: - return e->data; - case PCI_MSIX_ENTRY_VECTOR_CTRL: - return e->vector_ctrl; - default: - return 0; - } + return !(offset % sizeof(*e->latch)) + ? e->latch[offset / sizeof(*e->latch)] : 0; } =20 static void set_entry_value(XenPTMSIXEntry *e, int offset, uint32_t val) { - switch (offset) { - case PCI_MSIX_ENTRY_LOWER_ADDR: - e->addr =3D (e->addr & ((uint64_t)UINT32_MAX << 32)) | val; - break; - case PCI_MSIX_ENTRY_UPPER_ADDR: - e->addr =3D (uint64_t)val << 32 | (e->addr & UINT32_MAX); - break; - case PCI_MSIX_ENTRY_DATA: - e->data =3D val; - break; - case PCI_MSIX_ENTRY_VECTOR_CTRL: - e->vector_ctrl =3D val; - break; + if (!(offset % sizeof(*e->latch))) + { + e->latch[offset / sizeof(*e->latch)] =3D val; } } =20 @@ -444,39 +432,28 @@ static void pci_msix_write(void *opaque, offset =3D addr % PCI_MSIX_ENTRY_SIZE; =20 if (offset !=3D PCI_MSIX_ENTRY_VECTOR_CTRL) { - const volatile uint32_t *vec_ctrl; - if (get_entry_value(entry, offset) =3D=3D val && entry->pirq !=3D XEN_PT_UNASSIGNED_PIRQ) { return; } =20 + entry->updated =3D true; + } else if (msix->enabled && entry->updated && + !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { + const volatile uint32_t *vec_ctrl; + /* * If Xen intercepts the mask bit access, entry->vec_ctrl may not = be * up-to-date. Read from hardware directly. */ vec_ctrl =3D s->msix->phys_iomem_base + entry_nr * PCI_MSIX_ENTRY_= SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL; + set_entry_value(entry, offset, *vec_ctrl); =20 - if (msix->enabled && !(*vec_ctrl & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = { - if (!entry->warned) { - entry->warned =3D true; - XEN_PT_ERR(&s->dev, "Can't update msix entry %d since = MSI-X is" - " already enabled.\n", entry_nr); - } - return; - } - - entry->updated =3D true; + xen_pt_msix_update_one(s, entry_nr); } =20 set_entry_value(entry, offset, val); - - if (offset =3D=3D PCI_MSIX_ENTRY_VECTOR_CTRL) { - if (msix->enabled && !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) { - xen_pt_msix_update_one(s, entry_nr); - } - } } =20 static uint64_t pci_msix_read(void *opaque, hwaddr addr, --=__PartF2C6DB31.1__= Content-Type: text/plain; name="qemu-MSI-X-latch-writes.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="qemu-MSI-X-latch-writes.patch" xen/MSI-X: latch MSI-X table writes=0A=0AThe remaining log message in = pci_msix_write() is wrong, as there guest=0Abehavior may only appear to be = wrong: For one, the old logic didn't=0Atake the mask-all bit into account. = And then this shouldn't depend on=0Ahost device state (i.e. the host may = have masked the entry without the=0Aguest having done so). Plus these = writes shouldn't be dropped even when=0Aan entry gets unmasked. Instead, = if they can't be made take effect=0Aright away, they should take effect on = the next unmasking or enabling=0Aoperation - the specification explicitly = describes such caching=0Abehavior.=0A=0ASigned-off-by: Jan Beulich = =0A=0A--- a/qemu/upstream/hw/xen/xen_pt.h=0A+++ = b/qemu/upstream/hw/xen/xen_pt.h=0A@@ -175,9 +175,8 @@ typedef struct = XenPTMSIXEntry {=0A int pirq;=0A uint64_t addr;=0A uint32_t = data;=0A- uint32_t vector_ctrl;=0A+ uint32_t latch[4];=0A bool = updated; /* indicate whether MSI ADDR or DATA is updated */=0A- bool = warned; /* avoid issuing (bogus) warning more than once */=0A } XenPTMSIXE= ntry;=0A typedef struct XenPTMSIX {=0A uint32_t ctrl_offset;=0A--- = a/qemu/upstream/hw/xen/xen_pt_msi.c=0A+++ b/qemu/upstream/hw/xen/xen_pt_msi= .c=0A@@ -25,6 +25,7 @@=0A #define XEN_PT_GFLAGSSHIFT_DELIV_MODE 12=0A = #define XEN_PT_GFLAGSSHIFT_TRG_MODE 15=0A =0A+#define latch(fld) = latch[PCI_MSIX_ENTRY_##fld / sizeof(uint32_t)]=0A =0A /*=0A * Helpers=0A@@= -322,6 +323,13 @@ static int xen_pt_msix_update_one(XenPCI=0A =0A = pirq =3D entry->pirq;=0A =0A+ if (pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ || = s->msix->maskall ||=0A+ (entry->latch(VECTOR_CTRL) & PCI_MSIX_ENTRY_= CTRL_MASKBIT)) {=0A+ entry->addr =3D entry->latch(LOWER_ADDR) |=0A+ = ((uint64_t)entry->latch(UPPER_ADDR) << 32);=0A+ = entry->data =3D entry->latch(DATA);=0A+ }=0A+=0A rc =3D msi_msix_se= tup(s, entry->addr, entry->data, &pirq, true, entry_nr,=0A = entry->pirq =3D=3D XEN_PT_UNASSIGNED_PIRQ);=0A if (rc) {=0A@@ = -396,35 +404,15 @@ int xen_pt_msix_update_remap(XenPCIPasst=0A =0A static = uint32_t get_entry_value(XenPTMSIXEntry *e, int offset)=0A {=0A- switch = (offset) {=0A- case PCI_MSIX_ENTRY_LOWER_ADDR:=0A- return = e->addr & UINT32_MAX;=0A- case PCI_MSIX_ENTRY_UPPER_ADDR:=0A- = return e->addr >> 32;=0A- case PCI_MSIX_ENTRY_DATA:=0A- return = e->data;=0A- case PCI_MSIX_ENTRY_VECTOR_CTRL:=0A- return = e->vector_ctrl;=0A- default:=0A- return 0;=0A- }=0A+ = return !(offset % sizeof(*e->latch))=0A+ ? e->latch[offset / = sizeof(*e->latch)] : 0;=0A }=0A =0A static void set_entry_value(XenPTMSIXEn= try *e, int offset, uint32_t val)=0A {=0A- switch (offset) {=0A- = case PCI_MSIX_ENTRY_LOWER_ADDR:=0A- e->addr =3D (e->addr & = ((uint64_t)UINT32_MAX << 32)) | val;=0A- break;=0A- case = PCI_MSIX_ENTRY_UPPER_ADDR:=0A- e->addr =3D (uint64_t)val << 32 | = (e->addr & UINT32_MAX);=0A- break;=0A- case PCI_MSIX_ENTRY_DATA:= =0A- e->data =3D val;=0A- break;=0A- case PCI_MSIX_ENTRY_V= ECTOR_CTRL:=0A- e->vector_ctrl =3D val;=0A- break;=0A+ if = (!(offset % sizeof(*e->latch)))=0A+ {=0A+ e->latch[offset / = sizeof(*e->latch)] =3D val;=0A }=0A }=0A =0A@@ -444,39 +432,28 @@ = static void pci_msix_write(void *opaque,=0A offset =3D addr % = PCI_MSIX_ENTRY_SIZE;=0A =0A if (offset !=3D PCI_MSIX_ENTRY_VECTOR_CTRL)= {=0A- const volatile uint32_t *vec_ctrl;=0A-=0A if = (get_entry_value(entry, offset) =3D=3D val=0A && entry->pirq = !=3D XEN_PT_UNASSIGNED_PIRQ) {=0A return;=0A }=0A =0A+ = entry->updated =3D true;=0A+ } else if (msix->enabled && = entry->updated &&=0A+ !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = {=0A+ const volatile uint32_t *vec_ctrl;=0A+=0A /*=0A = * If Xen intercepts the mask bit access, entry->vec_ctrl may not be=0A = * up-to-date. Read from hardware directly.=0A */=0A = vec_ctrl =3D s->msix->phys_iomem_base + entry_nr * PCI_MSIX_ENTRY_SIZE=0A= + PCI_MSIX_ENTRY_VECTOR_CTRL;=0A+ set_entry_value(entry= , offset, *vec_ctrl);=0A =0A- if (msix->enabled && !(*vec_ctrl & = PCI_MSIX_ENTRY_CTRL_MASKBIT)) {=0A- if (!entry->warned) {=0A- = entry->warned =3D true;=0A- XEN_PT_ERR(&s->dev,= "Can't update msix entry %d since MSI-X is"=0A- = " already enabled.\n", entry_nr);=0A- }=0A- = return;=0A- }=0A-=0A- entry->updated =3D true;=0A+ = xen_pt_msix_update_one(s, entry_nr);=0A }=0A =0A set_entry_value(en= try, offset, val);=0A-=0A- if (offset =3D=3D PCI_MSIX_ENTRY_VECTOR_CTRL)= {=0A- if (msix->enabled && !(val & PCI_MSIX_ENTRY_CTRL_MASKBIT)) = {=0A- xen_pt_msix_update_one(s, entry_nr);=0A- }=0A- = }=0A }=0A =0A static uint64_t pci_msix_read(void *opaque, hwaddr addr,=0A --=__PartF2C6DB31.1__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --=__PartF2C6DB31.1__=--