1 /* 2 * Copyright (c) 2017-2019, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "ptunit.h" 30 31 #include "pt_msec_cache.h" 32 33 #include "intel-pt.h" 34 35 36 int pt_section_get(struct pt_section *section) 37 { 38 uint16_t ucount; 39 40 if (!section) 41 return -pte_internal; 42 43 ucount = section->ucount + 1; 44 if (!ucount) 45 return -pte_overflow; 46 47 section->ucount = ucount; 48 return 0; 49 } 50 51 int pt_section_put(struct pt_section *section) 52 { 53 uint16_t ucount; 54 55 if (!section) 56 return -pte_internal; 57 58 ucount = section->ucount; 59 if (!ucount) 60 return -pte_overflow; 61 62 section->ucount = ucount - 1; 63 return 0; 64 } 65 66 int pt_section_map(struct pt_section *section) 67 { 68 uint16_t ucount, mcount; 69 70 if (!section) 71 return -pte_internal; 72 73 ucount = section->ucount; 74 if (!ucount) 75 return -pte_internal; 76 77 mcount = section->mcount + 1; 78 if (!mcount) 79 return -pte_overflow; 80 81 section->mcount = mcount; 82 return 0; 83 } 84 85 int pt_section_unmap(struct pt_section *section) 86 { 87 uint16_t ucount, mcount; 88 89 if (!section) 90 return -pte_internal; 91 92 ucount = section->ucount; 93 if (!ucount) 94 return -pte_internal; 95 96 mcount = section->mcount; 97 if (!mcount) 98 return -pte_overflow; 99 100 section->mcount = mcount - 1; 101 return 0; 102 } 103 104 /* A mock image. */ 105 struct pt_image { 106 /* The section stored in the image. 107 * 108 * This is either the fixture's section or NULL. 109 */ 110 struct pt_section *section; 111 }; 112 113 extern int pt_image_validate(struct pt_image *, struct pt_mapped_section *, 114 uint64_t, int); 115 extern int pt_image_find(struct pt_image *, struct pt_mapped_section *, 116 const struct pt_asid *, uint64_t); 117 118 int pt_image_validate(struct pt_image *image, struct pt_mapped_section *msec, 119 uint64_t vaddr, int isid) 120 { 121 struct pt_section *section; 122 123 (void) vaddr; 124 (void) isid; 125 126 if (!image || !msec) 127 return -pte_internal; 128 129 section = image->section; 130 if (!section) 131 return -pte_nomap; 132 133 if (section != msec->section) 134 return -pte_nomap; 135 136 return 0; 137 } 138 139 int pt_image_find(struct pt_image *image, struct pt_mapped_section *msec, 140 const struct pt_asid *asid, uint64_t vaddr) 141 { 142 struct pt_section *section; 143 144 (void) vaddr; 145 146 if (!image || !msec || !asid) 147 return -pte_internal; 148 149 section = image->section; 150 if (!section) 151 return -pte_nomap; 152 153 if (msec->section) 154 return -pte_internal; 155 156 msec->section = section; 157 158 return pt_section_get(section); 159 } 160 161 /* A test fixture providing a section and checking the use and map count. */ 162 struct test_fixture { 163 /* A test section. */ 164 struct pt_section section; 165 166 /* A test cache. */ 167 struct pt_msec_cache mcache; 168 169 /* A test image. */ 170 struct pt_image image; 171 172 /* The test fixture initialization and finalization functions. */ 173 struct ptunit_result (*init)(struct test_fixture *); 174 struct ptunit_result (*fini)(struct test_fixture *); 175 }; 176 177 static struct ptunit_result init_null(void) 178 { 179 int status; 180 181 status = pt_msec_cache_init(NULL); 182 ptu_int_eq(status, -pte_internal); 183 184 return ptu_passed(); 185 } 186 187 static struct ptunit_result fini_null(void) 188 { 189 pt_msec_cache_fini(NULL); 190 191 return ptu_passed(); 192 } 193 194 static struct ptunit_result invalidate_null(void) 195 { 196 int status; 197 198 status = pt_msec_cache_invalidate(NULL); 199 ptu_int_eq(status, -pte_internal); 200 201 return ptu_passed(); 202 } 203 204 static struct ptunit_result read_null(void) 205 { 206 const struct pt_mapped_section *msec; 207 struct pt_msec_cache mcache; 208 struct pt_image image; 209 int status; 210 211 status = pt_msec_cache_read(NULL, &msec, &image, 0ull); 212 ptu_int_eq(status, -pte_internal); 213 214 status = pt_msec_cache_read(&mcache, NULL, &image, 0ull); 215 ptu_int_eq(status, -pte_internal); 216 217 status = pt_msec_cache_read(&mcache, &msec, NULL, 0ull); 218 ptu_int_eq(status, -pte_internal); 219 220 return ptu_passed(); 221 } 222 223 static struct ptunit_result fill_null(void) 224 { 225 const struct pt_mapped_section *msec; 226 struct pt_msec_cache mcache; 227 struct pt_image image; 228 struct pt_asid asid; 229 int status; 230 231 memset(&mcache, 0, sizeof(mcache)); 232 233 status = pt_msec_cache_fill(NULL, &msec, &image, &asid, 0ull); 234 ptu_int_eq(status, -pte_internal); 235 236 status = pt_msec_cache_fill(&mcache, NULL, &image, &asid, 0ull); 237 ptu_int_eq(status, -pte_internal); 238 239 status = pt_msec_cache_fill(&mcache, &msec, NULL, &asid, 0ull); 240 ptu_int_eq(status, -pte_internal); 241 242 status = pt_msec_cache_fill(&mcache, &msec, &image, NULL, 0ull); 243 ptu_int_eq(status, -pte_internal); 244 245 return ptu_passed(); 246 } 247 248 static struct ptunit_result invalidate(struct test_fixture *tfix) 249 { 250 struct pt_section *section; 251 int status; 252 253 status = pt_msec_cache_invalidate(&tfix->mcache); 254 ptu_int_eq(status, 0); 255 256 section = pt_msec_section(&tfix->mcache.msec); 257 ptu_null(section); 258 259 ptu_uint_eq(tfix->section.mcount, 0); 260 ptu_uint_eq(tfix->section.ucount, 0); 261 262 return ptu_passed(); 263 } 264 265 static struct ptunit_result read_nomap(struct test_fixture *tfix) 266 { 267 const struct pt_mapped_section *msec; 268 int status; 269 270 msec = NULL; 271 272 status = pt_msec_cache_read(&tfix->mcache, &msec, &tfix->image, 0ull); 273 ptu_int_eq(status, -pte_nomap); 274 ptu_null(msec); 275 276 return ptu_passed(); 277 } 278 279 static struct ptunit_result read(struct test_fixture *tfix) 280 { 281 const struct pt_mapped_section *msec; 282 struct pt_section *section; 283 int status; 284 285 status = pt_msec_cache_read(&tfix->mcache, &msec, &tfix->image, 0ull); 286 ptu_int_eq(status, 0); 287 288 ptu_ptr_eq(msec, &tfix->mcache.msec); 289 290 section = pt_msec_section(msec); 291 ptu_ptr_eq(section, &tfix->section); 292 293 return ptu_passed(); 294 } 295 296 static struct ptunit_result fill_nomap(struct test_fixture *tfix) 297 { 298 const struct pt_mapped_section *msec; 299 struct pt_asid asid; 300 struct pt_section *section; 301 int status; 302 303 msec = NULL; 304 305 status = pt_msec_cache_fill(&tfix->mcache, &msec, &tfix->image, &asid, 306 0ull); 307 ptu_int_eq(status, -pte_nomap); 308 309 section = pt_msec_section(&tfix->mcache.msec); 310 ptu_null(section); 311 ptu_null(msec); 312 313 ptu_uint_eq(tfix->section.mcount, 0); 314 ptu_uint_eq(tfix->section.ucount, 0); 315 316 return ptu_passed(); 317 } 318 319 static struct ptunit_result fill(struct test_fixture *tfix) 320 { 321 const struct pt_mapped_section *msec; 322 struct pt_section *section; 323 struct pt_asid asid; 324 int status; 325 326 status = pt_msec_cache_fill(&tfix->mcache, &msec, &tfix->image, &asid, 327 0ull); 328 ptu_int_eq(status, 0); 329 330 ptu_ptr_eq(msec, &tfix->mcache.msec); 331 332 section = pt_msec_section(msec); 333 ptu_ptr_eq(section, &tfix->section); 334 335 ptu_uint_eq(section->mcount, 1); 336 ptu_uint_eq(section->ucount, 1); 337 338 return ptu_passed(); 339 } 340 341 static struct ptunit_result sfix_init(struct test_fixture *tfix) 342 { 343 memset(&tfix->section, 0, sizeof(tfix->section)); 344 memset(&tfix->mcache, 0, sizeof(tfix->mcache)); 345 memset(&tfix->image, 0, sizeof(tfix->image)); 346 347 return ptu_passed(); 348 } 349 350 static struct ptunit_result ifix_init(struct test_fixture *tfix) 351 { 352 ptu_test(sfix_init, tfix); 353 354 tfix->image.section = &tfix->section; 355 356 return ptu_passed(); 357 } 358 359 static struct ptunit_result cfix_init(struct test_fixture *tfix) 360 { 361 ptu_test(sfix_init, tfix); 362 363 tfix->mcache.msec.section = &tfix->section; 364 365 tfix->section.ucount = 1; 366 tfix->section.mcount = 1; 367 368 return ptu_passed(); 369 } 370 371 static struct ptunit_result cifix_init(struct test_fixture *tfix) 372 { 373 ptu_test(cfix_init, tfix); 374 375 tfix->image.section = &tfix->section; 376 377 return ptu_passed(); 378 } 379 380 int main(int argc, char **argv) 381 { 382 struct ptunit_suite suite; 383 struct test_fixture sfix, ifix, cfix, cifix; 384 385 sfix.init = sfix_init; 386 sfix.fini = NULL; 387 388 ifix.init = ifix_init; 389 ifix.fini = NULL; 390 391 cfix.init = cfix_init; 392 cfix.fini = NULL; 393 394 cifix.init = cifix_init; 395 cifix.fini = NULL; 396 397 suite = ptunit_mk_suite(argc, argv); 398 399 ptu_run(suite, init_null); 400 ptu_run(suite, fini_null); 401 ptu_run(suite, invalidate_null); 402 ptu_run(suite, read_null); 403 ptu_run(suite, fill_null); 404 405 ptu_run_f(suite, invalidate, sfix); 406 ptu_run_f(suite, invalidate, cfix); 407 408 ptu_run_f(suite, read_nomap, sfix); 409 ptu_run_f(suite, read_nomap, ifix); 410 ptu_run_f(suite, read_nomap, cfix); 411 ptu_run_f(suite, read, cifix); 412 413 ptu_run_f(suite, fill_nomap, sfix); 414 ptu_run_f(suite, fill_nomap, cfix); 415 ptu_run_f(suite, fill, ifix); 416 ptu_run_f(suite, fill, cifix); 417 418 return ptunit_report(&suite); 419 } 420