diff mbox

[3/3] virtio: optimize virtio_access_is_big_endian() for little-endian targets

Message ID 20151109175834.4076.53346.stgit@bahia.huguette.org
State New
Headers show

Commit Message

Greg Kurz Nov. 9, 2015, 5:58 p.m. UTC
When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro
and the virtio_access_is_big_endian() helper to have a branchless fast path
in the virtio memory accessors for targets that don't switch endian.

This was considered as a strong requirement at the time.

Now we have added a runtime check for virtio 1.0, which ruins the benefit
of the virtio_access_is_big_endian() helper for always little-endian targets.

With this patch, fixed little-endian targets stop checking for virtio 1.0,
since the result is little-endian in all cases. The helper also gets renamed
so it is clear it is optimized for fast paths.

Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
---
 include/hw/virtio/virtio-access.h |   43 ++++++++++++++++++++-----------------
 1 file changed, 23 insertions(+), 20 deletions(-)

Comments

Cornelia Huck Nov. 12, 2015, 6:08 p.m. UTC | #1
On Mon, 09 Nov 2015 18:58:34 +0100
Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:

> When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro
> and the virtio_access_is_big_endian() helper to have a branchless fast path
> in the virtio memory accessors for targets that don't switch endian.
> 
> This was considered as a strong requirement at the time.
> 
> Now we have added a runtime check for virtio 1.0, which ruins the benefit
> of the virtio_access_is_big_endian() helper for always little-endian targets.
> 
> With this patch, fixed little-endian targets stop checking for virtio 1.0,
> since the result is little-endian in all cases. 

So always-LE gets optimized, while always-BE and bi-endian stay the same?

(Is there a measurable impact?)

> The helper also gets renamed
> so it is clear it is optimized for fast paths.

Even if it isn't actually 'fast' on anything other than fixed-LE?
> 
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
>  include/hw/virtio/virtio-access.h |   43 ++++++++++++++++++++-----------------
>  1 file changed, 23 insertions(+), 20 deletions(-)
Greg Kurz Nov. 13, 2015, 9:28 a.m. UTC | #2
On Thu, 12 Nov 2015 19:08:59 +0100
Cornelia Huck <cornelia.huck@de.ibm.com> wrote:

> On Mon, 09 Nov 2015 18:58:34 +0100
> Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> 
> > When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro
> > and the virtio_access_is_big_endian() helper to have a branchless fast path
> > in the virtio memory accessors for targets that don't switch endian.
> > 
> > This was considered as a strong requirement at the time.
> > 
> > Now we have added a runtime check for virtio 1.0, which ruins the benefit
> > of the virtio_access_is_big_endian() helper for always little-endian targets.
> > 
> > With this patch, fixed little-endian targets stop checking for virtio 1.0,
> > since the result is little-endian in all cases. 
> 
> So always-LE gets optimized, while always-BE and bi-endian stay the same?
> 

Yes.

> (Is there a measurable impact?)
> 

I tried to measure using iperf between host and guest but I could not
find any significant change... do you think about another test I could
try ?

> > The helper also gets renamed
> > so it is clear it is optimized for fast paths.
> 
> Even if it isn't actually 'fast' on anything other than fixed-LE?

Yes this is definitely a fixed-LE only optimization... should I drop the name
change and add a comment instead ?

> > 
> > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > ---
> >  include/hw/virtio/virtio-access.h |   43 ++++++++++++++++++++-----------------
> >  1 file changed, 23 insertions(+), 20 deletions(-)
Cornelia Huck Nov. 13, 2015, 2:42 p.m. UTC | #3
On Fri, 13 Nov 2015 10:28:31 +0100
Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:

> On Thu, 12 Nov 2015 19:08:59 +0100
> Cornelia Huck <cornelia.huck@de.ibm.com> wrote:
> 
> > On Mon, 09 Nov 2015 18:58:34 +0100
> > Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> > 
> > > When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro
> > > and the virtio_access_is_big_endian() helper to have a branchless fast path
> > > in the virtio memory accessors for targets that don't switch endian.
> > > 
> > > This was considered as a strong requirement at the time.
> > > 
> > > Now we have added a runtime check for virtio 1.0, which ruins the benefit
> > > of the virtio_access_is_big_endian() helper for always little-endian targets.
> > > 
> > > With this patch, fixed little-endian targets stop checking for virtio 1.0,
> > > since the result is little-endian in all cases. 
> > 
> > So always-LE gets optimized, while always-BE and bi-endian stay the same?
> > 
> 
> Yes.
> 
> > (Is there a measurable impact?)
> > 
> 
> I tried to measure using iperf between host and guest but I could not
> find any significant change... do you think about another test I could
> try ?

My hunch is that the impact is small anyway.

> 
> > > The helper also gets renamed
> > > so it is clear it is optimized for fast paths.
> > 
> > Even if it isn't actually 'fast' on anything other than fixed-LE?
> 
> Yes this is definitely a fixed-LE only optimization... should I drop the name
> change and add a comment instead ?

I think that would be better as it does not raise expectations :)

> 
> > > 
> > > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > > ---
> > >  include/hw/virtio/virtio-access.h |   43 ++++++++++++++++++++-----------------
> > >  1 file changed, 23 insertions(+), 20 deletions(-)
>
Greg Kurz Nov. 13, 2015, 3:25 p.m. UTC | #4
On Fri, 13 Nov 2015 15:42:53 +0100
Cornelia Huck <cornelia.huck@de.ibm.com> wrote:

> On Fri, 13 Nov 2015 10:28:31 +0100
> Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> 
> > On Thu, 12 Nov 2015 19:08:59 +0100
> > Cornelia Huck <cornelia.huck@de.ibm.com> wrote:
> > 
> > > On Mon, 09 Nov 2015 18:58:34 +0100
> > > Greg Kurz <gkurz@linux.vnet.ibm.com> wrote:
> > > 
> > > > When adding cross-endian support, we introduced the TARGET_IS_BIENDIAN macro
> > > > and the virtio_access_is_big_endian() helper to have a branchless fast path
> > > > in the virtio memory accessors for targets that don't switch endian.
> > > > 
> > > > This was considered as a strong requirement at the time.
> > > > 
> > > > Now we have added a runtime check for virtio 1.0, which ruins the benefit
> > > > of the virtio_access_is_big_endian() helper for always little-endian targets.
> > > > 
> > > > With this patch, fixed little-endian targets stop checking for virtio 1.0,
> > > > since the result is little-endian in all cases. 
> > > 
> > > So always-LE gets optimized, while always-BE and bi-endian stay the same?
> > > 
> > 
> > Yes.
> > 
> > > (Is there a measurable impact?)
> > > 
> > 
> > I tried to measure using iperf between host and guest but I could not
> > find any significant change... do you think about another test I could
> > try ?
> 
> My hunch is that the impact is small anyway.
> 

Yeah... even when running TCG I don't see any difference.

> > 
> > > > The helper also gets renamed
> > > > so it is clear it is optimized for fast paths.
> > > 
> > > Even if it isn't actually 'fast' on anything other than fixed-LE?
> > 
> > Yes this is definitely a fixed-LE only optimization... should I drop the name
> > change and add a comment instead ?
> 
> I think that would be better as it does not raise expectations :)
> 

Ok I'll revert to the original name then.

Thanks for the review.

--
Greg

> > 
> > > > 
> > > > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > > > ---
> > > >  include/hw/virtio/virtio-access.h |   43 ++++++++++++++++++++-----------------
> > > >  1 file changed, 23 insertions(+), 20 deletions(-)
> > 
>
diff mbox

Patch

diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index ba1530619939..ff013519b9dc 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -17,12 +17,15 @@ 
 #include "hw/virtio/virtio.h"
 #include "exec/address-spaces.h"
 
-static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
+static inline bool virtio_is_big_endian_fast(VirtIODevice *vdev)
 {
+#if defined(TARGET_IS_BIENDIAN) || defined(TARGET_WORDS_BIGENDIAN)
     if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
         /* Devices conforming to VIRTIO 1.0 or later are always LE. */
         return false;
     }
+#endif
+
 #if defined(TARGET_IS_BIENDIAN)
     return virtio_is_big_endian(vdev);
 #elif defined(TARGET_WORDS_BIGENDIAN)
@@ -34,7 +37,7 @@  static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
 
 static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return lduw_be_phys(&address_space_memory, pa);
     }
     return lduw_le_phys(&address_space_memory, pa);
@@ -42,7 +45,7 @@  static inline uint16_t virtio_lduw_phys(VirtIODevice *vdev, hwaddr pa)
 
 static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return ldl_be_phys(&address_space_memory, pa);
     }
     return ldl_le_phys(&address_space_memory, pa);
@@ -50,7 +53,7 @@  static inline uint32_t virtio_ldl_phys(VirtIODevice *vdev, hwaddr pa)
 
 static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return ldq_be_phys(&address_space_memory, pa);
     }
     return ldq_le_phys(&address_space_memory, pa);
@@ -59,7 +62,7 @@  static inline uint64_t virtio_ldq_phys(VirtIODevice *vdev, hwaddr pa)
 static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
                                    uint16_t value)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         stw_be_phys(&address_space_memory, pa, value);
     } else {
         stw_le_phys(&address_space_memory, pa, value);
@@ -69,7 +72,7 @@  static inline void virtio_stw_phys(VirtIODevice *vdev, hwaddr pa,
 static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
                                    uint32_t value)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         stl_be_phys(&address_space_memory, pa, value);
     } else {
         stl_le_phys(&address_space_memory, pa, value);
@@ -78,7 +81,7 @@  static inline void virtio_stl_phys(VirtIODevice *vdev, hwaddr pa,
 
 static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         stw_be_p(ptr, v);
     } else {
         stw_le_p(ptr, v);
@@ -87,7 +90,7 @@  static inline void virtio_stw_p(VirtIODevice *vdev, void *ptr, uint16_t v)
 
 static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         stl_be_p(ptr, v);
     } else {
         stl_le_p(ptr, v);
@@ -96,7 +99,7 @@  static inline void virtio_stl_p(VirtIODevice *vdev, void *ptr, uint32_t v)
 
 static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         stq_be_p(ptr, v);
     } else {
         stq_le_p(ptr, v);
@@ -105,7 +108,7 @@  static inline void virtio_stq_p(VirtIODevice *vdev, void *ptr, uint64_t v)
 
 static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return lduw_be_p(ptr);
     } else {
         return lduw_le_p(ptr);
@@ -114,7 +117,7 @@  static inline int virtio_lduw_p(VirtIODevice *vdev, const void *ptr)
 
 static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return ldl_be_p(ptr);
     } else {
         return ldl_le_p(ptr);
@@ -123,7 +126,7 @@  static inline int virtio_ldl_p(VirtIODevice *vdev, const void *ptr)
 
 static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
 {
-    if (virtio_access_is_big_endian(vdev)) {
+    if (virtio_is_big_endian_fast(vdev)) {
         return ldq_be_p(ptr);
     } else {
         return ldq_le_p(ptr);
@@ -133,18 +136,18 @@  static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
 static inline bool virtio_needs_swap(VirtIODevice *vdev)
 {
 #ifdef HOST_WORDS_BIGENDIAN
-    return virtio_access_is_big_endian(vdev) ? false : true;
+    return virtio_is_big_endian_fast(vdev) ? false : true;
 #else
-    return virtio_access_is_big_endian(vdev) ? true : false;
+    return virtio_is_big_endian_fast(vdev) ? true : false;
 #endif
 }
 
 static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
 {
 #ifdef HOST_WORDS_BIGENDIAN
-    return virtio_access_is_big_endian(vdev) ? s : bswap16(s);
+    return virtio_is_big_endian_fast(vdev) ? s : bswap16(s);
 #else
-    return virtio_access_is_big_endian(vdev) ? bswap16(s) : s;
+    return virtio_is_big_endian_fast(vdev) ? bswap16(s) : s;
 #endif
 }
 
@@ -156,9 +159,9 @@  static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s)
 static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s)
 {
 #ifdef HOST_WORDS_BIGENDIAN
-    return virtio_access_is_big_endian(vdev) ? s : bswap32(s);
+    return virtio_is_big_endian_fast(vdev) ? s : bswap32(s);
 #else
-    return virtio_access_is_big_endian(vdev) ? bswap32(s) : s;
+    return virtio_is_big_endian_fast(vdev) ? bswap32(s) : s;
 #endif
 }
 
@@ -170,9 +173,9 @@  static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s)
 static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s)
 {
 #ifdef HOST_WORDS_BIGENDIAN
-    return virtio_access_is_big_endian(vdev) ? s : bswap64(s);
+    return virtio_is_big_endian_fast(vdev) ? s : bswap64(s);
 #else
-    return virtio_access_is_big_endian(vdev) ? bswap64(s) : s;
+    return virtio_is_big_endian_fast(vdev) ? bswap64(s) : s;
 #endif
 }