diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp index bc292fe5..a6e6ee0c 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/const.hpp @@ -55,18 +55,28 @@ constexpr u64 AP_FLAGS_MASK = enum class AllocateVmMemoryError { AllocationFailed, + DeallocationFailed, }; -inline uptr AllocateVmMemory(u64 size) { +inline paddr_t AllocateVmMemory(u64 size) { ASSERT_ALIGNMENT(size, APPLE_PAGE_SIZE, Hypervisor, "size") - void* ptr; - const auto res = posix_memalign(&ptr, APPLE_PAGE_SIZE, size); - ASSERT_THROWING(res == 0, Hypervisor, + void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_THROWING(ptr != MAP_FAILED, Hypervisor, AllocateVmMemoryError::AllocationFailed, - "Failed to allocate memory: {:#x}", res); + "Failed to allocate memory: {:#x}", errno); return reinterpret_cast(ptr); } +inline void FreeVmMemory(paddr_t addr, u64 size) { + ASSERT_ALIGNMENT(size, APPLE_PAGE_SIZE, Hypervisor, "size") + + auto res = munmap(reinterpret_cast(addr), size); + + ASSERT_THROWING(res == 0, Hypervisor, + AllocateVmMemoryError::DeallocationFailed, + "Failed to deallocate memory: {:#x}", res); +} + } // namespace hydra::hw::tegra_x1::cpu::hypervisor diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp index 33ec6c6b..34e11552 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/cpu.cpp @@ -35,7 +35,18 @@ const u32 exception_trampoline[] = { } // namespace -VirtualMachine::VirtualMachine() { HV_ASSERT_SUCCESS(hv_vm_create(nullptr)); } +VirtualMachine::VirtualMachine() { + // HACK: since we're mapping our address space to the HV's "physical" + // space 1:1, we have to extend their space to include all of ours + // (or as close as possible as we can) + auto config = hv_vm_config_create(); + uint32_t max_bits; + HV_ASSERT_SUCCESS(hv_vm_config_get_max_ipa_size(&max_bits)); + HV_ASSERT_SUCCESS(hv_vm_config_set_ipa_size(config, max_bits)); + + HV_ASSERT_SUCCESS(hv_vm_create(config)); + os_release(config); +} VirtualMachine::~VirtualMachine() { HV_ASSERT_SUCCESS(hv_vm_destroy()); } diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/memory.hpp b/src/core/hw/tegra_x1/cpu/hypervisor/memory.hpp index dc44b2df..02b4591b 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/memory.hpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/memory.hpp @@ -29,7 +29,7 @@ class Memory : public IMemory { ptr = AllocateVmMemory(size); // Map - // TODO: Why does this fail occasionally? + // TODO: if AllocateVmMemory passes a pointer greater than 0x8000000000, this will fail HV_ASSERT_SUCCESS( hv_vm_map(reinterpret_cast(ptr), ptr, size, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC)); @@ -40,7 +40,7 @@ class Memory : public IMemory { HV_ASSERT_SUCCESS( hv_vm_unmap(ptr, align(GetSizeAligned(), APPLE_PAGE_SIZE))); - free(reinterpret_cast(ptr)); + FreeVmMemory(ptr, GetSizeAligned()); } }; diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp index 1a781fbc..53860331 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/page_allocator.cpp @@ -9,7 +9,7 @@ PageAllocator::PageAllocator(paddr_t base_pa_, usize page_count) PageAllocator::~PageAllocator() { for (const auto allocation : allocations) { - free(reinterpret_cast(allocation.ptr)); + FreeVmMemory(allocation.ptr, GUEST_PAGE_SIZE * allocation.page_count); } } diff --git a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp index 3826cc43..501e73e1 100644 --- a/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp +++ b/src/core/hw/tegra_x1/cpu/hypervisor/thread.cpp @@ -108,8 +108,8 @@ Thread::Thread(WallClock& wall_clock, Cpu& cpu_, IMmu* mmu, SetReg(HV_REG_CPSR, 0x3c0); SetSysReg(HV_SYS_REG_MAIR_EL1, 0xfful); - SetSysReg(HV_SYS_REG_TCR_EL1, 0x00000011B5193519ul); - SetSysReg(HV_SYS_REG_SCTLR_EL1, 0x0000000034D5D925ul); + SetSysReg(HV_SYS_REG_TCR_EL1, 0x12B5193519ul); + SetSysReg(HV_SYS_REG_SCTLR_EL1, 0x34D5D925ul); // Enable FP and SIMD instructions SetSysReg(HV_SYS_REG_CPACR_EL1, 0b11 << 20);