Changeset 108923 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Apr 9, 2025 6:55:17 PM (4 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168427
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/PGMAllGst-armv8.cpp.h
r108920 r108923 318 318 319 319 320 static const PGMWALKFAIL g_aPermPrivRead[] = 321 { 322 /* UXN PXN AP[2] AP[1] */ 323 /* 0 0 0 0 */ PGM_WALKFAIL_SUCCESS, 324 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 325 /* 0 0 1 0 */ PGM_WALKFAIL_SUCCESS, 326 /* 0 0 1 1 */ PGM_WALKFAIL_SUCCESS, 327 /* 0 1 0 0 */ PGM_WALKFAIL_SUCCESS, 328 /* 0 1 0 1 */ PGM_WALKFAIL_SUCCESS, 329 /* 0 1 1 0 */ PGM_WALKFAIL_SUCCESS, 330 /* 0 1 1 1 */ PGM_WALKFAIL_SUCCESS, 331 /* 1 0 0 0 */ PGM_WALKFAIL_SUCCESS, 332 /* 1 0 0 1 */ PGM_WALKFAIL_SUCCESS, 333 /* 1 0 1 0 */ PGM_WALKFAIL_SUCCESS, 334 /* 1 0 1 1 */ PGM_WALKFAIL_SUCCESS, 335 /* 1 1 0 0 */ PGM_WALKFAIL_SUCCESS, 336 /* 1 1 0 1 */ PGM_WALKFAIL_SUCCESS, 337 /* 1 1 1 0 */ PGM_WALKFAIL_SUCCESS, 338 /* 1 1 1 1 */ PGM_WALKFAIL_SUCCESS 339 }; 340 341 342 static const PGMWALKFAIL g_aPermPrivWrite[] = 343 { 344 /* UXN PXN AP[2] AP[1] */ 345 /* 0 0 0 0 */ PGM_WALKFAIL_SUCCESS, 346 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 347 /* 0 0 1 0 */ PGM_WALKFAIL_NOT_WRITABLE, 348 /* 0 0 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 349 /* 0 1 0 0 */ PGM_WALKFAIL_SUCCESS, 350 /* 0 1 0 1 */ PGM_WALKFAIL_SUCCESS, 351 /* 0 1 1 0 */ PGM_WALKFAIL_NOT_WRITABLE, 352 /* 0 1 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 353 /* 1 0 0 0 */ PGM_WALKFAIL_SUCCESS, 354 /* 1 0 0 1 */ PGM_WALKFAIL_SUCCESS, 355 /* 1 0 1 0 */ PGM_WALKFAIL_NOT_WRITABLE, 356 /* 1 0 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 357 /* 1 1 0 0 */ PGM_WALKFAIL_SUCCESS, 358 /* 1 1 0 1 */ PGM_WALKFAIL_SUCCESS, 359 /* 1 1 1 0 */ PGM_WALKFAIL_NOT_WRITABLE, 360 /* 1 1 1 1 */ PGM_WALKFAIL_NOT_WRITABLE 361 }; 362 363 364 static const PGMWALKFAIL g_aPermPrivExec[] = 365 { 366 /* UXN PXN AP[2] AP[1] */ 367 /* 0 0 0 0 */ PGM_WALKFAIL_SUCCESS, 368 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 369 /* 0 0 1 0 */ PGM_WALKFAIL_SUCCESS, 370 /* 0 0 1 1 */ PGM_WALKFAIL_SUCCESS, 371 /* 0 1 0 0 */ PGM_WALKFAIL_NOT_EXECUTABLE, 372 /* 0 1 0 1 */ PGM_WALKFAIL_NOT_EXECUTABLE, 373 /* 0 1 1 0 */ PGM_WALKFAIL_NOT_EXECUTABLE, 374 /* 0 1 1 1 */ PGM_WALKFAIL_NOT_EXECUTABLE, 375 /* 1 0 0 0 */ PGM_WALKFAIL_SUCCESS, 376 /* 1 0 0 1 */ PGM_WALKFAIL_SUCCESS, 377 /* 1 0 1 0 */ PGM_WALKFAIL_SUCCESS, 378 /* 1 0 1 1 */ PGM_WALKFAIL_SUCCESS, 379 /* 1 1 0 0 */ PGM_WALKFAIL_NOT_EXECUTABLE, 380 /* 1 1 0 1 */ PGM_WALKFAIL_NOT_EXECUTABLE, 381 /* 1 1 1 0 */ PGM_WALKFAIL_NOT_EXECUTABLE, 382 /* 1 1 1 1 */ PGM_WALKFAIL_NOT_EXECUTABLE 383 }; 384 385 386 static const PGMWALKFAIL g_aPermUnprivRead[] = 387 { 388 /* UXN PXN AP[2] AP[1] */ 389 /* 0 0 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 390 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 391 /* 0 0 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 392 /* 0 0 1 1 */ PGM_WALKFAIL_SUCCESS, 393 /* 0 1 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 394 /* 0 1 0 1 */ PGM_WALKFAIL_SUCCESS, 395 /* 0 1 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 396 /* 0 1 1 1 */ PGM_WALKFAIL_SUCCESS, 397 /* 1 0 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 398 /* 1 0 0 1 */ PGM_WALKFAIL_SUCCESS, 399 /* 1 0 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 400 /* 1 0 1 1 */ PGM_WALKFAIL_SUCCESS, 401 /* 1 1 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 402 /* 1 1 0 1 */ PGM_WALKFAIL_SUCCESS, 403 /* 1 1 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 404 /* 1 1 1 1 */ PGM_WALKFAIL_SUCCESS 405 }; 406 407 408 static const PGMWALKFAIL g_aPermUnprivWrite[] = 409 { 410 /* UXN PXN AP[2] AP[1] */ 411 /* 0 0 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 412 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 413 /* 0 0 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE, 414 /* 0 0 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 415 /* 0 1 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 416 /* 0 1 0 1 */ PGM_WALKFAIL_SUCCESS, 417 /* 0 1 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE, 418 /* 0 1 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 419 /* 1 0 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 420 /* 1 0 0 1 */ PGM_WALKFAIL_SUCCESS, 421 /* 1 0 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE, 422 /* 1 0 1 1 */ PGM_WALKFAIL_NOT_WRITABLE, 423 /* 1 1 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE, 424 /* 1 1 0 1 */ PGM_WALKFAIL_SUCCESS, 425 /* 1 1 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_WRITABLE, 426 /* 1 1 1 1 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE 427 }; 428 429 430 static const PGMWALKFAIL g_aPermUnprivExec[] = 431 { 432 /* UXN PXN AP[2] AP[1] */ 433 /* 0 0 0 0 */ PGM_WALKFAIL_SUCCESS, 434 /* 0 0 0 1 */ PGM_WALKFAIL_SUCCESS, 435 /* 0 0 1 0 */ PGM_WALKFAIL_SUCCESS, 436 /* 0 0 1 1 */ PGM_WALKFAIL_SUCCESS, 437 /* 0 1 0 0 */ PGM_WALKFAIL_SUCCESS, 438 /* 0 1 0 1 */ PGM_WALKFAIL_SUCCESS, 439 /* 0 1 1 0 */ PGM_WALKFAIL_SUCCESS, 440 /* 0 1 1 1 */ PGM_WALKFAIL_SUCCESS, 441 /* 1 0 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 442 /* 1 0 0 1 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 443 /* 1 0 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 444 /* 1 0 1 1 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 445 /* 1 1 0 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 446 /* 1 1 0 1 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 447 /* 1 1 1 0 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE, 448 /* 1 1 1 1 */ PGM_WALKFAIL_NOT_ACCESSIBLE_BY_MODE | PGM_WALKFAIL_NOT_EXECUTABLE 449 }; 450 451 452 DECL_FORCE_INLINE(uint32_t) pgmGstQueryPageCheckPermissions(PPGMPTWALKFAST pWalk, ARMV8VMSA64DESC Desc, uint32_t fFlags, uint8_t uLvl) 453 { 454 Assert(!(fFlags & ~PGMQPAGE_F_VALID_MASK)); 455 456 /* Descriptor flags to page table attribute flags mapping. */ 457 static const PGMPTATTRS s_aEffective[] = 458 { 459 /* UXN PXN AP[2] AP[1] */ 460 /* 0 0 0 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK, 461 /* 0 0 0 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK | PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK, 462 /* 0 0 1 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK, 463 /* 0 0 1 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_PX_MASK | PGM_PTATTRS_UX_MASK, 464 465 /* 0 1 0 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UX_MASK, 466 /* 0 1 0 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK | PGM_PTATTRS_UX_MASK, 467 /* 0 1 1 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_UX_MASK, 468 /* 0 1 1 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UX_MASK, 469 470 /* 1 0 0 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_PX_MASK, 471 /* 1 0 0 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK | PGM_PTATTRS_PX_MASK, 472 /* 1 0 1 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PX_MASK, 473 /* 1 0 1 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_PX_MASK, 474 475 /* 1 1 0 0 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK, 476 /* 1 1 0 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_PW_MASK | PGM_PTATTRS_UR_MASK | PGM_PTATTRS_UW_MASK , 477 /* 1 1 1 0 */ PGM_PTATTRS_PR_MASK, 478 /* 1 1 1 1 */ PGM_PTATTRS_PR_MASK | PGM_PTATTRS_UR_MASK, 479 }; 480 481 static const uint32_t *s_apaPerm[] = 482 { 483 /* U X W R */ 484 /* 0 0 0 0 */ NULL, /* Invalid */ 485 /* 0 0 0 1 */ &g_aPermPrivRead[0], /* Privileged read access */ 486 /* 0 0 1 0 */ &g_aPermPrivWrite[0], /* Privileged write access */ 487 /* 0 0 1 1 */ NULL, /* Invalid access flags */ 488 /* 0 1 0 0 */ &g_aPermPrivExec[0], /* Privileged execute access */ 489 /* 0 1 0 1 */ NULL, /* Invalid access flags */ 490 /* 0 1 1 0 */ NULL, /* Invalid access flags */ 491 /* 0 1 1 1 */ NULL, /* Invalid access flags */ 492 493 /* 1 0 0 0 */ NULL, /* Invalid access flags */ 494 /* 1 0 0 1 */ &g_aPermUnprivRead[0], /* Unprivileged read access */ 495 /* 1 0 1 0 */ &g_aPermUnprivWrite[0], /* Unprivileged read access */ 496 /* 1 0 1 1 */ NULL, /* Invalid access flags */ 497 /* 1 1 0 0 */ &g_aPermUnprivExec[0], /* Unprivileged execute access */ 498 /* 1 1 0 1 */ NULL, /* Invalid access flags */ 499 /* 1 1 1 0 */ NULL, /* Invalid access flags */ 500 /* 1 1 1 1 */ NULL, /* Invalid access flags */ 501 }; 502 Assert(fFlags < RT_ELEMENTS(s_apaPerm)); 503 504 const uint32_t *paPerm = s_apaPerm[fFlags]; 505 AssertReturn(paPerm, VERR_PGM_MODE_IPE); 506 507 uint32_t const idxPerm = RT_BF_GET(Desc, ARMV8_VMSA64_DESC_PG_OR_BLOCK_LATTR_AP) 508 | ((Desc & ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_PXN) >> ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_PXN_BIT) << 2 509 | ((Desc & ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_UXN) >> ARMV8_VMSA64_DESC_PG_OR_BLOCK_UATTR_2PRIV_UXN_BIT) << 3; 510 511 pWalk->fEffective = s_aEffective[idxPerm]; 512 513 PGMWALKFAIL const fFailed = paPerm[idxPerm]; 514 if (fFailed == PGM_WALKFAIL_SUCCESS) 515 { 516 pWalk->fInfo |= PGM_WALKINFO_SUCCEEDED; 517 return VINF_SUCCESS; 518 } 519 520 pWalk->fFailed = fFailed | (uLvl << PGM_WALKFAIL_LEVEL_SHIFT); 521 return VERR_ACCESS_DENIED; 522 } 523 524 320 525 template<bool a_fTtbr0, uint8_t a_InitialLookupLvl, uint8_t a_GranuleSz, bool a_fTbi, bool a_fEpd> 321 526 static PGM_CTX_DECL(int) PGM_CTX(pgm,GstQueryPageFast)(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fFlags, PPGMPTWALKFAST pWalk) 322 527 { 323 RT_NOREF(fFlags); /** @todo */ 324 325 /* 326 * Initial lookup level 3 is not valid and only instantiated because we need two 327 * bits for the lookup level when creating the index and have to fill the slots. 328 */ 329 if RT_CONSTEXPR_IF(a_InitialLookupLvl == 3) 330 { 331 AssertReleaseFailed(); 332 return VERR_PGM_MODE_IPE; 528 /* This also applies to TG1 granule sizes, as both share the same encoding in TCR. */ 529 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_INVALID == ARMV8_TCR_EL1_AARCH64_TG1_INVALID); 530 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_16KB == ARMV8_TCR_EL1_AARCH64_TG1_16KB); 531 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_4KB == ARMV8_TCR_EL1_AARCH64_TG1_4KB); 532 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_64KB == ARMV8_TCR_EL1_AARCH64_TG1_64KB); 533 534 uint64_t fLookupMaskFull; 535 RTGCPTR offPageMask; 536 537 RTGCPTR offLvl1BlockMask; 538 RTGCPTR offLvl2BlockMask; 539 540 uint64_t fNextTableOrPageMask; 541 uint8_t cLvl0Shift; 542 uint8_t cLvl1Shift; 543 uint8_t cLvl2Shift; 544 uint8_t cLvl3Shift; 545 546 RTGCPHYS fGCPhysLvl1BlockBase; 547 RTGCPHYS fGCPhysLvl2BlockBase; 548 549 /** @todo This needs to go into defines in armv8.h if final. */ 550 if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_4KB) 551 { 552 fLookupMaskFull = RT_BIT_64(9) - 1; 553 offLvl1BlockMask = (RTGCPTR)(_1G - 1); 554 offLvl2BlockMask = (RTGCPTR)(_2M - 1); 555 offPageMask = (RTGCPTR)(_4K - 1); 556 fNextTableOrPageMask = UINT64_C(0xfffffffff000); 557 cLvl0Shift = 39; 558 cLvl1Shift = 30; 559 cLvl2Shift = 21; 560 cLvl3Shift = 12; 561 fGCPhysLvl1BlockBase = UINT64_C(0xffffc0000000); 562 fGCPhysLvl2BlockBase = UINT64_C(0xffffffe00000); 563 } 564 else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_16KB) 565 { 566 fLookupMaskFull = RT_BIT_64(11) - 1; 567 offLvl1BlockMask = 0; /** @todo TCR_EL1.DS support. */ 568 offLvl2BlockMask = (RTGCPTR)(_32M - 1); 569 offPageMask = (RTGCPTR)(_16K - 1); 570 fNextTableOrPageMask = UINT64_C(0xffffffffc000); 571 cLvl0Shift = 47; 572 cLvl1Shift = 36; 573 cLvl2Shift = 25; 574 cLvl3Shift = 14; 575 fGCPhysLvl1BlockBase = 0; /* Not supported. */ 576 fGCPhysLvl2BlockBase = UINT64_C(0xfffffe000000); 577 } 578 else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_64KB) 579 { 580 Assert(a_InitialLookupLvl > 0); 581 582 fLookupMaskFull = RT_BIT_64(13) - 1; 583 offLvl1BlockMask = 0; /** @todo FEAT_LPA (RTGCPTR)(4*_1T - 1) */ 584 offLvl2BlockMask = (RTGCPTR)(_512M - 1); 585 offPageMask = (RTGCPTR)(_64K - 1); 586 fNextTableOrPageMask = UINT64_C(0xffffffff0000); 587 cLvl0Shift = 0; /* No Level 0 with 64KiB granules. */ 588 cLvl1Shift = 42; 589 cLvl2Shift = 29; 590 cLvl3Shift = 16; 591 fGCPhysLvl1BlockBase = 0; /* Not supported. */ 592 fGCPhysLvl2BlockBase = UINT64_C(0xffffe0000000); 333 593 } 334 594 else 335 { 336 /* This also applies to TG1 granule sizes, as both share the same encoding in TCR. */ 337 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_INVALID == ARMV8_TCR_EL1_AARCH64_TG1_INVALID); 338 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_16KB == ARMV8_TCR_EL1_AARCH64_TG1_16KB); 339 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_4KB == ARMV8_TCR_EL1_AARCH64_TG1_4KB); 340 AssertCompile(ARMV8_TCR_EL1_AARCH64_TG0_64KB == ARMV8_TCR_EL1_AARCH64_TG1_64KB); 341 342 uint64_t fLookupMaskFull; 343 RTGCPTR offPageMask; 344 345 RTGCPTR offLvl1BlockMask; 346 RTGCPTR offLvl2BlockMask; 347 348 uint64_t fNextTableOrPageMask; 349 uint8_t cLvl0Shift; 350 uint8_t cLvl1Shift; 351 uint8_t cLvl2Shift; 352 uint8_t cLvl3Shift; 353 354 RTGCPHYS fGCPhysLvl1BlockBase; 355 RTGCPHYS fGCPhysLvl2BlockBase; 356 357 /** @todo This needs to go into defines in armv8.h if final. */ 358 if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_4KB) 359 { 360 fLookupMaskFull = RT_BIT_64(9) - 1; 361 offLvl1BlockMask = (RTGCPTR)(_1G - 1); 362 offLvl2BlockMask = (RTGCPTR)(_2M - 1); 363 offPageMask = (RTGCPTR)(_4K - 1); 364 fNextTableOrPageMask = UINT64_C(0xfffffffff000); 365 cLvl0Shift = 39; 366 cLvl1Shift = 30; 367 cLvl2Shift = 21; 368 cLvl3Shift = 12; 369 fGCPhysLvl1BlockBase = UINT64_C(0xffffc0000000); 370 fGCPhysLvl2BlockBase = UINT64_C(0xffffffe00000); 371 } 372 else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_16KB) 373 { 374 fLookupMaskFull = RT_BIT_64(11) - 1; 375 offLvl1BlockMask = 0; /** @todo TCR_EL1.DS support. */ 376 offLvl2BlockMask = (RTGCPTR)(_32M - 1); 377 offPageMask = (RTGCPTR)(_16K - 1); 378 fNextTableOrPageMask = UINT64_C(0xffffffffc000); 379 cLvl0Shift = 47; 380 cLvl1Shift = 36; 381 cLvl2Shift = 25; 382 cLvl3Shift = 14; 383 fGCPhysLvl1BlockBase = 0; /* Not supported. */ 384 fGCPhysLvl2BlockBase = UINT64_C(0xfffffe000000); 385 } 386 else if RT_CONSTEXPR_IF(a_GranuleSz == ARMV8_TCR_EL1_AARCH64_TG0_64KB) 387 { 388 Assert(a_InitialLookupLvl > 0); 389 390 fLookupMaskFull = RT_BIT_64(13) - 1; 391 offLvl1BlockMask = 0; /** @todo FEAT_LPA (RTGCPTR)(4*_1T - 1) */ 392 offLvl2BlockMask = (RTGCPTR)(_512M - 1); 393 offPageMask = (RTGCPTR)(_64K - 1); 394 fNextTableOrPageMask = UINT64_C(0xffffffff0000); 395 cLvl0Shift = 0; /* No Level 0 with 64KiB granules. */ 396 cLvl1Shift = 42; 397 cLvl2Shift = 29; 398 cLvl3Shift = 16; 399 fGCPhysLvl1BlockBase = 0; /* Not supported. */ 400 fGCPhysLvl2BlockBase = UINT64_C(0xffffe0000000); 401 } 402 else 403 AssertReleaseFailedReturn(VERR_PGM_MODE_IPE); 404 405 /* Get the initial lookup mask. */ 406 uint8_t const bEl = CPUMGetGuestEL(pVCpu); 407 uint64_t fLookupMask; 408 if RT_CONSTEXPR_IF(a_fTtbr0 == true) 409 fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr0[bEl]; 410 else 411 fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr1[bEl]; 412 413 RTGCPHYS GCPhysPt = CPUMGetEffectiveTtbr(pVCpu, GCPtr); 414 PARMV8VMSA64DESC paDesc = NULL; 415 ARMV8VMSA64DESC Desc; 416 int rc; 417 if RT_CONSTEXPR_IF(a_InitialLookupLvl == 0) 418 { 419 Assert(cLvl0Shift != 0); 420 uint8_t const uLvl = 0; 421 422 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 423 if (RT_SUCCESS(rc)) { /* probable */ } 424 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 425 426 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl0Shift) & fLookupMask]); 427 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 428 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 429 430 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 431 else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /** @todo Only supported if TCR_EL1.DS is set. */ 432 433 /* Full lookup mask from now on. */ 434 fLookupMask = fLookupMaskFull; 435 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 436 } 437 438 if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 1) 439 { 440 uint8_t const uLvl = 1; 441 442 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 443 if (RT_SUCCESS(rc)) { /* probable */ } 444 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 445 446 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl1Shift) & fLookupMask]); 447 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 448 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 449 450 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 451 else 452 { 453 if (offLvl1BlockMask != 0) 454 { 455 /* Block descriptor. */ 456 pWalk->GCPtr = GCPtr; 457 pWalk->fInfo = PGM_WALKINFO_SUCCEEDED | PGM_WALKINFO_GIGANTIC_PAGE; 458 pWalk->GCPhys = (RTGCPHYS)(Desc & fGCPhysLvl1BlockBase) | (GCPtr & offLvl1BlockMask); 459 return VINF_SUCCESS; 460 } 461 else 462 return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); 463 } 464 465 /* Full lookup mask from now on. */ 466 fLookupMask = fLookupMaskFull; 467 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 468 } 469 470 if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 2) 471 { 472 uint8_t const uLvl = 2; 473 474 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 475 if (RT_SUCCESS(rc)) { /* probable */ } 476 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 477 478 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl2Shift) & fLookupMask]); 479 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 480 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 481 482 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 483 else 484 { 485 /* Block descriptor. */ 486 pWalk->GCPtr = GCPtr; 487 pWalk->fInfo = PGM_WALKINFO_SUCCEEDED | PGM_WALKINFO_BIG_PAGE; 488 pWalk->GCPhys = (RTGCPHYS)(Desc & fGCPhysLvl2BlockBase) | (GCPtr & offLvl2BlockMask); 489 return VINF_SUCCESS; 490 } 491 492 /* Full lookup mask from now on. */ 493 fLookupMask = fLookupMaskFull; 494 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 495 } 496 497 AssertCompile(a_InitialLookupLvl <= 3); 498 uint8_t const uLvl = 3; 499 500 /* Next level. */ 595 AssertReleaseFailedReturn(VERR_PGM_MODE_IPE); 596 597 /* Get the initial lookup mask. */ 598 uint8_t const bEl = (fFlags & PGMQPAGE_F_USER_MODE) ? 0 : 1; /** @todo EL2 support */ 599 uint64_t fLookupMask; 600 if RT_CONSTEXPR_IF(a_fTtbr0 == true) 601 fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr0[bEl]; 602 else 603 fLookupMask = pVCpu->pgm.s.afLookupMaskTtbr1[bEl]; 604 605 RTGCPHYS GCPhysPt = CPUMGetEffectiveTtbr(pVCpu, GCPtr); 606 PARMV8VMSA64DESC paDesc = NULL; 607 ARMV8VMSA64DESC Desc; 608 int rc; 609 if RT_CONSTEXPR_IF(a_InitialLookupLvl == 0) 610 { 611 Assert(cLvl0Shift != 0); 612 uint8_t const uLvl = 0; 613 501 614 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 502 615 if (RT_SUCCESS(rc)) { /* probable */ } 503 616 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 504 617 505 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl 3Shift) & fLookupMask]);618 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl0Shift) & fLookupMask]); 506 619 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 507 620 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 508 621 509 622 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 510 else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /* No block descriptors. */ 511 512 pWalk->GCPtr = GCPtr; 513 pWalk->fInfo = PGM_WALKINFO_SUCCEEDED; 514 pWalk->GCPhys = (RTGCPHYS)(Desc & fNextTableOrPageMask) | (GCPtr & offPageMask); 515 return VINF_SUCCESS; 516 } 623 else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /** @todo Only supported if TCR_EL1.DS is set. */ 624 625 /* Full lookup mask from now on. */ 626 fLookupMask = fLookupMaskFull; 627 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 628 } 629 630 if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 1) 631 { 632 uint8_t const uLvl = 1; 633 634 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 635 if (RT_SUCCESS(rc)) { /* probable */ } 636 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 637 638 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl1Shift) & fLookupMask]); 639 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 640 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 641 642 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 643 else 644 { 645 if (offLvl1BlockMask != 0) 646 { 647 /* Block descriptor. */ 648 pWalk->GCPtr = GCPtr; 649 pWalk->fInfo = PGM_WALKINFO_GIGANTIC_PAGE; 650 pWalk->GCPhys = (RTGCPHYS)(Desc & fGCPhysLvl1BlockBase) | (GCPtr & offLvl1BlockMask); 651 return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl); 652 } 653 else 654 return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); 655 } 656 657 /* Full lookup mask from now on. */ 658 fLookupMask = fLookupMaskFull; 659 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 660 } 661 662 if RT_CONSTEXPR_IF(a_InitialLookupLvl <= 2) 663 { 664 uint8_t const uLvl = 2; 665 666 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 667 if (RT_SUCCESS(rc)) { /* probable */ } 668 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 669 670 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl2Shift) & fLookupMask]); 671 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 672 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 673 674 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 675 else 676 { 677 /* Block descriptor. */ 678 pWalk->GCPtr = GCPtr; 679 pWalk->fInfo = PGM_WALKINFO_BIG_PAGE; 680 pWalk->GCPhys = (RTGCPHYS)(Desc & fGCPhysLvl2BlockBase) | (GCPtr & offLvl2BlockMask); 681 return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl); 682 } 683 684 /* Full lookup mask from now on. */ 685 fLookupMask = fLookupMaskFull; 686 GCPhysPt = (RTGCPHYS)(Desc & fNextTableOrPageMask); 687 } 688 689 AssertCompile(a_InitialLookupLvl <= 3); 690 uint8_t const uLvl = 3; 691 692 /* Next level. */ 693 rc = pgmPhysGCPhys2CCPtrLockless(pVCpu, GCPhysPt, (void **)&paDesc); 694 if (RT_SUCCESS(rc)) { /* probable */ } 695 else return pgmGstWalkFastReturnBadPhysAddr(pVCpu, pWalk, uLvl, rc); 696 697 Desc = ASMAtomicUoReadU64(&paDesc[(GCPtr >> cLvl3Shift) & fLookupMask]); 698 if (Desc & ARMV8_VMSA64_DESC_F_VALID) { /* probable */ } 699 else return pgmGstWalkFastReturnNotPresent(pVCpu, pWalk, uLvl); 700 701 if (Desc & ARMV8_VMSA64_DESC_F_TBL_OR_PG) { /* probable */ } 702 else return pgmGstWalkFastReturnRsvdError(pVCpu, pWalk, uLvl); /* No block descriptors. */ 703 704 pWalk->GCPtr = GCPtr; 705 pWalk->GCPhys = (RTGCPHYS)(Desc & fNextTableOrPageMask) | (GCPtr & offPageMask); 706 return pgmGstQueryPageCheckPermissions(pWalk, Desc, fFlags, uLvl); 517 707 } 518 708 … … 632 822 { 633 823 uint64_t const u64Tsz = (u64RegTcr >> a_offTsz) & 0x1f; 634 uint64_t constu64Tg = (u64RegTcr >> a_offTg) & 0x3;824 uint64_t u64Tg = (u64RegTcr >> a_offTg) & 0x3; 635 825 bool const fTbi = RT_BOOL(u64RegTcr & RT_BIT_64(a_offTbi)); 636 826 bool const fEpd = RT_BOOL(u64RegTcr & RT_BIT_64(a_offEpd)); 637 827 638 828 /* 639 * From: https://github.com/codingbelief/arm-architecture-reference-manual-for-armv8-a/blob/master/en/chapter_d4/d42_2_controlling_address_translation_stages.md 640 * For all translation stages 641 * The maximum TxSZ value is 39. If TxSZ is programmed to a value larger than 39 then it is IMPLEMENTATION DEFINED whether: 642 * - The implementation behaves as if the field is programmed to 39 for all purposes other than reading back the value of the field. 643 * - Any use of the TxSZ value generates a Level 0 Translation fault for the stage of translation at which TxSZ is used. 829 * From the ARM reference manual regarding granule size choices: 644 830 * 645 * For a stage 1 translation646 * The minimum TxSZ value is 16. If TxSZ is programmed to a value smaller than 16 then it is IMPLEMENTATION DEFINED whether:647 * - The implementation behaves as if the field were programmed to 16 for all purposes other than reading back the value of the field.648 * - Any use of the TxSZ value generates a stage 1 Level 0 Translation fault.831 * If the value is programmed to either a reserved value or a size that has not been implemented, then 832 * the hardware will treat the field as if it has been programmed to an IMPLEMENTATION DEFINED 833 * choice of the sizes that has been implemented for all purposes other than the value read back from 834 * this register. 649 835 * 650 * We currently choose the former for both.836 * We always fall back on the 4KiB granule size in that case. 651 837 */ 838 /** @todo Can this be made table driven? */ 652 839 uint64_t uLookupLvl; 653 if ( /*u64Tsz >= 16 &&*/ u64Tsz <= 24)840 if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_16KB) 654 841 { 655 uLookupLvl = 0; 656 if (u64Tsz >= 16) 657 *pfInitialLookupMask = RT_BIT_64(24 - u64Tsz + 1) - 1; 658 else 659 *pfInitialLookupMask = RT_BIT_64(24 - 16 + 1) - 1; 842 if (u64Tsz <= 16) 843 { 844 uLookupLvl = 0; 845 *pfInitialLookupMask = 0x1; 846 } 847 else if (u64Tsz >= 17 && u64Tsz <= 27) 848 { 849 uLookupLvl = 1; 850 *pfInitialLookupMask = RT_BIT_64(28 - u64Tsz + 1) - 1; 851 } 852 else if (u64Tsz >= 28 && u64Tsz <= 38) 853 { 854 uLookupLvl = 2; 855 *pfInitialLookupMask = RT_BIT_64(38 - u64Tsz + 1) - 1; 856 } 857 else /* if (u64Tsz == 39) */ 858 { 859 uLookupLvl = 3; 860 *pfInitialLookupMask = 0x1; 861 } 660 862 } 661 else if (u64T sz >= 25 && u64Tsz <= 33)863 else if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_64KB) 662 864 { 663 uLookupLvl = 1; 664 *pfInitialLookupMask = RT_BIT_64(33 - u64Tsz + 1) - 1; 865 if (/*u64Tsz >= 16 &&*/ u64Tsz <= 21) 866 { 867 uLookupLvl = 1; 868 *pfInitialLookupMask = RT_BIT_64(21 - u64Tsz + 1) - 1; 869 } 870 else if (u64Tsz >= 22 && u64Tsz <= 34) 871 { 872 uLookupLvl = 2; 873 *pfInitialLookupMask = RT_BIT_64(34 - u64Tsz + 1) - 1; 874 } 875 else /*if (u64Tsz >= 35 && u64Tsz <= 39)*/ 876 { 877 uLookupLvl = 3; 878 if (u64Tsz <= 39) 879 *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1; 880 else 881 *pfInitialLookupMask = 0x1; 882 } 665 883 } 666 else /* if (u64Tsz >= 34 && u64Tsz <= 39)*/884 else /* if (u64Tg == ARMV8_TCR_EL1_AARCH64_TG0_4KB) */ 667 885 { 668 uLookupLvl = 2; 669 if (u64Tsz <= 39) 670 *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1; 671 else 672 *pfInitialLookupMask = RT_BIT_64(39 - 39 + 1) - 1; 886 /* 887 * From: https://github.com/codingbelief/arm-architecture-reference-manual-for-armv8-a/blob/master/en/chapter_d4/d42_2_controlling_address_translation_stages.md 888 * For all translation stages 889 * The maximum TxSZ value is 39. If TxSZ is programmed to a value larger than 39 then it is IMPLEMENTATION DEFINED whether: 890 * - The implementation behaves as if the field is programmed to 39 for all purposes other than reading back the value of the field. 891 * - Any use of the TxSZ value generates a Level 0 Translation fault for the stage of translation at which TxSZ is used. 892 * 893 * For a stage 1 translation 894 * The minimum TxSZ value is 16. If TxSZ is programmed to a value smaller than 16 then it is IMPLEMENTATION DEFINED whether: 895 * - The implementation behaves as if the field were programmed to 16 for all purposes other than reading back the value of the field. 896 * - Any use of the TxSZ value generates a stage 1 Level 0 Translation fault. 897 * 898 * We currently choose the former for both. 899 */ 900 if (/*u64Tsz >= 16 &&*/ u64Tsz <= 24) 901 { 902 uLookupLvl = 0; 903 if (u64Tsz >= 16) 904 *pfInitialLookupMask = RT_BIT_64(24 - u64Tsz + 1) - 1; 905 else 906 *pfInitialLookupMask = RT_BIT_64(9) - 1; 907 } 908 else if (u64Tsz >= 25 && u64Tsz <= 33) 909 { 910 uLookupLvl = 1; 911 *pfInitialLookupMask = RT_BIT_64(33 - u64Tsz + 1) - 1; 912 } 913 else /*if (u64Tsz >= 34 && u64Tsz <= 39)*/ 914 { 915 uLookupLvl = 2; 916 if (u64Tsz <= 39) 917 *pfInitialLookupMask = RT_BIT_64(39 - u64Tsz + 1) - 1; 918 else 919 *pfInitialLookupMask = 0x1; 920 } 921 922 u64Tg = ARMV8_TCR_EL1_AARCH64_TG0_4KB; 673 923 } 674 924
Note:
See TracChangeset
for help on using the changeset viewer.