2
0

endianness-test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * QTest testcase for ISA endianness
  3. *
  4. * Copyright Red Hat, Inc. 2012
  5. *
  6. * Authors:
  7. * Paolo Bonzini <pbonzini@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 "libqtest.h"
  15. #include "qemu/bswap.h"
  16. typedef struct TestCase TestCase;
  17. struct TestCase {
  18. const char *arch;
  19. const char *machine;
  20. uint64_t isa_base;
  21. bool bswap;
  22. const char *superio;
  23. };
  24. static const TestCase test_cases[] = {
  25. { "i386", "pc", -1 },
  26. { "mips", "mips", 0x14000000, .bswap = true },
  27. { "mips", "malta", 0x10000000, .bswap = true },
  28. { "mips64", "magnum", 0x90000000, .bswap = true },
  29. { "mips64", "pica61", 0x90000000, .bswap = true },
  30. { "mips64", "mips", 0x14000000, .bswap = true },
  31. { "mips64", "malta", 0x10000000, .bswap = true },
  32. { "mips64el", "fulong2e", 0x1fd00000 },
  33. { "ppc", "g3beige", 0xfe000000, .bswap = true, .superio = "i82378" },
  34. { "ppc", "prep", 0x80000000, .bswap = true },
  35. { "ppc", "bamboo", 0xe8000000, .bswap = true, .superio = "i82378" },
  36. { "ppc64", "mac99", 0xf2000000, .bswap = true, .superio = "i82378" },
  37. { "ppc64", "pseries", (1ULL << 45), .bswap = true, .superio = "i82378" },
  38. { "ppc64", "pseries-2.7", 0x10080000000ULL,
  39. .bswap = true, .superio = "i82378" },
  40. { "sh4", "r2d", 0xfe240000, .superio = "i82378" },
  41. { "sh4eb", "r2d", 0xfe240000, .bswap = true, .superio = "i82378" },
  42. { "sparc64", "sun4u", 0x1fe02000000LL, .bswap = true },
  43. { "x86_64", "pc", -1 },
  44. {}
  45. };
  46. static uint8_t isa_inb(QTestState *qts, const TestCase *test, uint16_t addr)
  47. {
  48. uint8_t value;
  49. if (test->isa_base == -1) {
  50. value = qtest_inb(qts, addr);
  51. } else {
  52. value = qtest_readb(qts, test->isa_base + addr);
  53. }
  54. return value;
  55. }
  56. static uint16_t isa_inw(QTestState *qts, const TestCase *test, uint16_t addr)
  57. {
  58. uint16_t value;
  59. if (test->isa_base == -1) {
  60. value = qtest_inw(qts, addr);
  61. } else {
  62. value = qtest_readw(qts, test->isa_base + addr);
  63. }
  64. return test->bswap ? bswap16(value) : value;
  65. }
  66. static uint32_t isa_inl(QTestState *qts, const TestCase *test, uint16_t addr)
  67. {
  68. uint32_t value;
  69. if (test->isa_base == -1) {
  70. value = qtest_inl(qts, addr);
  71. } else {
  72. value = qtest_readl(qts, test->isa_base + addr);
  73. }
  74. return test->bswap ? bswap32(value) : value;
  75. }
  76. static void isa_outb(QTestState *qts, const TestCase *test, uint16_t addr,
  77. uint8_t value)
  78. {
  79. if (test->isa_base == -1) {
  80. qtest_outb(qts, addr, value);
  81. } else {
  82. qtest_writeb(qts, test->isa_base + addr, value);
  83. }
  84. }
  85. static void isa_outw(QTestState *qts, const TestCase *test, uint16_t addr,
  86. uint16_t value)
  87. {
  88. value = test->bswap ? bswap16(value) : value;
  89. if (test->isa_base == -1) {
  90. qtest_outw(qts, addr, value);
  91. } else {
  92. qtest_writew(qts, test->isa_base + addr, value);
  93. }
  94. }
  95. static void isa_outl(QTestState *qts, const TestCase *test, uint16_t addr,
  96. uint32_t value)
  97. {
  98. value = test->bswap ? bswap32(value) : value;
  99. if (test->isa_base == -1) {
  100. qtest_outl(qts, addr, value);
  101. } else {
  102. qtest_writel(qts, test->isa_base + addr, value);
  103. }
  104. }
  105. static void test_endianness(gconstpointer data)
  106. {
  107. const TestCase *test = data;
  108. QTestState *qts;
  109. qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
  110. test->superio ? " -device " : "",
  111. test->superio ?: "");
  112. isa_outl(qts, test, 0xe0, 0x87654321);
  113. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
  114. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  115. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  116. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
  117. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
  118. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
  119. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
  120. isa_outw(qts, test, 0xe2, 0x8866);
  121. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664321);
  122. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
  123. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  124. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x88);
  125. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
  126. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
  127. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
  128. isa_outw(qts, test, 0xe0, 0x4422);
  129. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664422);
  130. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
  131. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
  132. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x88);
  133. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
  134. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
  135. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
  136. isa_outb(qts, test, 0xe3, 0x87);
  137. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87664422);
  138. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8766);
  139. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
  140. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x66);
  141. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
  142. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
  143. isa_outb(qts, test, 0xe2, 0x65);
  144. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654422);
  145. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  146. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
  147. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
  148. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
  149. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x44);
  150. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
  151. isa_outb(qts, test, 0xe1, 0x43);
  152. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654322);
  153. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  154. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4322);
  155. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
  156. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
  157. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
  158. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x22);
  159. isa_outb(qts, test, 0xe0, 0x21);
  160. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
  161. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  162. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  163. g_assert_cmphex(isa_inb(qts, test, 0xe3), ==, 0x87);
  164. g_assert_cmphex(isa_inb(qts, test, 0xe2), ==, 0x65);
  165. g_assert_cmphex(isa_inb(qts, test, 0xe1), ==, 0x43);
  166. g_assert_cmphex(isa_inb(qts, test, 0xe0), ==, 0x21);
  167. qtest_quit(qts);
  168. }
  169. static void test_endianness_split(gconstpointer data)
  170. {
  171. const TestCase *test = data;
  172. QTestState *qts;
  173. qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
  174. test->superio ? " -device " : "",
  175. test->superio ?: "");
  176. isa_outl(qts, test, 0xe8, 0x87654321);
  177. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
  178. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  179. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  180. isa_outw(qts, test, 0xea, 0x8866);
  181. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664321);
  182. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
  183. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  184. isa_outw(qts, test, 0xe8, 0x4422);
  185. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x88664422);
  186. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8866);
  187. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
  188. isa_outb(qts, test, 0xeb, 0x87);
  189. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87664422);
  190. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8766);
  191. isa_outb(qts, test, 0xea, 0x65);
  192. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654422);
  193. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  194. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4422);
  195. isa_outb(qts, test, 0xe9, 0x43);
  196. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654322);
  197. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  198. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4322);
  199. isa_outb(qts, test, 0xe8, 0x21);
  200. g_assert_cmphex(isa_inl(qts, test, 0xe0), ==, 0x87654321);
  201. g_assert_cmphex(isa_inw(qts, test, 0xe2), ==, 0x8765);
  202. g_assert_cmphex(isa_inw(qts, test, 0xe0), ==, 0x4321);
  203. qtest_quit(qts);
  204. }
  205. static void test_endianness_combine(gconstpointer data)
  206. {
  207. const TestCase *test = data;
  208. QTestState *qts;
  209. qts = qtest_initf("-M %s%s%s -device pc-testdev", test->machine,
  210. test->superio ? " -device " : "",
  211. test->superio ?: "");
  212. isa_outl(qts, test, 0xe0, 0x87654321);
  213. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654321);
  214. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
  215. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
  216. isa_outw(qts, test, 0xe2, 0x8866);
  217. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x88664321);
  218. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8866);
  219. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
  220. isa_outw(qts, test, 0xe0, 0x4422);
  221. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x88664422);
  222. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8866);
  223. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4422);
  224. isa_outb(qts, test, 0xe3, 0x87);
  225. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87664422);
  226. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8766);
  227. isa_outb(qts, test, 0xe2, 0x65);
  228. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654422);
  229. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
  230. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4422);
  231. isa_outb(qts, test, 0xe1, 0x43);
  232. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654322);
  233. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
  234. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4322);
  235. isa_outb(qts, test, 0xe0, 0x21);
  236. g_assert_cmphex(isa_inl(qts, test, 0xe8), ==, 0x87654321);
  237. g_assert_cmphex(isa_inw(qts, test, 0xea), ==, 0x8765);
  238. g_assert_cmphex(isa_inw(qts, test, 0xe8), ==, 0x4321);
  239. qtest_quit(qts);
  240. }
  241. int main(int argc, char **argv)
  242. {
  243. const char *arch = qtest_get_arch();
  244. int i;
  245. g_test_init(&argc, &argv, NULL);
  246. for (i = 0; test_cases[i].arch; i++) {
  247. gchar *path;
  248. if (strcmp(test_cases[i].arch, arch) != 0) {
  249. continue;
  250. }
  251. path = g_strdup_printf("endianness/%s",
  252. test_cases[i].machine);
  253. qtest_add_data_func(path, &test_cases[i], test_endianness);
  254. g_free(path);
  255. path = g_strdup_printf("endianness/split/%s",
  256. test_cases[i].machine);
  257. qtest_add_data_func(path, &test_cases[i], test_endianness_split);
  258. g_free(path);
  259. path = g_strdup_printf("endianness/combine/%s",
  260. test_cases[i].machine);
  261. qtest_add_data_func(path, &test_cases[i], test_endianness_combine);
  262. g_free(path);
  263. }
  264. return g_test_run();
  265. }