1 /* 2 * Xor Based Zero Run Length Encoding unit tests. 3 * 4 * Copyright 2013 Red Hat, Inc. and/or its affiliates 5 * 6 * Authors: 7 * Orit Wasserman <owasserm@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 * 12 */ 13 #include "qemu/osdep.h" 14 #include "qemu/cutils.h" 15 #include "../migration/xbzrle.h" 16 17 #define XBZRLE_PAGE_SIZE 4096 18 19 int (*xbzrle_encode_buffer_func)(uint8_t *, uint8_t *, int, 20 uint8_t *, int) = xbzrle_encode_buffer; 21 #if defined(CONFIG_AVX512BW_OPT) 22 #include "qemu/cpuid.h" 23 static void __attribute__((constructor)) init_cpu_flag(void) 24 { 25 unsigned max = __get_cpuid_max(0, NULL); 26 int a, b, c, d; 27 if (max >= 1) { 28 __cpuid(1, a, b, c, d); 29 /* We must check that AVX is not just available, but usable. */ 30 if ((c & bit_OSXSAVE) && (c & bit_AVX) && max >= 7) { 31 int bv; 32 __asm("xgetbv" : "=a"(bv), "=d"(d) : "c"(0)); 33 __cpuid_count(7, 0, a, b, c, d); 34 /* 0xe6: 35 * XCR0[7:5] = 111b (OPMASK state, upper 256-bit of ZMM0-ZMM15 36 * and ZMM16-ZMM31 state are enabled by OS) 37 * XCR0[2:1] = 11b (XMM state and YMM state are enabled by OS) 38 */ 39 if ((bv & 0xe6) == 0xe6 && (b & bit_AVX512BW)) { 40 xbzrle_encode_buffer_func = xbzrle_encode_buffer_avx512; 41 } 42 } 43 } 44 return ; 45 } 46 #endif 47 48 static void test_uleb(void) 49 { 50 uint32_t i, val; 51 uint8_t buf[2]; 52 int encode_ret, decode_ret; 53 54 for (i = 0; i <= 0x3fff; i++) { 55 encode_ret = uleb128_encode_small(&buf[0], i); 56 decode_ret = uleb128_decode_small(&buf[0], &val); 57 g_assert(encode_ret == decode_ret); 58 g_assert(i == val); 59 } 60 61 /* decode invalid value */ 62 buf[0] = 0x80; 63 buf[1] = 0x80; 64 65 decode_ret = uleb128_decode_small(&buf[0], &val); 66 g_assert(decode_ret == -1); 67 g_assert(val == 0); 68 } 69 70 static void test_encode_decode_zero(void) 71 { 72 uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE); 73 uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE); 74 int i = 0; 75 int dlen = 0; 76 int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006); 77 78 for (i = diff_len; i > 0; i--) { 79 buffer[1000 + i] = i; 80 } 81 82 buffer[1000 + diff_len + 3] = 103; 83 buffer[1000 + diff_len + 5] = 105; 84 85 /* encode zero page */ 86 dlen = xbzrle_encode_buffer_func(buffer, buffer, XBZRLE_PAGE_SIZE, compressed, 87 XBZRLE_PAGE_SIZE); 88 g_assert(dlen == 0); 89 90 g_free(buffer); 91 g_free(compressed); 92 } 93 94 static void test_encode_decode_unchanged(void) 95 { 96 uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE); 97 uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE); 98 int i = 0; 99 int dlen = 0; 100 int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006); 101 102 for (i = diff_len; i > 0; i--) { 103 test[1000 + i] = i + 4; 104 } 105 106 test[1000 + diff_len + 3] = 107; 107 test[1000 + diff_len + 5] = 109; 108 109 /* test unchanged buffer */ 110 dlen = xbzrle_encode_buffer_func(test, test, XBZRLE_PAGE_SIZE, compressed, 111 XBZRLE_PAGE_SIZE); 112 g_assert(dlen == 0); 113 114 g_free(test); 115 g_free(compressed); 116 } 117 118 static void test_encode_decode_1_byte(void) 119 { 120 uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE); 121 uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE); 122 uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE); 123 int dlen = 0, rc = 0; 124 uint8_t buf[2]; 125 126 test[XBZRLE_PAGE_SIZE - 1] = 1; 127 128 dlen = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed, 129 XBZRLE_PAGE_SIZE); 130 g_assert(dlen == (uleb128_encode_small(&buf[0], 4095) + 2)); 131 132 rc = xbzrle_decode_buffer(compressed, dlen, buffer, XBZRLE_PAGE_SIZE); 133 g_assert(rc == XBZRLE_PAGE_SIZE); 134 g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0); 135 136 g_free(buffer); 137 g_free(compressed); 138 g_free(test); 139 } 140 141 static void test_encode_decode_overflow(void) 142 { 143 uint8_t *compressed = g_malloc0(XBZRLE_PAGE_SIZE); 144 uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE); 145 uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE); 146 int i = 0, rc = 0; 147 148 for (i = 0; i < XBZRLE_PAGE_SIZE / 2 - 1; i++) { 149 test[i * 2] = 1; 150 } 151 152 /* encode overflow */ 153 rc = xbzrle_encode_buffer_func(buffer, test, XBZRLE_PAGE_SIZE, compressed, 154 XBZRLE_PAGE_SIZE); 155 g_assert(rc == -1); 156 157 g_free(buffer); 158 g_free(compressed); 159 g_free(test); 160 } 161 162 static void encode_decode_range(void) 163 { 164 uint8_t *buffer = g_malloc0(XBZRLE_PAGE_SIZE); 165 uint8_t *compressed = g_malloc(XBZRLE_PAGE_SIZE); 166 uint8_t *test = g_malloc0(XBZRLE_PAGE_SIZE); 167 int i = 0, rc = 0; 168 int dlen = 0; 169 170 int diff_len = g_test_rand_int_range(0, XBZRLE_PAGE_SIZE - 1006); 171 172 for (i = diff_len; i > 0; i--) { 173 buffer[1000 + i] = i; 174 test[1000 + i] = i + 4; 175 } 176 177 buffer[1000 + diff_len + 3] = 103; 178 test[1000 + diff_len + 3] = 107; 179 180 buffer[1000 + diff_len + 5] = 105; 181 test[1000 + diff_len + 5] = 109; 182 183 /* test encode/decode */ 184 dlen = xbzrle_encode_buffer_func(test, buffer, XBZRLE_PAGE_SIZE, compressed, 185 XBZRLE_PAGE_SIZE); 186 187 rc = xbzrle_decode_buffer(compressed, dlen, test, XBZRLE_PAGE_SIZE); 188 g_assert(rc < XBZRLE_PAGE_SIZE); 189 g_assert(memcmp(test, buffer, XBZRLE_PAGE_SIZE) == 0); 190 191 g_free(buffer); 192 g_free(compressed); 193 g_free(test); 194 } 195 196 static void test_encode_decode(void) 197 { 198 int i; 199 200 for (i = 0; i < 10000; i++) { 201 encode_decode_range(); 202 } 203 } 204 205 int main(int argc, char **argv) 206 { 207 g_test_init(&argc, &argv, NULL); 208 g_test_rand_int(); 209 g_test_add_func("/xbzrle/uleb", test_uleb); 210 g_test_add_func("/xbzrle/encode_decode_zero", test_encode_decode_zero); 211 g_test_add_func("/xbzrle/encode_decode_unchanged", 212 test_encode_decode_unchanged); 213 g_test_add_func("/xbzrle/encode_decode_1_byte", test_encode_decode_1_byte); 214 g_test_add_func("/xbzrle/encode_decode_overflow", 215 test_encode_decode_overflow); 216 g_test_add_func("/xbzrle/encode_decode", test_encode_decode); 217 218 return g_test_run(); 219 } 220