diff mbox series

[v5,3/6] bswap: Add the ability to store to an unaligned 24 bit field

Message ID 20230423162013.4535-4-Jonathan.Cameron@huawei.com
State Superseded
Headers show
Series hw/cxl: Poison get, inject, clear | expand

Commit Message

Jonathan Cameron April 23, 2023, 4:20 p.m. UTC
From: Ira Weiny <ira.weiny@intel.com>

CXL has 24 bit unaligned fields which need to be stored to.  CXL is
specified as little endian.

Define st24_le_p() and the supporting functions to store such a field
from a 32 bit host native value.

The use of b, w, l, q as the size specifier is limiting.  So "24" was
used for the size part of the function name.

Reviewed-by: Fan Ni <fan.ni@samsung.com>
Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

---
v5:
  - Added assertion that upper bits of the input parameter aren't set.
  - Mask value in bswap24s()
  - update docs
---
 docs/devel/loads-stores.rst |  1 +
 include/qemu/bswap.h        | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

Comments

Jonathan Cameron May 19, 2023, 11:33 a.m. UTC | #1
On Sun, 23 Apr 2023 17:20:10 +0100
Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote:

> From: Ira Weiny <ira.weiny@intel.com>
> 
> CXL has 24 bit unaligned fields which need to be stored to.  CXL is
> specified as little endian.
> 
> Define st24_le_p() and the supporting functions to store such a field
> from a 32 bit host native value.
> 
> The use of b, w, l, q as the size specifier is limiting.  So "24" was
> used for the size part of the function name.
> 
> Reviewed-by: Fan Ni <fan.ni@samsung.com>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

This doesn't work for s390 (probably big endian hosts in general)

I'll post a new version of the series with adjusted logic shortly. 
I think all we can do is special case the 24 bit logic in the block
dealing with big vs little endian accessors.

Something like the following.
I'll drop Fan's tag as this is a substantial change. Fan, if you can
take a look at v6 when I post it that would be great.

I'm having issues with gitlab CI minutes running out on my fork.
Hopefully I can get that resolved and test this properly. 

diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 91ed9c7e2c..f546b1fc06 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -40,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
 #if HOST_BIG_ENDIAN
 #define be_bswap(v, size) (v)
 #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
+#define le_bswap24(v) bswap24(v)
 #define be_bswaps(v, size)
 #define le_bswaps(p, size) \
             do { *p = glue(__builtin_bswap, size)(*p); } while (0)
 #else
 #define le_bswap(v, size) (v)
+#define le_bswap24(v) (v)
 #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
 #define le_bswaps(v, size)
 #define be_bswaps(p, size) \
@@ -319,7 +321,7 @@ static inline void stw_le_p(void *ptr, uint16_t v)

 static inline void st24_le_p(void *ptr, uint32_t v)
 {
-    st24_he_p(ptr, le_bswap(v, 24));
+    st24_he_p(ptr, le_bswap24(v));
 }

 static inline void stl_le_p(void *ptr, uint32_t v)

> 
> ---
> v5:
>   - Added assertion that upper bits of the input parameter aren't set.
>   - Mask value in bswap24s()
>   - update docs
> ---
>  docs/devel/loads-stores.rst |  1 +
>  include/qemu/bswap.h        | 25 +++++++++++++++++++++++++
>  2 files changed, 26 insertions(+)
> 
> diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> index ad5dfe133e..57b4396f7a 100644
> --- a/docs/devel/loads-stores.rst
> +++ b/docs/devel/loads-stores.rst
> @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
>  ``size``
>   - ``b`` : 8 bits
>   - ``w`` : 16 bits
> + - ``24`` : 24 bits
>   - ``l`` : 32 bits
>   - ``q`` : 64 bits
>  
> diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
> index 15a78c0db5..91ed9c7e2c 100644
> --- a/include/qemu/bswap.h
> +++ b/include/qemu/bswap.h
> @@ -8,11 +8,25 @@
>  #undef  bswap64
>  #define bswap64(_x) __builtin_bswap64(_x)
>  
> +static inline uint32_t bswap24(uint32_t x)
> +{
> +    assert((x & 0xff000000U) == 0);
> +
> +    return (((x & 0x000000ffU) << 16) |
> +            ((x & 0x0000ff00U) <<  0) |
> +            ((x & 0x00ff0000U) >> 16));
> +}
> +
>  static inline void bswap16s(uint16_t *s)
>  {
>      *s = __builtin_bswap16(*s);
>  }
>  
> +static inline void bswap24s(uint32_t *s)
> +{
> +    *s = bswap24(*s & 0x00ffffffU);
> +}
> +
>  static inline void bswap32s(uint32_t *s)
>  {
>      *s = __builtin_bswap32(*s);
> @@ -176,6 +190,7 @@ CPU_CONVERT(le, 64, uint64_t)
>   * size is:
>   *   b: 8 bits
>   *   w: 16 bits
> + *   24: 24 bits
>   *   l: 32 bits
>   *   q: 64 bits
>   *
> @@ -248,6 +263,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
>      __builtin_memcpy(ptr, &v, sizeof(v));
>  }
>  
> +static inline void st24_he_p(void *ptr, uint32_t v)
> +{
> +    __builtin_memcpy(ptr, &v, 3);
> +}
> +
>  static inline int ldl_he_p(const void *ptr)
>  {
>      int32_t r;
> @@ -297,6 +317,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
>      stw_he_p(ptr, le_bswap(v, 16));
>  }
>  
> +static inline void st24_le_p(void *ptr, uint32_t v)
> +{
> +    st24_he_p(ptr, le_bswap(v, 24));
> +}
> +
>  static inline void stl_le_p(void *ptr, uint32_t v)
>  {
>      stl_he_p(ptr, le_bswap(v, 32));
Jonathan Cameron May 19, 2023, 1:42 p.m. UTC | #2
On Fri, 19 May 2023 12:33:53 +0100
Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote:

> On Sun, 23 Apr 2023 17:20:10 +0100
> Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote:
> 
> > From: Ira Weiny <ira.weiny@intel.com>
> > 
> > CXL has 24 bit unaligned fields which need to be stored to.  CXL is
> > specified as little endian.
> > 
> > Define st24_le_p() and the supporting functions to store such a field
> > from a 32 bit host native value.
> > 
> > The use of b, w, l, q as the size specifier is limiting.  So "24" was
> > used for the size part of the function name.
> > 
> > Reviewed-by: Fan Ni <fan.ni@samsung.com>
> > Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> > Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>  
> 
> This doesn't work for s390 (probably big endian hosts in general)
> 
> I'll post a new version of the series with adjusted logic shortly. 
> I think all we can do is special case the 24 bit logic in the block
> dealing with big vs little endian accessors.
> 
> Something like the following.
> I'll drop Fan's tag as this is a substantial change. Fan, if you can
> take a look at v6 when I post it that would be great.
> 
> I'm having issues with gitlab CI minutes running out on my fork.
> Hopefully I can get that resolved and test this properly. 

Got this tested using a cross compile in docker via
make docker-test-build@debian-x390x-cross

and a bunch of docker config.

Anyhow, will send out new version of patches 3-6 shortly. 

Thanks,

Jonathan

> 
> diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
> index 91ed9c7e2c..f546b1fc06 100644
> --- a/include/qemu/bswap.h
> +++ b/include/qemu/bswap.h
> @@ -40,11 +40,13 @@ static inline void bswap64s(uint64_t *s)
>  #if HOST_BIG_ENDIAN
>  #define be_bswap(v, size) (v)
>  #define le_bswap(v, size) glue(__builtin_bswap, size)(v)
> +#define le_bswap24(v) bswap24(v)
>  #define be_bswaps(v, size)
>  #define le_bswaps(p, size) \
>              do { *p = glue(__builtin_bswap, size)(*p); } while (0)
>  #else
>  #define le_bswap(v, size) (v)
> +#define le_bswap24(v) (v)
>  #define be_bswap(v, size) glue(__builtin_bswap, size)(v)
>  #define le_bswaps(v, size)
>  #define be_bswaps(p, size) \
> @@ -319,7 +321,7 @@ static inline void stw_le_p(void *ptr, uint16_t v)
> 
>  static inline void st24_le_p(void *ptr, uint32_t v)
>  {
> -    st24_he_p(ptr, le_bswap(v, 24));
> +    st24_he_p(ptr, le_bswap24(v));
>  }
> 
>  static inline void stl_le_p(void *ptr, uint32_t v)
> 
> > 
> > ---
> > v5:
> >   - Added assertion that upper bits of the input parameter aren't set.
> >   - Mask value in bswap24s()
> >   - update docs
> > ---
> >  docs/devel/loads-stores.rst |  1 +
> >  include/qemu/bswap.h        | 25 +++++++++++++++++++++++++
> >  2 files changed, 26 insertions(+)
> > 
> > diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
> > index ad5dfe133e..57b4396f7a 100644
> > --- a/docs/devel/loads-stores.rst
> > +++ b/docs/devel/loads-stores.rst
> > @@ -36,6 +36,7 @@ store: ``st{size}_{endian}_p(ptr, val)``
> >  ``size``
> >   - ``b`` : 8 bits
> >   - ``w`` : 16 bits
> > + - ``24`` : 24 bits
> >   - ``l`` : 32 bits
> >   - ``q`` : 64 bits
> >  
> > diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
> > index 15a78c0db5..91ed9c7e2c 100644
> > --- a/include/qemu/bswap.h
> > +++ b/include/qemu/bswap.h
> > @@ -8,11 +8,25 @@
> >  #undef  bswap64
> >  #define bswap64(_x) __builtin_bswap64(_x)
> >  
> > +static inline uint32_t bswap24(uint32_t x)
> > +{
> > +    assert((x & 0xff000000U) == 0);
> > +
> > +    return (((x & 0x000000ffU) << 16) |
> > +            ((x & 0x0000ff00U) <<  0) |
> > +            ((x & 0x00ff0000U) >> 16));
> > +}
> > +
> >  static inline void bswap16s(uint16_t *s)
> >  {
> >      *s = __builtin_bswap16(*s);
> >  }
> >  
> > +static inline void bswap24s(uint32_t *s)
> > +{
> > +    *s = bswap24(*s & 0x00ffffffU);
> > +}
> > +
> >  static inline void bswap32s(uint32_t *s)
> >  {
> >      *s = __builtin_bswap32(*s);
> > @@ -176,6 +190,7 @@ CPU_CONVERT(le, 64, uint64_t)
> >   * size is:
> >   *   b: 8 bits
> >   *   w: 16 bits
> > + *   24: 24 bits
> >   *   l: 32 bits
> >   *   q: 64 bits
> >   *
> > @@ -248,6 +263,11 @@ static inline void stw_he_p(void *ptr, uint16_t v)
> >      __builtin_memcpy(ptr, &v, sizeof(v));
> >  }
> >  
> > +static inline void st24_he_p(void *ptr, uint32_t v)
> > +{
> > +    __builtin_memcpy(ptr, &v, 3);
> > +}
> > +
> >  static inline int ldl_he_p(const void *ptr)
> >  {
> >      int32_t r;
> > @@ -297,6 +317,11 @@ static inline void stw_le_p(void *ptr, uint16_t v)
> >      stw_he_p(ptr, le_bswap(v, 16));
> >  }
> >  
> > +static inline void st24_le_p(void *ptr, uint32_t v)
> > +{
> > +    st24_he_p(ptr, le_bswap(v, 24));
> > +}
> > +
> >  static inline void stl_le_p(void *ptr, uint32_t v)
> >  {
> >      stl_he_p(ptr, le_bswap(v, 32));  
> 
>
diff mbox series

Patch

diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst
index ad5dfe133e..57b4396f7a 100644
--- a/docs/devel/loads-stores.rst
+++ b/docs/devel/loads-stores.rst
@@ -36,6 +36,7 @@  store: ``st{size}_{endian}_p(ptr, val)``
 ``size``
  - ``b`` : 8 bits
  - ``w`` : 16 bits
+ - ``24`` : 24 bits
  - ``l`` : 32 bits
  - ``q`` : 64 bits
 
diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h
index 15a78c0db5..91ed9c7e2c 100644
--- a/include/qemu/bswap.h
+++ b/include/qemu/bswap.h
@@ -8,11 +8,25 @@ 
 #undef  bswap64
 #define bswap64(_x) __builtin_bswap64(_x)
 
+static inline uint32_t bswap24(uint32_t x)
+{
+    assert((x & 0xff000000U) == 0);
+
+    return (((x & 0x000000ffU) << 16) |
+            ((x & 0x0000ff00U) <<  0) |
+            ((x & 0x00ff0000U) >> 16));
+}
+
 static inline void bswap16s(uint16_t *s)
 {
     *s = __builtin_bswap16(*s);
 }
 
+static inline void bswap24s(uint32_t *s)
+{
+    *s = bswap24(*s & 0x00ffffffU);
+}
+
 static inline void bswap32s(uint32_t *s)
 {
     *s = __builtin_bswap32(*s);
@@ -176,6 +190,7 @@  CPU_CONVERT(le, 64, uint64_t)
  * size is:
  *   b: 8 bits
  *   w: 16 bits
+ *   24: 24 bits
  *   l: 32 bits
  *   q: 64 bits
  *
@@ -248,6 +263,11 @@  static inline void stw_he_p(void *ptr, uint16_t v)
     __builtin_memcpy(ptr, &v, sizeof(v));
 }
 
+static inline void st24_he_p(void *ptr, uint32_t v)
+{
+    __builtin_memcpy(ptr, &v, 3);
+}
+
 static inline int ldl_he_p(const void *ptr)
 {
     int32_t r;
@@ -297,6 +317,11 @@  static inline void stw_le_p(void *ptr, uint16_t v)
     stw_he_p(ptr, le_bswap(v, 16));
 }
 
+static inline void st24_le_p(void *ptr, uint32_t v)
+{
+    st24_he_p(ptr, le_bswap(v, 24));
+}
+
 static inline void stl_le_p(void *ptr, uint32_t v)
 {
     stl_he_p(ptr, le_bswap(v, 32));