[s390x] Add missing condition code clobbers to inline assembly

For x86, GCC will assume that any inline assembly instruction clobbers
the condition code and so it is not necessary to explicitly include
"cc" within the clobber list.

For s390x, GCC will assume that the condition code is preserved unless
explicitly clobbered.  It is extremely rare for GCC to emit code that
actually relies upon this behaviour, but it has been observed to
happen within a series of memcpy() calls with condition-dependent
source addresses.

Fix by adding "cc" to the clobber list on all inline assembly blocks
where the condition code is not guaranteed to be preserved.

It would be possible to use "=@cc" as an output constraint to obtain
the carry result from bigint_add() and bigint_subtract(), but the
instructions generated by GCC to extract the condition code end up
being larger than the single "alcr"/"slbr" that we currently use to
obtain the carry result.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2026-08-21 11:47:52 +01:00
parent e6d0a97c05
commit 87a2016ddd
9 changed files with 37 additions and 21 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ int facility_is_installed ( unsigned int facility ) {
memset ( &facilities, 0, sizeof ( facilities ) );
max = ( ( sizeof ( facilities.mask ) /
sizeof ( facilities.mask[0] ) ) - 1 );
__asm__ ( "stfle %0" : "=R" ( facilities ), "+r" ( max ) );
__asm__ ( "stfle %0" : "=R" ( facilities ), "+r" ( max ) : : "cc" );
DBGC ( &facilities, "FACILITY %016llx:%016llx:%016llx:%016llx\n",
facilities.mask[0], facilities.mask[1], facilities.mask[2],
facilities.mask[3] );
+4 -2
View File
@@ -69,7 +69,8 @@ static int prno_entropy_enable ( void ) {
"=a" ( dummy2 ),
"=m" ( params )
: "0" ( PRNO_FN_QUERY ),
"1" ( &params ) );
"1" ( &params )
: "cc" );
if ( ! prno_is_supported ( &params.supported, PRNO_FN_TRNG ) ) {
DBGC ( colour, "PRNO does not support TRNG (%016llx:%016llx)\n",
params.supported.mask[0], params.supported.mask[1] );
@@ -111,7 +112,8 @@ static int prno_get_noise ( noise_sample_t *noise ) {
"+a" ( raw ),
"+a" ( conditioned ),
"=m" ( *noise )
: "0" ( PRNO_FN_TRNG ) );
: "0" ( PRNO_FN_TRNG )
: "cc" );
return 0;
}
+14 -7
View File
@@ -46,7 +46,8 @@ bigint_add_raw ( const unsigned long *addend0, unsigned long *value0,
"=&r" ( index_carry ),
"+S" ( *value )
: "S" ( *addend ),
"2" ( size ) );
"2" ( size )
: "cc" );
return index_carry;
}
@@ -86,7 +87,8 @@ bigint_subtract_raw ( const unsigned long *subtrahend0, unsigned long *value0,
"=&r" ( index_borrow ),
"+S" ( *value )
: "S" ( *subtrahend ),
"2" ( size ) );
"2" ( size )
: "cc" );
return ( -index_borrow );
}
@@ -122,7 +124,8 @@ bigint_shl_raw ( unsigned long *value0, unsigned int size ) {
"+S" ( *value )
: "0" ( 0UL ),
"2" ( size ),
"3" ( 0U ) );
"3" ( 0U )
: "cc" );
return carry;
}
@@ -155,7 +158,8 @@ bigint_shr_raw ( unsigned long *value0, unsigned int size ) {
"=&r" ( carry ),
"+S" ( *value )
: "0" ( sizeof ( *value ) ),
"2" ( 0 ) );
"2" ( 0 )
: "cc" );
return ( carry & 1 );
}
@@ -183,7 +187,8 @@ bigint_grow_raw ( const unsigned long *source0, unsigned int source_size,
"mvcle %0, %1, 0\n\t"
"jo 1b\n\t"
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest )
: "m" ( *source ) );
: "m" ( *source )
: "cc" );
}
/**
@@ -209,7 +214,8 @@ bigint_shrink_raw ( const unsigned long *source0, unsigned int source_size,
"mvcle %0, %1, 0\n\t"
"jo 1b\n\t"
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dest )
: "m" ( *source ) );
: "m" ( *source )
: "cc" );
}
/**
@@ -242,7 +248,8 @@ bigint_multiply_one ( const unsigned long multiplicand,
"+T" ( *result ),
"+r" ( *carry )
: "r" ( multiplicand ),
"r" ( multiplier ) );
"r" ( multiplier )
: "cc" );
}
#endif /* _BITS_BIGINT_H */
+4 -2
View File
@@ -29,7 +29,8 @@ test_and_set_bit ( unsigned int bit, volatile void *bits ) {
__asm__ __volatile__ ( "lao %0, %2, %1"
: "=r" ( old ), "+S" ( *word )
: "r" ( mask ) );
: "r" ( mask )
: "cc" );
return ( !! ( old & mask ) );
}
@@ -51,7 +52,8 @@ test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
__asm__ __volatile__ ( "lan %0, %2, %1"
: "=r" ( old ), "+S" ( *word )
: "r" ( ~mask ) );
: "r" ( ~mask )
: "cc" );
return ( !! ( old & mask ) );
}
+1 -1
View File
@@ -21,7 +21,7 @@ profile_timestamp ( void ) {
uint64_t cycles;
/* Read timestamp counter */
__asm__ ( "stckf %0" : "=Q" ( cycles ) );
__asm__ ( "stckf %0" : "=Q" ( cycles ) : : "cc" );
return cycles;
}
+8 -4
View File
@@ -34,21 +34,24 @@ memset ( void *dest, int character, size_t len ) {
/* Constant small length, zeroing: use XOR-in-place */
__asm__ ( "xc %O0(%1, %R0), %0"
: "=Q" ( *dmem )
: "i" ( len ) );
: "i" ( len )
: "cc" );
} else if ( __builtin_constant_p ( character ) ) {
/* Constant fill character: use "mvcle" with an immediate */
__asm__ ( "\n1:\n\t"
"mvcle %0, %2, %3\n\t"
"jo 1b\n\t"
: "+r" ( dpair ), "=m" ( *dmem )
: "r" ( spair ), "i" ( character ) );
: "r" ( spair ), "i" ( character )
: "cc" );
} else {
/* Variable fill character: use "mvcle" with a register */
__asm__ ( "\n1:\n\t"
"mvcle %0, %2, 0(%3)\n\t"
"jo 1b\n\t"
: "+r" ( dpair ), "=m" ( *dmem )
: "r" ( spair ), "a" ( character ) );
: "r" ( spair ), "a" ( character )
: "cc" );
}
return dest;
@@ -82,7 +85,8 @@ memcpy ( void *dest, const void *src, size_t len ) {
"mvcle %0, %1, 0\n\t"
"jo 1b\n\t"
: "+r" ( dpair ), "+r" ( spair ), "=m" ( *dmem )
: "m" ( *smem ) );
: "m" ( *smem )
: "cc" );
}
return dest;
+2 -2
View File
@@ -22,7 +22,7 @@ static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
value &= -value;
/* Count number of leading zeros before LSB */
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) );
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) : "cc" );
return ( 64 - pair.even );
}
@@ -48,7 +48,7 @@ static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
struct s390x_scalar_pair pair;
/* Count leading zeros */
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) );
__asm__ ( "flogr %0, %1" : "=r" ( pair ) : "r" ( value ) : "cc" );
return ( 64 - pair.even );
}
+2 -1
View File
@@ -33,7 +33,8 @@ tcpip_continue_chksum ( uint16_t partial, const void *data, size_t len ) {
"alcr %0, %N1\n\t"
: "=&r" ( cksum ),
"+r" ( pair )
: "0" ( ~partial ) );
: "0" ( ~partial )
: "cc" );
return ~cksum;
}
+1 -1
View File
@@ -63,7 +63,7 @@ static inline unsigned long tod_ticks ( void ) {
union tod_extended tod;
/* Read clock */
__asm__ ( "stcke %0" : "=R" ( tod ) );
__asm__ ( "stcke %0" : "=R" ( tod ) : : "cc" );
return tod.ticks;
}