]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
IBM Z DFLTCC: fix STFLE usage
authorIlya Leoshkevich <iii@linux.ibm.com>
Mon, 3 Jun 2019 14:47:14 +0000 (16:47 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Tue, 4 Jun 2019 08:59:40 +0000 (10:59 +0200)
QEMU maintainers have found and issue related to incorrect usage of
STFLE instruction [1], which is used to get features supported by the
machine. There are three potential problems with the current usage:

- R0 must contain the number of requested doublewords *minus one*. The
existing code lacks the "minus one" part.
- Older machines may not fill all the doublewords - this is fixed by
calling `memset`.
- STFLE updates R0, but we don't tell the compiler about this - this is
fixed by using a `+` constraint.
- Not really a problem, but it's enough to load 8 bits into R0, so its
type was changed to `uint8_t`. Also, STFLE only writes to `facilities`
variable, therefore memory clobber is unnecessary.

[1] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg00113.html

arch/s390/dfltcc_common.c

index 98c9765b904542bfa8e11a5c15f7567203f9c845..2f2e22fd091e0a84909f0af0506b478fc99c09eb 100644 (file)
 static inline int is_dfltcc_enabled(void)
 {
     uint64_t facilities[(DFLTCC_FACILITY / 64) + 1];
-    register int r0 __asm__("r0");
+    register uint8_t r0 __asm__("r0");
 
-    r0 = sizeof(facilities) / sizeof(facilities[0]);
-    __asm__ volatile("stfle %[facilities]\n"
-                     : [facilities] "=Q" (facilities)
-                     : [r0] "r" (r0)
-                     : "cc", "memory");
+    memset(facilities, 0, sizeof(facilities));
+    r0 = sizeof(facilities) / sizeof(facilities[0]) - 1;
+    __asm__ volatile("stfle %[facilities]\n" : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc");
     return is_bit_set((const char *)facilities, DFLTCC_FACILITY);
 }