From 563263bb1c508cf74314f8d623477898ea7a996a Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 3 Jun 2019 16:47:14 +0200 Subject: [PATCH] IBM Z DFLTCC: fix STFLE usage 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 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/s390/dfltcc_common.c b/arch/s390/dfltcc_common.c index 98c9765b..2f2e22fd 100644 --- a/arch/s390/dfltcc_common.c +++ b/arch/s390/dfltcc_common.c @@ -15,13 +15,11 @@ 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); } -- 2.47.2