From eab799b1ab4ee49569abfefea6136e7cd595043b Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 2 Feb 2023 02:44:36 +0100 Subject: [PATCH] early-access version 3358 --- README.md | 2 +- src/core/CMakeLists.txt | 2 + src/core/hid/emulated_controller.cpp | 6 +- src/core/hid/emulated_controller.h | 2 +- src/core/hle/kernel/init/init_slab_setup.cpp | 2 + .../hle/kernel/k_device_address_space.cpp | 150 ++++++++++++++++++ src/core/hle/kernel/k_device_address_space.h | 60 +++++++ src/core/hle/kernel/kernel.h | 4 + src/core/hle/kernel/svc_types.h | 14 ++ 9 files changed, 238 insertions(+), 4 deletions(-) create mode 100755 src/core/hle/kernel/k_device_address_space.cpp create mode 100755 src/core/hle/kernel/k_device_address_space.h diff --git a/README.md b/README.md index cc5d07b4f..889861e1e 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3357. +This is the source code for early-access 3358. ## Legal Notice diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ec95e3ca0..264d97011 100755 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -195,6 +195,8 @@ add_library(core STATIC hle/kernel/k_condition_variable.cpp hle/kernel/k_condition_variable.h hle/kernel/k_debug.h + hle/kernel/k_device_address_space.cpp + hle/kernel/k_device_address_space.h hle/kernel/k_dynamic_page_manager.h hle/kernel/k_dynamic_resource_manager.h hle/kernel/k_dynamic_slab_heap.h diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 08932ac77..b57288f68 100755 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -12,6 +12,7 @@ namespace Core::HID { constexpr s32 HID_JOYSTICK_MAX = 0x7fff; constexpr s32 HID_TRIGGER_MAX = 0x7fff; +constexpr u32 TURBO_BUTTON_DELAY = 4; // Use a common UUID for TAS and Virtual Gamepad constexpr Common::UUID TAS_UUID = Common::UUID{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xA5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; @@ -447,6 +448,7 @@ void EmulatedController::ReloadInput() { }, }); } + turbo_button_state = 0; } void EmulatedController::UnloadInput() { @@ -1659,12 +1661,12 @@ void EmulatedController::DeleteCallback(int key) { } void EmulatedController::TurboButtonUpdate() { - turbo_button_state = !turbo_button_state; + turbo_button_state = (turbo_button_state + 1) % (TURBO_BUTTON_DELAY * 2); } NpadButton EmulatedController::GetTurboButtonMask() const { // Apply no mask when disabled - if (!turbo_button_state) { + if (turbo_button_state < TURBO_BUTTON_DELAY) { return {NpadButton::All}; } diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 77963e32d..f48c4f50d 100755 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h @@ -525,7 +525,7 @@ private: bool system_buttons_enabled{true}; f32 motion_sensitivity{0.01f}; bool force_update_motion{false}; - bool turbo_button_state{false}; + u32 turbo_button_state{0}; // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index fd02469ef..4cc35d2ed 100755 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -11,6 +11,7 @@ #include "core/hle/kernel/init/init_slab_setup.h" #include "core/hle/kernel/k_code_memory.h" #include "core/hle/kernel/k_debug.h" +#include "core/hle/kernel/k_device_address_space.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event_info.h" #include "core/hle/kernel/k_memory_layout.h" @@ -43,6 +44,7 @@ namespace Kernel::Init { HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \ + HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ##__VA_ARGS__) \ HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ HANDLER(KThreadLocalPage, \ (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \ diff --git a/src/core/hle/kernel/k_device_address_space.cpp b/src/core/hle/kernel/k_device_address_space.cpp new file mode 100755 index 000000000..27659ea3b --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.cpp @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/assert.h" +#include "core/core.h" +#include "core/hle/kernel/k_device_address_space.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel { + +KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_) + : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {} +KDeviceAddressSpace::~KDeviceAddressSpace() = default; + +void KDeviceAddressSpace::Initialize() { + // This just forwards to the device page table manager. + // KDevicePageTable::Initialize(); +} + +// Member functions. +Result KDeviceAddressSpace::Initialize(u64 address, u64 size) { + // Initialize the device page table. + // R_TRY(m_table.Initialize(address, size)); + + // Set member variables. + m_space_address = address; + m_space_size = size; + m_is_initialized = true; + + R_SUCCEED(); +} + +void KDeviceAddressSpace::Finalize() { + // Finalize the table. + // m_table.Finalize(); +} + +Result KDeviceAddressSpace::Attach(Svc::DeviceName device_name) { + // Lock the address space. + KScopedLightLock lk(m_lock); + + // Attach. + // R_RETURN(m_table.Attach(device_name, m_space_address, m_space_size)); + R_SUCCEED(); +} + +Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) { + // Lock the address space. + KScopedLightLock lk(m_lock); + + // Detach. + // R_RETURN(m_table.Detach(device_name)); + R_SUCCEED(); +} + +Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size, + u64 device_address, u32 option, bool is_aligned) { + // Check that the address falls within the space. + R_UNLESS((m_space_address <= device_address && + device_address + size - 1 <= m_space_address + m_space_size - 1), + ResultInvalidCurrentMemory); + + // Decode the option. + const Svc::MapDeviceAddressSpaceOption option_pack{option}; + const auto device_perm = option_pack.permission.Value(); + const auto flags = option_pack.flags.Value(); + const auto reserved = option_pack.reserved.Value(); + + // Validate the option. + // TODO: It is likely that this check for flags == none is only on NX board. + R_UNLESS(flags == Svc::MapDeviceAddressSpaceFlag::None, ResultInvalidEnumValue); + R_UNLESS(reserved == 0, ResultInvalidEnumValue); + + // Lock the address space. + KScopedLightLock lk(m_lock); + + // Lock the page table to prevent concurrent device mapping operations. + // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); + + // Lock the pages. + bool is_io{}; + R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size, + ConvertToKMemoryPermission(device_perm), + is_aligned, true)); + + // Ensure that if we fail, we don't keep unmapped pages locked. + ON_RESULT_FAILURE { + ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); + }; + + // Check that the io status is allowable. + if (is_io) { + R_UNLESS(static_cast(flags & Svc::MapDeviceAddressSpaceFlag::NotIoRegister) == 0, + ResultInvalidCombination); + } + + // Map the pages. + { + // Perform the mapping. + // R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, + // is_aligned, is_io)); + + // Ensure that we unmap the pages if we fail to update the protections. + // NOTE: Nintendo does not check the result of this unmap call. + // ON_RESULT_FAILURE { m_table.Unmap(device_address, size); }; + + // Update the protections in accordance with how much we mapped. + // R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size)); + } + + // We succeeded. + R_SUCCEED(); +} + +Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size, + u64 device_address) { + // Check that the address falls within the space. + R_UNLESS((m_space_address <= device_address && + device_address + size - 1 <= m_space_address + m_space_size - 1), + ResultInvalidCurrentMemory); + + // Lock the address space. + KScopedLightLock lk(m_lock); + + // Lock the page table to prevent concurrent device mapping operations. + // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); + + // Lock the pages. + R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true)); + + // Unmap the pages. + { + // If we fail to unmap, we want to do a partial unlock. + // ON_RESULT_FAILURE { + // ASSERT(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size) == + // ResultSuccess); + // }; + + // Perform the unmap. + // R_TRY(m_table.Unmap(page_table, process_address, size, device_address)); + } + + // Unlock the pages. + ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); + + R_SUCCEED(); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h new file mode 100755 index 000000000..4709df995 --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.h @@ -0,0 +1,60 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "common/common_types.h" +#include "core/hle/kernel/k_page_table.h" +#include "core/hle/kernel/slab_helpers.h" +#include "core/hle/result.h" + +namespace Kernel { + +class KDeviceAddressSpace final + : public KAutoObjectWithSlabHeapAndContainer { + KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject); + +public: + explicit KDeviceAddressSpace(KernelCore& kernel); + ~KDeviceAddressSpace(); + + Result Initialize(u64 address, u64 size); + void Finalize(); + + bool IsInitialized() const { + return m_is_initialized; + } + static void PostDestroy(uintptr_t arg) {} + + Result Attach(Svc::DeviceName device_name); + Result Detach(Svc::DeviceName device_name); + + Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size, + u64 device_address, u32 option) { + R_RETURN(this->Map(page_table, process_address, size, device_address, option, false)); + } + + Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size, + u64 device_address, u32 option) { + R_RETURN(this->Map(page_table, process_address, size, device_address, option, true)); + } + + Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address); + + static void Initialize(); + +private: + Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address, + u32 option, bool is_aligned); + +private: + KLightLock m_lock; + // KDevicePageTable m_table; + u64 m_space_address{}; + u64 m_space_size{}; + bool m_is_initialized{}; +}; + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3a4e59120..b29410961 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -35,6 +35,7 @@ class GlobalSchedulerContext; class KAutoObjectWithListContainer; class KClientSession; class KDebug; +class KDeviceAddressSpace; class KDynamicPageManager; class KEvent; class KEventInfo; @@ -359,6 +360,8 @@ public: return slab_heap_container->transfer_memory; } else if constexpr (std::is_same_v) { return slab_heap_container->code_memory; + } else if constexpr (std::is_same_v) { + return slab_heap_container->device_address_space; } else if constexpr (std::is_same_v) { return slab_heap_container->page_buffer; } else if constexpr (std::is_same_v) { @@ -431,6 +434,7 @@ private: KSlabHeap thread; KSlabHeap transfer_memory; KSlabHeap code_memory; + KSlabHeap device_address_space; KSlabHeap page_buffer; KSlabHeap thread_local_page; KSlabHeap session_request; diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 44a7a7014..6c573fb64 100755 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -5,6 +5,7 @@ #include +#include "common/bit_field.h" #include "common/common_funcs.h" #include "common/common_types.h" @@ -498,6 +499,19 @@ enum class MemoryMapping : u32 { Memory = 2, }; +enum class MapDeviceAddressSpaceFlag : u32 { + None = (0U << 0), + NotIoRegister = (1U << 0), +}; +DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag); + +union MapDeviceAddressSpaceOption { + u32 raw; + BitField<0, 16, MemoryPermission> permission; + BitField<16, 1, MapDeviceAddressSpaceFlag> flags; + BitField<17, 15, u32> reserved; +}; + enum class KernelDebugType : u32 { Thread = 0, ThreadCallStack = 1,