qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

target/i386: fix fbstp handling of out-of-range values

The fbstp implementation fails to check for out-of-range and invalid
values, instead just taking the result of conversion to int64_t and
storing its sign and low 18 decimal digits. Fix this by checking for
an out-of-range result (invalid conversions always result in INT64_MAX
or INT64_MIN from the softfloat code, which are large enough to be
considered as out-of-range by this code) and storing the packed BCD
indefinite encoding in that case.

Signed-off-by: Joseph Myers <joseph@codesourcery.com>
Message-Id: <alpine.DEB.2.21.2005132351110.11687@digraph.polyomino.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Joseph Myers and committed by
Paolo Bonzini
374ff4d0 18c53e1e

+125
+10
target/i386/fpu_helper.c
··· 732 732 733 733 val = floatx80_to_int64(ST0, &env->fp_status); 734 734 mem_ref = ptr; 735 + if (val >= 1000000000000000000LL || val <= -1000000000000000000LL) { 736 + float_raise(float_flag_invalid, &env->fp_status); 737 + while (mem_ref < ptr + 7) { 738 + cpu_stb_data_ra(env, mem_ref++, 0, GETPC()); 739 + } 740 + cpu_stb_data_ra(env, mem_ref++, 0xc0, GETPC()); 741 + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); 742 + cpu_stb_data_ra(env, mem_ref++, 0xff, GETPC()); 743 + return; 744 + } 735 745 mem_end = mem_ref + 9; 736 746 if (SIGND(temp)) { 737 747 cpu_stb_data_ra(env, mem_end, 0x80, GETPC());
+115
tests/tcg/i386/test-i386-fbstp.c
··· 1 1 /* Test fbstp instruction. */ 2 2 3 + #include <stdint.h> 3 4 #include <stdio.h> 4 5 #include <string.h> 6 + 7 + union u { 8 + struct { uint64_t sig; uint16_t sign_exp; } s; 9 + long double ld; 10 + }; 11 + 12 + volatile union u ld_invalid_1 = { .s = { 1, 1234 } }; 13 + volatile union u ld_invalid_2 = { .s = { 0, 1234 } }; 14 + volatile union u ld_invalid_3 = { .s = { 0, 0x7fff } }; 15 + volatile union u ld_invalid_4 = { .s = { (UINT64_C(1) << 63) - 1, 0x7fff } }; 5 16 6 17 int main(void) 7 18 { ··· 19 30 out[9] &= 0x80; 20 31 if (memcmp(out, "\0\0\0\0\0\0\0\0\0\x80", sizeof out) != 0) { 21 32 printf("FAIL: fbstp -0.1\n"); 33 + ret = 1; 34 + } 35 + memset(out, 0x1f, sizeof out); 36 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-987654321987654321.0L) : 37 + "st"); 38 + out[9] &= 0x80; 39 + if (memcmp(out, "\x21\x43\x65\x87\x19\x32\x54\x76\x98\x80", 40 + sizeof out) != 0) { 41 + printf("FAIL: fbstp -987654321987654321\n"); 42 + ret = 1; 43 + } 44 + memset(out, 0x12, sizeof out); 45 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (999999999999999999.5L) : 46 + "st"); 47 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 48 + printf("FAIL: fbstp 999999999999999999.5\n"); 49 + ret = 1; 50 + } 51 + memset(out, 0x12, sizeof out); 52 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1000000000000000000.0L) : 53 + "st"); 54 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 55 + printf("FAIL: fbstp 1000000000000000000\n"); 56 + ret = 1; 57 + } 58 + memset(out, 0x12, sizeof out); 59 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (1e30L) : "st"); 60 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 61 + printf("FAIL: fbstp 1e30\n"); 62 + ret = 1; 63 + } 64 + memset(out, 0x12, sizeof out); 65 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-999999999999999999.5L) : 66 + "st"); 67 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 68 + printf("FAIL: fbstp -999999999999999999.5\n"); 69 + ret = 1; 70 + } 71 + memset(out, 0x12, sizeof out); 72 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1000000000000000000.0L) : 73 + "st"); 74 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 75 + printf("FAIL: fbstp -1000000000000000000\n"); 76 + ret = 1; 77 + } 78 + memset(out, 0x12, sizeof out); 79 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-1e30L) : "st"); 80 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 81 + printf("FAIL: fbstp -1e30\n"); 82 + ret = 1; 83 + } 84 + memset(out, 0x12, sizeof out); 85 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_infl()) : "st"); 86 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 87 + printf("FAIL: fbstp inf\n"); 88 + ret = 1; 89 + } 90 + memset(out, 0x12, sizeof out); 91 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_infl()) : 92 + "st"); 93 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 94 + printf("FAIL: fbstp -inf\n"); 95 + ret = 1; 96 + } 97 + memset(out, 0x12, sizeof out); 98 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (__builtin_nanl("")) : 99 + "st"); 100 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 101 + printf("FAIL: fbstp nan\n"); 102 + ret = 1; 103 + } 104 + memset(out, 0x12, sizeof out); 105 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (-__builtin_nanl("")) : 106 + "st"); 107 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 108 + printf("FAIL: fbstp -nan\n"); 109 + ret = 1; 110 + } 111 + memset(out, 0x12, sizeof out); 112 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_1.ld) : 113 + "st"); 114 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 115 + printf("FAIL: fbstp invalid 1\n"); 116 + ret = 1; 117 + } 118 + memset(out, 0x12, sizeof out); 119 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_2.ld) : 120 + "st"); 121 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 122 + printf("FAIL: fbstp invalid 2\n"); 123 + ret = 1; 124 + } 125 + memset(out, 0x12, sizeof out); 126 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_3.ld) : 127 + "st"); 128 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 129 + printf("FAIL: fbstp invalid 3\n"); 130 + ret = 1; 131 + } 132 + memset(out, 0x12, sizeof out); 133 + __asm__ volatile ("fbstp %0" : "=m" (out) : "t" (ld_invalid_4.ld) : 134 + "st"); 135 + if (memcmp(out, "\0\0\0\0\0\0\0\xc0\xff\xff", sizeof out) != 0) { 136 + printf("FAIL: fbstp invalid 4\n"); 22 137 ret = 1; 23 138 } 24 139 return ret;