| 1 | /* |
| 2 | * QTest testcase for CXL |
| 3 | * |
| 4 | * This work is licensed under the terms of the GNU GPL, version 2 or later. |
| 5 | * See the COPYING file in the top-level directory. |
| 6 | */ |
| 7 | |
| 8 | #include "qemu/osdep.h" |
| 9 | #include "libqtest-single.h" |
| 10 | |
| 11 | #define QEMU_PXB_CMD \ |
| 12 | "-machine q35,cxl=on " \ |
| 13 | "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \ |
| 14 | "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.size=4G " |
| 15 | |
| 16 | #define QEMU_2PXB_CMD \ |
| 17 | "-machine q35,cxl=on " \ |
| 18 | "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \ |
| 19 | "-device pxb-cxl,id=cxl.1,bus=pcie.0,bus_nr=53 " \ |
| 20 | "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=4G " |
| 21 | |
| 22 | #define QEMU_VIRT_2PXB_CMD \ |
| 23 | "-machine virt,cxl=on -cpu max " \ |
| 24 | "-device pxb-cxl,id=cxl.0,bus=pcie.0,bus_nr=52 " \ |
| 25 | "-device pxb-cxl,id=cxl.1,bus=pcie.0,bus_nr=53 " \ |
| 26 | "-M cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=4G " |
| 27 | |
| 28 | #define QEMU_RP \ |
| 29 | "-device cxl-rp,id=rp0,bus=cxl.0,chassis=0,slot=0 " |
| 30 | |
| 31 | /* Dual ports on first pxb */ |
| 32 | #define QEMU_2RP \ |
| 33 | "-device cxl-rp,id=rp0,bus=cxl.0,chassis=0,slot=0 " \ |
| 34 | "-device cxl-rp,id=rp1,bus=cxl.0,chassis=0,slot=1 " |
| 35 | |
| 36 | /* Dual ports on each of the pxb instances */ |
| 37 | #define QEMU_4RP \ |
| 38 | "-device cxl-rp,id=rp0,bus=cxl.0,chassis=0,slot=0 " \ |
| 39 | "-device cxl-rp,id=rp1,bus=cxl.0,chassis=0,slot=1 " \ |
| 40 | "-device cxl-rp,id=rp2,bus=cxl.1,chassis=0,slot=2 " \ |
| 41 | "-device cxl-rp,id=rp3,bus=cxl.1,chassis=0,slot=3 " |
| 42 | |
| 43 | #define QEMU_T3D_DEPRECATED \ |
| 44 | "-object memory-backend-file,id=cxl-mem0,mem-path=%s,size=256M " \ |
| 45 | "-object memory-backend-file,id=lsa0,mem-path=%s,size=256M " \ |
| 46 | "-device cxl-type3,bus=rp0,memdev=cxl-mem0,lsa=lsa0,id=cxl-pmem0 " |
| 47 | |
| 48 | #define QEMU_T3D_PMEM \ |
| 49 | "-object memory-backend-file,id=cxl-mem0,mem-path=%s,size=256M " \ |
| 50 | "-object memory-backend-file,id=lsa0,mem-path=%s,size=256M " \ |
| 51 | "-device cxl-type3,bus=rp0,persistent-memdev=cxl-mem0,lsa=lsa0,id=pmem0 " |
| 52 | |
| 53 | #define QEMU_T3D_VMEM \ |
| 54 | "-object memory-backend-ram,id=cxl-mem0,size=256M " \ |
| 55 | "-device cxl-type3,bus=rp0,volatile-memdev=cxl-mem0,id=mem0 " |
| 56 | |
| 57 | #define QEMU_T3D_VMEM_LSA \ |
| 58 | "-object memory-backend-ram,id=cxl-mem0,size=256M " \ |
| 59 | "-object memory-backend-file,id=lsa0,mem-path=%s,size=256M " \ |
| 60 | "-device cxl-type3,bus=rp0,volatile-memdev=cxl-mem0,lsa=lsa0,id=mem0 " |
| 61 | |
| 62 | #define QEMU_2T3D \ |
| 63 | "-object memory-backend-file,id=cxl-mem0,mem-path=%s,size=256M " \ |
| 64 | "-object memory-backend-file,id=lsa0,mem-path=%s,size=256M " \ |
| 65 | "-device cxl-type3,bus=rp0,persistent-memdev=cxl-mem0,lsa=lsa0,id=pmem0 " \ |
| 66 | "-object memory-backend-file,id=cxl-mem1,mem-path=%s,size=256M " \ |
| 67 | "-object memory-backend-file,id=lsa1,mem-path=%s,size=256M " \ |
| 68 | "-device cxl-type3,bus=rp1,persistent-memdev=cxl-mem1,lsa=lsa1,id=pmem1 " |
| 69 | |
| 70 | #define QEMU_4T3D \ |
| 71 | "-object memory-backend-file,id=cxl-mem0,mem-path=%s,size=256M " \ |
| 72 | "-object memory-backend-file,id=lsa0,mem-path=%s,size=256M " \ |
| 73 | "-device cxl-type3,bus=rp0,persistent-memdev=cxl-mem0,lsa=lsa0,id=pmem0 " \ |
| 74 | "-object memory-backend-file,id=cxl-mem1,mem-path=%s,size=256M " \ |
| 75 | "-object memory-backend-file,id=lsa1,mem-path=%s,size=256M " \ |
| 76 | "-device cxl-type3,bus=rp1,persistent-memdev=cxl-mem1,lsa=lsa1,id=pmem1 " \ |
| 77 | "-object memory-backend-file,id=cxl-mem2,mem-path=%s,size=256M " \ |
| 78 | "-object memory-backend-file,id=lsa2,mem-path=%s,size=256M " \ |
| 79 | "-device cxl-type3,bus=rp2,persistent-memdev=cxl-mem2,lsa=lsa2,id=pmem2 " \ |
| 80 | "-object memory-backend-file,id=cxl-mem3,mem-path=%s,size=256M " \ |
| 81 | "-object memory-backend-file,id=lsa3,mem-path=%s,size=256M " \ |
| 82 | "-device cxl-type3,bus=rp3,persistent-memdev=cxl-mem3,lsa=lsa3,id=pmem3 " |
| 83 | |
| 84 | static void cxl_basic_hb(void) |
| 85 | { |
| 86 | qtest_start("-machine q35,cxl=on"); |
| 87 | qtest_end(); |
| 88 | } |
| 89 | |
| 90 | static void cxl_basic_pxb(void) |
| 91 | { |
| 92 | qtest_start("-machine q35,cxl=on -device pxb-cxl,bus=pcie.0"); |
| 93 | qtest_end(); |
| 94 | } |
| 95 | |
| 96 | static void cxl_pxb_with_window(void) |
| 97 | { |
| 98 | qtest_start(QEMU_PXB_CMD); |
| 99 | qtest_end(); |
| 100 | } |
| 101 | |
| 102 | static void cxl_2pxb_with_window(void) |
| 103 | { |
| 104 | qtest_start(QEMU_2PXB_CMD); |
| 105 | qtest_end(); |
| 106 | } |
| 107 | |
| 108 | static void cxl_root_port(void) |
| 109 | { |
| 110 | qtest_start(QEMU_PXB_CMD QEMU_RP); |
| 111 | qtest_end(); |
| 112 | } |
| 113 | |
| 114 | static void cxl_2root_port(void) |
| 115 | { |
| 116 | qtest_start(QEMU_PXB_CMD QEMU_2RP); |
| 117 | qtest_end(); |
| 118 | } |
| 119 | |
| 120 | #ifdef CONFIG_POSIX |
| 121 | static void cxl_t3d_deprecated(void) |
| 122 | { |
| 123 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 124 | g_autofree const char *tmpfs = NULL; |
| 125 | |
| 126 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 127 | |
| 128 | g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D_DEPRECATED, |
| 129 | tmpfs, tmpfs); |
| 130 | |
| 131 | qtest_start(cmdline->str); |
| 132 | qtest_end(); |
| 133 | rmdir(tmpfs); |
| 134 | } |
| 135 | |
| 136 | static void cxl_t3d_persistent(void) |
| 137 | { |
| 138 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 139 | g_autofree const char *tmpfs = NULL; |
| 140 | |
| 141 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 142 | |
| 143 | g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D_PMEM, |
| 144 | tmpfs, tmpfs); |
| 145 | |
| 146 | qtest_start(cmdline->str); |
| 147 | qtest_end(); |
| 148 | rmdir(tmpfs); |
| 149 | } |
| 150 | |
| 151 | static void cxl_t3d_volatile(void) |
| 152 | { |
| 153 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 154 | |
| 155 | g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D_VMEM); |
| 156 | |
| 157 | qtest_start(cmdline->str); |
| 158 | qtest_end(); |
| 159 | } |
| 160 | |
| 161 | static void cxl_t3d_volatile_lsa(void) |
| 162 | { |
| 163 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 164 | g_autofree const char *tmpfs = NULL; |
| 165 | |
| 166 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 167 | |
| 168 | g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D_VMEM_LSA, |
| 169 | tmpfs); |
| 170 | |
| 171 | qtest_start(cmdline->str); |
| 172 | qtest_end(); |
| 173 | rmdir(tmpfs); |
| 174 | } |
| 175 | |
| 176 | static void cxl_1pxb_2rp_2t3d(void) |
| 177 | { |
| 178 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 179 | g_autofree const char *tmpfs = NULL; |
| 180 | |
| 181 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 182 | |
| 183 | g_string_printf(cmdline, QEMU_PXB_CMD QEMU_2RP QEMU_2T3D, |
| 184 | tmpfs, tmpfs, tmpfs, tmpfs); |
| 185 | |
| 186 | qtest_start(cmdline->str); |
| 187 | qtest_end(); |
| 188 | rmdir(tmpfs); |
| 189 | } |
| 190 | |
| 191 | static void cxl_2pxb_4rp_4t3d(void) |
| 192 | { |
| 193 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 194 | g_autofree const char *tmpfs = NULL; |
| 195 | |
| 196 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 197 | |
| 198 | g_string_printf(cmdline, QEMU_2PXB_CMD QEMU_4RP QEMU_4T3D, |
| 199 | tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, |
| 200 | tmpfs, tmpfs); |
| 201 | |
| 202 | qtest_start(cmdline->str); |
| 203 | qtest_end(); |
| 204 | rmdir(tmpfs); |
| 205 | } |
| 206 | |
| 207 | static void cxl_virt_2pxb_4rp_4t3d(void) |
| 208 | { |
| 209 | g_autoptr(GString) cmdline = g_string_new(NULL); |
| 210 | g_autofree const char *tmpfs = NULL; |
| 211 | |
| 212 | tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); |
| 213 | |
| 214 | g_string_printf(cmdline, QEMU_VIRT_2PXB_CMD QEMU_4RP QEMU_4T3D, |
| 215 | tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, |
| 216 | tmpfs, tmpfs); |
| 217 | |
| 218 | qtest_start(cmdline->str); |
| 219 | qtest_end(); |
| 220 | rmdir(tmpfs); |
| 221 | } |
| 222 | #endif /* CONFIG_POSIX */ |
| 223 | |
| 224 | int main(int argc, char **argv) |
| 225 | { |
| 226 | const char *arch = qtest_get_arch(); |
| 227 | |
| 228 | g_test_init(&argc, &argv, NULL); |
| 229 | if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { |
| 230 | qtest_add_func("/pci/cxl/basic_hostbridge", cxl_basic_hb); |
| 231 | qtest_add_func("/pci/cxl/basic_pxb", cxl_basic_pxb); |
| 232 | qtest_add_func("/pci/cxl/pxb_with_window", cxl_pxb_with_window); |
| 233 | qtest_add_func("/pci/cxl/pxb_x2_with_window", cxl_2pxb_with_window); |
| 234 | qtest_add_func("/pci/cxl/rp", cxl_root_port); |
| 235 | qtest_add_func("/pci/cxl/rp_x2", cxl_2root_port); |
| 236 | #ifdef CONFIG_POSIX |
| 237 | qtest_add_func("/pci/cxl/type3_device", cxl_t3d_deprecated); |
| 238 | qtest_add_func("/pci/cxl/type3_device_pmem", cxl_t3d_persistent); |
| 239 | qtest_add_func("/pci/cxl/type3_device_vmem", cxl_t3d_volatile); |
| 240 | qtest_add_func("/pci/cxl/type3_device_vmem_lsa", cxl_t3d_volatile_lsa); |
| 241 | qtest_add_func("/pci/cxl/rp_x2_type3_x2", cxl_1pxb_2rp_2t3d); |
| 242 | qtest_add_func("/pci/cxl/pxb_x2_root_port_x4_type3_x4", |
| 243 | cxl_2pxb_4rp_4t3d); |
| 244 | #endif |
| 245 | } else if (strcmp(arch, "aarch64") == 0) { |
| 246 | #ifdef CONFIG_POSIX |
| 247 | qtest_add_func("/pci/cxl/virt/pxb_x2_root_port_x4_type3_x4", |
| 248 | cxl_virt_2pxb_4rp_4t3d); |
| 249 | #endif |
| 250 | } |
| 251 | |
| 252 | return g_test_run(); |
| 253 | } |