test-vmstate.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. /*
  2. * Test code for VMState
  3. *
  4. * Copyright (c) 2013 Red Hat Inc.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "qemu/osdep.h"
  25. #include "../migration/migration.h"
  26. #include "migration/vmstate.h"
  27. #include "migration/qemu-file-types.h"
  28. #include "../migration/qemu-file.h"
  29. #include "../migration/qemu-file-channel.h"
  30. #include "../migration/savevm.h"
  31. #include "qemu/coroutine.h"
  32. #include "qemu/module.h"
  33. #include "io/channel-file.h"
  34. static char temp_file[] = "/tmp/vmst.test.XXXXXX";
  35. static int temp_fd;
  36. /* Duplicate temp_fd and seek to the beginning of the file */
  37. static QEMUFile *open_test_file(bool write)
  38. {
  39. int fd = dup(temp_fd);
  40. QIOChannel *ioc;
  41. QEMUFile *f;
  42. lseek(fd, 0, SEEK_SET);
  43. if (write) {
  44. g_assert_cmpint(ftruncate(fd, 0), ==, 0);
  45. }
  46. ioc = QIO_CHANNEL(qio_channel_file_new_fd(fd));
  47. if (write) {
  48. f = qemu_fopen_channel_output(ioc);
  49. } else {
  50. f = qemu_fopen_channel_input(ioc);
  51. }
  52. object_unref(OBJECT(ioc));
  53. return f;
  54. }
  55. #define SUCCESS(val) \
  56. g_assert_cmpint((val), ==, 0)
  57. #define FAILURE(val) \
  58. g_assert_cmpint((val), !=, 0)
  59. static void save_vmstate(const VMStateDescription *desc, void *obj)
  60. {
  61. QEMUFile *f = open_test_file(true);
  62. /* Save file with vmstate */
  63. int ret = vmstate_save_state(f, desc, obj, NULL);
  64. g_assert(!ret);
  65. qemu_put_byte(f, QEMU_VM_EOF);
  66. g_assert(!qemu_file_get_error(f));
  67. qemu_fclose(f);
  68. }
  69. static void save_buffer(const uint8_t *buf, size_t buf_size)
  70. {
  71. QEMUFile *fsave = open_test_file(true);
  72. qemu_put_buffer(fsave, buf, buf_size);
  73. qemu_fclose(fsave);
  74. }
  75. static void compare_vmstate(const uint8_t *wire, size_t size)
  76. {
  77. QEMUFile *f = open_test_file(false);
  78. uint8_t result[size];
  79. /* read back as binary */
  80. g_assert_cmpint(qemu_get_buffer(f, result, sizeof(result)), ==,
  81. sizeof(result));
  82. g_assert(!qemu_file_get_error(f));
  83. /* Compare that what is on the file is the same that what we
  84. expected to be there */
  85. SUCCESS(memcmp(result, wire, sizeof(result)));
  86. /* Must reach EOF */
  87. qemu_get_byte(f);
  88. g_assert_cmpint(qemu_file_get_error(f), ==, -EIO);
  89. qemu_fclose(f);
  90. }
  91. static int load_vmstate_one(const VMStateDescription *desc, void *obj,
  92. int version, const uint8_t *wire, size_t size)
  93. {
  94. QEMUFile *f;
  95. int ret;
  96. f = open_test_file(true);
  97. qemu_put_buffer(f, wire, size);
  98. qemu_fclose(f);
  99. f = open_test_file(false);
  100. ret = vmstate_load_state(f, desc, obj, version);
  101. if (ret) {
  102. g_assert(qemu_file_get_error(f));
  103. } else{
  104. g_assert(!qemu_file_get_error(f));
  105. }
  106. qemu_fclose(f);
  107. return ret;
  108. }
  109. static int load_vmstate(const VMStateDescription *desc,
  110. void *obj, void *obj_clone,
  111. void (*obj_copy)(void *, void*),
  112. int version, const uint8_t *wire, size_t size)
  113. {
  114. /* We test with zero size */
  115. obj_copy(obj_clone, obj);
  116. FAILURE(load_vmstate_one(desc, obj, version, wire, 0));
  117. /* Stream ends with QEMU_EOF, so we need at least 3 bytes to be
  118. * able to test in the middle */
  119. if (size > 3) {
  120. /* We test with size - 2. We can't test size - 1 due to EOF tricks */
  121. obj_copy(obj, obj_clone);
  122. FAILURE(load_vmstate_one(desc, obj, version, wire, size - 2));
  123. /* Test with size/2, first half of real state */
  124. obj_copy(obj, obj_clone);
  125. FAILURE(load_vmstate_one(desc, obj, version, wire, size/2));
  126. /* Test with size/2, second half of real state */
  127. obj_copy(obj, obj_clone);
  128. FAILURE(load_vmstate_one(desc, obj, version, wire + (size/2), size/2));
  129. }
  130. obj_copy(obj, obj_clone);
  131. return load_vmstate_one(desc, obj, version, wire, size);
  132. }
  133. /* Test struct that we are going to use for our tests */
  134. typedef struct TestSimple {
  135. bool b_1, b_2;
  136. uint8_t u8_1;
  137. uint16_t u16_1;
  138. uint32_t u32_1;
  139. uint64_t u64_1;
  140. int8_t i8_1, i8_2;
  141. int16_t i16_1, i16_2;
  142. int32_t i32_1, i32_2;
  143. int64_t i64_1, i64_2;
  144. } TestSimple;
  145. /* Object instantiation, we are going to use it in more than one test */
  146. TestSimple obj_simple = {
  147. .b_1 = true,
  148. .b_2 = false,
  149. .u8_1 = 130,
  150. .u16_1 = 512,
  151. .u32_1 = 70000,
  152. .u64_1 = 12121212,
  153. .i8_1 = 65,
  154. .i8_2 = -65,
  155. .i16_1 = 512,
  156. .i16_2 = -512,
  157. .i32_1 = 70000,
  158. .i32_2 = -70000,
  159. .i64_1 = 12121212,
  160. .i64_2 = -12121212,
  161. };
  162. /* Description of the values. If you add a primitive type
  163. you are expected to add a test here */
  164. static const VMStateDescription vmstate_simple_primitive = {
  165. .name = "simple/primitive",
  166. .version_id = 1,
  167. .minimum_version_id = 1,
  168. .fields = (VMStateField[]) {
  169. VMSTATE_BOOL(b_1, TestSimple),
  170. VMSTATE_BOOL(b_2, TestSimple),
  171. VMSTATE_UINT8(u8_1, TestSimple),
  172. VMSTATE_UINT16(u16_1, TestSimple),
  173. VMSTATE_UINT32(u32_1, TestSimple),
  174. VMSTATE_UINT64(u64_1, TestSimple),
  175. VMSTATE_INT8(i8_1, TestSimple),
  176. VMSTATE_INT8(i8_2, TestSimple),
  177. VMSTATE_INT16(i16_1, TestSimple),
  178. VMSTATE_INT16(i16_2, TestSimple),
  179. VMSTATE_INT32(i32_1, TestSimple),
  180. VMSTATE_INT32(i32_2, TestSimple),
  181. VMSTATE_INT64(i64_1, TestSimple),
  182. VMSTATE_INT64(i64_2, TestSimple),
  183. VMSTATE_END_OF_LIST()
  184. }
  185. };
  186. /* It describes what goes through the wire. Our tests are basically:
  187. * save test
  188. - save a struct a vmstate to a file
  189. - read that file back (binary read, no vmstate)
  190. - compare it with what we expect to be on the wire
  191. * load test
  192. - save to the file what we expect to be on the wire
  193. - read struct back with vmstate in a different
  194. - compare back with the original struct
  195. */
  196. uint8_t wire_simple_primitive[] = {
  197. /* b_1 */ 0x01,
  198. /* b_2 */ 0x00,
  199. /* u8_1 */ 0x82,
  200. /* u16_1 */ 0x02, 0x00,
  201. /* u32_1 */ 0x00, 0x01, 0x11, 0x70,
  202. /* u64_1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf4, 0x7c,
  203. /* i8_1 */ 0x41,
  204. /* i8_2 */ 0xbf,
  205. /* i16_1 */ 0x02, 0x00,
  206. /* i16_2 */ 0xfe, 0x0,
  207. /* i32_1 */ 0x00, 0x01, 0x11, 0x70,
  208. /* i32_2 */ 0xff, 0xfe, 0xee, 0x90,
  209. /* i64_1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf4, 0x7c,
  210. /* i64_2 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x0b, 0x84,
  211. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  212. };
  213. static void obj_simple_copy(void *target, void *source)
  214. {
  215. memcpy(target, source, sizeof(TestSimple));
  216. }
  217. static void test_simple_primitive(void)
  218. {
  219. TestSimple obj, obj_clone;
  220. memset(&obj, 0, sizeof(obj));
  221. save_vmstate(&vmstate_simple_primitive, &obj_simple);
  222. compare_vmstate(wire_simple_primitive, sizeof(wire_simple_primitive));
  223. SUCCESS(load_vmstate(&vmstate_simple_primitive, &obj, &obj_clone,
  224. obj_simple_copy, 1, wire_simple_primitive,
  225. sizeof(wire_simple_primitive)));
  226. #define FIELD_EQUAL(name) g_assert_cmpint(obj.name, ==, obj_simple.name)
  227. FIELD_EQUAL(b_1);
  228. FIELD_EQUAL(b_2);
  229. FIELD_EQUAL(u8_1);
  230. FIELD_EQUAL(u16_1);
  231. FIELD_EQUAL(u32_1);
  232. FIELD_EQUAL(u64_1);
  233. FIELD_EQUAL(i8_1);
  234. FIELD_EQUAL(i8_2);
  235. FIELD_EQUAL(i16_1);
  236. FIELD_EQUAL(i16_2);
  237. FIELD_EQUAL(i32_1);
  238. FIELD_EQUAL(i32_2);
  239. FIELD_EQUAL(i64_1);
  240. FIELD_EQUAL(i64_2);
  241. }
  242. typedef struct TestSimpleArray {
  243. uint16_t u16_1[3];
  244. } TestSimpleArray;
  245. /* Object instantiation, we are going to use it in more than one test */
  246. TestSimpleArray obj_simple_arr = {
  247. .u16_1 = { 0x42, 0x43, 0x44 },
  248. };
  249. /* Description of the values. If you add a primitive type
  250. you are expected to add a test here */
  251. static const VMStateDescription vmstate_simple_arr = {
  252. .name = "simple/array",
  253. .version_id = 1,
  254. .minimum_version_id = 1,
  255. .fields = (VMStateField[]) {
  256. VMSTATE_UINT16_ARRAY(u16_1, TestSimpleArray, 3),
  257. VMSTATE_END_OF_LIST()
  258. }
  259. };
  260. uint8_t wire_simple_arr[] = {
  261. /* u16_1 */ 0x00, 0x42,
  262. /* u16_1 */ 0x00, 0x43,
  263. /* u16_1 */ 0x00, 0x44,
  264. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  265. };
  266. static void obj_simple_arr_copy(void *target, void *source)
  267. {
  268. memcpy(target, source, sizeof(TestSimpleArray));
  269. }
  270. static void test_simple_array(void)
  271. {
  272. TestSimpleArray obj, obj_clone;
  273. memset(&obj, 0, sizeof(obj));
  274. save_vmstate(&vmstate_simple_arr, &obj_simple_arr);
  275. compare_vmstate(wire_simple_arr, sizeof(wire_simple_arr));
  276. SUCCESS(load_vmstate(&vmstate_simple_arr, &obj, &obj_clone,
  277. obj_simple_arr_copy, 1, wire_simple_arr,
  278. sizeof(wire_simple_arr)));
  279. }
  280. typedef struct TestStruct {
  281. uint32_t a, b, c, e;
  282. uint64_t d, f;
  283. bool skip_c_e;
  284. } TestStruct;
  285. static const VMStateDescription vmstate_versioned = {
  286. .name = "test/versioned",
  287. .version_id = 2,
  288. .minimum_version_id = 1,
  289. .fields = (VMStateField[]) {
  290. VMSTATE_UINT32(a, TestStruct),
  291. VMSTATE_UINT32_V(b, TestStruct, 2), /* Versioned field in the middle, so
  292. * we catch bugs more easily.
  293. */
  294. VMSTATE_UINT32(c, TestStruct),
  295. VMSTATE_UINT64(d, TestStruct),
  296. VMSTATE_UINT32_V(e, TestStruct, 2),
  297. VMSTATE_UINT64_V(f, TestStruct, 2),
  298. VMSTATE_END_OF_LIST()
  299. }
  300. };
  301. static void test_load_v1(void)
  302. {
  303. uint8_t buf[] = {
  304. 0, 0, 0, 10, /* a */
  305. 0, 0, 0, 30, /* c */
  306. 0, 0, 0, 0, 0, 0, 0, 40, /* d */
  307. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  308. };
  309. save_buffer(buf, sizeof(buf));
  310. QEMUFile *loading = open_test_file(false);
  311. TestStruct obj = { .b = 200, .e = 500, .f = 600 };
  312. vmstate_load_state(loading, &vmstate_versioned, &obj, 1);
  313. g_assert(!qemu_file_get_error(loading));
  314. g_assert_cmpint(obj.a, ==, 10);
  315. g_assert_cmpint(obj.b, ==, 200);
  316. g_assert_cmpint(obj.c, ==, 30);
  317. g_assert_cmpint(obj.d, ==, 40);
  318. g_assert_cmpint(obj.e, ==, 500);
  319. g_assert_cmpint(obj.f, ==, 600);
  320. qemu_fclose(loading);
  321. }
  322. static void test_load_v2(void)
  323. {
  324. uint8_t buf[] = {
  325. 0, 0, 0, 10, /* a */
  326. 0, 0, 0, 20, /* b */
  327. 0, 0, 0, 30, /* c */
  328. 0, 0, 0, 0, 0, 0, 0, 40, /* d */
  329. 0, 0, 0, 50, /* e */
  330. 0, 0, 0, 0, 0, 0, 0, 60, /* f */
  331. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  332. };
  333. save_buffer(buf, sizeof(buf));
  334. QEMUFile *loading = open_test_file(false);
  335. TestStruct obj;
  336. vmstate_load_state(loading, &vmstate_versioned, &obj, 2);
  337. g_assert_cmpint(obj.a, ==, 10);
  338. g_assert_cmpint(obj.b, ==, 20);
  339. g_assert_cmpint(obj.c, ==, 30);
  340. g_assert_cmpint(obj.d, ==, 40);
  341. g_assert_cmpint(obj.e, ==, 50);
  342. g_assert_cmpint(obj.f, ==, 60);
  343. qemu_fclose(loading);
  344. }
  345. static bool test_skip(void *opaque, int version_id)
  346. {
  347. TestStruct *t = (TestStruct *)opaque;
  348. return !t->skip_c_e;
  349. }
  350. static const VMStateDescription vmstate_skipping = {
  351. .name = "test/skip",
  352. .version_id = 2,
  353. .minimum_version_id = 1,
  354. .fields = (VMStateField[]) {
  355. VMSTATE_UINT32(a, TestStruct),
  356. VMSTATE_UINT32(b, TestStruct),
  357. VMSTATE_UINT32_TEST(c, TestStruct, test_skip),
  358. VMSTATE_UINT64(d, TestStruct),
  359. VMSTATE_UINT32_TEST(e, TestStruct, test_skip),
  360. VMSTATE_UINT64_V(f, TestStruct, 2),
  361. VMSTATE_END_OF_LIST()
  362. }
  363. };
  364. static void test_save_noskip(void)
  365. {
  366. QEMUFile *fsave = open_test_file(true);
  367. TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
  368. .skip_c_e = false };
  369. int ret = vmstate_save_state(fsave, &vmstate_skipping, &obj, NULL);
  370. g_assert(!ret);
  371. g_assert(!qemu_file_get_error(fsave));
  372. uint8_t expected[] = {
  373. 0, 0, 0, 1, /* a */
  374. 0, 0, 0, 2, /* b */
  375. 0, 0, 0, 3, /* c */
  376. 0, 0, 0, 0, 0, 0, 0, 4, /* d */
  377. 0, 0, 0, 5, /* e */
  378. 0, 0, 0, 0, 0, 0, 0, 6, /* f */
  379. };
  380. qemu_fclose(fsave);
  381. compare_vmstate(expected, sizeof(expected));
  382. }
  383. static void test_save_skip(void)
  384. {
  385. QEMUFile *fsave = open_test_file(true);
  386. TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
  387. .skip_c_e = true };
  388. int ret = vmstate_save_state(fsave, &vmstate_skipping, &obj, NULL);
  389. g_assert(!ret);
  390. g_assert(!qemu_file_get_error(fsave));
  391. uint8_t expected[] = {
  392. 0, 0, 0, 1, /* a */
  393. 0, 0, 0, 2, /* b */
  394. 0, 0, 0, 0, 0, 0, 0, 4, /* d */
  395. 0, 0, 0, 0, 0, 0, 0, 6, /* f */
  396. };
  397. qemu_fclose(fsave);
  398. compare_vmstate(expected, sizeof(expected));
  399. }
  400. static void test_load_noskip(void)
  401. {
  402. uint8_t buf[] = {
  403. 0, 0, 0, 10, /* a */
  404. 0, 0, 0, 20, /* b */
  405. 0, 0, 0, 30, /* c */
  406. 0, 0, 0, 0, 0, 0, 0, 40, /* d */
  407. 0, 0, 0, 50, /* e */
  408. 0, 0, 0, 0, 0, 0, 0, 60, /* f */
  409. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  410. };
  411. save_buffer(buf, sizeof(buf));
  412. QEMUFile *loading = open_test_file(false);
  413. TestStruct obj = { .skip_c_e = false };
  414. vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
  415. g_assert(!qemu_file_get_error(loading));
  416. g_assert_cmpint(obj.a, ==, 10);
  417. g_assert_cmpint(obj.b, ==, 20);
  418. g_assert_cmpint(obj.c, ==, 30);
  419. g_assert_cmpint(obj.d, ==, 40);
  420. g_assert_cmpint(obj.e, ==, 50);
  421. g_assert_cmpint(obj.f, ==, 60);
  422. qemu_fclose(loading);
  423. }
  424. static void test_load_skip(void)
  425. {
  426. uint8_t buf[] = {
  427. 0, 0, 0, 10, /* a */
  428. 0, 0, 0, 20, /* b */
  429. 0, 0, 0, 0, 0, 0, 0, 40, /* d */
  430. 0, 0, 0, 0, 0, 0, 0, 60, /* f */
  431. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  432. };
  433. save_buffer(buf, sizeof(buf));
  434. QEMUFile *loading = open_test_file(false);
  435. TestStruct obj = { .skip_c_e = true, .c = 300, .e = 500 };
  436. vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
  437. g_assert(!qemu_file_get_error(loading));
  438. g_assert_cmpint(obj.a, ==, 10);
  439. g_assert_cmpint(obj.b, ==, 20);
  440. g_assert_cmpint(obj.c, ==, 300);
  441. g_assert_cmpint(obj.d, ==, 40);
  442. g_assert_cmpint(obj.e, ==, 500);
  443. g_assert_cmpint(obj.f, ==, 60);
  444. qemu_fclose(loading);
  445. }
  446. typedef struct {
  447. int32_t i;
  448. } TestStructTriv;
  449. const VMStateDescription vmsd_tst = {
  450. .name = "test/tst",
  451. .version_id = 1,
  452. .minimum_version_id = 1,
  453. .fields = (VMStateField[]) {
  454. VMSTATE_INT32(i, TestStructTriv),
  455. VMSTATE_END_OF_LIST()
  456. }
  457. };
  458. /* test array migration */
  459. #define AR_SIZE 4
  460. typedef struct {
  461. TestStructTriv *ar[AR_SIZE];
  462. } TestArrayOfPtrToStuct;
  463. const VMStateDescription vmsd_arps = {
  464. .name = "test/arps",
  465. .version_id = 1,
  466. .minimum_version_id = 1,
  467. .fields = (VMStateField[]) {
  468. VMSTATE_ARRAY_OF_POINTER_TO_STRUCT(ar, TestArrayOfPtrToStuct,
  469. AR_SIZE, 0, vmsd_tst, TestStructTriv),
  470. VMSTATE_END_OF_LIST()
  471. }
  472. };
  473. static uint8_t wire_arr_ptr_no0[] = {
  474. 0x00, 0x00, 0x00, 0x00,
  475. 0x00, 0x00, 0x00, 0x01,
  476. 0x00, 0x00, 0x00, 0x02,
  477. 0x00, 0x00, 0x00, 0x03,
  478. QEMU_VM_EOF
  479. };
  480. static void test_arr_ptr_str_no0_save(void)
  481. {
  482. TestStructTriv ar[AR_SIZE] = {{.i = 0}, {.i = 1}, {.i = 2}, {.i = 3} };
  483. TestArrayOfPtrToStuct sample = {.ar = {&ar[0], &ar[1], &ar[2], &ar[3]} };
  484. save_vmstate(&vmsd_arps, &sample);
  485. compare_vmstate(wire_arr_ptr_no0, sizeof(wire_arr_ptr_no0));
  486. }
  487. static void test_arr_ptr_str_no0_load(void)
  488. {
  489. TestStructTriv ar_gt[AR_SIZE] = {{.i = 0}, {.i = 1}, {.i = 2}, {.i = 3} };
  490. TestStructTriv ar[AR_SIZE] = {};
  491. TestArrayOfPtrToStuct obj = {.ar = {&ar[0], &ar[1], &ar[2], &ar[3]} };
  492. int idx;
  493. save_buffer(wire_arr_ptr_no0, sizeof(wire_arr_ptr_no0));
  494. SUCCESS(load_vmstate_one(&vmsd_arps, &obj, 1,
  495. wire_arr_ptr_no0, sizeof(wire_arr_ptr_no0)));
  496. for (idx = 0; idx < AR_SIZE; ++idx) {
  497. /* compare the target array ar with the ground truth array ar_gt */
  498. g_assert_cmpint(ar_gt[idx].i, ==, ar[idx].i);
  499. }
  500. }
  501. static uint8_t wire_arr_ptr_0[] = {
  502. 0x00, 0x00, 0x00, 0x00,
  503. VMS_NULLPTR_MARKER,
  504. 0x00, 0x00, 0x00, 0x02,
  505. 0x00, 0x00, 0x00, 0x03,
  506. QEMU_VM_EOF
  507. };
  508. static void test_arr_ptr_str_0_save(void)
  509. {
  510. TestStructTriv ar[AR_SIZE] = {{.i = 0}, {.i = 1}, {.i = 2}, {.i = 3} };
  511. TestArrayOfPtrToStuct sample = {.ar = {&ar[0], NULL, &ar[2], &ar[3]} };
  512. save_vmstate(&vmsd_arps, &sample);
  513. compare_vmstate(wire_arr_ptr_0, sizeof(wire_arr_ptr_0));
  514. }
  515. static void test_arr_ptr_str_0_load(void)
  516. {
  517. TestStructTriv ar_gt[AR_SIZE] = {{.i = 0}, {.i = 0}, {.i = 2}, {.i = 3} };
  518. TestStructTriv ar[AR_SIZE] = {};
  519. TestArrayOfPtrToStuct obj = {.ar = {&ar[0], NULL, &ar[2], &ar[3]} };
  520. int idx;
  521. save_buffer(wire_arr_ptr_0, sizeof(wire_arr_ptr_0));
  522. SUCCESS(load_vmstate_one(&vmsd_arps, &obj, 1,
  523. wire_arr_ptr_0, sizeof(wire_arr_ptr_0)));
  524. for (idx = 0; idx < AR_SIZE; ++idx) {
  525. /* compare the target array ar with the ground truth array ar_gt */
  526. g_assert_cmpint(ar_gt[idx].i, ==, ar[idx].i);
  527. }
  528. for (idx = 0; idx < AR_SIZE; ++idx) {
  529. if (idx == 1) {
  530. g_assert_cmpint((uintptr_t)(obj.ar[idx]), ==, 0);
  531. } else {
  532. g_assert_cmpint((uintptr_t)(obj.ar[idx]), !=, 0);
  533. }
  534. }
  535. }
  536. typedef struct TestArrayOfPtrToInt {
  537. int32_t *ar[AR_SIZE];
  538. } TestArrayOfPtrToInt;
  539. const VMStateDescription vmsd_arpp = {
  540. .name = "test/arps",
  541. .version_id = 1,
  542. .minimum_version_id = 1,
  543. .fields = (VMStateField[]) {
  544. VMSTATE_ARRAY_OF_POINTER(ar, TestArrayOfPtrToInt,
  545. AR_SIZE, 0, vmstate_info_int32, int32_t*),
  546. VMSTATE_END_OF_LIST()
  547. }
  548. };
  549. static void test_arr_ptr_prim_0_save(void)
  550. {
  551. int32_t ar[AR_SIZE] = {0 , 1, 2, 3};
  552. TestArrayOfPtrToInt sample = {.ar = {&ar[0], NULL, &ar[2], &ar[3]} };
  553. save_vmstate(&vmsd_arpp, &sample);
  554. compare_vmstate(wire_arr_ptr_0, sizeof(wire_arr_ptr_0));
  555. }
  556. static void test_arr_ptr_prim_0_load(void)
  557. {
  558. int32_t ar_gt[AR_SIZE] = {0, 1, 2, 3};
  559. int32_t ar[AR_SIZE] = {3 , 42, 1, 0};
  560. TestArrayOfPtrToInt obj = {.ar = {&ar[0], NULL, &ar[2], &ar[3]} };
  561. int idx;
  562. save_buffer(wire_arr_ptr_0, sizeof(wire_arr_ptr_0));
  563. SUCCESS(load_vmstate_one(&vmsd_arpp, &obj, 1,
  564. wire_arr_ptr_0, sizeof(wire_arr_ptr_0)));
  565. for (idx = 0; idx < AR_SIZE; ++idx) {
  566. /* compare the target array ar with the ground truth array ar_gt */
  567. if (idx == 1) {
  568. g_assert_cmpint(42, ==, ar[idx]);
  569. } else {
  570. g_assert_cmpint(ar_gt[idx], ==, ar[idx]);
  571. }
  572. }
  573. }
  574. /* test QTAILQ migration */
  575. typedef struct TestQtailqElement TestQtailqElement;
  576. struct TestQtailqElement {
  577. bool b;
  578. uint8_t u8;
  579. QTAILQ_ENTRY(TestQtailqElement) next;
  580. };
  581. typedef struct TestQtailq {
  582. int16_t i16;
  583. QTAILQ_HEAD(, TestQtailqElement) q;
  584. int32_t i32;
  585. } TestQtailq;
  586. static const VMStateDescription vmstate_q_element = {
  587. .name = "test/queue-element",
  588. .version_id = 1,
  589. .minimum_version_id = 1,
  590. .fields = (VMStateField[]) {
  591. VMSTATE_BOOL(b, TestQtailqElement),
  592. VMSTATE_UINT8(u8, TestQtailqElement),
  593. VMSTATE_END_OF_LIST()
  594. },
  595. };
  596. static const VMStateDescription vmstate_q = {
  597. .name = "test/queue",
  598. .version_id = 1,
  599. .minimum_version_id = 1,
  600. .fields = (VMStateField[]) {
  601. VMSTATE_INT16(i16, TestQtailq),
  602. VMSTATE_QTAILQ_V(q, TestQtailq, 1, vmstate_q_element, TestQtailqElement,
  603. next),
  604. VMSTATE_INT32(i32, TestQtailq),
  605. VMSTATE_END_OF_LIST()
  606. }
  607. };
  608. uint8_t wire_q[] = {
  609. /* i16 */ 0xfe, 0x0,
  610. /* start of element 0 of q */ 0x01,
  611. /* .b */ 0x01,
  612. /* .u8 */ 0x82,
  613. /* start of element 1 of q */ 0x01,
  614. /* b */ 0x00,
  615. /* u8 */ 0x41,
  616. /* end of q */ 0x00,
  617. /* i32 */ 0x00, 0x01, 0x11, 0x70,
  618. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  619. };
  620. static void test_save_q(void)
  621. {
  622. TestQtailq obj_q = {
  623. .i16 = -512,
  624. .i32 = 70000,
  625. };
  626. TestQtailqElement obj_qe1 = {
  627. .b = true,
  628. .u8 = 130,
  629. };
  630. TestQtailqElement obj_qe2 = {
  631. .b = false,
  632. .u8 = 65,
  633. };
  634. QTAILQ_INIT(&obj_q.q);
  635. QTAILQ_INSERT_TAIL(&obj_q.q, &obj_qe1, next);
  636. QTAILQ_INSERT_TAIL(&obj_q.q, &obj_qe2, next);
  637. save_vmstate(&vmstate_q, &obj_q);
  638. compare_vmstate(wire_q, sizeof(wire_q));
  639. }
  640. static void test_load_q(void)
  641. {
  642. TestQtailq obj_q = {
  643. .i16 = -512,
  644. .i32 = 70000,
  645. };
  646. TestQtailqElement obj_qe1 = {
  647. .b = true,
  648. .u8 = 130,
  649. };
  650. TestQtailqElement obj_qe2 = {
  651. .b = false,
  652. .u8 = 65,
  653. };
  654. QTAILQ_INIT(&obj_q.q);
  655. QTAILQ_INSERT_TAIL(&obj_q.q, &obj_qe1, next);
  656. QTAILQ_INSERT_TAIL(&obj_q.q, &obj_qe2, next);
  657. QEMUFile *fsave = open_test_file(true);
  658. qemu_put_buffer(fsave, wire_q, sizeof(wire_q));
  659. g_assert(!qemu_file_get_error(fsave));
  660. qemu_fclose(fsave);
  661. QEMUFile *fload = open_test_file(false);
  662. TestQtailq tgt;
  663. QTAILQ_INIT(&tgt.q);
  664. vmstate_load_state(fload, &vmstate_q, &tgt, 1);
  665. char eof = qemu_get_byte(fload);
  666. g_assert(!qemu_file_get_error(fload));
  667. g_assert_cmpint(tgt.i16, ==, obj_q.i16);
  668. g_assert_cmpint(tgt.i32, ==, obj_q.i32);
  669. g_assert_cmpint(eof, ==, QEMU_VM_EOF);
  670. TestQtailqElement *qele_from = QTAILQ_FIRST(&obj_q.q);
  671. TestQtailqElement *qlast_from = QTAILQ_LAST(&obj_q.q);
  672. TestQtailqElement *qele_to = QTAILQ_FIRST(&tgt.q);
  673. TestQtailqElement *qlast_to = QTAILQ_LAST(&tgt.q);
  674. while (1) {
  675. g_assert_cmpint(qele_to->b, ==, qele_from->b);
  676. g_assert_cmpint(qele_to->u8, ==, qele_from->u8);
  677. if ((qele_from == qlast_from) || (qele_to == qlast_to)) {
  678. break;
  679. }
  680. qele_from = QTAILQ_NEXT(qele_from, next);
  681. qele_to = QTAILQ_NEXT(qele_to, next);
  682. }
  683. g_assert_cmpint((uintptr_t) qele_from, ==, (uintptr_t) qlast_from);
  684. g_assert_cmpint((uintptr_t) qele_to, ==, (uintptr_t) qlast_to);
  685. /* clean up */
  686. TestQtailqElement *qele;
  687. while (!QTAILQ_EMPTY(&tgt.q)) {
  688. qele = QTAILQ_LAST(&tgt.q);
  689. QTAILQ_REMOVE(&tgt.q, qele, next);
  690. free(qele);
  691. qele = NULL;
  692. }
  693. qemu_fclose(fload);
  694. }
  695. /* interval (key) */
  696. typedef struct TestGTreeInterval {
  697. uint64_t low;
  698. uint64_t high;
  699. } TestGTreeInterval;
  700. #define VMSTATE_INTERVAL \
  701. { \
  702. .name = "interval", \
  703. .version_id = 1, \
  704. .minimum_version_id = 1, \
  705. .fields = (VMStateField[]) { \
  706. VMSTATE_UINT64(low, TestGTreeInterval), \
  707. VMSTATE_UINT64(high, TestGTreeInterval), \
  708. VMSTATE_END_OF_LIST() \
  709. } \
  710. }
  711. /* mapping (value) */
  712. typedef struct TestGTreeMapping {
  713. uint64_t phys_addr;
  714. uint32_t flags;
  715. } TestGTreeMapping;
  716. #define VMSTATE_MAPPING \
  717. { \
  718. .name = "mapping", \
  719. .version_id = 1, \
  720. .minimum_version_id = 1, \
  721. .fields = (VMStateField[]) { \
  722. VMSTATE_UINT64(phys_addr, TestGTreeMapping), \
  723. VMSTATE_UINT32(flags, TestGTreeMapping), \
  724. VMSTATE_END_OF_LIST() \
  725. }, \
  726. }
  727. static const VMStateDescription vmstate_interval_mapping[2] = {
  728. VMSTATE_MAPPING, /* value */
  729. VMSTATE_INTERVAL /* key */
  730. };
  731. typedef struct TestGTreeDomain {
  732. int32_t id;
  733. GTree *mappings;
  734. } TestGTreeDomain;
  735. typedef struct TestGTreeIOMMU {
  736. int32_t id;
  737. GTree *domains;
  738. } TestGTreeIOMMU;
  739. /* Interval comparison function */
  740. static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
  741. {
  742. TestGTreeInterval *inta = (TestGTreeInterval *)a;
  743. TestGTreeInterval *intb = (TestGTreeInterval *)b;
  744. if (inta->high < intb->low) {
  745. return -1;
  746. } else if (intb->high < inta->low) {
  747. return 1;
  748. } else {
  749. return 0;
  750. }
  751. }
  752. /* ID comparison function */
  753. static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
  754. {
  755. uint ua = GPOINTER_TO_UINT(a);
  756. uint ub = GPOINTER_TO_UINT(b);
  757. return (ua > ub) - (ua < ub);
  758. }
  759. static void destroy_domain(gpointer data)
  760. {
  761. TestGTreeDomain *domain = (TestGTreeDomain *)data;
  762. g_tree_destroy(domain->mappings);
  763. g_free(domain);
  764. }
  765. static int domain_preload(void *opaque)
  766. {
  767. TestGTreeDomain *domain = opaque;
  768. domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
  769. NULL, g_free, g_free);
  770. return 0;
  771. }
  772. static int iommu_preload(void *opaque)
  773. {
  774. TestGTreeIOMMU *iommu = opaque;
  775. iommu->domains = g_tree_new_full((GCompareDataFunc)int_cmp,
  776. NULL, NULL, destroy_domain);
  777. return 0;
  778. }
  779. static const VMStateDescription vmstate_domain = {
  780. .name = "domain",
  781. .version_id = 1,
  782. .minimum_version_id = 1,
  783. .pre_load = domain_preload,
  784. .fields = (VMStateField[]) {
  785. VMSTATE_INT32(id, TestGTreeDomain),
  786. VMSTATE_GTREE_V(mappings, TestGTreeDomain, 1,
  787. vmstate_interval_mapping,
  788. TestGTreeInterval, TestGTreeMapping),
  789. VMSTATE_END_OF_LIST()
  790. }
  791. };
  792. static const VMStateDescription vmstate_iommu = {
  793. .name = "iommu",
  794. .version_id = 1,
  795. .minimum_version_id = 1,
  796. .pre_load = iommu_preload,
  797. .fields = (VMStateField[]) {
  798. VMSTATE_INT32(id, TestGTreeIOMMU),
  799. VMSTATE_GTREE_DIRECT_KEY_V(domains, TestGTreeIOMMU, 1,
  800. &vmstate_domain, TestGTreeDomain),
  801. VMSTATE_END_OF_LIST()
  802. }
  803. };
  804. uint8_t first_domain_dump[] = {
  805. /* id */
  806. 0x00, 0x0, 0x0, 0x6,
  807. 0x00, 0x0, 0x0, 0x2, /* 2 mappings */
  808. 0x1, /* start of a */
  809. /* a */
  810. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  811. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
  812. /* map_a */
  813. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00,
  814. 0x00, 0x00, 0x00, 0x01,
  815. 0x1, /* start of b */
  816. /* b */
  817. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
  818. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0xFF,
  819. /* map_b */
  820. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
  821. 0x00, 0x00, 0x00, 0x02,
  822. 0x0, /* end of gtree */
  823. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  824. };
  825. static TestGTreeDomain *create_first_domain(void)
  826. {
  827. TestGTreeDomain *domain;
  828. TestGTreeMapping *map_a, *map_b;
  829. TestGTreeInterval *a, *b;
  830. domain = g_malloc0(sizeof(TestGTreeDomain));
  831. domain->id = 6;
  832. a = g_malloc0(sizeof(TestGTreeInterval));
  833. a->low = 0x1000;
  834. a->high = 0x1FFF;
  835. b = g_malloc0(sizeof(TestGTreeInterval));
  836. b->low = 0x4000;
  837. b->high = 0x4FFF;
  838. map_a = g_malloc0(sizeof(TestGTreeMapping));
  839. map_a->phys_addr = 0xa000;
  840. map_a->flags = 1;
  841. map_b = g_malloc0(sizeof(TestGTreeMapping));
  842. map_b->phys_addr = 0xe0000;
  843. map_b->flags = 2;
  844. domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp, NULL,
  845. (GDestroyNotify)g_free,
  846. (GDestroyNotify)g_free);
  847. g_tree_insert(domain->mappings, a, map_a);
  848. g_tree_insert(domain->mappings, b, map_b);
  849. return domain;
  850. }
  851. static void test_gtree_save_domain(void)
  852. {
  853. TestGTreeDomain *first_domain = create_first_domain();
  854. save_vmstate(&vmstate_domain, first_domain);
  855. compare_vmstate(first_domain_dump, sizeof(first_domain_dump));
  856. destroy_domain(first_domain);
  857. }
  858. struct match_node_data {
  859. GTree *tree;
  860. gpointer key;
  861. gpointer value;
  862. };
  863. struct tree_cmp_data {
  864. GTree *tree1;
  865. GTree *tree2;
  866. GTraverseFunc match_node;
  867. };
  868. static gboolean match_interval_mapping_node(gpointer key,
  869. gpointer value, gpointer data)
  870. {
  871. TestGTreeMapping *map_a, *map_b;
  872. TestGTreeInterval *a, *b;
  873. struct match_node_data *d = (struct match_node_data *)data;
  874. char *str = g_strdup_printf("dest");
  875. g_free(str);
  876. a = (TestGTreeInterval *)key;
  877. b = (TestGTreeInterval *)d->key;
  878. map_a = (TestGTreeMapping *)value;
  879. map_b = (TestGTreeMapping *)d->value;
  880. assert(a->low == b->low);
  881. assert(a->high == b->high);
  882. assert(map_a->phys_addr == map_b->phys_addr);
  883. assert(map_a->flags == map_b->flags);
  884. g_tree_remove(d->tree, key);
  885. return true;
  886. }
  887. static gboolean diff_tree(gpointer key, gpointer value, gpointer data)
  888. {
  889. struct tree_cmp_data *tp = (struct tree_cmp_data *)data;
  890. struct match_node_data d = {tp->tree2, key, value};
  891. g_tree_foreach(tp->tree2, tp->match_node, &d);
  892. g_tree_remove(tp->tree1, key);
  893. return false;
  894. }
  895. static void compare_trees(GTree *tree1, GTree *tree2,
  896. GTraverseFunc function)
  897. {
  898. struct tree_cmp_data tp = {tree1, tree2, function};
  899. g_tree_foreach(tree1, diff_tree, &tp);
  900. assert(g_tree_nnodes(tree1) == 0);
  901. assert(g_tree_nnodes(tree2) == 0);
  902. }
  903. static void diff_domain(TestGTreeDomain *d1, TestGTreeDomain *d2)
  904. {
  905. assert(d1->id == d2->id);
  906. compare_trees(d1->mappings, d2->mappings, match_interval_mapping_node);
  907. }
  908. static gboolean match_domain_node(gpointer key, gpointer value, gpointer data)
  909. {
  910. uint64_t id1, id2;
  911. TestGTreeDomain *d1, *d2;
  912. struct match_node_data *d = (struct match_node_data *)data;
  913. id1 = (uint64_t)(uintptr_t)key;
  914. id2 = (uint64_t)(uintptr_t)d->key;
  915. d1 = (TestGTreeDomain *)value;
  916. d2 = (TestGTreeDomain *)d->value;
  917. assert(id1 == id2);
  918. diff_domain(d1, d2);
  919. g_tree_remove(d->tree, key);
  920. return true;
  921. }
  922. static void diff_iommu(TestGTreeIOMMU *iommu1, TestGTreeIOMMU *iommu2)
  923. {
  924. assert(iommu1->id == iommu2->id);
  925. compare_trees(iommu1->domains, iommu2->domains, match_domain_node);
  926. }
  927. static void test_gtree_load_domain(void)
  928. {
  929. TestGTreeDomain *dest_domain = g_malloc0(sizeof(TestGTreeDomain));
  930. TestGTreeDomain *orig_domain = create_first_domain();
  931. QEMUFile *fload, *fsave;
  932. char eof;
  933. fsave = open_test_file(true);
  934. qemu_put_buffer(fsave, first_domain_dump, sizeof(first_domain_dump));
  935. g_assert(!qemu_file_get_error(fsave));
  936. qemu_fclose(fsave);
  937. fload = open_test_file(false);
  938. vmstate_load_state(fload, &vmstate_domain, dest_domain, 1);
  939. eof = qemu_get_byte(fload);
  940. g_assert(!qemu_file_get_error(fload));
  941. g_assert_cmpint(orig_domain->id, ==, dest_domain->id);
  942. g_assert_cmpint(eof, ==, QEMU_VM_EOF);
  943. diff_domain(orig_domain, dest_domain);
  944. destroy_domain(orig_domain);
  945. destroy_domain(dest_domain);
  946. qemu_fclose(fload);
  947. }
  948. uint8_t iommu_dump[] = {
  949. /* iommu id */
  950. 0x00, 0x0, 0x0, 0x7,
  951. 0x00, 0x0, 0x0, 0x2, /* 2 domains */
  952. 0x1,/* start of domain 5 */
  953. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x0, 0x5, /* key = 5 */
  954. 0x00, 0x0, 0x0, 0x5, /* domain1 id */
  955. 0x00, 0x0, 0x0, 0x1, /* 1 mapping */
  956. 0x1, /* start of mappings */
  957. /* c */
  958. 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  959. 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF,
  960. /* map_c */
  961. 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00,
  962. 0x00, 0x0, 0x0, 0x3,
  963. 0x0, /* end of domain1 mappings*/
  964. 0x1,/* start of domain 6 */
  965. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x0, 0x6, /* key = 6 */
  966. 0x00, 0x0, 0x0, 0x6, /* domain6 id */
  967. 0x00, 0x0, 0x0, 0x2, /* 2 mappings */
  968. 0x1, /* start of a */
  969. /* a */
  970. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  971. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
  972. /* map_a */
  973. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00,
  974. 0x00, 0x00, 0x00, 0x01,
  975. 0x1, /* start of b */
  976. /* b */
  977. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
  978. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0xFF,
  979. /* map_b */
  980. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00,
  981. 0x00, 0x00, 0x00, 0x02,
  982. 0x0, /* end of domain6 mappings*/
  983. 0x0, /* end of domains */
  984. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  985. };
  986. static TestGTreeIOMMU *create_iommu(void)
  987. {
  988. TestGTreeIOMMU *iommu = g_malloc0(sizeof(TestGTreeIOMMU));
  989. TestGTreeDomain *first_domain = create_first_domain();
  990. TestGTreeDomain *second_domain;
  991. TestGTreeMapping *map_c;
  992. TestGTreeInterval *c;
  993. iommu->id = 7;
  994. iommu->domains = g_tree_new_full((GCompareDataFunc)int_cmp, NULL,
  995. NULL,
  996. destroy_domain);
  997. second_domain = g_malloc0(sizeof(TestGTreeDomain));
  998. second_domain->id = 5;
  999. second_domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
  1000. NULL,
  1001. (GDestroyNotify)g_free,
  1002. (GDestroyNotify)g_free);
  1003. g_tree_insert(iommu->domains, GUINT_TO_POINTER(6), first_domain);
  1004. g_tree_insert(iommu->domains, (gpointer)0x0000000000000005, second_domain);
  1005. c = g_malloc0(sizeof(TestGTreeInterval));
  1006. c->low = 0x1000000;
  1007. c->high = 0x1FFFFFF;
  1008. map_c = g_malloc0(sizeof(TestGTreeMapping));
  1009. map_c->phys_addr = 0xF000000;
  1010. map_c->flags = 0x3;
  1011. g_tree_insert(second_domain->mappings, c, map_c);
  1012. return iommu;
  1013. }
  1014. static void destroy_iommu(TestGTreeIOMMU *iommu)
  1015. {
  1016. g_tree_destroy(iommu->domains);
  1017. g_free(iommu);
  1018. }
  1019. static void test_gtree_save_iommu(void)
  1020. {
  1021. TestGTreeIOMMU *iommu = create_iommu();
  1022. save_vmstate(&vmstate_iommu, iommu);
  1023. compare_vmstate(iommu_dump, sizeof(iommu_dump));
  1024. destroy_iommu(iommu);
  1025. }
  1026. static void test_gtree_load_iommu(void)
  1027. {
  1028. TestGTreeIOMMU *dest_iommu = g_malloc0(sizeof(TestGTreeIOMMU));
  1029. TestGTreeIOMMU *orig_iommu = create_iommu();
  1030. QEMUFile *fsave, *fload;
  1031. char eof;
  1032. int ret;
  1033. fsave = open_test_file(true);
  1034. qemu_put_buffer(fsave, iommu_dump, sizeof(iommu_dump));
  1035. g_assert(!qemu_file_get_error(fsave));
  1036. qemu_fclose(fsave);
  1037. fload = open_test_file(false);
  1038. vmstate_load_state(fload, &vmstate_iommu, dest_iommu, 1);
  1039. ret = qemu_file_get_error(fload);
  1040. eof = qemu_get_byte(fload);
  1041. ret = qemu_file_get_error(fload);
  1042. g_assert(!ret);
  1043. g_assert_cmpint(orig_iommu->id, ==, dest_iommu->id);
  1044. g_assert_cmpint(eof, ==, QEMU_VM_EOF);
  1045. diff_iommu(orig_iommu, dest_iommu);
  1046. destroy_iommu(orig_iommu);
  1047. destroy_iommu(dest_iommu);
  1048. qemu_fclose(fload);
  1049. }
  1050. typedef struct TmpTestStruct {
  1051. TestStruct *parent;
  1052. int64_t diff;
  1053. } TmpTestStruct;
  1054. static int tmp_child_pre_save(void *opaque)
  1055. {
  1056. struct TmpTestStruct *tts = opaque;
  1057. tts->diff = tts->parent->b - tts->parent->a;
  1058. return 0;
  1059. }
  1060. static int tmp_child_post_load(void *opaque, int version_id)
  1061. {
  1062. struct TmpTestStruct *tts = opaque;
  1063. tts->parent->b = tts->parent->a + tts->diff;
  1064. return 0;
  1065. }
  1066. static const VMStateDescription vmstate_tmp_back_to_parent = {
  1067. .name = "test/tmp_child_parent",
  1068. .fields = (VMStateField[]) {
  1069. VMSTATE_UINT64(f, TestStruct),
  1070. VMSTATE_END_OF_LIST()
  1071. }
  1072. };
  1073. static const VMStateDescription vmstate_tmp_child = {
  1074. .name = "test/tmp_child",
  1075. .pre_save = tmp_child_pre_save,
  1076. .post_load = tmp_child_post_load,
  1077. .fields = (VMStateField[]) {
  1078. VMSTATE_INT64(diff, TmpTestStruct),
  1079. VMSTATE_STRUCT_POINTER(parent, TmpTestStruct,
  1080. vmstate_tmp_back_to_parent, TestStruct),
  1081. VMSTATE_END_OF_LIST()
  1082. }
  1083. };
  1084. static const VMStateDescription vmstate_with_tmp = {
  1085. .name = "test/with_tmp",
  1086. .version_id = 1,
  1087. .fields = (VMStateField[]) {
  1088. VMSTATE_UINT32(a, TestStruct),
  1089. VMSTATE_UINT64(d, TestStruct),
  1090. VMSTATE_WITH_TMP(TestStruct, TmpTestStruct, vmstate_tmp_child),
  1091. VMSTATE_END_OF_LIST()
  1092. }
  1093. };
  1094. static void obj_tmp_copy(void *target, void *source)
  1095. {
  1096. memcpy(target, source, sizeof(TestStruct));
  1097. }
  1098. static void test_tmp_struct(void)
  1099. {
  1100. TestStruct obj, obj_clone;
  1101. uint8_t const wire_with_tmp[] = {
  1102. /* u32 a */ 0x00, 0x00, 0x00, 0x02,
  1103. /* u64 d */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
  1104. /* diff */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
  1105. /* u64 f */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
  1106. QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
  1107. };
  1108. memset(&obj, 0, sizeof(obj));
  1109. obj.a = 2;
  1110. obj.b = 4;
  1111. obj.d = 1;
  1112. obj.f = 8;
  1113. save_vmstate(&vmstate_with_tmp, &obj);
  1114. compare_vmstate(wire_with_tmp, sizeof(wire_with_tmp));
  1115. memset(&obj, 0, sizeof(obj));
  1116. SUCCESS(load_vmstate(&vmstate_with_tmp, &obj, &obj_clone,
  1117. obj_tmp_copy, 1, wire_with_tmp,
  1118. sizeof(wire_with_tmp)));
  1119. g_assert_cmpint(obj.a, ==, 2); /* From top level vmsd */
  1120. g_assert_cmpint(obj.b, ==, 4); /* from the post_load */
  1121. g_assert_cmpint(obj.d, ==, 1); /* From top level vmsd */
  1122. g_assert_cmpint(obj.f, ==, 8); /* From the child->parent */
  1123. }
  1124. int main(int argc, char **argv)
  1125. {
  1126. temp_fd = mkstemp(temp_file);
  1127. module_call_init(MODULE_INIT_QOM);
  1128. setenv("QTEST_SILENT_ERRORS", "1", 1);
  1129. g_test_init(&argc, &argv, NULL);
  1130. g_test_add_func("/vmstate/simple/primitive", test_simple_primitive);
  1131. g_test_add_func("/vmstate/simple/array", test_simple_array);
  1132. g_test_add_func("/vmstate/versioned/load/v1", test_load_v1);
  1133. g_test_add_func("/vmstate/versioned/load/v2", test_load_v2);
  1134. g_test_add_func("/vmstate/field_exists/load/noskip", test_load_noskip);
  1135. g_test_add_func("/vmstate/field_exists/load/skip", test_load_skip);
  1136. g_test_add_func("/vmstate/field_exists/save/noskip", test_save_noskip);
  1137. g_test_add_func("/vmstate/field_exists/save/skip", test_save_skip);
  1138. g_test_add_func("/vmstate/array/ptr/str/no0/save",
  1139. test_arr_ptr_str_no0_save);
  1140. g_test_add_func("/vmstate/array/ptr/str/no0/load",
  1141. test_arr_ptr_str_no0_load);
  1142. g_test_add_func("/vmstate/array/ptr/str/0/save", test_arr_ptr_str_0_save);
  1143. g_test_add_func("/vmstate/array/ptr/str/0/load",
  1144. test_arr_ptr_str_0_load);
  1145. g_test_add_func("/vmstate/array/ptr/prim/0/save",
  1146. test_arr_ptr_prim_0_save);
  1147. g_test_add_func("/vmstate/array/ptr/prim/0/load",
  1148. test_arr_ptr_prim_0_load);
  1149. g_test_add_func("/vmstate/qtailq/save/saveq", test_save_q);
  1150. g_test_add_func("/vmstate/qtailq/load/loadq", test_load_q);
  1151. g_test_add_func("/vmstate/gtree/save/savedomain", test_gtree_save_domain);
  1152. g_test_add_func("/vmstate/gtree/load/loaddomain", test_gtree_load_domain);
  1153. g_test_add_func("/vmstate/gtree/save/saveiommu", test_gtree_save_iommu);
  1154. g_test_add_func("/vmstate/gtree/load/loadiommu", test_gtree_load_iommu);
  1155. g_test_add_func("/vmstate/tmp_struct", test_tmp_struct);
  1156. g_test_run();
  1157. close(temp_fd);
  1158. unlink(temp_file);
  1159. return 0;
  1160. }