<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/arch/x86/include/asm/bitops.h, branch linux-3.15.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.15.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.15.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2013-12-04T22:31:28Z</updated>
<entry>
<title>x86, bitops: Correct the assembly constraints to testing bitops</title>
<updated>2013-12-04T22:31:28Z</updated>
<author>
<name>H. Peter Anvin</name>
</author>
<published>2013-12-04T22:31:28Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e0f6dec35f9286e78879fe1ac92803fd69fc4fdc'/>
<id>urn:sha1:e0f6dec35f9286e78879fe1ac92803fd69fc4fdc</id>
<content type='text'>
In checkin:

0c44c2d0f459 x86: Use asm goto to implement better modify_and_test() functions

the various functions which do modify and test were unified and
optimized using "asm goto".  However, this change missed the detail
that the bitops require an "Ir" constraint rather than an "er"
constraint ("I" = integer constant from 0-31, "e" = signed 32-bit
integer constant).  This would cause code to miscompile if these
functions were used on constant bit positions 32-255 and the build to
fail if used on constant bit positions above 255.

Add the constraints as a parameter to the GEN_BINARY_RMWcc() macro to
avoid this problem.

Reported-by: Jesse Brandeburg &lt;jesse.brandeburg@intel.com&gt;
Signed-off-by: H. Peter Anvin &lt;hpa@linux.intel.com&gt;
Cc: Peter Zijlstra &lt;peterz@infradead.org&gt;
Link: http://lkml.kernel.org/r/529E8719.4070202@zytor.com
</content>
</entry>
<entry>
<title>x86: Use asm goto to implement better modify_and_test() functions</title>
<updated>2013-09-25T11:53:08Z</updated>
<author>
<name>Peter Zijlstra</name>
</author>
<published>2013-09-11T13:19:24Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=0c44c2d0f459cd7e275242b72f500137c4fa834d'/>
<id>urn:sha1:0c44c2d0f459cd7e275242b72f500137c4fa834d</id>
<content type='text'>
Linus suggested using asm goto to get rid of the typical SETcc + TEST
instruction pair -- which also clobbers an extra register -- for our
typical modify_and_test() functions.

Because asm goto doesn't allow output fields it has to include an
unconditinal memory clobber when it changes a memory variable to force
a reload.

Luckily all atomic ops already imply a compiler barrier to go along
with their memory barrier semantics.

Suggested-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Peter Zijlstra &lt;peterz@infradead.org&gt;
Link: http://lkml.kernel.org/n/tip-0mtn9siwbeo1d33bap1422se@git.kernel.org
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
</entry>
<entry>
<title>x86, bitops: Change bitops to be native operand size</title>
<updated>2013-07-16T22:24:04Z</updated>
<author>
<name>H. Peter Anvin</name>
</author>
<published>2013-07-16T22:20:14Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=9b710506a03b01a9fdd83962912bc9d8237b82e8'/>
<id>urn:sha1:9b710506a03b01a9fdd83962912bc9d8237b82e8</id>
<content type='text'>
Change the bitops operation to be naturally "long", i.e. 63 bits on
the 64-bit kernel.  Additional bugs are likely to crop up in the
future.

We already have bugs which machines with &gt; 16 TiB of memory in a
single node, as can happen if memory is interleaved.  The x86 bitop
operations take a signed index, so using an unsigned type is not an
option.

Jim Kukunas measured the effect of this patch on kernel size: it adds
2779 bytes to the allyesconfig kernel.  Some of that probably could be
elided by replacing the inline functions with macros which select the
32-bit type if the index is a 32-bit value, something like:

In that case we could also use "Jr" constraints for the 64-bit
version.

However, this would more than double the amount of code for a
relatively small gain.

Note that we can't use ilog2() for _BITOPS_LONG_SHIFT, as that causes
a recursive header inclusion problem.

The change to constant_test_bit() should both generate better code and
give correct result for negative bit indicies.  As previously written
the compiler had to generate extra code to create the proper wrong
result for negative values.

Signed-off-by: H. Peter Anvin &lt;hpa@linux.intel.com&gt;
Cc: Jim Kukunas &lt;james.t.kukunas@intel.com&gt;
Link: http://lkml.kernel.org/n/tip-z61ofiwe90xeyb461o72h8ya@git.kernel.org
</content>
</entry>
<entry>
<title>x86: Use REP BSF unconditionally</title>
<updated>2012-09-19T15:26:08Z</updated>
<author>
<name>Jan Beulich</name>
</author>
<published>2012-09-18T11:16:14Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e26a44a2d618a491d5c6a2a8aaf66ee03a94739f'/>
<id>urn:sha1:e26a44a2d618a491d5c6a2a8aaf66ee03a94739f</id>
<content type='text'>
Make "REP BSF" unconditional, as per the suggestion of hpa
and Linus, this removes the insane BSF_PREFIX conditional
and simplifies the logic.

Suggested-by: "H. Peter Anvin" &lt;hpa@zytor.com&gt;
Suggested-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Jan Beulich &lt;jbeulich@suse.com&gt;
Link: http://lkml.kernel.org/r/5058741E020000780009C014@nat28.tlf.novell.com
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
</entry>
<entry>
<title>x86: Prefer TZCNT over BFS</title>
<updated>2012-09-13T15:44:01Z</updated>
<author>
<name>Jan Beulich</name>
</author>
<published>2012-09-10T11:24:43Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=5870661c091e827973674cc3469b50c959008c2b'/>
<id>urn:sha1:5870661c091e827973674cc3469b50c959008c2b</id>
<content type='text'>
Following a relatively recent compiler change, make use of the
fact that for non-zero input BSF and TZCNT produce the same
result, and that CPUs not knowing of TZCNT will treat the
instruction as BSF (i.e. ignore what looks like a REP prefix to
them). The assumption here is that TZCNT would never have worse
performance than BSF.

For the moment, only do this when the respective generic-CPU
option is selected (as there are no specific-CPU options
covering the CPUs supporting TZCNT), and don't do that when size
optimization was requested.

Signed-off-by: Jan Beulich &lt;jbeulich@suse.com&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Link: http://lkml.kernel.org/r/504DEA1B020000780009A277@nat28.tlf.novell.com
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
</entry>
<entry>
<title>x86/64: Adjust types of temporaries used by ffs()/fls()/fls64()</title>
<updated>2012-09-13T15:43:58Z</updated>
<author>
<name>Jan Beulich</name>
</author>
<published>2012-09-10T11:04:16Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=1edfbb4153bd29bcf8d2236676238d5237972be1'/>
<id>urn:sha1:1edfbb4153bd29bcf8d2236676238d5237972be1</id>
<content type='text'>
The 64-bit special cases of the former two (the thrird one is
64-bit only anyway) don't need to use "long" temporaries, as the
result will always fit in a 32-bit variable, and the functions
return plain "int". This avoids a few REX prefixes, i.e.
minimally reduces code size.

Signed-off-by: Jan Beulich &lt;jbeulich@suse.com&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Link: http://lkml.kernel.org/r/504DE550020000780009A258@nat28.tlf.novell.com
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
</entry>
<entry>
<title>x86, bitops: note on __test_and_clear_bit atomicity</title>
<updated>2012-06-25T09:38:35Z</updated>
<author>
<name>Michael S. Tsirkin</name>
</author>
<published>2012-06-24T16:24:42Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=d0a69d6321ca759bb8d47803d06ba8571ab42d07'/>
<id>urn:sha1:d0a69d6321ca759bb8d47803d06ba8571ab42d07</id>
<content type='text'>
__test_and_clear_bit is actually atomic with respect
to the local CPU. Add a note saying that KVM on x86
relies on this behaviour so people don't accidentaly break it.
Also warn not to rely on this in portable code.

Signed-off-by: Michael S. Tsirkin &lt;mst@redhat.com&gt;
Signed-off-by: Avi Kivity &lt;avi@redhat.com&gt;
</content>
</entry>
<entry>
<title>x86/bitops: Move BIT_64() for a wider use</title>
<updated>2012-05-23T15:16:42Z</updated>
<author>
<name>Borislav Petkov</name>
</author>
<published>2012-05-22T10:53:45Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=e8f380e00840f694599e6ab42806639f7de26f11'/>
<id>urn:sha1:e8f380e00840f694599e6ab42806639f7de26f11</id>
<content type='text'>
Needed for shifting 64-bit values on 32-bit, like MSR values,
for example.

Signed-off-by: Borislav Petkov &lt;borislav.petkov@amd.com&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Cc: Andrew Morton &lt;akpm@linux-foundation.org&gt;
Cc: Peter Zijlstra &lt;a.p.zijlstra@chello.nl&gt;
Cc: Frank Arnold &lt;frank.arnold@amd.com&gt;
Link: http://lkml.kernel.org/r/1337684026-19740-1-git-send-email-bp@amd64.org
Signed-off-by: Ingo Molnar &lt;mingo@kernel.org&gt;
</content>
</entry>
<entry>
<title>x86_64, asm: Optimise fls(), ffs() and fls64()</title>
<updated>2011-12-15T23:16:49Z</updated>
<author>
<name>David Howells</name>
</author>
<published>2011-12-13T14:56:54Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=ca3d30cc02f780f68771087040ce935add6ba2b7'/>
<id>urn:sha1:ca3d30cc02f780f68771087040ce935add6ba2b7</id>
<content type='text'>
fls(N), ffs(N) and fls64(N) can be optimised on x86_64.  Currently they use a
CMOV instruction after the BSR/BSF to set the destination register to -1 if the
value to be scanned was 0 (in which case BSR/BSF set the Z flag).

Instead, according to the AMD64 specification, we can make use of the fact that
BSR/BSF doesn't modify its output register if its input is 0.  By preloading
the output with -1 and incrementing the result, we achieve the desired result
without the need for a conditional check.

The Intel x86_64 specification, however, says that the result of BSR/BSF in
such a case is undefined.  That said, when queried, one of the Intel CPU
architects said that the behaviour on all Intel CPUs is that:

 (1) with BSRQ/BSFQ, the 64-bit destination register is written with its
     original value if the source is 0, thus, in essence, giving the effect we
     want.  And,

 (2) with BSRL/BSFL, the lower half of the 64-bit destination register is
     written with its original value if the source is 0, and the upper half is
     cleared, thus giving us the effect we want (we return a 4-byte int).

Further, it was indicated that they (Intel) are unlikely to get away with
changing the behaviour.

It might be possible to optimise the 32-bit versions of these functions, but
there's a lot more variation, and so the effective non-destructive property of
BSRL/BSRF cannot be relied on.

[ hpa: specifically, some 486 chips are known to NOT have this property. ]

I have benchmarked these functions on my Core2 Duo test machine using the
following program:

	#include &lt;stdlib.h&gt;
	#include &lt;stdio.h&gt;

	#ifndef __x86_64__
	#error
	#endif

	#define PAGE_SHIFT 12

	typedef unsigned long long __u64, u64;
	typedef unsigned int __u32, u32;
	#define noinline	__attribute__((noinline))

	static __always_inline int fls64(__u64 x)
	{
		long bitpos = -1;

		asm("bsrq %1,%0"
		    : "+r" (bitpos)
		    : "rm" (x));
		return bitpos + 1;
	}

	static inline unsigned long __fls(unsigned long word)
	{
		asm("bsr %1,%0"
		    : "=r" (word)
		    : "rm" (word));
		return word;
	}
	static __always_inline int old_fls64(__u64 x)
	{
		if (x == 0)
			return 0;
		return __fls(x) + 1;
	}

	static noinline // __attribute__((const))
	int old_get_order(unsigned long size)
	{
		int order;

		size = (size - 1) &gt;&gt; (PAGE_SHIFT - 1);
		order = -1;
		do {
			size &gt;&gt;= 1;
			order++;
		} while (size);
		return order;
	}

	static inline __attribute__((const))
	int get_order_old_fls64(unsigned long size)
	{
		int order;
		size--;
		size &gt;&gt;= PAGE_SHIFT;
		order = old_fls64(size);
		return order;
	}

	static inline __attribute__((const))
	int get_order(unsigned long size)
	{
		int order;
		size--;
		size &gt;&gt;= PAGE_SHIFT;
		order = fls64(size);
		return order;
	}

	unsigned long prevent_optimise_out;

	static noinline unsigned long test_old_get_order(void)
	{
		unsigned long n, total = 0;
		long rep, loop;

		for (rep = 1000000; rep &gt; 0; rep--) {
			for (loop = 0; loop &lt;= 16384; loop += 4) {
				n = 1UL &lt;&lt; loop;
				total += old_get_order(n);
			}
		}
		return total;
	}

	static noinline unsigned long test_get_order_old_fls64(void)
	{
		unsigned long n, total = 0;
		long rep, loop;

		for (rep = 1000000; rep &gt; 0; rep--) {
			for (loop = 0; loop &lt;= 16384; loop += 4) {
				n = 1UL &lt;&lt; loop;
				total += get_order_old_fls64(n);
			}
		}
		return total;
	}

	static noinline unsigned long test_get_order(void)
	{
		unsigned long n, total = 0;
		long rep, loop;

		for (rep = 1000000; rep &gt; 0; rep--) {
			for (loop = 0; loop &lt;= 16384; loop += 4) {
				n = 1UL &lt;&lt; loop;
				total += get_order(n);
			}
		}
		return total;
	}

	int main(int argc, char **argv)
	{
		unsigned long total;

		switch (argc) {
		case 1:  total = test_old_get_order();		break;
		case 2:  total = test_get_order_old_fls64();	break;
		default: total = test_get_order();		break;
		}
		prevent_optimise_out = total;
		return 0;
	}

This allows me to test the use of the old fls64() implementation and the new
fls64() implementation and also to contrast these to the out-of-line loop-based
implementation of get_order().  The results were:

	warthog&gt;time ./get_order
	real    1m37.191s
	user    1m36.313s
	sys     0m0.861s
	warthog&gt;time ./get_order x
	real    0m16.892s
	user    0m16.586s
	sys     0m0.287s
	warthog&gt;time ./get_order x x
	real    0m7.731s
	user    0m7.727s
	sys     0m0.002s

Using the current upstream fls64() as a basis for an inlined get_order() [the
second result above] is much faster than using the current out-of-line
loop-based get_order() [the first result above].

Using my optimised inline fls64()-based get_order() [the third result above]
is even faster still.

[ hpa: changed the selection of 32 vs 64 bits to use CONFIG_X86_64
  instead of comparing BITS_PER_LONG, updated comments, rebased manually
  on top of 83d99df7c4bf x86, bitops: Move fls64.h inside __KERNEL__ ]

Signed-off-by: David Howells &lt;dhowells@redhat.com&gt;
Link: http://lkml.kernel.org/r/20111213145654.14362.39868.stgit@warthog.procyon.org.uk
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: H. Peter Anvin &lt;hpa@linux.intel.com&gt;
</content>
</entry>
<entry>
<title>x86, bitops: Move fls64.h inside __KERNEL__</title>
<updated>2011-12-15T23:04:07Z</updated>
<author>
<name>H. Peter Anvin</name>
</author>
<published>2011-12-15T22:55:53Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=83d99df7c4bf37176d8c7b199e3b129a51fa04c8'/>
<id>urn:sha1:83d99df7c4bf37176d8c7b199e3b129a51fa04c8</id>
<content type='text'>
We would include &lt;asm-generic/bitops/fls64.h&gt; even without __KERNEL__,
but that doesn't make sense, as:

1. That file provides fls64(), but the corresponding function fls() is
   not exported to user space.
2. The implementation of fls64.h uses kernel-only symbols.
3. fls64.h is not exported to user space.

This appears to have been a bug introduced in checkin:

d57594c203b1 bitops: use __fls for fls64 on 64-bit archs

Cc: Stephen Hemminger &lt;shemminger@vyatta.com&gt;
Cc: Alexander van Heukelum &lt;heukelum@mailshack.com&gt;
Cc: David Howells &lt;dhowells@redhat.com&gt;
Signed-off-by: H. Peter Anvin &lt;hpa@zytor.com&gt;
Link: http://lkml.kernel.org/r/4EEA77E1.6050009@zytor.com
</content>
</entry>
</feed>
