1// Copyright 2017 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include <assert.h> 8#include <err.h> 9#include <hypervisor/guest_physical_address_space.h> 10#include <lib/unittest/unittest.h> 11#include <vm/pmm.h> 12#include <vm/vm.h> 13#include <vm/vm_address_region.h> 14#include <vm/vm_aspace.h> 15#include <vm/vm_object.h> 16#include <vm/vm_object_paged.h> 17 18static constexpr uint kMmuFlags = 19 ARCH_MMU_FLAG_PERM_READ | 20 ARCH_MMU_FLAG_PERM_WRITE | 21 ARCH_MMU_FLAG_PERM_EXECUTE; 22 23static bool hypervisor_supported() { 24#if ARCH_ARM64 25 if (arm64_get_boot_el() < 2) { 26 unittest_printf("Hypervisor not supported\n"); 27 return false; 28 } 29#endif 30 return true; 31} 32 33static zx_status_t get_paddr(void* context, size_t offset, size_t index, paddr_t pa) { 34 *static_cast<paddr_t*>(context) = pa; 35 return ZX_OK; 36} 37 38static zx_status_t create_vmo(size_t vmo_size, fbl::RefPtr<VmObject>* vmo) { 39 return VmObjectPaged::Create(PMM_ALLOC_FLAG_ANY, 0u, vmo_size, vmo); 40} 41 42static zx_status_t commit_vmo(fbl::RefPtr<VmObject> vmo) { 43 uint64_t committed = 0; 44 zx_status_t status = vmo->CommitRange(0, vmo->size(), &committed); 45 if (status != ZX_OK) { 46 return status; 47 } 48 if (committed != vmo->size()) { 49 return ZX_ERR_BAD_STATE; 50 } 51 return ZX_OK; 52} 53 54static zx_status_t create_gpas(fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace>* gpas) { 55#if ARCH_ARM64 56 return hypervisor::GuestPhysicalAddressSpace::Create(1 /* vmid */, gpas); 57#elif ARCH_X86 58 return hypervisor::GuestPhysicalAddressSpace::Create(gpas); 59#endif 60} 61 62static zx_status_t create_mapping(fbl::RefPtr<VmAddressRegion> vmar, fbl::RefPtr<VmObject> vmo, 63 zx_gpaddr_t addr, uint mmu_flags = kMmuFlags) { 64 fbl::RefPtr<VmMapping> mapping; 65 return vmar->CreateVmMapping(addr, vmo->size(), 0 /* align_pow2 */, VMAR_FLAG_SPECIFIC, vmo, 66 0 /* vmo_offset */, mmu_flags, "vmo", &mapping); 67} 68 69static zx_status_t create_sub_vmar(fbl::RefPtr<VmAddressRegion> vmar, size_t offset, size_t size, 70 fbl::RefPtr<VmAddressRegion>* sub_vmar) { 71 return vmar->CreateSubVmar(offset, size, 0 /* align_pow2 */, vmar->flags() | VMAR_FLAG_SPECIFIC, 72 "vmar", sub_vmar); 73} 74 75static bool guest_physical_address_space_unmap_range() { 76 BEGIN_TEST; 77 78 if (!hypervisor_supported()) { 79 return true; 80 } 81 82 // Setup. 83 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 84 zx_status_t status = create_gpas(&gpas); 85 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 86 fbl::RefPtr<VmObject> vmo; 87 status = create_vmo(PAGE_SIZE, &vmo); 88 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 89 status = create_mapping(gpas->RootVmar(), vmo, 0); 90 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 91 92 // Unmap page. 93 status = gpas->UnmapRange(0, PAGE_SIZE); 94 EXPECT_EQ(ZX_OK, status, "Failed to unmap page from GuestPhysicalAddressSpace\n"); 95 96 // Verify GetPage for unmapped address fails. 97 zx_paddr_t gpas_paddr; 98 status = gpas->GetPage(0, &gpas_paddr); 99 EXPECT_EQ(ZX_ERR_NOT_FOUND, status, 100 "GetPage returning unexpected value for unmapped address\n"); 101 102 END_TEST; 103} 104 105static bool guest_physical_address_space_unmap_range_outside_of_mapping() { 106 BEGIN_TEST; 107 108 if (!hypervisor_supported()) { 109 return true; 110 } 111 112 // Setup. 113 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 114 zx_status_t status = create_gpas(&gpas); 115 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 116 fbl::RefPtr<VmObject> vmo; 117 status = create_vmo(PAGE_SIZE, &vmo); 118 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 119 status = create_mapping(gpas->RootVmar(), vmo, 0); 120 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 121 122 // Unmap page. 123 status = gpas->UnmapRange(PAGE_SIZE * 8, PAGE_SIZE); 124 EXPECT_EQ(ZX_OK, status, "Failed to unmap page from GuestPhysicalAddressSpace\n"); 125 126 END_TEST; 127} 128 129static bool guest_physical_address_space_unmap_range_multiple_mappings() { 130 BEGIN_TEST; 131 132 if (!hypervisor_supported()) { 133 return true; 134 } 135 136 // Setup. 137 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 138 zx_status_t status = create_gpas(&gpas); 139 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 140 141 fbl::RefPtr<VmObject> vmo1; 142 status = create_vmo(PAGE_SIZE * 2, &vmo1); 143 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 144 status = create_mapping(gpas->RootVmar(), vmo1, 0); 145 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 146 147 fbl::RefPtr<VmObject> vmo2; 148 status = create_vmo(PAGE_SIZE * 2, &vmo2); 149 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 150 status = create_mapping(gpas->RootVmar(), vmo2, PAGE_SIZE * 3); 151 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 152 153 // Unmap pages. 154 status = gpas->UnmapRange(PAGE_SIZE, PAGE_SIZE * 3); 155 EXPECT_EQ(ZX_OK, status, "Failed to multiple unmap pages from GuestPhysicalAddressSpace\n"); 156 157 // Verify GetPage for unmapped addresses fails. 158 zx_paddr_t gpas_paddr = 0; 159 for (zx_gpaddr_t addr = PAGE_SIZE; addr < PAGE_SIZE * 4; addr += PAGE_SIZE) { 160 status = gpas->GetPage(addr, &gpas_paddr); 161 EXPECT_EQ(ZX_ERR_NOT_FOUND, status, 162 "GetPage returning unexpected value for unmapped address\n"); 163 } 164 165 // Verify GetPage for mapped addresses succeeds. 166 status = gpas->GetPage(0, &gpas_paddr); 167 EXPECT_EQ(ZX_OK, status, "Failed to read page from GuestPhysicalAddressSpace\n"); 168 status = gpas->GetPage(PAGE_SIZE * 4, &gpas_paddr); 169 EXPECT_EQ(ZX_OK, status, "Failed to read page from GuestPhysicalAddressSpace\n"); 170 171 END_TEST; 172} 173 174static bool guest_physical_address_space_unmap_range_sub_region() { 175 BEGIN_TEST; 176 177 if (!hypervisor_supported()) { 178 return true; 179 } 180 181 // Setup. 182 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 183 zx_status_t status = create_gpas(&gpas); 184 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 185 fbl::RefPtr<VmAddressRegion> root_vmar = gpas->RootVmar(); 186 // To test partial unmapping within sub-VMAR: 187 // Sub-VMAR from [0, PAGE_SIZE * 2). 188 // Map within sub-VMAR from [PAGE_SIZE, PAGE_SIZE * 2). 189 fbl::RefPtr<VmAddressRegion> sub_vmar1; 190 status = create_sub_vmar(root_vmar, 0, PAGE_SIZE * 2, &sub_vmar1); 191 EXPECT_EQ(ZX_OK, status, "Failed to create sub-VMAR\n"); 192 EXPECT_TRUE(sub_vmar1->has_parent(), "Sub-VMAR does not have a parent"); 193 fbl::RefPtr<VmObject> vmo1; 194 status = create_vmo(PAGE_SIZE, &vmo1); 195 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 196 status = create_mapping(sub_vmar1, vmo1, PAGE_SIZE); 197 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 198 // To test destroying of sub-VMAR: 199 // Sub-VMAR from [PAGE_SIZE * 2, PAGE_SIZE * 3). 200 // Map within sub-VMAR from [0, PAGE_SIZE). 201 fbl::RefPtr<VmAddressRegion> sub_vmar2; 202 status = create_sub_vmar(root_vmar, PAGE_SIZE * 2, PAGE_SIZE, &sub_vmar2); 203 EXPECT_EQ(ZX_OK, status, "Failed to create sub-VMAR\n"); 204 EXPECT_TRUE(sub_vmar2->has_parent(), "Sub-VMAR does not have a parent"); 205 fbl::RefPtr<VmObject> vmo2; 206 status = create_vmo(PAGE_SIZE, &vmo2); 207 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 208 status = create_mapping(sub_vmar2, vmo2, 0); 209 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 210 // To test partial unmapping within root-VMAR: 211 // Map within root-VMAR from [PAGE_SIZE * 3, PAGE_SIZE * 5). 212 fbl::RefPtr<VmObject> vmo3; 213 status = create_vmo(PAGE_SIZE * 2, &vmo3); 214 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 215 status = create_mapping(root_vmar, vmo3, PAGE_SIZE * 3); 216 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 217 218 // Unmap pages from [PAGE_SIZE, PAGE_SIZE * 4). 219 status = gpas->UnmapRange(PAGE_SIZE, PAGE_SIZE * 3); 220 EXPECT_EQ(ZX_OK, status, "Failed to multiple unmap pages from GuestPhysicalAddressSpace\n"); 221 222 // Verify GetPage for unmapped addresses fails. 223 zx_paddr_t gpas_paddr = 0; 224 for (zx_gpaddr_t addr = 0; addr < PAGE_SIZE * 4; addr += PAGE_SIZE) { 225 status = gpas->GetPage(addr, &gpas_paddr); 226 EXPECT_EQ(ZX_ERR_NOT_FOUND, status, 227 "GetPage returning unexpected value for unmapped address\n"); 228 } 229 230 // Verify GetPage for mapped addresses succeeds. 231 status = gpas->GetPage(PAGE_SIZE * 4, &gpas_paddr); 232 EXPECT_EQ(ZX_OK, status, "Failed to read page from GuestPhysicalAddressSpace\n"); 233 234 // Verify that sub-VMARs still have a parent. 235 EXPECT_TRUE(sub_vmar1->has_parent(), "Sub-VMAR does not have a parent"); 236 EXPECT_TRUE(sub_vmar2->has_parent(), "Sub-VMAR does not have a parent"); 237 238 END_TEST; 239} 240 241static bool guest_physical_address_space_get_page() { 242 BEGIN_TEST; 243 244 if (!hypervisor_supported()) { 245 return true; 246 } 247 248 // Setup. 249 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 250 zx_status_t status = create_gpas(&gpas); 251 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 252 fbl::RefPtr<VmObject> vmo; 253 status = create_vmo(PAGE_SIZE, &vmo); 254 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 255 status = create_mapping(gpas->RootVmar(), vmo, 0); 256 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 257 258 // Commit VMO. 259 status = commit_vmo(vmo); 260 EXPECT_EQ(ZX_OK, status, "Failed to commit VMO\n"); 261 262 // Read expected physical address from the VMO. 263 zx_paddr_t vmo_paddr = 0; 264 status = vmo->Lookup(0, PAGE_SIZE, 0, get_paddr, &vmo_paddr); 265 EXPECT_EQ(ZX_OK, status, "Failed to lookup physical address of VMO\n"); 266 EXPECT_NE(0u, vmo_paddr, "Failed to lookup physical address of VMO\n"); 267 268 // Read physical address from GPAS & compare with address read from VMO. 269 zx_paddr_t gpas_paddr = 0; 270 status = gpas->GetPage(0, &gpas_paddr); 271 EXPECT_EQ(ZX_OK, status, "Failed to read page from GuestPhysicalAddressSpace\n"); 272 EXPECT_EQ(vmo_paddr, gpas_paddr, 273 "Incorrect physical address returned from GuestPhysicalAddressSpace::GetPage\n"); 274 275 END_TEST; 276} 277 278static bool guest_physical_address_space_get_page_complex() { 279 BEGIN_TEST; 280 281 if (!hypervisor_supported()) { 282 return true; 283 } 284 285 // Test GetPage with a less trivial VMAR configuration. 286 // 287 // 0 -->+--------+ 288 // | Root | 289 // | VMO | 290 // ROOT_VMO_SIZE -->---------+ +--------+ 291 // | | | Second | 292 // ROOT_VMO_SIZE + | | | VMO | 293 // SECOND_VMO_SIZE -->---------+ +--------+ 294 // | Root | | Shadow | 295 // | VMAR | | VMAR | 296 // ~~~~~~~~ ~~~~~~~~ 297 // 298 // The 'Root VMO/VMAR' is the default configuration when initializing 299 // GuestPhysicalAddressSpace with a VMO size of 'PAGE_SIZE'. This test 300 // allocates a second VMAR and VMO and attaches them both into the 'Root 301 // VMAR' to ensure we correctly locate addresses in these structures. 302 const uint ROOT_VMO_SIZE = PAGE_SIZE; 303 const uint SECOND_VMO_SIZE = PAGE_SIZE; 304 305 // Setup. 306 fbl::RefPtr<VmObject> vmo1; 307 zx_status_t status = create_vmo(ROOT_VMO_SIZE, &vmo1); 308 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 309 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 310 status = create_gpas(&gpas); 311 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 312 fbl::RefPtr<VmAddressRegion> root_vmar = gpas->RootVmar(); 313 status = create_mapping(root_vmar, vmo1, 0); 314 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 315 316 // Commit first VMO. 317 status = commit_vmo(vmo1); 318 EXPECT_EQ(ZX_OK, status, "Failed to commit VMO\n"); 319 320 // Allocate second VMAR, offset one page into the root. 321 fbl::RefPtr<VmAddressRegion> shadow_vmar; 322 status = create_sub_vmar(root_vmar, ROOT_VMO_SIZE, root_vmar->size() - ROOT_VMO_SIZE, 323 &shadow_vmar); 324 EXPECT_EQ(ZX_OK, status, "Failed to create shadow VMAR\n"); 325 326 // Allocate second VMO; we'll map the original VMO on top of this one. 327 fbl::RefPtr<VmObject> vmo2; 328 status = create_vmo(SECOND_VMO_SIZE, &vmo2); 329 EXPECT_EQ(ZX_OK, status, "Failed allocate second VMO\n"); 330 331 // Commit second VMO. 332 status = commit_vmo(vmo2); 333 EXPECT_EQ(ZX_OK, status, "Failed to commit second VMO\n"); 334 335 // Map second VMO into second VMAR. 336 status = create_mapping(shadow_vmar, vmo2, 0); 337 EXPECT_EQ(ZX_OK, status, "Failed to map vmo into shadow vmar\n"); 338 339 // Read expected physical address from the VMO. 340 zx_paddr_t vmo_paddr = 0; 341 status = vmo2->Lookup(0, PAGE_SIZE, 0, get_paddr, &vmo_paddr); 342 EXPECT_EQ(ZX_OK, status, "Failed to lookup physical address of VMO\n"); 343 EXPECT_NE(0u, vmo_paddr, "Failed to lookup physical address of VMO\n"); 344 345 // Read physical address from GPAS. 346 zx_paddr_t gpas_paddr = 0; 347 status = gpas->GetPage(ROOT_VMO_SIZE, &gpas_paddr); 348 EXPECT_EQ(ZX_OK, status, "Failed to read page from GuestPhysicalAddressSpace\n"); 349 EXPECT_EQ(vmo_paddr, gpas_paddr, 350 "Incorrect physical address returned from GuestPhysicalAddressSpace::GetPage\n"); 351 END_TEST; 352} 353 354static bool guest_physical_address_space_get_page_not_present() { 355 BEGIN_TEST; 356 357 if (!hypervisor_supported()) { 358 return true; 359 } 360 361 // Setup. 362 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 363 zx_status_t status = create_gpas(&gpas); 364 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 365 fbl::RefPtr<VmObject> vmo; 366 status = create_vmo(PAGE_SIZE, &vmo); 367 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 368 status = create_mapping(gpas->RootVmar(), vmo, 0); 369 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 370 371 // Commit VMO. 372 status = commit_vmo(vmo); 373 EXPECT_EQ(ZX_OK, status, "Failed to commit VMO\n"); 374 375 // Query unmapped address. 376 zx_paddr_t gpas_paddr = 0; 377 status = gpas->GetPage(UINTPTR_MAX, &gpas_paddr); 378 EXPECT_EQ(ZX_ERR_NOT_FOUND, status, 379 "GetPage returning unexpected value for unmapped address\n"); 380 381 END_TEST; 382} 383 384static bool guest_physical_address_space_page_fault() { 385 BEGIN_TEST; 386 387 if (!hypervisor_supported()) { 388 return true; 389 } 390 391 // Setup. 392 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 393 zx_status_t status = create_gpas(&gpas); 394 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 395 fbl::RefPtr<VmObject> vmo; 396 status = create_vmo(PAGE_SIZE, &vmo); 397 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 398 status = create_mapping(gpas->RootVmar(), vmo, 0); 399 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 400 status = create_mapping(gpas->RootVmar(), vmo, PAGE_SIZE, ARCH_MMU_FLAG_PERM_READ); 401 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 402 status = create_mapping(gpas->RootVmar(), vmo, PAGE_SIZE * 2, 403 ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE); 404 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 405 status = create_mapping(gpas->RootVmar(), vmo, PAGE_SIZE * 3, 406 ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_EXECUTE); 407 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 408 409 // Fault in each page. 410 for (zx_gpaddr_t addr = 0; addr < PAGE_SIZE * 4; addr += PAGE_SIZE) { 411 status = gpas->PageFault(addr); 412 EXPECT_EQ(ZX_OK, status, "Failed to fault page\n"); 413 } 414 415 END_TEST; 416} 417 418static bool guest_physical_address_space_map_interrupt_controller() { 419 BEGIN_TEST; 420 421 if (!hypervisor_supported()) { 422 return true; 423 } 424 425 // Setup. 426 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 427 zx_status_t status = create_gpas(&gpas); 428 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 429 fbl::RefPtr<VmObject> vmo; 430 status = create_vmo(PAGE_SIZE, &vmo); 431 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 432 status = create_mapping(gpas->RootVmar(), vmo, 0); 433 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 434 435 // Allocate a page to use as the APIC page. 436 paddr_t paddr = 0; 437 vm_page* vm_page; 438 status = pmm_alloc_page(0, &vm_page, &paddr); 439 EXPECT_EQ(ZX_OK, status, "Unable to allocate a page\n"); 440 441 // Map APIC page in an arbitrary location. 442 const vaddr_t APIC_ADDRESS = 0xffff0000; 443 status = gpas->MapInterruptController(APIC_ADDRESS, paddr, PAGE_SIZE); 444 EXPECT_EQ(ZX_OK, status, "Failed to map APIC page\n"); 445 446 // Cleanup 447 pmm_free_page(vm_page); 448 END_TEST; 449} 450 451static bool guest_physical_address_space_uncached() { 452 BEGIN_TEST; 453 454 if (!hypervisor_supported()) { 455 return true; 456 } 457 458 // Setup. 459 fbl::RefPtr<VmObject> vmo; 460 zx_status_t status = create_vmo(PAGE_SIZE, &vmo); 461 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 462 status = vmo->SetMappingCachePolicy(ZX_CACHE_POLICY_UNCACHED); 463 EXPECT_EQ(ZX_OK, status, "Failed to set cache policy\n"); 464 465 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 466 status = create_gpas(&gpas); 467 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 468 status = create_mapping(gpas->RootVmar(), vmo, 0); 469 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 470 471 END_TEST; 472} 473 474static bool guest_physical_address_space_uncached_device() { 475 BEGIN_TEST; 476 477 if (!hypervisor_supported()) { 478 return true; 479 } 480 481 // Setup. 482 fbl::RefPtr<VmObject> vmo; 483 zx_status_t status = create_vmo(PAGE_SIZE, &vmo); 484 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 485 status = vmo->SetMappingCachePolicy(ZX_CACHE_POLICY_UNCACHED_DEVICE); 486 EXPECT_EQ(ZX_OK, status, "Failed to set cache policy\n"); 487 488 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 489 status = create_gpas(&gpas); 490 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 491 status = create_mapping(gpas->RootVmar(), vmo, 0); 492 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 493 494 END_TEST; 495} 496 497static bool guest_physical_address_space_write_combining() { 498 BEGIN_TEST; 499 500 if (!hypervisor_supported()) { 501 return true; 502 } 503 504 // Setup. 505 fbl::RefPtr<VmObject> vmo; 506 zx_status_t status = create_vmo(PAGE_SIZE, &vmo); 507 EXPECT_EQ(ZX_OK, status, "Failed to create VMO\n"); 508 status = vmo->SetMappingCachePolicy(ZX_CACHE_POLICY_WRITE_COMBINING); 509 EXPECT_EQ(ZX_OK, status, "Failed to set cache policy\n"); 510 511 fbl::unique_ptr<hypervisor::GuestPhysicalAddressSpace> gpas; 512 status = create_gpas(&gpas); 513 EXPECT_EQ(ZX_OK, status, "Failed to create GuestPhysicalAddressSpace\n"); 514 status = create_mapping(gpas->RootVmar(), vmo, 0); 515 EXPECT_EQ(ZX_OK, status, "Failed to create mapping\n"); 516 517 END_TEST; 518} 519 520// Use the function name as the test name 521#define HYPERVISOR_UNITTEST(fname) UNITTEST(#fname, fname) 522 523UNITTEST_START_TESTCASE(hypervisor) 524HYPERVISOR_UNITTEST(guest_physical_address_space_unmap_range) 525HYPERVISOR_UNITTEST(guest_physical_address_space_unmap_range_outside_of_mapping) 526HYPERVISOR_UNITTEST(guest_physical_address_space_unmap_range_multiple_mappings) 527HYPERVISOR_UNITTEST(guest_physical_address_space_unmap_range_sub_region) 528HYPERVISOR_UNITTEST(guest_physical_address_space_get_page) 529HYPERVISOR_UNITTEST(guest_physical_address_space_get_page_complex) 530HYPERVISOR_UNITTEST(guest_physical_address_space_get_page_not_present) 531HYPERVISOR_UNITTEST(guest_physical_address_space_page_fault) 532HYPERVISOR_UNITTEST(guest_physical_address_space_map_interrupt_controller) 533HYPERVISOR_UNITTEST(guest_physical_address_space_uncached) 534HYPERVISOR_UNITTEST(guest_physical_address_space_uncached_device) 535HYPERVISOR_UNITTEST(guest_physical_address_space_write_combining) 536UNITTEST_END_TESTCASE(hypervisor, "hypervisor", "Hypervisor unit tests."); 537