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

Re: [PATCH v3 16/34] xen/lib: introduce generic find next bit operations



On Tue, 2024-01-23 at 12:14 +0100, Jan Beulich wrote:
> On 22.12.2023 16:13, Oleksii Kurochko wrote:
> > --- a/xen/arch/riscv/include/asm/fence.h
> > +++ b/xen/arch/riscv/include/asm/fence.h
> > @@ -1,4 +1,4 @@
> > -/* SPDX-License-Identifier: GPL-2.0-or-later */
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> >  #ifndef _ASM_RISCV_FENCE_H
> >  #define _ASM_RISCV_FENCE_H
> >  
> > @@ -11,3 +11,12 @@
> >  #endif
> >  
> >  #endif     /* _ASM_RISCV_FENCE_H */
> > +
> > +/*
> > + * Local variables:
> > + * mode: C
> > + * c-file-style: "BSD"
> > + * c-basic-offset: 4
> > + * indent-tabs-mode: nil
> > + * End:
> > + */
> 
> Surely all of this wants doing in the previous patch, where the
> header
> is introduced?
Yes, it should be in the previous patch. I'll do the proper rebase.

> 
> > --- a/xen/common/Kconfig
> > +++ b/xen/common/Kconfig
> > @@ -47,6 +47,9 @@ config ARCH_MAP_DOMAIN_PAGE
> >  config GENERIC_BUG_FRAME
> >     bool
> >  
> > +config GENERIC_FIND_NEXT_BIT
> > +   bool
> 
> There's no need for this, as ...
> 
> > --- a/xen/lib/Makefile
> > +++ b/xen/lib/Makefile
> > @@ -3,6 +3,7 @@ obj-$(CONFIG_X86) += x86/
> >  lib-y += bsearch.o
> >  lib-y += ctors.o
> >  lib-y += ctype.o
> > +lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find-next-bit.o
> 
> ... you're moving this to lib/. Or have you encountered any issue
> with building this uniformly, and you forgot to mention this in
> the description?
I didn't check. My intention was to provide opportunity to check if an
architecture want to use generic version or not. Otherwise, I expected
that we will have multiple definiotion of the funcion.

But considering that they are all defined under #ifdef...#endif we can
remove the declaration of the config GENERIC_FIND_NEXT_BIT.
> 
> > --- /dev/null
> > +++ b/xen/lib/find-next-bit.c
> > @@ -0,0 +1,281 @@
> > +/* find_next_bit.c: fallback find next bit implementation
> > + *
> > + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
> > + * Written by David Howells (dhowells@xxxxxxxxxx)
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License
> > + * as published by the Free Software Foundation; either version
> > + * 2 of the License, or (at your option) any later version.
> > + */
> > +#include <xen/bitops.h>
> > +
> > +#include <asm/byteorder.h>
> > +
> > +#ifndef find_next_bit
> > +/*
> > + * Find the next set bit in a memory region.
> > + */
> > +unsigned long find_next_bit(const unsigned long *addr, unsigned
> > long size,
> > +                       unsigned long offset)
> > +{
> > +   const unsigned long *p = addr + BIT_WORD(offset);
> > +   unsigned long result = offset & ~(BITS_PER_LONG-1);
> > +   unsigned long tmp;
> > +
> > +   if (offset >= size)
> > +           return size;
> > +   size -= result;
> > +   offset %= BITS_PER_LONG;
> > +   if (offset) {
> > +           tmp = *(p++);
> > +           tmp &= (~0UL << offset);
> > +           if (size < BITS_PER_LONG)
> > +                   goto found_first;
> > +           if (tmp)
> > +                   goto found_middle;
> > +           size -= BITS_PER_LONG;
> > +           result += BITS_PER_LONG;
> > +   }
> > +   while (size & ~(BITS_PER_LONG-1)) {
> > +           if ((tmp = *(p++)))
> > +                   goto found_middle;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +   tmp = *p;
> > +
> > +found_first:
> > +   tmp &= (~0UL >> (BITS_PER_LONG - size));
> > +   if (tmp == 0UL)         /* Are any bits set? */
> > +           return result + size;   /* Nope. */
> > +found_middle:
> > +   return result + __ffs(tmp);
> > +}
> > +EXPORT_SYMBOL(find_next_bit);
> > +#endif
> > +
> > +#ifndef find_next_zero_bit
> > +/*
> > + * This implementation of find_{first,next}_zero_bit was stolen
> > from
> > + * Linus' asm-alpha/bitops.h.
> > + */
> > +unsigned long find_next_zero_bit(const unsigned long *addr,
> > unsigned long size,
> > +                            unsigned long offset)
> > +{
> > +   const unsigned long *p = addr + BIT_WORD(offset);
> > +   unsigned long result = offset & ~(BITS_PER_LONG-1);
> > +   unsigned long tmp;
> > +
> > +   if (offset >= size)
> > +           return size;
> > +   size -= result;
> > +   offset %= BITS_PER_LONG;
> > +   if (offset) {
> > +           tmp = *(p++);
> > +           tmp |= ~0UL >> (BITS_PER_LONG - offset);
> > +           if (size < BITS_PER_LONG)
> > +                   goto found_first;
> > +           if (~tmp)
> > +                   goto found_middle;
> > +           size -= BITS_PER_LONG;
> > +           result += BITS_PER_LONG;
> > +   }
> > +   while (size & ~(BITS_PER_LONG-1)) {
> > +           if (~(tmp = *(p++)))
> > +                   goto found_middle;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +   tmp = *p;
> > +
> > +found_first:
> > +   tmp |= ~0UL << size;
> > +   if (tmp == ~0UL)        /* Are any bits zero? */
> > +           return result + size;   /* Nope. */
> > +found_middle:
> > +   return result + ffz(tmp);
> > +}
> > +EXPORT_SYMBOL(find_next_zero_bit);
> > +#endif
> > +
> > +#ifndef find_first_bit
> > +/*
> > + * Find the first set bit in a memory region.
> > + */
> > +unsigned long find_first_bit(const unsigned long *addr, unsigned
> > long size)
> > +{
> > +   const unsigned long *p = addr;
> > +   unsigned long result = 0;
> > +   unsigned long tmp;
> > +
> > +   while (size & ~(BITS_PER_LONG-1)) {
> > +           if ((tmp = *(p++)))
> > +                   goto found;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +
> > +   tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
> > +   if (tmp == 0UL)         /* Are any bits set? */
> > +           return result + size;   /* Nope. */
> > +found:
> > +   return result + __ffs(tmp);
> > +}
> > +EXPORT_SYMBOL(find_first_bit);
> > +#endif
> > +
> > +#ifndef find_first_zero_bit
> > +/*
> > + * Find the first cleared bit in a memory region.
> > + */
> > +unsigned long find_first_zero_bit(const unsigned long *addr,
> > unsigned long size)
> > +{
> > +   const unsigned long *p = addr;
> > +   unsigned long result = 0;
> > +   unsigned long tmp;
> > +
> > +   while (size & ~(BITS_PER_LONG-1)) {
> > +           if (~(tmp = *(p++)))
> > +                   goto found;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +
> > +   tmp = (*p) | (~0UL << size);
> > +   if (tmp == ~0UL)        /* Are any bits zero? */
> > +           return result + size;   /* Nope. */
> > +found:
> > +   return result + ffz(tmp);
> > +}
> > +EXPORT_SYMBOL(find_first_zero_bit);
> > +#endif
> > +
> > +#ifdef __BIG_ENDIAN
> > +
> > +/* include/linux/byteorder does not support "unsigned long" type
> > */
> > +static inline unsigned long ext2_swabp(const unsigned long * x)
> > +{
> > +#if BITS_PER_LONG == 64
> > +   return (unsigned long) __swab64p((u64 *) x);
> > +#elif BITS_PER_LONG == 32
> > +   return (unsigned long) __swab32p((u32 *) x);
> > +#else
> > +#error BITS_PER_LONG not defined
> > +#endif
> > +}
> > +
> > +/* include/linux/byteorder doesn't support "unsigned long" type */
> > +static inline unsigned long ext2_swab(const unsigned long y)
> > +{
> > +#if BITS_PER_LONG == 64
> > +   return (unsigned long) __swab64((u64) y);
> > +#elif BITS_PER_LONG == 32
> > +   return (unsigned long) __swab32((u32) y);
> > +#else
> > +#error BITS_PER_LONG not defined
> > +#endif
> > +}
> > +
> > +#ifndef find_next_zero_bit_le
> > +unsigned long find_next_zero_bit_le(const void *addr, unsigned
> > +           long size, unsigned long offset)
> > +{
> > +   const unsigned long *p = addr;
> > +   unsigned long result = offset & ~(BITS_PER_LONG - 1);
> > +   unsigned long tmp;
> > +
> > +   if (offset >= size)
> > +           return size;
> > +   p += BIT_WORD(offset);
> > +   size -= result;
> > +   offset &= (BITS_PER_LONG - 1UL);
> > +   if (offset) {
> > +           tmp = ext2_swabp(p++);
> > +           tmp |= (~0UL >> (BITS_PER_LONG - offset));
> > +           if (size < BITS_PER_LONG)
> > +                   goto found_first;
> > +           if (~tmp)
> > +                   goto found_middle;
> > +           size -= BITS_PER_LONG;
> > +           result += BITS_PER_LONG;
> > +   }
> > +
> > +   while (size & ~(BITS_PER_LONG - 1)) {
> > +           if (~(tmp = *(p++)))
> > +                   goto found_middle_swap;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +   tmp = ext2_swabp(p);
> > +found_first:
> > +   tmp |= ~0UL << size;
> > +   if (tmp == ~0UL)        /* Are any bits zero? */
> > +           return result + size; /* Nope. Skip ffz */
> > +found_middle:
> > +   return result + ffz(tmp);
> > +
> > +found_middle_swap:
> > +   return result + ffz(ext2_swab(tmp));
> > +}
> > +EXPORT_SYMBOL(find_next_zero_bit_le);
> > +#endif
> > +
> > +#ifndef find_next_bit_le
> > +unsigned long find_next_bit_le(const void *addr, unsigned
> > +           long size, unsigned long offset)
> > +{
> > +   const unsigned long *p = addr;
> > +   unsigned long result = offset & ~(BITS_PER_LONG - 1);
> > +   unsigned long tmp;
> > +
> > +   if (offset >= size)
> > +           return size;
> > +   p += BIT_WORD(offset);
> > +   size -= result;
> > +   offset &= (BITS_PER_LONG - 1UL);
> > +   if (offset) {
> > +           tmp = ext2_swabp(p++);
> > +           tmp &= (~0UL << offset);
> > +           if (size < BITS_PER_LONG)
> > +                   goto found_first;
> > +           if (tmp)
> > +                   goto found_middle;
> > +           size -= BITS_PER_LONG;
> > +           result += BITS_PER_LONG;
> > +   }
> > +
> > +   while (size & ~(BITS_PER_LONG - 1)) {
> > +           tmp = *(p++);
> > +           if (tmp)
> > +                   goto found_middle_swap;
> > +           result += BITS_PER_LONG;
> > +           size -= BITS_PER_LONG;
> > +   }
> > +   if (!size)
> > +           return result;
> > +   tmp = ext2_swabp(p);
> > +found_first:
> > +   tmp &= (~0UL >> (BITS_PER_LONG - size));
> > +   if (tmp == 0UL)         /* Are any bits set? */
> > +           return result + size; /* Nope. */
> > +found_middle:
> > +   return result + __ffs(tmp);
> > +
> > +found_middle_swap:
> > +   return result + __ffs(ext2_swab(tmp));
> > +}
> > +EXPORT_SYMBOL(find_next_bit_le);
> > +#endif
> > +
> > +#endif /* __BIG_ENDIAN */
> 
> I was going to ask that you convince git to actually present a proper
> diff, to make visible what changes. But other than the description
> says
> you don't really move the file, you copy it. Judging from further
> titles
> there's also nowhere you'd make Arm actually use this now generic
> code.
I wanted to do it separately, outside this patch series to simplify
review and not have Arm specific changes in RISC-V patch series.

Regarding a proper diff, you would like me to make git shows that it
was copy from Arm and it is not newly created file. Am I understand you
correctly?

~ Oleksii



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.