Compare commits
39 Commits
android-14
...
android-21
Author | SHA1 | Date | |
---|---|---|---|
f3b4384f3d | |||
a1c355051e | |||
d3da1e6517 | |||
6ffcc3d5d2 | |||
01b379fe20 | |||
4742627744 | |||
43920aa1a0 | |||
18000df5e9 | |||
bb0edb53ae | |||
099295d7c6 | |||
a0ed0e4e10 | |||
dad0d076ee | |||
3e3294e1c2 | |||
9f3f615e05 | |||
d144168442 | |||
3e4029b238 | |||
b1aed2c5b7 | |||
0ea138fb5b | |||
482c957f5d | |||
39edd2ff82 | |||
05bc024260 | |||
4bee333d84 | |||
c067046387 | |||
efda6cc9ec | |||
8927f016e1 | |||
c0202da9ac | |||
7fc5ef68d2 | |||
8f1d48fda6 | |||
54f150b70a | |||
4347dd26c6 | |||
d7c532d889 | |||
474db2d8da | |||
a85ce8ea56 | |||
63a0a1f826 | |||
9e0d6f7d54 | |||
13755c0903 | |||
833306bf5e | |||
90d76333da | |||
b417b8562e |
@ -35,7 +35,7 @@ DESTDIR="$PWD/AppDir" ninja install
|
|||||||
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester
|
||||||
|
|
||||||
# Download tools needed to build an AppImage
|
# Download tools needed to build an AppImage
|
||||||
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/gcc/deploy-linux.sh
|
wget -nc https://raw.githubusercontent.com/yuzu-emu/ext-linux-bin/main/appimage/deploy-linux.sh
|
||||||
wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh
|
wget -nc https://raw.githubusercontent.com/yuzu-emu/AppImageKit-checkrt/old/AppRun.sh
|
||||||
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
|
wget -nc https://github.com/yuzu-emu/ext-linux-bin/raw/main/appimage/exec-x86_64.so
|
||||||
# Set executable bit
|
# Set executable bit
|
||||||
|
@ -12,7 +12,7 @@ steps:
|
|||||||
inputs:
|
inputs:
|
||||||
targetType: 'filePath'
|
targetType: 'filePath'
|
||||||
filePath: './.ci/scripts/windows/install-vulkan-sdk.ps1'
|
filePath: './.ci/scripts/windows/install-vulkan-sdk.ps1'
|
||||||
- script: refreshenv && glslangValidator --version && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_ENABLE_LTO=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
- script: refreshenv && glslangValidator --version && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_ENABLE_LTO=ON -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||||
displayName: 'Configure CMake'
|
displayName: 'Configure CMake'
|
||||||
- task: MSBuild@1
|
- task: MSBuild@1
|
||||||
displayName: 'Build'
|
displayName: 'Build'
|
||||||
|
@ -136,6 +136,22 @@ if (YUZU_USE_BUNDLED_VCPKG)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (MSVC)
|
||||||
|
set(VCPKG_DOWNLOADS_PATH ${PROJECT_SOURCE_DIR}/externals/vcpkg/downloads)
|
||||||
|
set(NASM_VERSION "2.16.01")
|
||||||
|
set(NASM_DESTINATION_PATH ${VCPKG_DOWNLOADS_PATH}/nasm-${NASM_VERSION}-win64.zip)
|
||||||
|
set(NASM_DOWNLOAD_URL "https://github.com/yuzu-emu/ext-windows-bin/raw/master/nasm/nasm-${NASM_VERSION}-win64.zip")
|
||||||
|
|
||||||
|
if (NOT EXISTS ${NASM_DESTINATION_PATH})
|
||||||
|
file(DOWNLOAD ${NASM_DOWNLOAD_URL} ${NASM_DESTINATION_PATH} SHOW_PROGRESS STATUS NASM_STATUS)
|
||||||
|
|
||||||
|
if (NOT NASM_STATUS EQUAL 0)
|
||||||
|
# Warn and not fail since vcpkg is supposed to download this package for us in the first place
|
||||||
|
message(WARNING "External nasm vcpkg package download from ${NASM_DOWNLOAD_URL} failed with status ${NASM_STATUS}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (YUZU_TESTS)
|
if (YUZU_TESTS)
|
||||||
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
| Pull Request | Commit | Title | Author | Merged? |
|
||||||
|
|----|----|----|----|----|
|
||||||
|
|
||||||
|
|
||||||
|
End of merge log. You can find the original README.md below the break.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
@ -449,7 +449,7 @@ private:
|
|||||||
loader->ReadTitle(entry.title);
|
loader->ReadTitle(entry.title);
|
||||||
loader->ReadIcon(entry.icon);
|
loader->ReadIcon(entry.icon);
|
||||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||||
jauto loader_nro = dynamic_cast<Loader::AppLoader_NRO*>(loader.get());
|
jauto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||||
} else {
|
} else {
|
||||||
entry.isHomebrew = false;
|
entry.isHomebrew = false;
|
||||||
|
@ -51,7 +51,7 @@ struct PageTable {
|
|||||||
class PageInfo {
|
class PageInfo {
|
||||||
public:
|
public:
|
||||||
/// Returns the page pointer
|
/// Returns the page pointer
|
||||||
[[nodiscard]] u8* Pointer() const noexcept {
|
[[nodiscard]] uintptr_t Pointer() const noexcept {
|
||||||
return ExtractPointer(raw.load(std::memory_order_relaxed));
|
return ExtractPointer(raw.load(std::memory_order_relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ struct PageTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the page pointer and attribute pair, extracted from the same atomic read
|
/// Returns the page pointer and attribute pair, extracted from the same atomic read
|
||||||
[[nodiscard]] std::pair<u8*, PageType> PointerType() const noexcept {
|
[[nodiscard]] std::pair<uintptr_t, PageType> PointerType() const noexcept {
|
||||||
const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
|
const uintptr_t non_atomic_raw = raw.load(std::memory_order_relaxed);
|
||||||
return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
|
return {ExtractPointer(non_atomic_raw), ExtractType(non_atomic_raw)};
|
||||||
}
|
}
|
||||||
@ -73,13 +73,13 @@ struct PageTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write a page pointer and type pair atomically
|
/// Write a page pointer and type pair atomically
|
||||||
void Store(u8* pointer, PageType type) noexcept {
|
void Store(uintptr_t pointer, PageType type) noexcept {
|
||||||
raw.store(reinterpret_cast<uintptr_t>(pointer) | static_cast<uintptr_t>(type));
|
raw.store(pointer | static_cast<uintptr_t>(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpack a pointer from a page info raw representation
|
/// Unpack a pointer from a page info raw representation
|
||||||
[[nodiscard]] static u8* ExtractPointer(uintptr_t raw) noexcept {
|
[[nodiscard]] static uintptr_t ExtractPointer(uintptr_t raw) noexcept {
|
||||||
return reinterpret_cast<u8*>(raw & (~uintptr_t{0} << ATTRIBUTE_BITS));
|
return raw & (~uintptr_t{0} << ATTRIBUTE_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpack a page type from a page info raw representation
|
/// Unpack a page type from a page info raw representation
|
||||||
|
@ -26,7 +26,8 @@ std::string GetTimeZoneString() {
|
|||||||
|
|
||||||
std::string location_name;
|
std::string location_name;
|
||||||
if (time_zone_index == 0) { // Auto
|
if (time_zone_index == 0) { // Auto
|
||||||
#if __cpp_lib_chrono >= 201907L
|
#if __cpp_lib_chrono >= 201907L && !defined(MINGW)
|
||||||
|
// Disabled for MinGW -- tzdb always returns Etc/UTC
|
||||||
try {
|
try {
|
||||||
const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb();
|
const struct std::chrono::tzdb& time_zone_data = std::chrono::get_tzdb();
|
||||||
const std::chrono::time_zone* current_zone = time_zone_data.current_zone();
|
const std::chrono::time_zone* current_zone = time_zone_data.current_zone();
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <fmt/chrono.h>
|
#include <fmt/chrono.h>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/time_zone.h"
|
#include "common/time_zone.h"
|
||||||
|
|
||||||
namespace Common::TimeZone {
|
namespace Common::TimeZone {
|
||||||
@ -33,32 +33,29 @@ std::string GetDefaultTimeZone() {
|
|||||||
return "GMT";
|
return "GMT";
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetOsTimeZoneOffset() {
|
// Results are not comparable to seconds since Epoch
|
||||||
const std::time_t t{std::time(nullptr)};
|
static std::time_t TmSpecToSeconds(const struct std::tm& spec) {
|
||||||
const std::tm tm{*std::localtime(&t)};
|
const int year = spec.tm_year - 1; // Years up to now
|
||||||
|
const int leap_years = year / 4 - year / 100;
|
||||||
return fmt::format("{:%z}", tm);
|
std::time_t cumulative = spec.tm_year;
|
||||||
}
|
cumulative = cumulative * 365 + leap_years + spec.tm_yday; // Years to days
|
||||||
|
cumulative = cumulative * 24 + spec.tm_hour; // Days to hours
|
||||||
static int ConvertOsTimeZoneOffsetToInt(const std::string& timezone) {
|
cumulative = cumulative * 60 + spec.tm_min; // Hours to minutes
|
||||||
try {
|
cumulative = cumulative * 60 + spec.tm_sec; // Minutes to seconds
|
||||||
return std::stoi(timezone);
|
return cumulative;
|
||||||
} catch (const std::invalid_argument&) {
|
|
||||||
LOG_CRITICAL(Common, "invalid_argument with {}!", timezone);
|
|
||||||
return 0;
|
|
||||||
} catch (const std::out_of_range&) {
|
|
||||||
LOG_CRITICAL(Common, "out_of_range with {}!", timezone);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::seconds GetCurrentOffsetSeconds() {
|
std::chrono::seconds GetCurrentOffsetSeconds() {
|
||||||
const int offset{ConvertOsTimeZoneOffsetToInt(GetOsTimeZoneOffset())};
|
const std::time_t t{std::time(nullptr)};
|
||||||
|
const std::tm local{*std::localtime(&t)};
|
||||||
|
const std::tm gmt{*std::gmtime(&t)};
|
||||||
|
|
||||||
int seconds{(offset / 100) * 60 * 60}; // Convert hour component to seconds
|
// gmt_seconds is a different offset than time(nullptr)
|
||||||
seconds += (offset % 100) * 60; // Convert minute component to seconds
|
const auto gmt_seconds = TmSpecToSeconds(gmt);
|
||||||
|
const auto local_seconds = TmSpecToSeconds(local);
|
||||||
|
const auto seconds_offset = local_seconds - gmt_seconds;
|
||||||
|
|
||||||
return std::chrono::seconds{seconds};
|
return std::chrono::seconds{seconds_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key is [Hours * 100 + Minutes], multiplied by 100 if DST
|
// Key is [Hours * 100 + Minutes], multiplied by 100 if DST
|
||||||
@ -71,11 +68,6 @@ const static std::map<s64, const char*> off_timezones = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string FindSystemTimeZone() {
|
std::string FindSystemTimeZone() {
|
||||||
#if defined(MINGW)
|
|
||||||
// MinGW has broken strftime -- https://sourceforge.net/p/mingw-w64/bugs/793/
|
|
||||||
// e.g. fmt::format("{:%z}") -- returns "Eastern Daylight Time" when it should be "-0400"
|
|
||||||
return timezones[0];
|
|
||||||
#else
|
|
||||||
const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count());
|
const s64 seconds = static_cast<s64>(GetCurrentOffsetSeconds().count());
|
||||||
|
|
||||||
const s64 minutes = seconds / 60;
|
const s64 minutes = seconds / 60;
|
||||||
@ -97,7 +89,6 @@ std::string FindSystemTimeZone() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours));
|
return fmt::format("Etc/GMT{:s}{:d}", hours > 0 ? "-" : "+", std::abs(hours));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Common::TimeZone
|
} // namespace Common::TimeZone
|
||||||
|
@ -217,8 +217,8 @@ void ARM_Interface::Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) {
|
void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
|
||||||
watchpoints = ℘
|
watchpoints = wp;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
|
const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(
|
||||||
|
@ -186,7 +186,7 @@ public:
|
|||||||
virtual void SaveContext(ThreadContext64& ctx) const = 0;
|
virtual void SaveContext(ThreadContext64& ctx) const = 0;
|
||||||
virtual void LoadContext(const ThreadContext32& ctx) = 0;
|
virtual void LoadContext(const ThreadContext32& ctx) = 0;
|
||||||
virtual void LoadContext(const ThreadContext64& ctx) = 0;
|
virtual void LoadContext(const ThreadContext64& ctx) = 0;
|
||||||
void LoadWatchpointArray(const WatchpointArray& wp);
|
void LoadWatchpointArray(const WatchpointArray* wp);
|
||||||
|
|
||||||
/// Clears the exclusive monitor's state.
|
/// Clears the exclusive monitor's state.
|
||||||
virtual void ClearExclusiveState() = 0;
|
virtual void ClearExclusiveState() = 0;
|
||||||
|
@ -346,11 +346,11 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
|
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
|
||||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
|
DynarmicExclusiveMonitor& exclusive_monitor_,
|
||||||
|
std::size_t core_index_)
|
||||||
: ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
|
: ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
|
||||||
cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
|
cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
|
||||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
|
exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
|
||||||
null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
|
|
||||||
|
|
||||||
ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
|
ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
|
||||||
|
|
||||||
namespace Core::Memory {
|
namespace Core::Memory {
|
||||||
class Memory;
|
class Memory;
|
||||||
@ -28,8 +28,8 @@ class System;
|
|||||||
|
|
||||||
class ARM_Dynarmic_32 final : public ARM_Interface {
|
class ARM_Dynarmic_32 final : public ARM_Interface {
|
||||||
public:
|
public:
|
||||||
ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
|
||||||
std::size_t core_index_);
|
DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
|
||||||
~ARM_Dynarmic_32() override;
|
~ARM_Dynarmic_32() override;
|
||||||
|
|
||||||
void SetPC(u64 pc) override;
|
void SetPC(u64 pc) override;
|
||||||
|
@ -405,11 +405,11 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
|
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
|
||||||
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
|
DynarmicExclusiveMonitor& exclusive_monitor_,
|
||||||
|
std::size_t core_index_)
|
||||||
: ARM_Interface{system_, uses_wall_clock_},
|
: ARM_Interface{system_, uses_wall_clock_},
|
||||||
cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
|
cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
|
||||||
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
|
exclusive_monitor{exclusive_monitor_}, null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
|
||||||
null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
|
|
||||||
|
|
||||||
ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
|
ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h"
|
||||||
|
|
||||||
namespace Core::Memory {
|
namespace Core::Memory {
|
||||||
class Memory;
|
class Memory;
|
||||||
@ -25,8 +25,8 @@ class System;
|
|||||||
|
|
||||||
class ARM_Dynarmic_64 final : public ARM_Interface {
|
class ARM_Dynarmic_64 final : public ARM_Interface {
|
||||||
public:
|
public:
|
||||||
ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
|
ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
|
||||||
std::size_t core_index_);
|
DynarmicExclusiveMonitor& exclusive_monitor_, std::size_t core_index_);
|
||||||
~ARM_Dynarmic_64() override;
|
~ARM_Dynarmic_64() override;
|
||||||
|
|
||||||
void SetPC(u64 pc) override;
|
void SetPC(u64 pc) override;
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
#include <dynarmic/interface/exclusive_monitor.h>
|
#include <dynarmic/interface/exclusive_monitor.h>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/arm/dynarmic/arm_dynarmic_32.h"
|
|
||||||
#include "core/arm/dynarmic/arm_dynarmic_64.h"
|
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/exclusive_monitor.h"
|
||||||
|
|
||||||
namespace Core::Memory {
|
namespace Core::Memory {
|
||||||
@ -16,6 +14,9 @@ class Memory;
|
|||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
|
class ARM_Dynarmic_32;
|
||||||
|
class ARM_Dynarmic_64;
|
||||||
|
|
||||||
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
|
class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
|
||||||
public:
|
public:
|
||||||
explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_);
|
explicit DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_);
|
||||||
|
@ -880,6 +880,14 @@ const FileSys::ContentProvider& System::GetContentProvider() const {
|
|||||||
return *impl->content_provider;
|
return *impl->content_provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileSys::ContentProviderUnion& System::GetContentProviderUnion() {
|
||||||
|
return *impl->content_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::ContentProviderUnion& System::GetContentProviderUnion() const {
|
||||||
|
return *impl->content_provider;
|
||||||
|
}
|
||||||
|
|
||||||
Service::FileSystem::FileSystemController& System::GetFileSystemController() {
|
Service::FileSystem::FileSystemController& System::GetFileSystemController() {
|
||||||
return impl->fs_controller;
|
return impl->fs_controller;
|
||||||
}
|
}
|
||||||
|
@ -381,6 +381,9 @@ public:
|
|||||||
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
|
[[nodiscard]] FileSys::ContentProvider& GetContentProvider();
|
||||||
[[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const;
|
[[nodiscard]] const FileSys::ContentProvider& GetContentProvider() const;
|
||||||
|
|
||||||
|
[[nodiscard]] FileSys::ContentProviderUnion& GetContentProviderUnion();
|
||||||
|
[[nodiscard]] const FileSys::ContentProviderUnion& GetContentProviderUnion() const;
|
||||||
|
|
||||||
[[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController();
|
[[nodiscard]] Service::FileSystem::FileSystemController& GetFileSystemController();
|
||||||
[[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const;
|
[[nodiscard]] const Service::FileSystem::FileSystemController& GetFileSystemController() const;
|
||||||
|
|
||||||
|
@ -261,10 +261,8 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
|||||||
const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
|
const size_t addr{static_cast<size_t>(strtoll(command.data(), nullptr, 16))};
|
||||||
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
|
const size_t size{static_cast<size_t>(strtoll(command.data() + sep, nullptr, 16))};
|
||||||
|
|
||||||
if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
std::vector<u8> mem(size);
|
||||||
std::vector<u8> mem(size);
|
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
|
||||||
system.ApplicationMemory().ReadBlock(addr, mem.data(), size);
|
|
||||||
|
|
||||||
SendReply(Common::HexToString(mem));
|
SendReply(Common::HexToString(mem));
|
||||||
} else {
|
} else {
|
||||||
SendReply(GDB_STUB_REPLY_ERR);
|
SendReply(GDB_STUB_REPLY_ERR);
|
||||||
@ -281,8 +279,7 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
|||||||
const auto mem_substr{std::string_view(command).substr(mem_sep)};
|
const auto mem_substr{std::string_view(command).substr(mem_sep)};
|
||||||
const auto mem{Common::HexStringToVector(mem_substr, false)};
|
const auto mem{Common::HexStringToVector(mem_substr, false)};
|
||||||
|
|
||||||
if (system.ApplicationMemory().IsValidVirtualAddressRange(addr, size)) {
|
if (system.ApplicationMemory().WriteBlock(addr, mem.data(), size)) {
|
||||||
system.ApplicationMemory().WriteBlock(addr, mem.data(), size);
|
|
||||||
system.InvalidateCpuInstructionCacheRange(addr, size);
|
system.InvalidateCpuInstructionCacheRange(addr, size);
|
||||||
SendReply(GDB_STUB_REPLY_OK);
|
SendReply(GDB_STUB_REPLY_OK);
|
||||||
} else {
|
} else {
|
||||||
@ -556,7 +553,7 @@ void GDBStub::HandleQuery(std::string_view command) {
|
|||||||
} else {
|
} else {
|
||||||
SendReply(fmt::format(
|
SendReply(fmt::format(
|
||||||
"TextSeg={:x}",
|
"TextSeg={:x}",
|
||||||
GetInteger(system.ApplicationProcess()->PageTable().GetCodeRegionStart())));
|
GetInteger(system.ApplicationProcess()->GetPageTable().GetCodeRegionStart())));
|
||||||
}
|
}
|
||||||
} else if (command.starts_with("Xfer:libraries:read::")) {
|
} else if (command.starts_with("Xfer:libraries:read::")) {
|
||||||
Loader::AppLoader::Modules modules;
|
Loader::AppLoader::Modules modules;
|
||||||
@ -731,7 +728,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
|
|||||||
std::string reply;
|
std::string reply;
|
||||||
|
|
||||||
auto* process = system.ApplicationProcess();
|
auto* process = system.ApplicationProcess();
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
|
|
||||||
const char* commands = "Commands:\n"
|
const char* commands = "Commands:\n"
|
||||||
" get fastmem\n"
|
" get fastmem\n"
|
||||||
|
@ -15,8 +15,8 @@ void KAutoObject::RegisterWithKernel() {
|
|||||||
m_kernel.RegisterKernelObject(this);
|
m_kernel.RegisterKernelObject(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KAutoObject::UnregisterWithKernel() {
|
void KAutoObject::UnregisterWithKernel(KernelCore& kernel, KAutoObject* self) {
|
||||||
m_kernel.UnregisterKernelObject(this);
|
kernel.UnregisterKernelObject(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
@ -159,14 +159,15 @@ public:
|
|||||||
|
|
||||||
// If ref count hits zero, destroy the object.
|
// If ref count hits zero, destroy the object.
|
||||||
if (cur_ref_count - 1 == 0) {
|
if (cur_ref_count - 1 == 0) {
|
||||||
|
KernelCore& kernel = m_kernel;
|
||||||
this->Destroy();
|
this->Destroy();
|
||||||
this->UnregisterWithKernel();
|
KAutoObject::UnregisterWithKernel(kernel, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RegisterWithKernel();
|
void RegisterWithKernel();
|
||||||
void UnregisterWithKernel();
|
static void UnregisterWithKernel(KernelCore& kernel, KAutoObject* self);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
KernelCore& m_kernel;
|
KernelCore& m_kernel;
|
||||||
|
@ -25,7 +25,7 @@ Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, KProcessAddres
|
|||||||
m_owner = GetCurrentProcessPointer(m_kernel);
|
m_owner = GetCurrentProcessPointer(m_kernel);
|
||||||
|
|
||||||
// Get the owner page table.
|
// Get the owner page table.
|
||||||
auto& page_table = m_owner->PageTable();
|
auto& page_table = m_owner->GetPageTable();
|
||||||
|
|
||||||
// Construct the page group.
|
// Construct the page group.
|
||||||
m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
|
m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
|
||||||
@ -53,7 +53,7 @@ void KCodeMemory::Finalize() {
|
|||||||
// Unlock.
|
// Unlock.
|
||||||
if (!m_is_mapped && !m_is_owner_mapped) {
|
if (!m_is_mapped && !m_is_owner_mapped) {
|
||||||
const size_t size = m_page_group->GetNumPages() * PageSize;
|
const size_t size = m_page_group->GetNumPages() * PageSize;
|
||||||
m_owner->PageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
|
m_owner->GetPageTable().UnlockForCodeMemory(m_address, size, *m_page_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the page group.
|
// Close the page group.
|
||||||
@ -75,7 +75,7 @@ Result KCodeMemory::Map(KProcessAddress address, size_t size) {
|
|||||||
R_UNLESS(!m_is_mapped, ResultInvalidState);
|
R_UNLESS(!m_is_mapped, ResultInvalidState);
|
||||||
|
|
||||||
// Map the memory.
|
// Map the memory.
|
||||||
R_TRY(GetCurrentProcess(m_kernel).PageTable().MapPageGroup(
|
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
|
||||||
address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
|
address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
|
||||||
|
|
||||||
// Mark ourselves as mapped.
|
// Mark ourselves as mapped.
|
||||||
@ -92,8 +92,8 @@ Result KCodeMemory::Unmap(KProcessAddress address, size_t size) {
|
|||||||
KScopedLightLock lk(m_lock);
|
KScopedLightLock lk(m_lock);
|
||||||
|
|
||||||
// Unmap the memory.
|
// Unmap the memory.
|
||||||
R_TRY(GetCurrentProcess(m_kernel).PageTable().UnmapPageGroup(address, *m_page_group,
|
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group,
|
||||||
KMemoryState::CodeOut));
|
KMemoryState::CodeOut));
|
||||||
|
|
||||||
// Mark ourselves as unmapped.
|
// Mark ourselves as unmapped.
|
||||||
m_is_mapped = false;
|
m_is_mapped = false;
|
||||||
@ -126,8 +126,8 @@ Result KCodeMemory::MapToOwner(KProcessAddress address, size_t size, Svc::Memory
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Map the memory.
|
// Map the memory.
|
||||||
R_TRY(m_owner->PageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode,
|
R_TRY(m_owner->GetPageTable().MapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode,
|
||||||
k_perm));
|
k_perm));
|
||||||
|
|
||||||
// Mark ourselves as mapped.
|
// Mark ourselves as mapped.
|
||||||
m_is_owner_mapped = true;
|
m_is_owner_mapped = true;
|
||||||
@ -143,7 +143,8 @@ Result KCodeMemory::UnmapFromOwner(KProcessAddress address, size_t size) {
|
|||||||
KScopedLightLock lk(m_lock);
|
KScopedLightLock lk(m_lock);
|
||||||
|
|
||||||
// Unmap the memory.
|
// Unmap the memory.
|
||||||
R_TRY(m_owner->PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::GeneratedCode));
|
R_TRY(m_owner->GetPageTable().UnmapPageGroup(address, *m_page_group,
|
||||||
|
KMemoryState::GeneratedCode));
|
||||||
|
|
||||||
// Mark ourselves as unmapped.
|
// Mark ourselves as unmapped.
|
||||||
m_is_owner_mapped = false;
|
m_is_owner_mapped = false;
|
||||||
|
@ -388,39 +388,6 @@ public:
|
|||||||
constexpr size_t GetHeapSize() const {
|
constexpr size_t GetHeapSize() const {
|
||||||
return m_current_heap_end - m_heap_region_start;
|
return m_current_heap_end - m_heap_region_start;
|
||||||
}
|
}
|
||||||
constexpr bool IsInsideAddressSpace(KProcessAddress address, size_t size) const {
|
|
||||||
return m_address_space_start <= address && address + size - 1 <= m_address_space_end - 1;
|
|
||||||
}
|
|
||||||
constexpr bool IsOutsideAliasRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return m_alias_region_start > address || address + size - 1 > m_alias_region_end - 1;
|
|
||||||
}
|
|
||||||
constexpr bool IsOutsideStackRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return m_stack_region_start > address || address + size - 1 > m_stack_region_end - 1;
|
|
||||||
}
|
|
||||||
constexpr bool IsInvalidRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return address + size - 1 > GetAliasCodeRegionStart() + GetAliasCodeRegionSize() - 1;
|
|
||||||
}
|
|
||||||
constexpr bool IsInsideHeapRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return address + size > m_heap_region_start && m_heap_region_end > address;
|
|
||||||
}
|
|
||||||
constexpr bool IsInsideAliasRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return address + size > m_alias_region_start && m_alias_region_end > address;
|
|
||||||
}
|
|
||||||
constexpr bool IsOutsideASLRRegion(KProcessAddress address, size_t size) const {
|
|
||||||
if (IsInvalidRegion(address, size)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (IsInsideHeapRegion(address, size)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (IsInsideAliasRegion(address, size)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
constexpr bool IsInsideASLRRegion(KProcessAddress address, size_t size) const {
|
|
||||||
return !IsOutsideASLRRegion(address, size);
|
|
||||||
}
|
|
||||||
constexpr size_t GetNumGuardPages() const {
|
constexpr size_t GetNumGuardPages() const {
|
||||||
return IsKernel() ? 1 : 4;
|
return IsKernel() ? 1 : 4;
|
||||||
}
|
}
|
||||||
@ -436,6 +403,14 @@ public:
|
|||||||
return m_address_space_start <= addr && addr < addr + size &&
|
return m_address_space_start <= addr && addr < addr + size &&
|
||||||
addr + size - 1 <= m_address_space_end - 1;
|
addr + size - 1 <= m_address_space_end - 1;
|
||||||
}
|
}
|
||||||
|
constexpr bool IsInAliasRegion(KProcessAddress addr, size_t size) const {
|
||||||
|
return this->Contains(addr, size) && m_alias_region_start <= addr &&
|
||||||
|
addr + size - 1 <= m_alias_region_end - 1;
|
||||||
|
}
|
||||||
|
constexpr bool IsInHeapRegion(KProcessAddress addr, size_t size) const {
|
||||||
|
return this->Contains(addr, size) && m_heap_region_start <= addr &&
|
||||||
|
addr + size - 1 <= m_heap_region_end - 1;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout,
|
static KVirtualAddress GetLinearMappedVirtualAddress(const KMemoryLayout& layout,
|
||||||
|
@ -38,7 +38,7 @@ namespace {
|
|||||||
*/
|
*/
|
||||||
void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
|
void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority,
|
||||||
KProcessAddress stack_top) {
|
KProcessAddress stack_top) {
|
||||||
const KProcessAddress entry_point = owner_process.PageTable().GetCodeRegionStart();
|
const KProcessAddress entry_point = owner_process.GetPageTable().GetCodeRegionStart();
|
||||||
ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
|
ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
|
||||||
|
|
||||||
KThread* thread = KThread::Create(system.Kernel());
|
KThread* thread = KThread::Create(system.Kernel());
|
||||||
|
@ -109,16 +109,6 @@ public:
|
|||||||
static Result Initialize(KProcess* process, Core::System& system, std::string process_name,
|
static Result Initialize(KProcess* process, Core::System& system, std::string process_name,
|
||||||
ProcessType type, KResourceLimit* res_limit);
|
ProcessType type, KResourceLimit* res_limit);
|
||||||
|
|
||||||
/// Gets a reference to the process' page table.
|
|
||||||
KPageTable& PageTable() {
|
|
||||||
return m_page_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets const a reference to the process' page table.
|
|
||||||
const KPageTable& PageTable() const {
|
|
||||||
return m_page_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a reference to the process' page table.
|
/// Gets a reference to the process' page table.
|
||||||
KPageTable& GetPageTable() {
|
KPageTable& GetPageTable() {
|
||||||
return m_page_table;
|
return m_page_table;
|
||||||
|
@ -510,11 +510,12 @@ void KScheduler::Unload(KThread* thread) {
|
|||||||
|
|
||||||
void KScheduler::Reload(KThread* thread) {
|
void KScheduler::Reload(KThread* thread) {
|
||||||
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
|
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
|
||||||
|
auto* process = thread->GetOwnerProcess();
|
||||||
cpu_core.LoadContext(thread->GetContext32());
|
cpu_core.LoadContext(thread->GetContext32());
|
||||||
cpu_core.LoadContext(thread->GetContext64());
|
cpu_core.LoadContext(thread->GetContext64());
|
||||||
cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
|
cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
|
||||||
cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
|
cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
|
||||||
cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints());
|
cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
|
||||||
cpu_core.ClearExclusiveState();
|
cpu_core.ClearExclusiveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ Result KSharedMemory::Map(KProcess& target_process, KProcessAddress address, std
|
|||||||
R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission);
|
R_UNLESS(map_perm == test_perm, ResultInvalidNewMemoryPermission);
|
||||||
}
|
}
|
||||||
|
|
||||||
R_RETURN(target_process.PageTable().MapPageGroup(address, *m_page_group, KMemoryState::Shared,
|
R_RETURN(target_process.GetPageTable().MapPageGroup(
|
||||||
ConvertToKMemoryPermission(map_perm)));
|
address, *m_page_group, KMemoryState::Shared, ConvertToKMemoryPermission(map_perm)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
|
Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
|
||||||
@ -100,7 +100,7 @@ Result KSharedMemory::Unmap(KProcess& target_process, KProcessAddress address,
|
|||||||
R_UNLESS(m_size == unmap_size, ResultInvalidSize);
|
R_UNLESS(m_size == unmap_size, ResultInvalidSize);
|
||||||
|
|
||||||
R_RETURN(
|
R_RETURN(
|
||||||
target_process.PageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared));
|
target_process.GetPageTable().UnmapPageGroup(address, *m_page_group, KMemoryState::Shared));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
@ -129,7 +129,7 @@ Result KThread::Initialize(KThreadFunction func, uintptr_t arg, KProcessAddress
|
|||||||
case ThreadType::User:
|
case ThreadType::User:
|
||||||
ASSERT(((owner == nullptr) ||
|
ASSERT(((owner == nullptr) ||
|
||||||
(owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
|
(owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask()));
|
||||||
ASSERT(((owner == nullptr) ||
|
ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) ||
|
||||||
(owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
|
(owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask()));
|
||||||
break;
|
break;
|
||||||
case ThreadType::Kernel:
|
case ThreadType::Kernel:
|
||||||
|
@ -25,9 +25,9 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
|
|||||||
|
|
||||||
// Map the address in.
|
// Map the address in.
|
||||||
const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);
|
const auto phys_addr = kernel.System().DeviceMemory().GetPhysicalAddr(page_buf);
|
||||||
R_TRY(m_owner->PageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr,
|
R_TRY(m_owner->GetPageTable().MapPages(std::addressof(m_virt_addr), 1, PageSize, phys_addr,
|
||||||
KMemoryState::ThreadLocal,
|
KMemoryState::ThreadLocal,
|
||||||
KMemoryPermission::UserReadWrite));
|
KMemoryPermission::UserReadWrite));
|
||||||
|
|
||||||
// We succeeded.
|
// We succeeded.
|
||||||
page_buf_guard.Cancel();
|
page_buf_guard.Cancel();
|
||||||
@ -37,11 +37,11 @@ Result KThreadLocalPage::Initialize(KernelCore& kernel, KProcess* process) {
|
|||||||
|
|
||||||
Result KThreadLocalPage::Finalize() {
|
Result KThreadLocalPage::Finalize() {
|
||||||
// Get the physical address of the page.
|
// Get the physical address of the page.
|
||||||
const KPhysicalAddress phys_addr = m_owner->PageTable().GetPhysicalAddr(m_virt_addr);
|
const KPhysicalAddress phys_addr = m_owner->GetPageTable().GetPhysicalAddr(m_virt_addr);
|
||||||
ASSERT(phys_addr);
|
ASSERT(phys_addr);
|
||||||
|
|
||||||
// Unmap the page.
|
// Unmap the page.
|
||||||
R_TRY(m_owner->PageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal));
|
R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState::ThreadLocal));
|
||||||
|
|
||||||
// Free the page.
|
// Free the page.
|
||||||
KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr));
|
KPageBuffer::Free(*m_kernel, KPageBuffer::FromPhysicalAddress(m_kernel->System(), phys_addr));
|
||||||
|
@ -17,7 +17,9 @@ PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KSchedu
|
|||||||
// a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
|
// a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
|
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
|
||||||
system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index);
|
system, kernel.IsMulticore(),
|
||||||
|
reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
|
||||||
|
m_core_index);
|
||||||
#else
|
#else
|
||||||
#error Platform not supported yet.
|
#error Platform not supported yet.
|
||||||
#endif
|
#endif
|
||||||
@ -31,7 +33,9 @@ void PhysicalCore::Initialize(bool is_64_bit) {
|
|||||||
if (!is_64_bit) {
|
if (!is_64_bit) {
|
||||||
// We already initialized a 64-bit core, replace with a 32-bit one.
|
// We already initialized a 64-bit core, replace with a 32-bit one.
|
||||||
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
|
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
|
||||||
m_system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), m_core_index);
|
m_system, kernel.IsMulticore(),
|
||||||
|
reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
|
||||||
|
m_core_index);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error Platform not supported yet.
|
#error Platform not supported yet.
|
||||||
|
@ -42,7 +42,7 @@ Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 ad
|
|||||||
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Verify the region is within range.
|
// Verify the region is within range.
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Perform the operation.
|
// Perform the operation.
|
||||||
|
@ -48,7 +48,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t
|
|||||||
SCOPE_EXIT({ code_mem->Close(); });
|
SCOPE_EXIT({ code_mem->Close(); });
|
||||||
|
|
||||||
// Verify that the region is in range.
|
// Verify that the region is in range.
|
||||||
R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size),
|
R_UNLESS(GetCurrentProcess(system.Kernel()).GetPageTable().Contains(address, size),
|
||||||
ResultInvalidCurrentMemory);
|
ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Initialize the code memory.
|
// Initialize the code memory.
|
||||||
@ -92,7 +92,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
|||||||
case CodeMemoryOperation::Map: {
|
case CodeMemoryOperation::Map: {
|
||||||
// Check that the region is in range.
|
// Check that the region is in range.
|
||||||
R_UNLESS(GetCurrentProcess(system.Kernel())
|
R_UNLESS(GetCurrentProcess(system.Kernel())
|
||||||
.PageTable()
|
.GetPageTable()
|
||||||
.CanContain(address, size, KMemoryState::CodeOut),
|
.CanContain(address, size, KMemoryState::CodeOut),
|
||||||
ResultInvalidMemoryRegion);
|
ResultInvalidMemoryRegion);
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
|||||||
case CodeMemoryOperation::Unmap: {
|
case CodeMemoryOperation::Unmap: {
|
||||||
// Check that the region is in range.
|
// Check that the region is in range.
|
||||||
R_UNLESS(GetCurrentProcess(system.Kernel())
|
R_UNLESS(GetCurrentProcess(system.Kernel())
|
||||||
.PageTable()
|
.GetPageTable()
|
||||||
.CanContain(address, size, KMemoryState::CodeOut),
|
.CanContain(address, size, KMemoryState::CodeOut),
|
||||||
ResultInvalidMemoryRegion);
|
ResultInvalidMemoryRegion);
|
||||||
|
|
||||||
@ -117,8 +117,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
|||||||
} break;
|
} break;
|
||||||
case CodeMemoryOperation::MapToOwner: {
|
case CodeMemoryOperation::MapToOwner: {
|
||||||
// Check that the region is in range.
|
// Check that the region is in range.
|
||||||
R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
|
R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
|
||||||
KMemoryState::GeneratedCode),
|
KMemoryState::GeneratedCode),
|
||||||
ResultInvalidMemoryRegion);
|
ResultInvalidMemoryRegion);
|
||||||
|
|
||||||
// Check the memory permission.
|
// Check the memory permission.
|
||||||
@ -129,8 +129,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
|||||||
} break;
|
} break;
|
||||||
case CodeMemoryOperation::UnmapFromOwner: {
|
case CodeMemoryOperation::UnmapFromOwner: {
|
||||||
// Check that the region is in range.
|
// Check that the region is in range.
|
||||||
R_UNLESS(code_mem->GetOwner()->PageTable().CanContain(address, size,
|
R_UNLESS(code_mem->GetOwner()->GetPageTable().CanContain(address, size,
|
||||||
KMemoryState::GeneratedCode),
|
KMemoryState::GeneratedCode),
|
||||||
ResultInvalidMemoryRegion);
|
ResultInvalidMemoryRegion);
|
||||||
|
|
||||||
// Check the memory permission.
|
// Check the memory permission.
|
||||||
|
@ -107,7 +107,7 @@ Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Han
|
|||||||
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Validate that the process address is within range.
|
// Validate that the process address is within range.
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Map.
|
// Map.
|
||||||
@ -148,7 +148,7 @@ Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Han
|
|||||||
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Validate that the process address is within range.
|
// Validate that the process address is within range.
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Map.
|
// Map.
|
||||||
@ -180,7 +180,7 @@ Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle p
|
|||||||
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Validate that the process address is within range.
|
// Validate that the process address is within range.
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
|
R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
|
||||||
|
@ -54,35 +54,35 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AliasRegionAddress:
|
case InfoType::AliasRegionAddress:
|
||||||
*result = GetInteger(process->PageTable().GetAliasRegionStart());
|
*result = GetInteger(process->GetPageTable().GetAliasRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AliasRegionSize:
|
case InfoType::AliasRegionSize:
|
||||||
*result = process->PageTable().GetAliasRegionSize();
|
*result = process->GetPageTable().GetAliasRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::HeapRegionAddress:
|
case InfoType::HeapRegionAddress:
|
||||||
*result = GetInteger(process->PageTable().GetHeapRegionStart());
|
*result = GetInteger(process->GetPageTable().GetHeapRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::HeapRegionSize:
|
case InfoType::HeapRegionSize:
|
||||||
*result = process->PageTable().GetHeapRegionSize();
|
*result = process->GetPageTable().GetHeapRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AslrRegionAddress:
|
case InfoType::AslrRegionAddress:
|
||||||
*result = GetInteger(process->PageTable().GetAliasCodeRegionStart());
|
*result = GetInteger(process->GetPageTable().GetAliasCodeRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::AslrRegionSize:
|
case InfoType::AslrRegionSize:
|
||||||
*result = process->PageTable().GetAliasCodeRegionSize();
|
*result = process->GetPageTable().GetAliasCodeRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::StackRegionAddress:
|
case InfoType::StackRegionAddress:
|
||||||
*result = GetInteger(process->PageTable().GetStackRegionStart());
|
*result = GetInteger(process->GetPageTable().GetStackRegionStart());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::StackRegionSize:
|
case InfoType::StackRegionSize:
|
||||||
*result = process->PageTable().GetStackRegionSize();
|
*result = process->GetPageTable().GetStackRegionSize();
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
case InfoType::TotalMemorySize:
|
case InfoType::TotalMemorySize:
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_server_session.h"
|
#include "core/hle/kernel/k_server_session.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel::Svc {
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
@ -49,14 +50,10 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad
|
|||||||
|
|
||||||
// Copy user handles.
|
// Copy user handles.
|
||||||
if (num_handles > 0) {
|
if (num_handles > 0) {
|
||||||
// Ensure we can try to get the handles.
|
|
||||||
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
|
|
||||||
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
|
|
||||||
ResultInvalidPointer);
|
|
||||||
|
|
||||||
// Get the handles.
|
// Get the handles.
|
||||||
GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
|
R_UNLESS(GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
|
||||||
sizeof(Handle) * num_handles);
|
sizeof(Handle) * num_handles),
|
||||||
|
ResultInvalidPointer);
|
||||||
|
|
||||||
// Convert the handles to objects.
|
// Convert the handles to objects.
|
||||||
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
|
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
|
||||||
|
@ -63,36 +63,13 @@ Result MapUnmapMemorySanityChecks(const KPageTable& manager, u64 dst_addr, u64 s
|
|||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager.IsInsideAddressSpace(src_addr, size)) {
|
if (!manager.Contains(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager.IsOutsideStackRegion(dst_addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
|
|
||||||
dst_addr, size);
|
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager.IsInsideHeapRegion(dst_addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination does not fit within the heap region, addr=0x{:016X}, "
|
|
||||||
"size=0x{:016X}",
|
|
||||||
dst_addr, size);
|
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manager.IsInsideAliasRegion(dst_addr, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination does not fit within the map region, addr=0x{:016X}, "
|
|
||||||
"size=0x{:016X}",
|
|
||||||
dst_addr, size);
|
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +89,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe
|
|||||||
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
|
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
|
||||||
|
|
||||||
// Validate that the region is in range for the current process.
|
// Validate that the region is in range for the current process.
|
||||||
auto& page_table = GetCurrentProcess(system.Kernel()).PageTable();
|
auto& page_table = GetCurrentProcess(system.Kernel()).GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Set the memory attribute.
|
// Set the memory attribute.
|
||||||
@ -136,7 +113,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask,
|
|||||||
R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
|
R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
|
||||||
|
|
||||||
// Validate that the region is in range for the current process.
|
// Validate that the region is in range for the current process.
|
||||||
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
|
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
||||||
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Set the memory attribute.
|
// Set the memory attribute.
|
||||||
@ -148,7 +125,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
|||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
|
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
||||||
|
|
||||||
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
@ -163,7 +140,7 @@ Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
|||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
|
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
||||||
|
|
||||||
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
|
||||||
result.IsError()) {
|
result.IsError()) {
|
||||||
|
@ -16,7 +16,7 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
|
|||||||
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
|
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
|
||||||
|
|
||||||
// Set the heap size.
|
// Set the heap size.
|
||||||
R_RETURN(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size));
|
R_RETURN(GetCurrentProcess(system.Kernel()).GetPageTable().SetHeapSize(out_address, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps memory at a desired address
|
/// Maps memory at a desired address
|
||||||
@ -44,21 +44,21 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
|
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
|
||||||
auto& page_table{current_process->PageTable()};
|
auto& page_table{current_process->GetPageTable()};
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
R_THROW(ResultInvalidState);
|
R_THROW(ResultInvalidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
if (!page_table.Contains(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
if (!page_table.IsInAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
@ -93,21 +93,21 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
|
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
|
||||||
auto& page_table{current_process->PageTable()};
|
auto& page_table{current_process->GetPageTable()};
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
R_THROW(ResultInvalidState);
|
R_THROW(ResultInvalidState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
if (!page_table.Contains(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
if (!page_table.IsInAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
|
@ -66,8 +66,8 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
|
|||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
const auto total_copy_size = out_process_ids_size * sizeof(u64);
|
const auto total_copy_size = out_process_ids_size * sizeof(u64);
|
||||||
|
|
||||||
if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace(
|
if (out_process_ids_size > 0 &&
|
||||||
out_process_ids, total_copy_size)) {
|
!GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_process_ids, out_process_ids + total_copy_size);
|
out_process_ids, out_process_ids + total_copy_size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
|
@ -49,7 +49,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u
|
|||||||
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Validate that the address is in range.
|
// Validate that the address is in range.
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Set the memory permission.
|
// Set the memory permission.
|
||||||
@ -77,8 +77,8 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha
|
|||||||
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Get the page tables.
|
// Get the page tables.
|
||||||
auto& dst_pt = dst_process->PageTable();
|
auto& dst_pt = dst_process->GetPageTable();
|
||||||
auto& src_pt = src_process->PageTable();
|
auto& src_pt = src_process->GetPageTable();
|
||||||
|
|
||||||
// Validate that the mapping is in range.
|
// Validate that the mapping is in range.
|
||||||
R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
|
||||||
@ -118,8 +118,8 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_
|
|||||||
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
|
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
|
||||||
|
|
||||||
// Get the page tables.
|
// Get the page tables.
|
||||||
auto& dst_pt = dst_process->PageTable();
|
auto& dst_pt = dst_process->GetPageTable();
|
||||||
auto& src_pt = src_process->PageTable();
|
auto& src_pt = src_process->GetPageTable();
|
||||||
|
|
||||||
// Validate that the mapping is in range.
|
// Validate that the mapping is in range.
|
||||||
R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(src_pt.Contains(src_address, size), ResultInvalidCurrentMemory);
|
||||||
@ -178,8 +178,8 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
|
|||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
if (!page_table.IsInsideAddressSpace(src_address, size)) {
|
if (!page_table.Contains(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
@ -187,14 +187,6 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
|
|||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size));
|
R_RETURN(page_table.MapCodeMemory(dst_address, src_address, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,8 +238,8 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
|
|||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
if (!page_table.IsInsideAddressSpace(src_address, size)) {
|
if (!page_table.Contains(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
@ -255,14 +247,6 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
|
|||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
|
||||||
LOG_ERROR(Kernel_SVC,
|
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
|
||||||
"size=0x{:016X}).",
|
|
||||||
dst_address, size);
|
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size,
|
R_RETURN(page_table.UnmapCodeMemory(dst_address, src_address, size,
|
||||||
KPageTable::ICacheInvalidationStrategy::InvalidateAll));
|
KPageTable::ICacheInvalidationStrategy::InvalidateAll));
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& current_memory{GetCurrentMemory(system.Kernel())};
|
auto& current_memory{GetCurrentMemory(system.Kernel())};
|
||||||
const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
|
const auto memory_info{process->GetPageTable().QueryInfo(address).GetSvcMemoryInfo()};
|
||||||
|
|
||||||
current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
|
current_memory.WriteBlock(out_memory_info, std::addressof(memory_info), sizeof(memory_info));
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u
|
|||||||
|
|
||||||
// Get the current process.
|
// Get the current process.
|
||||||
auto& process = GetCurrentProcess(system.Kernel());
|
auto& process = GetCurrentProcess(system.Kernel());
|
||||||
auto& page_table = process.PageTable();
|
auto& page_table = process.GetPageTable();
|
||||||
|
|
||||||
// Get the shared memory.
|
// Get the shared memory.
|
||||||
KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
|
KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
|
||||||
@ -73,7 +73,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, u64 address,
|
|||||||
|
|
||||||
// Get the current process.
|
// Get the current process.
|
||||||
auto& process = GetCurrentProcess(system.Kernel());
|
auto& process = GetCurrentProcess(system.Kernel());
|
||||||
auto& page_table = process.PageTable();
|
auto& page_table = process.GetPageTable();
|
||||||
|
|
||||||
// Get the shared memory.
|
// Get the shared memory.
|
||||||
KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
|
KScopedAutoObject shmem = process.GetHandleTable().GetObject<KSharedMemory>(shmem_handle);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/svc.h"
|
#include "core/hle/kernel/svc.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel::Svc {
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
@ -64,14 +65,10 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
|||||||
|
|
||||||
// Copy user handles.
|
// Copy user handles.
|
||||||
if (num_handles > 0) {
|
if (num_handles > 0) {
|
||||||
// Ensure we can try to get the handles.
|
|
||||||
R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
|
|
||||||
user_handles, static_cast<u64>(sizeof(Handle) * num_handles)),
|
|
||||||
ResultInvalidPointer);
|
|
||||||
|
|
||||||
// Get the handles.
|
// Get the handles.
|
||||||
GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
|
R_UNLESS(GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
|
||||||
sizeof(Handle) * num_handles);
|
sizeof(Handle) * num_handles),
|
||||||
|
ResultInvalidPointer);
|
||||||
|
|
||||||
// Convert the handles to objects.
|
// Convert the handles to objects.
|
||||||
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
|
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
|
||||||
|
@ -236,7 +236,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
|
|||||||
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
|
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
|
||||||
|
|
||||||
if (out_thread_ids_size > 0 &&
|
if (out_thread_ids_size > 0 &&
|
||||||
!current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
|
!current_process->GetPageTable().Contains(out_thread_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_thread_ids, out_thread_ids + total_copy_size);
|
out_thread_ids, out_thread_ids + total_copy_size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
|
@ -55,7 +55,7 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
|
|||||||
SCOPE_EXIT({ trmem->Close(); });
|
SCOPE_EXIT({ trmem->Close(); });
|
||||||
|
|
||||||
// Ensure that the region is in range.
|
// Ensure that the region is in range.
|
||||||
R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory);
|
R_UNLESS(process.GetPageTable().Contains(address, size), ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// Initialize the transfer memory.
|
// Initialize the transfer memory.
|
||||||
R_TRY(trmem->Initialize(address, size, map_perm));
|
R_TRY(trmem->Initialize(address, size, map_perm));
|
||||||
|
@ -496,8 +496,9 @@ public:
|
|||||||
void LoadIdTokenCache(HLERequestContext& ctx) {
|
void LoadIdTokenCache(HLERequestContext& ctx) {
|
||||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -2,13 +2,48 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "core/hle/service/glue/ectx.h"
|
#include "core/hle/service/glue/ectx.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
namespace Service::Glue {
|
namespace Service::Glue {
|
||||||
|
|
||||||
|
// This is nn::err::context::IContextRegistrar
|
||||||
|
class IContextRegistrar : public ServiceFramework<IContextRegistrar> {
|
||||||
|
public:
|
||||||
|
IContextRegistrar(Core::System& system_) : ServiceFramework{system_, "IContextRegistrar"} {
|
||||||
|
// clang-format off
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &IContextRegistrar::Complete, "Complete"},
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
~IContextRegistrar() override = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Complete(HLERequestContext& ctx) {
|
||||||
|
struct InputParameters {
|
||||||
|
u32 unk;
|
||||||
|
};
|
||||||
|
struct OutputParameters {
|
||||||
|
u32 unk;
|
||||||
|
};
|
||||||
|
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
[[maybe_unused]] auto input = rp.PopRaw<InputParameters>();
|
||||||
|
[[maybe_unused]] auto value = ctx.ReadBuffer();
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
|
ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, nullptr, "CreateContextRegistrar"},
|
{0, &ECTX_AW::CreateContextRegistrar, "CreateContextRegistrar"},
|
||||||
{1, nullptr, "CommitContext"},
|
{1, nullptr, "CommitContext"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@ -18,4 +53,10 @@ ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
|
|||||||
|
|
||||||
ECTX_AW::~ECTX_AW() = default;
|
ECTX_AW::~ECTX_AW() = default;
|
||||||
|
|
||||||
|
void ECTX_AW::CreateContextRegistrar(HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.PushIpcInterface<IContextRegistrar>(std::make_shared<IContextRegistrar>(system));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::Glue
|
} // namespace Service::Glue
|
||||||
|
@ -15,6 +15,9 @@ class ECTX_AW final : public ServiceFramework<ECTX_AW> {
|
|||||||
public:
|
public:
|
||||||
explicit ECTX_AW(Core::System& system_);
|
explicit ECTX_AW(Core::System& system_);
|
||||||
~ECTX_AW() override;
|
~ECTX_AW() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateContextRegistrar(HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Glue
|
} // namespace Service::Glue
|
||||||
|
@ -318,15 +318,15 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideAddressSpace(out_addr, size)) {
|
if (!page_table.Contains(out_addr, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsInsideHeapRegion(out_addr, size)) {
|
if (page_table.IsInHeapRegion(out_addr, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsInsideAliasRegion(out_addr, size)) {
|
if (page_table.IsInAliasRegion(out_addr, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +358,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
|
ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
|
||||||
auto& page_table{process->PageTable()};
|
auto& page_table{process->GetPageTable()};
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
|
|
||||||
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
||||||
@ -382,7 +382,7 @@ public:
|
|||||||
ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
|
ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
|
||||||
VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
VAddr bss_addr, std::size_t bss_size, std::size_t size) {
|
||||||
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
|
||||||
auto& page_table{process->PageTable()};
|
auto& page_table{process->GetPageTable()};
|
||||||
VAddr addr{};
|
VAddr addr{};
|
||||||
|
|
||||||
CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
|
CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
|
||||||
@ -437,12 +437,12 @@ public:
|
|||||||
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
|
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
|
||||||
nro_header.segment_headers[DATA_INDEX].memory_size);
|
nro_header.segment_headers[DATA_INDEX].memory_size);
|
||||||
|
|
||||||
CASCADE_CODE(process->PageTable().SetProcessMemoryPermission(
|
CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
|
||||||
text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
|
text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
|
||||||
CASCADE_CODE(process->PageTable().SetProcessMemoryPermission(
|
CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
|
||||||
ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
|
ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
|
||||||
|
|
||||||
return process->PageTable().SetProcessMemoryPermission(
|
return process->GetPageTable().SetProcessMemoryPermission(
|
||||||
data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite);
|
data_start, bss_end_addr - data_start, Kernel::Svc::MemoryPermission::ReadWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +571,7 @@ public:
|
|||||||
|
|
||||||
Result UnmapNro(const NROInfo& info) {
|
Result UnmapNro(const NROInfo& info) {
|
||||||
// Each region must be unmapped separately to validate memory state
|
// Each region must be unmapped separately to validate memory state
|
||||||
auto& page_table{system.ApplicationProcess()->PageTable()};
|
auto& page_table{system.ApplicationProcess()->GetPageTable()};
|
||||||
|
|
||||||
if (info.bss_size != 0) {
|
if (info.bss_size != 0) {
|
||||||
CASCADE_CODE(page_table.UnmapCodeMemory(
|
CASCADE_CODE(page_table.UnmapCodeMemory(
|
||||||
@ -643,7 +643,7 @@ public:
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
current_map_addr =
|
current_map_addr =
|
||||||
GetInteger(system.ApplicationProcess()->PageTable().GetAliasCodeRegionStart());
|
GetInteger(system.ApplicationProcess()->GetPageTable().GetAliasCodeRegionStart());
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
@ -180,7 +180,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
|
void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
|
||||||
const std::vector<u8>& seed) {
|
std::span<const u8> seed) {
|
||||||
// Initialize context
|
// Initialize context
|
||||||
ctx.used = false;
|
ctx.used = false;
|
||||||
ctx.counter = 0;
|
ctx.counter = 0;
|
||||||
|
@ -75,7 +75,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
|
|||||||
|
|
||||||
// Initializes mbedtls context
|
// Initializes mbedtls context
|
||||||
void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
|
void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
|
||||||
const std::vector<u8>& seed);
|
std::span<const u8> seed);
|
||||||
|
|
||||||
// Feeds data to mbedtls context to generate the derived key
|
// Feeds data to mbedtls context to generate the derived key
|
||||||
void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
|
void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
#include "core/hle/service/nfc/mifare_result.h"
|
#include "core/hle/service/nfc/mifare_result.h"
|
||||||
#include "core/hle/service/nfc/nfc_result.h"
|
#include "core/hle/service/nfc/nfc_result.h"
|
||||||
#include "core/hle/service/time/time_manager.h"
|
#include "core/hle/service/time/time_manager.h"
|
||||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
|
||||||
#include "core/hle/service/time/time_zone_types.h"
|
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
|
NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
|
||||||
@ -1486,6 +1484,7 @@ DeviceState NfcDevice::GetCurrentState() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const {
|
Result NfcDevice::GetNpadId(Core::HID::NpadIdType& out_npad_id) const {
|
||||||
|
// TODO: This should get the npad id from nn::hid::system::GetXcdHandleForNpadWithNfc
|
||||||
out_npad_id = npad_id;
|
out_npad_id = npad_id;
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hid/hid_types.h"
|
#include "core/hid/hid_types.h"
|
||||||
@ -10,6 +12,7 @@
|
|||||||
#include "core/hle/service/nfc/common/device_manager.h"
|
#include "core/hle/service/nfc/common/device_manager.h"
|
||||||
#include "core/hle/service/nfc/nfc_result.h"
|
#include "core/hle/service/nfc/nfc_result.h"
|
||||||
#include "core/hle/service/time/clock_types.h"
|
#include "core/hle/service/time/clock_types.h"
|
||||||
|
#include "core/hle/service/time/time_manager.h"
|
||||||
|
|
||||||
namespace Service::NFC {
|
namespace Service::NFC {
|
||||||
|
|
||||||
@ -51,22 +54,53 @@ Result DeviceManager::Finalize() {
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices,
|
Result DeviceManager::ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices,
|
||||||
std::size_t max_allowed_devices) const {
|
bool skip_fatal_errors) const {
|
||||||
|
std::scoped_lock lock{mutex};
|
||||||
|
if (max_allowed_devices < 1) {
|
||||||
|
return ResultInvalidArgument;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result result = IsNfcParameterSet();
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IsNfcEnabled();
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IsNfcInitialized();
|
||||||
|
if (result.IsError()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& device : devices) {
|
for (auto& device : devices) {
|
||||||
if (nfp_devices.size() >= max_allowed_devices) {
|
if (nfp_devices.size() >= max_allowed_devices) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (device->GetCurrentState() != DeviceState::Unavailable) {
|
if (skip_fatal_errors) {
|
||||||
nfp_devices.push_back(device->GetHandle());
|
constexpr u64 MinimumRecoveryTime = 60;
|
||||||
|
auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
||||||
|
const u64 elapsed_time = standard_steady_clock.GetCurrentTimePoint(system).time_point -
|
||||||
|
time_since_last_error;
|
||||||
|
|
||||||
|
if (time_since_last_error != 0 && elapsed_time < MinimumRecoveryTime) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (device->GetCurrentState() == DeviceState::Unavailable) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nfp_devices.push_back(device->GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfp_devices.empty()) {
|
if (nfp_devices.empty()) {
|
||||||
return ResultDeviceNotFound;
|
return ResultDeviceNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
|
DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
|
||||||
@ -79,10 +113,10 @@ DeviceState DeviceManager::GetDeviceState(u64 device_handle) const {
|
|||||||
return device->GetCurrentState();
|
return device->GetCurrentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
return DeviceState::Unavailable;
|
return DeviceState::Finalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const {
|
Result DeviceManager::GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -128,7 +162,7 @@ Result DeviceManager::StopDetection(u64 device_handle) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {
|
Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -142,24 +176,46 @@ Result DeviceManager::GetTagInfo(u64 device_handle, TagInfo& tag_info) const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::KReadableEvent& DeviceManager::AttachActivateEvent(u64 device_handle) const {
|
Result DeviceManager::AttachActivateEvent(Kernel::KReadableEvent** out_event,
|
||||||
std::scoped_lock lock{mutex};
|
u64 device_handle) const {
|
||||||
|
std::vector<u64> nfp_devices;
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
GetDeviceFromHandle(device_handle, device, false);
|
Result result = ListDevices(nfp_devices, 9, false);
|
||||||
|
|
||||||
// TODO: Return proper error code on failure
|
if (result.IsSuccess()) {
|
||||||
return device->GetActivateEvent();
|
result = CheckHandleOnList(device_handle, nfp_devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = GetDeviceFromHandle(device_handle, device, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
*out_event = &device->GetActivateEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::KReadableEvent& DeviceManager::AttachDeactivateEvent(u64 device_handle) const {
|
Result DeviceManager::AttachDeactivateEvent(Kernel::KReadableEvent** out_event,
|
||||||
std::scoped_lock lock{mutex};
|
u64 device_handle) const {
|
||||||
|
std::vector<u64> nfp_devices;
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
GetDeviceFromHandle(device_handle, device, false);
|
Result result = ListDevices(nfp_devices, 9, false);
|
||||||
|
|
||||||
// TODO: Return proper error code on failure
|
if (result.IsSuccess()) {
|
||||||
return device->GetDeactivateEvent();
|
result = CheckHandleOnList(device_handle, nfp_devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
result = GetDeviceFromHandle(device_handle, device, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.IsSuccess()) {
|
||||||
|
*out_event = &device->GetDeactivateEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::ReadMifare(u64 device_handle,
|
Result DeviceManager::ReadMifare(u64 device_handle,
|
||||||
@ -253,7 +309,7 @@ Result DeviceManager::OpenApplicationArea(u64 device_handle, u32 access_id) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) const {
|
Result DeviceManager::GetApplicationArea(u64 device_handle, std::span<u8> data) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -324,7 +380,7 @@ Result DeviceManager::CreateApplicationArea(u64 device_handle, u32 access_id,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const {
|
Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -338,7 +394,7 @@ Result DeviceManager::GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& regi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const {
|
Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -352,7 +408,7 @@ Result DeviceManager::GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_i
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const {
|
Result DeviceManager::GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -399,7 +455,7 @@ Result DeviceManager::Format(u64 device_handle) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const {
|
Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -414,7 +470,7 @@ Result DeviceManager::GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle,
|
Result DeviceManager::GetRegisterInfoPrivate(u64 device_handle,
|
||||||
NFP::RegisterInfoPrivate& register_info) const {
|
NFP::RegisterInfoPrivate& register_info) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -471,7 +527,7 @@ Result DeviceManager::DeleteApplicationArea(u64 device_handle) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) const {
|
Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_application_area) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -485,7 +541,7 @@ Result DeviceManager::ExistsApplicationArea(u64 device_handle, bool& has_applica
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) const {
|
Result DeviceManager::GetAll(u64 device_handle, NFP::NfpData& nfp_data) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -541,7 +597,7 @@ Result DeviceManager::BreakTag(u64 device_handle, NFP::BreakType break_type) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) const {
|
Result DeviceManager::ReadBackupData(u64 device_handle, std::span<u8> data) {
|
||||||
std::scoped_lock lock{mutex};
|
std::scoped_lock lock{mutex};
|
||||||
|
|
||||||
std::shared_ptr<NfcDevice> device = nullptr;
|
std::shared_ptr<NfcDevice> device = nullptr;
|
||||||
@ -593,6 +649,19 @@ Result DeviceManager::WriteNtf(u64 device_handle, NFP::WriteType, std::span<cons
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result DeviceManager::CheckHandleOnList(u64 device_handle,
|
||||||
|
const std::span<const u64> device_list) const {
|
||||||
|
if (device_list.size() < 1) {
|
||||||
|
return ResultDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (std::find(device_list.begin(), device_list.end(), device_handle) != device_list.end()) {
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device,
|
Result DeviceManager::GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& nfc_device,
|
||||||
bool check_state) const {
|
bool check_state) const {
|
||||||
if (check_state) {
|
if (check_state) {
|
||||||
@ -647,7 +716,7 @@ Result DeviceManager::GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& de
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
|
Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
|
||||||
Result operation_result) const {
|
Result operation_result) {
|
||||||
if (operation_result.IsSuccess()) {
|
if (operation_result.IsSuccess()) {
|
||||||
return operation_result;
|
return operation_result;
|
||||||
}
|
}
|
||||||
@ -669,6 +738,12 @@ Result DeviceManager::VerifyDeviceResult(std::shared_ptr<NfcDevice> device,
|
|||||||
return device_state;
|
return device_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (operation_result == ResultUnknown112 || operation_result == ResultUnknown114 ||
|
||||||
|
operation_result == ResultUnknown115) {
|
||||||
|
auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
|
||||||
|
time_since_last_error = standard_steady_clock.GetCurrentTimePoint(system).time_point;
|
||||||
|
}
|
||||||
|
|
||||||
return operation_result;
|
return operation_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,15 +27,16 @@ public:
|
|||||||
// Nfc device manager
|
// Nfc device manager
|
||||||
Result Initialize();
|
Result Initialize();
|
||||||
Result Finalize();
|
Result Finalize();
|
||||||
Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices) const;
|
Result ListDevices(std::vector<u64>& nfp_devices, std::size_t max_allowed_devices,
|
||||||
|
bool skip_fatal_errors) const;
|
||||||
DeviceState GetDeviceState(u64 device_handle) const;
|
DeviceState GetDeviceState(u64 device_handle) const;
|
||||||
Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id) const;
|
Result GetNpadId(u64 device_handle, Core::HID::NpadIdType& npad_id);
|
||||||
Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
|
Kernel::KReadableEvent& AttachAvailabilityChangeEvent() const;
|
||||||
Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
|
Result StartDetection(u64 device_handle, NfcProtocol tag_protocol);
|
||||||
Result StopDetection(u64 device_handle);
|
Result StopDetection(u64 device_handle);
|
||||||
Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info) const;
|
Result GetTagInfo(u64 device_handle, NFP::TagInfo& tag_info);
|
||||||
Kernel::KReadableEvent& AttachActivateEvent(u64 device_handle) const;
|
Result AttachActivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const;
|
||||||
Kernel::KReadableEvent& AttachDeactivateEvent(u64 device_handle) const;
|
Result AttachDeactivateEvent(Kernel::KReadableEvent** event, u64 device_handle) const;
|
||||||
Result ReadMifare(u64 device_handle,
|
Result ReadMifare(u64 device_handle,
|
||||||
const std::span<const MifareReadBlockParameter> read_parameters,
|
const std::span<const MifareReadBlockParameter> read_parameters,
|
||||||
std::span<MifareReadBlockData> read_data);
|
std::span<MifareReadBlockData> read_data);
|
||||||
@ -48,28 +49,28 @@ public:
|
|||||||
Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
|
Result Mount(u64 device_handle, NFP::ModelType model_type, NFP::MountTarget mount_target);
|
||||||
Result Unmount(u64 device_handle);
|
Result Unmount(u64 device_handle);
|
||||||
Result OpenApplicationArea(u64 device_handle, u32 access_id);
|
Result OpenApplicationArea(u64 device_handle, u32 access_id);
|
||||||
Result GetApplicationArea(u64 device_handle, std::span<u8> data) const;
|
Result GetApplicationArea(u64 device_handle, std::span<u8> data);
|
||||||
Result SetApplicationArea(u64 device_handle, std::span<const u8> data);
|
Result SetApplicationArea(u64 device_handle, std::span<const u8> data);
|
||||||
Result Flush(u64 device_handle);
|
Result Flush(u64 device_handle);
|
||||||
Result Restore(u64 device_handle);
|
Result Restore(u64 device_handle);
|
||||||
Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
|
Result CreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
|
||||||
Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info) const;
|
Result GetRegisterInfo(u64 device_handle, NFP::RegisterInfo& register_info);
|
||||||
Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info) const;
|
Result GetCommonInfo(u64 device_handle, NFP::CommonInfo& common_info);
|
||||||
Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info) const;
|
Result GetModelInfo(u64 device_handle, NFP::ModelInfo& model_info);
|
||||||
u32 GetApplicationAreaSize() const;
|
u32 GetApplicationAreaSize() const;
|
||||||
Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
|
Result RecreateApplicationArea(u64 device_handle, u32 access_id, std::span<const u8> data);
|
||||||
Result Format(u64 device_handle);
|
Result Format(u64 device_handle);
|
||||||
Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info) const;
|
Result GetAdminInfo(u64 device_handle, NFP::AdminInfo& admin_info);
|
||||||
Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info) const;
|
Result GetRegisterInfoPrivate(u64 device_handle, NFP::RegisterInfoPrivate& register_info);
|
||||||
Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info);
|
Result SetRegisterInfoPrivate(u64 device_handle, const NFP::RegisterInfoPrivate& register_info);
|
||||||
Result DeleteRegisterInfo(u64 device_handle);
|
Result DeleteRegisterInfo(u64 device_handle);
|
||||||
Result DeleteApplicationArea(u64 device_handle);
|
Result DeleteApplicationArea(u64 device_handle);
|
||||||
Result ExistsApplicationArea(u64 device_handle, bool& has_application_area) const;
|
Result ExistsApplicationArea(u64 device_handle, bool& has_application_area);
|
||||||
Result GetAll(u64 device_handle, NFP::NfpData& nfp_data) const;
|
Result GetAll(u64 device_handle, NFP::NfpData& nfp_data);
|
||||||
Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data);
|
Result SetAll(u64 device_handle, const NFP::NfpData& nfp_data);
|
||||||
Result FlushDebug(u64 device_handle);
|
Result FlushDebug(u64 device_handle);
|
||||||
Result BreakTag(u64 device_handle, NFP::BreakType break_type);
|
Result BreakTag(u64 device_handle, NFP::BreakType break_type);
|
||||||
Result ReadBackupData(u64 device_handle, std::span<u8> data) const;
|
Result ReadBackupData(u64 device_handle, std::span<u8> data);
|
||||||
Result WriteBackupData(u64 device_handle, std::span<const u8> data);
|
Result WriteBackupData(u64 device_handle, std::span<const u8> data);
|
||||||
Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data);
|
Result WriteNtf(u64 device_handle, NFP::WriteType, std::span<const u8> data);
|
||||||
|
|
||||||
@ -78,17 +79,20 @@ private:
|
|||||||
Result IsNfcParameterSet() const;
|
Result IsNfcParameterSet() const;
|
||||||
Result IsNfcInitialized() const;
|
Result IsNfcInitialized() const;
|
||||||
|
|
||||||
|
Result CheckHandleOnList(u64 device_handle, std::span<const u64> device_list) const;
|
||||||
|
|
||||||
Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device,
|
Result GetDeviceFromHandle(u64 handle, std::shared_ptr<NfcDevice>& device,
|
||||||
bool check_state) const;
|
bool check_state) const;
|
||||||
|
|
||||||
Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const;
|
Result GetDeviceHandle(u64 handle, std::shared_ptr<NfcDevice>& device) const;
|
||||||
Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result) const;
|
Result VerifyDeviceResult(std::shared_ptr<NfcDevice> device, Result operation_result);
|
||||||
Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const;
|
Result CheckDeviceState(std::shared_ptr<NfcDevice> device) const;
|
||||||
|
|
||||||
std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
|
std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle);
|
||||||
const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const;
|
const std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle) const;
|
||||||
|
|
||||||
bool is_initialized = false;
|
bool is_initialized = false;
|
||||||
|
u64 time_since_last_error = 0;
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
std::array<std::shared_ptr<NfcDevice>, 10> devices{};
|
std::array<std::shared_ptr<NfcDevice>, 10> devices{};
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ void NfcInterface::ListDevices(HLERequestContext& ctx) {
|
|||||||
const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
|
const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>();
|
||||||
LOG_DEBUG(Service_NFC, "called");
|
LOG_DEBUG(Service_NFC, "called");
|
||||||
|
|
||||||
auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices);
|
auto result = GetManager()->ListDevices(nfp_devices, max_allowed_devices, true);
|
||||||
result = TranslateResultToServiceError(result);
|
result = TranslateResultToServiceError(result);
|
||||||
|
|
||||||
if (result.IsError()) {
|
if (result.IsError()) {
|
||||||
@ -190,9 +190,13 @@ void NfcInterface::AttachActivateEvent(HLERequestContext& ctx) {
|
|||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
|
LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
|
||||||
|
|
||||||
|
Kernel::KReadableEvent* out_event = nullptr;
|
||||||
|
auto result = GetManager()->AttachActivateEvent(&out_event, device_handle);
|
||||||
|
result = TranslateResultToServiceError(result);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
rb.PushCopyObjects(GetManager()->AttachActivateEvent(device_handle));
|
rb.PushCopyObjects(out_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
|
void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
|
||||||
@ -200,9 +204,13 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) {
|
|||||||
const auto device_handle{rp.Pop<u64>()};
|
const auto device_handle{rp.Pop<u64>()};
|
||||||
LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
|
LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle);
|
||||||
|
|
||||||
|
Kernel::KReadableEvent* out_event = nullptr;
|
||||||
|
auto result = GetManager()->AttachDeactivateEvent(&out_event, device_handle);
|
||||||
|
result = TranslateResultToServiceError(result);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(result);
|
||||||
rb.PushCopyObjects(GetManager()->AttachDeactivateEvent(device_handle));
|
rb.PushCopyObjects(out_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NfcInterface::ReadMifare(HLERequestContext& ctx) {
|
void NfcInterface::ReadMifare(HLERequestContext& ctx) {
|
||||||
|
@ -17,7 +17,10 @@ constexpr Result ResultNfcNotInitialized(ErrorModule::NFC, 77);
|
|||||||
constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80);
|
constexpr Result ResultNfcDisabled(ErrorModule::NFC, 80);
|
||||||
constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88);
|
constexpr Result ResultWriteAmiiboFailed(ErrorModule::NFC, 88);
|
||||||
constexpr Result ResultTagRemoved(ErrorModule::NFC, 97);
|
constexpr Result ResultTagRemoved(ErrorModule::NFC, 97);
|
||||||
|
constexpr Result ResultUnknown112(ErrorModule::NFC, 112);
|
||||||
constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113);
|
constexpr Result ResultUnableToAccessBackupFile(ErrorModule::NFC, 113);
|
||||||
|
constexpr Result ResultUnknown114(ErrorModule::NFC, 114);
|
||||||
|
constexpr Result ResultUnknown115(ErrorModule::NFC, 115);
|
||||||
constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120);
|
constexpr Result ResultRegistrationIsNotInitialized(ErrorModule::NFC, 120);
|
||||||
constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128);
|
constexpr Result ResultApplicationAreaIsNotInitialized(ErrorModule::NFC, 128);
|
||||||
constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136);
|
constexpr Result ResultCorruptedDataWithBackup(ErrorModule::NFC, 136);
|
||||||
|
@ -128,7 +128,7 @@ NvResult nvmap::IocAlloc(std::span<const u8> input, std::span<u8> output) {
|
|||||||
}
|
}
|
||||||
bool is_out_io{};
|
bool is_out_io{};
|
||||||
ASSERT(system.ApplicationProcess()
|
ASSERT(system.ApplicationProcess()
|
||||||
->PageTable()
|
->GetPageTable()
|
||||||
.LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
|
.LockForMapDeviceAddressSpace(&is_out_io, handle_description->address,
|
||||||
handle_description->size,
|
handle_description->size,
|
||||||
Kernel::KMemoryPermission::None, true, false)
|
Kernel::KMemoryPermission::None, true, false)
|
||||||
@ -255,7 +255,7 @@ NvResult nvmap::IocFree(std::span<const u8> input, std::span<u8> output) {
|
|||||||
if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
|
if (auto freeInfo{file.FreeHandle(params.handle, false)}) {
|
||||||
if (freeInfo->can_unlock) {
|
if (freeInfo->can_unlock) {
|
||||||
ASSERT(system.ApplicationProcess()
|
ASSERT(system.ApplicationProcess()
|
||||||
->PageTable()
|
->GetPageTable()
|
||||||
.UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
|
.UnlockForDeviceAddressSpace(freeInfo->address, freeInfo->size)
|
||||||
.IsSuccess());
|
.IsSuccess());
|
||||||
}
|
}
|
||||||
|
@ -559,7 +559,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
|
|||||||
|
|
||||||
const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
|
const std::optional<FileDescriptor>& descriptor = file_descriptors[pollfd.fd];
|
||||||
if (!descriptor) {
|
if (!descriptor) {
|
||||||
LOG_ERROR(Service, "File descriptor handle={} is not allocated", pollfd.fd);
|
LOG_TRACE(Service, "File descriptor handle={} is not allocated", pollfd.fd);
|
||||||
pollfd.revents = PollEvents::Nval;
|
pollfd.revents = PollEvents::Nval;
|
||||||
return {0, Errno::SUCCESS};
|
return {0, Errno::SUCCESS};
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,21 @@ namespace Service::Sockets {
|
|||||||
|
|
||||||
constexpr Result ResultOverflow{ErrorModule::NSD, 6};
|
constexpr Result ResultOverflow{ErrorModule::NSD, 6};
|
||||||
|
|
||||||
|
// This is nn::oe::ServerEnvironmentType
|
||||||
|
enum class ServerEnvironmentType : u8 {
|
||||||
|
Dd,
|
||||||
|
Lp,
|
||||||
|
Sd,
|
||||||
|
Sp,
|
||||||
|
Dp,
|
||||||
|
};
|
||||||
|
|
||||||
NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
|
NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{5, nullptr, "GetSettingUrl"},
|
{5, nullptr, "GetSettingUrl"},
|
||||||
{10, nullptr, "GetSettingName"},
|
{10, nullptr, "GetSettingName"},
|
||||||
{11, nullptr, "GetEnvironmentIdentifier"},
|
{11, &NSD::GetEnvironmentIdentifier, "GetEnvironmentIdentifier"},
|
||||||
{12, nullptr, "GetDeviceId"},
|
{12, nullptr, "GetDeviceId"},
|
||||||
{13, nullptr, "DeleteSettings"},
|
{13, nullptr, "DeleteSettings"},
|
||||||
{14, nullptr, "ImportSettings"},
|
{14, nullptr, "ImportSettings"},
|
||||||
@ -36,7 +45,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
|
|||||||
{62, nullptr, "DeleteSaveDataOfFsForTest"},
|
{62, nullptr, "DeleteSaveDataOfFsForTest"},
|
||||||
{63, nullptr, "IsChangeEnvironmentIdentifierDisabled"},
|
{63, nullptr, "IsChangeEnvironmentIdentifierDisabled"},
|
||||||
{64, nullptr, "SetWithoutDomainExchangeFqdns"},
|
{64, nullptr, "SetWithoutDomainExchangeFqdns"},
|
||||||
{100, nullptr, "GetApplicationServerEnvironmentType"},
|
{100, &NSD::GetApplicationServerEnvironmentType, "GetApplicationServerEnvironmentType"},
|
||||||
{101, nullptr, "SetApplicationServerEnvironmentType"},
|
{101, nullptr, "SetApplicationServerEnvironmentType"},
|
||||||
{102, nullptr, "DeleteApplicationServerEnvironmentType"},
|
{102, nullptr, "DeleteApplicationServerEnvironmentType"},
|
||||||
};
|
};
|
||||||
@ -94,6 +103,20 @@ void NSD::ResolveEx(HLERequestContext& ctx) {
|
|||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) {
|
||||||
|
const std::string environment_identifier = "lp1";
|
||||||
|
ctx.WriteBuffer(environment_identifier);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NSD::GetApplicationServerEnvironmentType(HLERequestContext& ctx) {
|
||||||
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push(static_cast<u32>(ServerEnvironmentType::Lp));
|
||||||
|
}
|
||||||
|
|
||||||
NSD::~NSD() = default;
|
NSD::~NSD() = default;
|
||||||
|
|
||||||
} // namespace Service::Sockets
|
} // namespace Service::Sockets
|
||||||
|
@ -19,6 +19,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void Resolve(HLERequestContext& ctx);
|
void Resolve(HLERequestContext& ctx);
|
||||||
void ResolveEx(HLERequestContext& ctx);
|
void ResolveEx(HLERequestContext& ctx);
|
||||||
|
void GetEnvironmentIdentifier(HLERequestContext& ctx);
|
||||||
|
void GetApplicationServerEnvironmentType(HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Sockets
|
} // namespace Service::Sockets
|
||||||
|
@ -24,7 +24,7 @@ SFDNSRES::SFDNSRES(Core::System& system_) : ServiceFramework{system_, "sfdnsres"
|
|||||||
{2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"},
|
{2, &SFDNSRES::GetHostByNameRequest, "GetHostByNameRequest"},
|
||||||
{3, nullptr, "GetHostByAddrRequest"},
|
{3, nullptr, "GetHostByAddrRequest"},
|
||||||
{4, nullptr, "GetHostStringErrorRequest"},
|
{4, nullptr, "GetHostStringErrorRequest"},
|
||||||
{5, nullptr, "GetGaiStringErrorRequest"},
|
{5, &SFDNSRES::GetGaiStringErrorRequest, "GetGaiStringErrorRequest"},
|
||||||
{6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
|
{6, &SFDNSRES::GetAddrInfoRequest, "GetAddrInfoRequest"},
|
||||||
{7, nullptr, "GetNameInfoRequest"},
|
{7, nullptr, "GetNameInfoRequest"},
|
||||||
{8, nullptr, "RequestCancelHandleRequest"},
|
{8, nullptr, "RequestCancelHandleRequest"},
|
||||||
@ -300,6 +300,20 @@ void SFDNSRES::GetAddrInfoRequest(HLERequestContext& ctx) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SFDNSRES::GetGaiStringErrorRequest(HLERequestContext& ctx) {
|
||||||
|
struct InputParameters {
|
||||||
|
GetAddrInfoError gai_errno;
|
||||||
|
};
|
||||||
|
IPC::RequestParser rp{ctx};
|
||||||
|
auto input = rp.PopRaw<InputParameters>();
|
||||||
|
|
||||||
|
const std::string result = Translate(input.gai_errno);
|
||||||
|
ctx.WriteBuffer(result);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
|
void SFDNSRES::GetAddrInfoRequestWithOptions(HLERequestContext& ctx) {
|
||||||
// Additional options are ignored
|
// Additional options are ignored
|
||||||
auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
|
auto [data_size, emu_gai_err] = GetAddrInfoRequestImpl(ctx);
|
||||||
|
@ -18,6 +18,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void GetHostByNameRequest(HLERequestContext& ctx);
|
void GetHostByNameRequest(HLERequestContext& ctx);
|
||||||
|
void GetGaiStringErrorRequest(HLERequestContext& ctx);
|
||||||
void GetHostByNameRequestWithOptions(HLERequestContext& ctx);
|
void GetHostByNameRequestWithOptions(HLERequestContext& ctx);
|
||||||
void GetAddrInfoRequest(HLERequestContext& ctx);
|
void GetAddrInfoRequest(HLERequestContext& ctx);
|
||||||
void GetAddrInfoRequestWithOptions(HLERequestContext& ctx);
|
void GetAddrInfoRequestWithOptions(HLERequestContext& ctx);
|
||||||
|
@ -81,6 +81,44 @@ GetAddrInfoError Translate(Network::GetAddrInfoError error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* Translate(GetAddrInfoError error) {
|
||||||
|
// https://android.googlesource.com/platform/bionic/+/085543106/libc/dns/net/getaddrinfo.c#254
|
||||||
|
switch (error) {
|
||||||
|
case GetAddrInfoError::SUCCESS:
|
||||||
|
return "Success";
|
||||||
|
case GetAddrInfoError::ADDRFAMILY:
|
||||||
|
return "Address family for hostname not supported";
|
||||||
|
case GetAddrInfoError::AGAIN:
|
||||||
|
return "Temporary failure in name resolution";
|
||||||
|
case GetAddrInfoError::BADFLAGS:
|
||||||
|
return "Invalid value for ai_flags";
|
||||||
|
case GetAddrInfoError::FAIL:
|
||||||
|
return "Non-recoverable failure in name resolution";
|
||||||
|
case GetAddrInfoError::FAMILY:
|
||||||
|
return "ai_family not supported";
|
||||||
|
case GetAddrInfoError::MEMORY:
|
||||||
|
return "Memory allocation failure";
|
||||||
|
case GetAddrInfoError::NODATA:
|
||||||
|
return "No address associated with hostname";
|
||||||
|
case GetAddrInfoError::NONAME:
|
||||||
|
return "hostname nor servname provided, or not known";
|
||||||
|
case GetAddrInfoError::SERVICE:
|
||||||
|
return "servname not supported for ai_socktype";
|
||||||
|
case GetAddrInfoError::SOCKTYPE:
|
||||||
|
return "ai_socktype not supported";
|
||||||
|
case GetAddrInfoError::SYSTEM:
|
||||||
|
return "System error returned in errno";
|
||||||
|
case GetAddrInfoError::BADHINTS:
|
||||||
|
return "Invalid value for hints";
|
||||||
|
case GetAddrInfoError::PROTOCOL:
|
||||||
|
return "Resolved protocol is unknown";
|
||||||
|
case GetAddrInfoError::OVERFLOW_:
|
||||||
|
return "Argument buffer overflow";
|
||||||
|
default:
|
||||||
|
return "Unknown error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Network::Domain Translate(Domain domain) {
|
Network::Domain Translate(Domain domain) {
|
||||||
switch (domain) {
|
switch (domain) {
|
||||||
case Domain::Unspecified:
|
case Domain::Unspecified:
|
||||||
|
@ -20,6 +20,9 @@ std::pair<s32, Errno> Translate(std::pair<s32, Network::Errno> value);
|
|||||||
/// Translate abstract getaddrinfo error to guest getaddrinfo error
|
/// Translate abstract getaddrinfo error to guest getaddrinfo error
|
||||||
GetAddrInfoError Translate(Network::GetAddrInfoError value);
|
GetAddrInfoError Translate(Network::GetAddrInfoError value);
|
||||||
|
|
||||||
|
/// Translate guest error to string
|
||||||
|
const char* Translate(GetAddrInfoError value);
|
||||||
|
|
||||||
/// Translate guest domain to abstract domain
|
/// Translate guest domain to abstract domain
|
||||||
Network::Domain Translate(Domain domain);
|
Network::Domain Translate(Domain domain);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
|||||||
|
|
||||||
// Load NSO modules
|
// Load NSO modules
|
||||||
modules.clear();
|
modules.clear();
|
||||||
const VAddr base_address{GetInteger(process.PageTable().GetCodeRegionStart())};
|
const VAddr base_address{GetInteger(process.GetPageTable().GetCodeRegionStart())};
|
||||||
VAddr next_load_addr{base_address};
|
VAddr next_load_addr{base_address};
|
||||||
const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
|
const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
|
@ -96,7 +96,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
|
|||||||
}
|
}
|
||||||
|
|
||||||
codeset.memory = std::move(program_image);
|
codeset.memory = std::move(program_image);
|
||||||
const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
|
const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
|
||||||
process.LoadModule(std::move(codeset), base_address);
|
process.LoadModule(std::move(codeset), base_address);
|
||||||
|
|
||||||
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
|
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
|
||||||
|
@ -203,7 +203,7 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data)
|
|||||||
|
|
||||||
// Load codeset for current process
|
// Load codeset for current process
|
||||||
codeset.memory = std::move(program_image);
|
codeset.memory = std::move(program_image);
|
||||||
process.LoadModule(std::move(codeset), process.PageTable().GetCodeRegionStart());
|
process.LoadModule(std::move(codeset), process.GetPageTable().GetCodeRegionStart());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
|
|||||||
modules.clear();
|
modules.clear();
|
||||||
|
|
||||||
// Load module
|
// Load module
|
||||||
const VAddr base_address = GetInteger(process.PageTable().GetCodeRegionStart());
|
const VAddr base_address = GetInteger(process.GetPageTable().GetCodeRegionStart());
|
||||||
if (!LoadModule(process, system, *file, base_address, true, true)) {
|
if (!LoadModule(process, system, *file, base_address, true, true)) {
|
||||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,10 @@ struct Memory::Impl {
|
|||||||
explicit Impl(Core::System& system_) : system{system_} {}
|
explicit Impl(Core::System& system_) : system{system_} {}
|
||||||
|
|
||||||
void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
|
void SetCurrentPageTable(Kernel::KProcess& process, u32 core_id) {
|
||||||
current_page_table = &process.PageTable().PageTableImpl();
|
current_page_table = &process.GetPageTable().PageTableImpl();
|
||||||
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
|
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
|
||||||
|
|
||||||
const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth();
|
const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
|
||||||
|
|
||||||
system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
|
system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ struct Memory::Impl {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
|
return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
|
[[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
|
||||||
@ -84,7 +84,7 @@ struct Memory::Impl {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return system.DeviceMemory().GetPointer<u8>(paddr) + vaddr;
|
return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Read8(const Common::ProcessAddress addr) {
|
u8 Read8(const Common::ProcessAddress addr) {
|
||||||
@ -183,13 +183,13 @@ struct Memory::Impl {
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr,
|
bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped,
|
||||||
const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer,
|
auto on_memory, auto on_rasterizer, auto increment) {
|
||||||
auto increment) {
|
const auto& page_table = system.ApplicationProcess()->GetPageTable().PageTableImpl();
|
||||||
const auto& page_table = process.PageTable().PageTableImpl();
|
|
||||||
std::size_t remaining_size = size;
|
std::size_t remaining_size = size;
|
||||||
std::size_t page_index = addr >> YUZU_PAGEBITS;
|
std::size_t page_index = addr >> YUZU_PAGEBITS;
|
||||||
std::size_t page_offset = addr & YUZU_PAGEMASK;
|
std::size_t page_offset = addr & YUZU_PAGEMASK;
|
||||||
|
bool user_accessible = true;
|
||||||
|
|
||||||
while (remaining_size) {
|
while (remaining_size) {
|
||||||
const std::size_t copy_amount =
|
const std::size_t copy_amount =
|
||||||
@ -200,11 +200,13 @@ struct Memory::Impl {
|
|||||||
const auto [pointer, type] = page_table.pointers[page_index].PointerType();
|
const auto [pointer, type] = page_table.pointers[page_index].PointerType();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Common::PageType::Unmapped: {
|
case Common::PageType::Unmapped: {
|
||||||
|
user_accessible = false;
|
||||||
on_unmapped(copy_amount, current_vaddr);
|
on_unmapped(copy_amount, current_vaddr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Common::PageType::Memory: {
|
case Common::PageType::Memory: {
|
||||||
u8* mem_ptr = pointer + page_offset + (page_index << YUZU_PAGEBITS);
|
u8* mem_ptr =
|
||||||
|
reinterpret_cast<u8*>(pointer + page_offset + (page_index << YUZU_PAGEBITS));
|
||||||
on_memory(copy_amount, mem_ptr);
|
on_memory(copy_amount, mem_ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -227,13 +229,15 @@ struct Memory::Impl {
|
|||||||
increment(copy_amount);
|
increment(copy_amount);
|
||||||
remaining_size -= copy_amount;
|
remaining_size -= copy_amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return user_accessible;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool UNSAFE>
|
template <bool UNSAFE>
|
||||||
void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr,
|
bool ReadBlockImpl(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
void* dest_buffer, const std::size_t size) {
|
const std::size_t size) {
|
||||||
WalkBlock(
|
return WalkBlock(
|
||||||
process, src_addr, size,
|
src_addr, size,
|
||||||
[src_addr, size, &dest_buffer](const std::size_t copy_amount,
|
[src_addr, size, &dest_buffer](const std::size_t copy_amount,
|
||||||
const Common::ProcessAddress current_vaddr) {
|
const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
@ -256,14 +260,14 @@ struct Memory::Impl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
bool ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size);
|
return ReadBlockImpl<false>(src_addr, dest_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
|
bool ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size);
|
return ReadBlockImpl<true>(src_addr, dest_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const {
|
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const {
|
||||||
@ -283,10 +287,10 @@ struct Memory::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool UNSAFE>
|
template <bool UNSAFE>
|
||||||
void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr,
|
bool WriteBlockImpl(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const void* src_buffer, const std::size_t size) {
|
const std::size_t size) {
|
||||||
WalkBlock(
|
return WalkBlock(
|
||||||
process, dest_addr, size,
|
dest_addr, size,
|
||||||
[dest_addr, size](const std::size_t copy_amount,
|
[dest_addr, size](const std::size_t copy_amount,
|
||||||
const Common::ProcessAddress current_vaddr) {
|
const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
@ -308,20 +312,19 @@ struct Memory::Impl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
bool WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size);
|
return WriteBlockImpl<false>(dest_addr, src_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
bool WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size);
|
return WriteBlockImpl<true>(dest_addr, src_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr,
|
bool ZeroBlock(const Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
const std::size_t size) {
|
return WalkBlock(
|
||||||
WalkBlock(
|
dest_addr, size,
|
||||||
process, dest_addr, size,
|
|
||||||
[dest_addr, size](const std::size_t copy_amount,
|
[dest_addr, size](const std::size_t copy_amount,
|
||||||
const Common::ProcessAddress current_vaddr) {
|
const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
@ -339,23 +342,23 @@ struct Memory::Impl {
|
|||||||
[](const std::size_t copy_amount) {});
|
[](const std::size_t copy_amount) {});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
||||||
Common::ProcessAddress src_addr, const std::size_t size) {
|
const std::size_t size) {
|
||||||
WalkBlock(
|
return WalkBlock(
|
||||||
process, dest_addr, size,
|
dest_addr, size,
|
||||||
[&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
[&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory,
|
LOG_ERROR(HW_Memory,
|
||||||
"Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
"Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
GetInteger(current_vaddr), GetInteger(src_addr), size);
|
GetInteger(current_vaddr), GetInteger(src_addr), size);
|
||||||
ZeroBlock(process, dest_addr, copy_amount);
|
ZeroBlock(dest_addr, copy_amount);
|
||||||
},
|
},
|
||||||
[&](const std::size_t copy_amount, const u8* const src_ptr) {
|
[&](const std::size_t copy_amount, const u8* const src_ptr) {
|
||||||
WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount);
|
WriteBlockImpl<false>(dest_addr, src_ptr, copy_amount);
|
||||||
},
|
},
|
||||||
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
||||||
u8* const host_ptr) {
|
u8* const host_ptr) {
|
||||||
HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount);
|
HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount);
|
||||||
WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount);
|
WriteBlockImpl<false>(dest_addr, host_ptr, copy_amount);
|
||||||
},
|
},
|
||||||
[&](const std::size_t copy_amount) {
|
[&](const std::size_t copy_amount) {
|
||||||
dest_addr += copy_amount;
|
dest_addr += copy_amount;
|
||||||
@ -364,13 +367,13 @@ struct Memory::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result PerformCacheOperation(Common::ProcessAddress dest_addr, std::size_t size,
|
||||||
std::size_t size, Callback&& cb) {
|
Callback&& cb) {
|
||||||
class InvalidMemoryException : public std::exception {};
|
class InvalidMemoryException : public std::exception {};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WalkBlock(
|
WalkBlock(
|
||||||
process, dest_addr, size,
|
dest_addr, size,
|
||||||
[&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) {
|
[&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}",
|
LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}",
|
||||||
GetInteger(current_vaddr));
|
GetInteger(current_vaddr));
|
||||||
@ -387,37 +390,34 @@ struct Memory::Impl {
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
|
||||||
std::size_t size) {
|
|
||||||
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc ivac: Invalidate to point of coherency
|
// dc ivac: Invalidate to point of coherency
|
||||||
// GPU flush -> CPU invalidate
|
// GPU flush -> CPU invalidate
|
||||||
HandleRasterizerDownload(GetInteger(current_vaddr), block_size);
|
HandleRasterizerDownload(GetInteger(current_vaddr), block_size);
|
||||||
};
|
};
|
||||||
return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
|
||||||
std::size_t size) {
|
|
||||||
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc cvac: Store to point of coherency
|
// dc cvac: Store to point of coherency
|
||||||
// CPU flush -> GPU invalidate
|
// CPU flush -> GPU invalidate
|
||||||
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
||||||
};
|
};
|
||||||
return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr,
|
Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
|
||||||
std::size_t size) {
|
|
||||||
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
|
||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc civac: Store to point of coherency, and invalidate from cache
|
// dc civac: Store to point of coherency, and invalidate from cache
|
||||||
// CPU flush -> GPU invalidate
|
// CPU flush -> GPU invalidate
|
||||||
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
|
||||||
};
|
};
|
||||||
return PerformCacheOperation(process, dest_addr, size, on_rasterizer);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarkRegionDebug(u64 vaddr, u64 size, bool debug) {
|
void MarkRegionDebug(u64 vaddr, u64 size, bool debug) {
|
||||||
@ -448,7 +448,7 @@ struct Memory::Impl {
|
|||||||
break;
|
break;
|
||||||
case Common::PageType::Memory:
|
case Common::PageType::Memory:
|
||||||
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
||||||
nullptr, Common::PageType::DebugMemory);
|
0, Common::PageType::DebugMemory);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@ -466,7 +466,8 @@ struct Memory::Impl {
|
|||||||
case Common::PageType::DebugMemory: {
|
case Common::PageType::DebugMemory: {
|
||||||
u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)};
|
u8* const pointer{GetPointerFromDebugMemory(vaddr & ~YUZU_PAGEMASK)};
|
||||||
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
||||||
pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory);
|
reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
|
||||||
|
Common::PageType::Memory);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -506,7 +507,7 @@ struct Memory::Impl {
|
|||||||
case Common::PageType::DebugMemory:
|
case Common::PageType::DebugMemory:
|
||||||
case Common::PageType::Memory:
|
case Common::PageType::Memory:
|
||||||
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
||||||
nullptr, Common::PageType::RasterizerCachedMemory);
|
0, Common::PageType::RasterizerCachedMemory);
|
||||||
break;
|
break;
|
||||||
case Common::PageType::RasterizerCachedMemory:
|
case Common::PageType::RasterizerCachedMemory:
|
||||||
// There can be more than one GPU region mapped per CPU region, so it's common
|
// There can be more than one GPU region mapped per CPU region, so it's common
|
||||||
@ -534,10 +535,11 @@ struct Memory::Impl {
|
|||||||
// pagetable after unmapping a VMA. In that case the underlying VMA will no
|
// pagetable after unmapping a VMA. In that case the underlying VMA will no
|
||||||
// longer exist, and we should just leave the pagetable entry blank.
|
// longer exist, and we should just leave the pagetable entry blank.
|
||||||
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
||||||
nullptr, Common::PageType::Unmapped);
|
0, Common::PageType::Unmapped);
|
||||||
} else {
|
} else {
|
||||||
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Store(
|
||||||
pointer - (vaddr & ~YUZU_PAGEMASK), Common::PageType::Memory);
|
reinterpret_cast<uintptr_t>(pointer) - (vaddr & ~YUZU_PAGEMASK),
|
||||||
|
Common::PageType::Memory);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -584,7 +586,7 @@ struct Memory::Impl {
|
|||||||
"Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE);
|
"Mapping memory page without a pointer @ {:016x}", base * YUZU_PAGESIZE);
|
||||||
|
|
||||||
while (base != end) {
|
while (base != end) {
|
||||||
page_table.pointers[base].Store(nullptr, type);
|
page_table.pointers[base].Store(0, type);
|
||||||
page_table.backing_addr[base] = 0;
|
page_table.backing_addr[base] = 0;
|
||||||
page_table.blocks[base] = 0;
|
page_table.blocks[base] = 0;
|
||||||
base += 1;
|
base += 1;
|
||||||
@ -593,7 +595,8 @@ struct Memory::Impl {
|
|||||||
auto orig_base = base;
|
auto orig_base = base;
|
||||||
while (base != end) {
|
while (base != end) {
|
||||||
auto host_ptr =
|
auto host_ptr =
|
||||||
system.DeviceMemory().GetPointer<u8>(target) - (base << YUZU_PAGEBITS);
|
reinterpret_cast<uintptr_t>(system.DeviceMemory().GetPointer<u8>(target)) -
|
||||||
|
(base << YUZU_PAGEBITS);
|
||||||
auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
|
auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
|
||||||
page_table.pointers[base].Store(host_ptr, type);
|
page_table.pointers[base].Store(host_ptr, type);
|
||||||
page_table.backing_addr[base] = backing;
|
page_table.backing_addr[base] = backing;
|
||||||
@ -619,8 +622,8 @@ struct Memory::Impl {
|
|||||||
|
|
||||||
// Avoid adding any extra logic to this fast-path block
|
// Avoid adding any extra logic to this fast-path block
|
||||||
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
|
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Raw();
|
||||||
if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
|
if (const uintptr_t pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
|
||||||
return &pointer[vaddr];
|
return reinterpret_cast<u8*>(pointer + vaddr);
|
||||||
}
|
}
|
||||||
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
||||||
case Common::PageType::Unmapped:
|
case Common::PageType::Unmapped:
|
||||||
@ -808,13 +811,13 @@ void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress b
|
|||||||
|
|
||||||
bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
|
bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
|
||||||
const Kernel::KProcess& process = *system.ApplicationProcess();
|
const Kernel::KProcess& process = *system.ApplicationProcess();
|
||||||
const auto& page_table = process.PageTable().PageTableImpl();
|
const auto& page_table = process.GetPageTable().PageTableImpl();
|
||||||
const size_t page = vaddr >> YUZU_PAGEBITS;
|
const size_t page = vaddr >> YUZU_PAGEBITS;
|
||||||
if (page >= page_table.pointers.size()) {
|
if (page >= page_table.pointers.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto [pointer, type] = page_table.pointers[page].PointerType();
|
const auto [pointer, type] = page_table.pointers[page].PointerType();
|
||||||
return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory ||
|
return pointer != 0 || type == Common::PageType::RasterizerCachedMemory ||
|
||||||
type == Common::PageType::DebugMemory;
|
type == Common::PageType::DebugMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,14 +902,14 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le
|
|||||||
return impl->ReadCString(vaddr, max_length);
|
return impl->ReadCString(vaddr, max_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
bool Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->ReadBlock(src_addr, dest_buffer, size);
|
return impl->ReadBlock(src_addr, dest_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
|
bool Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
|
return impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const {
|
const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const {
|
||||||
@ -917,23 +920,23 @@ u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) {
|
|||||||
return impl->GetSpan(src_addr, size);
|
return impl->GetSpan(src_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
bool Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->WriteBlock(dest_addr, src_buffer, size);
|
return impl->WriteBlock(dest_addr, src_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
bool Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
|
return impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
bool Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
||||||
const std::size_t size) {
|
const std::size_t size) {
|
||||||
impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size);
|
return impl->CopyBlock(dest_addr, src_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
|
bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size);
|
return impl->ZeroBlock(dest_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) {
|
void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) {
|
||||||
@ -941,15 +944,15 @@ void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size);
|
return impl->InvalidateDataCache(dest_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size);
|
return impl->StoreDataCache(dest_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
|
||||||
return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size);
|
return impl->FlushDataCache(dest_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
|
void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {
|
||||||
|
@ -24,7 +24,6 @@ class GPUDirtyMemoryManager;
|
|||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
class PhysicalMemory;
|
|
||||||
class KProcess;
|
class KProcess;
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
||||||
@ -330,7 +329,7 @@ public:
|
|||||||
* @post The range [dest_buffer, size) contains the read bytes from the
|
* @post The range [dest_buffer, size) contains the read bytes from the
|
||||||
* current process' address space.
|
* current process' address space.
|
||||||
*/
|
*/
|
||||||
void ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
|
bool ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a contiguous block of bytes from the current process' address space.
|
* Reads a contiguous block of bytes from the current process' address space.
|
||||||
@ -349,7 +348,7 @@ public:
|
|||||||
* @post The range [dest_buffer, size) contains the read bytes from the
|
* @post The range [dest_buffer, size) contains the read bytes from the
|
||||||
* current process' address space.
|
* current process' address space.
|
||||||
*/
|
*/
|
||||||
void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
|
bool ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
|
||||||
|
|
||||||
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const;
|
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const;
|
||||||
u8* GetSpan(const VAddr src_addr, const std::size_t size);
|
u8* GetSpan(const VAddr src_addr, const std::size_t size);
|
||||||
@ -373,7 +372,7 @@ public:
|
|||||||
* and will mark that region as invalidated to caches that the active
|
* and will mark that region as invalidated to caches that the active
|
||||||
* graphics backend may be maintaining over the course of execution.
|
* graphics backend may be maintaining over the course of execution.
|
||||||
*/
|
*/
|
||||||
void WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size);
|
bool WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a range of bytes into the current process' address space at the specified
|
* Writes a range of bytes into the current process' address space at the specified
|
||||||
@ -391,7 +390,7 @@ public:
|
|||||||
* will be ignored and an error will be logged.
|
* will be ignored and an error will be logged.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer,
|
bool WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer,
|
||||||
std::size_t size);
|
std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -405,7 +404,7 @@ public:
|
|||||||
* @post The range [dest_addr, size) within the process' address space contains the
|
* @post The range [dest_addr, size) within the process' address space contains the
|
||||||
* same data within the range [src_addr, size).
|
* same data within the range [src_addr, size).
|
||||||
*/
|
*/
|
||||||
void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
|
||||||
std::size_t size);
|
std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -418,7 +417,7 @@ public:
|
|||||||
* @post The range [dest_addr, size) within the process' address space contains the
|
* @post The range [dest_addr, size) within the process' address space contains the
|
||||||
* value 0.
|
* value 0.
|
||||||
*/
|
*/
|
||||||
void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
|
bool ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates a range of bytes within the current process' address space at the specified
|
* Invalidates a range of bytes within the current process' address space at the specified
|
||||||
|
@ -199,7 +199,7 @@ void CheatEngine::Initialize() {
|
|||||||
metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
||||||
metadata.title_id = system.GetApplicationProcessProgramID();
|
metadata.title_id = system.GetApplicationProcessProgramID();
|
||||||
|
|
||||||
const auto& page_table = system.ApplicationProcess()->PageTable();
|
const auto& page_table = system.ApplicationProcess()->GetPageTable();
|
||||||
metadata.heap_extents = {
|
metadata.heap_extents = {
|
||||||
.base = GetInteger(page_table.GetHeapRegionStart()),
|
.base = GetInteger(page_table.GetHeapRegionStart()),
|
||||||
.size = page_table.GetHeapRegionSize(),
|
.size = page_table.GetHeapRegionSize(),
|
||||||
|
@ -117,8 +117,8 @@ json GetProcessorStateDataAuto(Core::System& system) {
|
|||||||
arm.SaveContext(context);
|
arm.SaveContext(context);
|
||||||
|
|
||||||
return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
|
return GetProcessorStateData(process->Is64BitProcess() ? "AArch64" : "AArch32",
|
||||||
GetInteger(process->PageTable().GetCodeRegionStart()), context.sp,
|
GetInteger(process->GetPageTable().GetCodeRegionStart()),
|
||||||
context.pc, context.pstate, context.cpu_registers);
|
context.sp, context.pc, context.pstate, context.cpu_registers);
|
||||||
}
|
}
|
||||||
|
|
||||||
json GetBacktraceData(Core::System& system) {
|
json GetBacktraceData(Core::System& system) {
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/container/flat_map.hpp>
|
|
||||||
|
|
||||||
#include "shader_recompiler/frontend/ir/basic_block.h"
|
#include "shader_recompiler/frontend/ir/basic_block.h"
|
||||||
#include "shader_recompiler/frontend/ir/opcodes.h"
|
#include "shader_recompiler/frontend/ir/opcodes.h"
|
||||||
#include "shader_recompiler/frontend/ir/pred.h"
|
#include "shader_recompiler/frontend/ir/pred.h"
|
||||||
@ -52,7 +52,7 @@ struct IndirectBranchVariable {
|
|||||||
|
|
||||||
using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
|
using Variant = std::variant<IR::Reg, IR::Pred, ZeroFlagTag, SignFlagTag, CarryFlagTag,
|
||||||
OverflowFlagTag, GotoVariable, IndirectBranchVariable>;
|
OverflowFlagTag, GotoVariable, IndirectBranchVariable>;
|
||||||
using ValueMap = boost::container::flat_map<IR::Block*, IR::Value>;
|
using ValueMap = std::unordered_map<IR::Block*, IR::Value>;
|
||||||
|
|
||||||
struct DefTable {
|
struct DefTable {
|
||||||
const IR::Value& Def(IR::Block* block, IR::Reg variable) {
|
const IR::Value& Def(IR::Block* block, IR::Reg variable) {
|
||||||
@ -112,7 +112,7 @@ struct DefTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::array<ValueMap, IR::NUM_USER_PREDS> preds;
|
std::array<ValueMap, IR::NUM_USER_PREDS> preds;
|
||||||
boost::container::flat_map<u32, ValueMap> goto_vars;
|
std::unordered_map<u32, ValueMap> goto_vars;
|
||||||
ValueMap indirect_branch_var;
|
ValueMap indirect_branch_var;
|
||||||
ValueMap zero_flag;
|
ValueMap zero_flag;
|
||||||
ValueMap sign_flag;
|
ValueMap sign_flag;
|
||||||
@ -295,8 +295,7 @@ private:
|
|||||||
return same;
|
return same;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::container::flat_map<IR::Block*, boost::container::flat_map<Variant, IR::Inst*>>
|
std::unordered_map<IR::Block*, std::map<Variant, IR::Inst*>> incomplete_phis;
|
||||||
incomplete_phis;
|
|
||||||
DefTable current_def;
|
DefTable current_def;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -442,6 +442,11 @@ void BufferCache<P>::UnbindComputeStorageBuffers() {
|
|||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
||||||
bool is_written) {
|
bool is_written) {
|
||||||
|
if (ssbo_index >= channel_state->compute_storage_buffers.size()) [[unlikely]] {
|
||||||
|
LOG_ERROR(HW_GPU, "Storage buffer index {} exceeds maximum storage buffer count",
|
||||||
|
ssbo_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index;
|
channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index;
|
||||||
channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
|
channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
|
||||||
|
|
||||||
@ -464,6 +469,11 @@ void BufferCache<P>::UnbindComputeTextureBuffers() {
|
|||||||
template <class P>
|
template <class P>
|
||||||
void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
||||||
PixelFormat format, bool is_written, bool is_image) {
|
PixelFormat format, bool is_written, bool is_image) {
|
||||||
|
if (tbo_index >= channel_state->compute_texture_buffers.size()) [[unlikely]] {
|
||||||
|
LOG_ERROR(HW_GPU, "Texture buffer index {} exceeds maximum texture buffer count",
|
||||||
|
tbo_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
channel_state->enabled_compute_texture_buffers |= 1U << tbo_index;
|
channel_state->enabled_compute_texture_buffers |= 1U << tbo_index;
|
||||||
channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
|
channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
|
||||||
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
|
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
|
||||||
|
@ -67,7 +67,7 @@ constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
|
|||||||
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
|
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
|
||||||
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
||||||
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
||||||
constexpr u32 NUM_TEXTURE_BUFFERS = 16;
|
constexpr u32 NUM_TEXTURE_BUFFERS = 32;
|
||||||
constexpr u32 NUM_STAGES = 5;
|
constexpr u32 NUM_STAGES = 5;
|
||||||
|
|
||||||
using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;
|
using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;
|
||||||
|
@ -103,7 +103,9 @@ public:
|
|||||||
explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_,
|
explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_,
|
||||||
Core::Memory::Memory& cpu_memory_)
|
Core::Memory::Memory& cpu_memory_)
|
||||||
: rasterizer{rasterizer_},
|
: rasterizer{rasterizer_},
|
||||||
cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this),
|
// Use reinterpret_cast instead of static_cast as workaround for
|
||||||
|
// UBSan bug (https://github.com/llvm/llvm-project/issues/59060)
|
||||||
|
cpu_memory{cpu_memory_}, streams{{CounterStream{reinterpret_cast<QueryCache&>(*this),
|
||||||
VideoCore::QueryType::SamplesPassed}}} {
|
VideoCore::QueryType::SamplesPassed}}} {
|
||||||
(void)slot_async_jobs.insert(); // Null value
|
(void)slot_async_jobs.insert(); // Null value
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ namespace VideoCore {
|
|||||||
|
|
||||||
using namespace Core::Memory;
|
using namespace Core::Memory;
|
||||||
|
|
||||||
RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_) : cpu_memory{cpu_memory_} {}
|
RasterizerAccelerated::RasterizerAccelerated(Memory& cpu_memory_)
|
||||||
|
: cached_pages(std::make_unique<CachedPages>()), cpu_memory{cpu_memory_} {}
|
||||||
|
|
||||||
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
RasterizerAccelerated::~RasterizerAccelerated() = default;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ void RasterizerAccelerated::UpdatePagesCachedCount(VAddr addr, u64 size, int del
|
|||||||
std::atomic_thread_fence(std::memory_order_acquire);
|
std::atomic_thread_fence(std::memory_order_acquire);
|
||||||
const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
|
const u64 page_end = Common::DivCeil(addr + size, YUZU_PAGESIZE);
|
||||||
for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
|
for (u64 page = addr >> YUZU_PAGEBITS; page != page_end; ++page) {
|
||||||
std::atomic_uint16_t& count = cached_pages.at(page >> 2).Count(page);
|
std::atomic_uint16_t& count = cached_pages->at(page >> 2).Count(page);
|
||||||
|
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
|
ASSERT_MSG(count.load(std::memory_order::relaxed) < UINT16_MAX, "Count may overflow!");
|
||||||
|
@ -41,7 +41,8 @@ private:
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
|
static_assert(sizeof(CacheEntry) == 8, "CacheEntry should be 8 bytes!");
|
||||||
|
|
||||||
std::array<CacheEntry, 0x2000000> cached_pages;
|
using CachedPages = std::array<CacheEntry, 0x2000000>;
|
||||||
|
std::unique_ptr<CachedPages> cached_pages;
|
||||||
Core::Memory::Memory& cpu_memory;
|
Core::Memory::Memory& cpu_memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,9 +3,14 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
|
||||||
#include <discord_rpc.h>
|
#include <discord_rpc.h>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <httplib.h>
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
@ -31,7 +36,7 @@ void DiscordImpl::Pause() {
|
|||||||
Discord_ClearPresence();
|
Discord_ClearPresence();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string GetGameString(const std::string& title) {
|
std::string DiscordImpl::GetGameString(const std::string& title) {
|
||||||
// Convert to lowercase
|
// Convert to lowercase
|
||||||
std::string icon_name = Common::ToLower(title);
|
std::string icon_name = Common::ToLower(title);
|
||||||
|
|
||||||
@ -56,51 +61,56 @@ static std::string GetGameString(const std::string& title) {
|
|||||||
return icon_name;
|
return icon_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiscordImpl::Update() {
|
void DiscordImpl::UpdateGameStatus(bool use_default) {
|
||||||
|
const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
|
||||||
|
const std::string default_image = "yuzu_logo";
|
||||||
|
const std::string url = use_default ? default_image : game_url;
|
||||||
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
|
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
std::chrono::system_clock::now().time_since_epoch())
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
|
|
||||||
const std::string default_image = "yuzu_logo";
|
|
||||||
std::string game_cover_url = "https://yuzu-emu.org";
|
|
||||||
std::string title;
|
|
||||||
|
|
||||||
DiscordRichPresence presence{};
|
DiscordRichPresence presence{};
|
||||||
|
|
||||||
|
presence.largeImageKey = url.c_str();
|
||||||
|
presence.largeImageText = game_title.c_str();
|
||||||
|
presence.smallImageKey = default_image.c_str();
|
||||||
|
presence.smallImageText = default_text.c_str();
|
||||||
|
presence.state = game_title.c_str();
|
||||||
|
presence.details = "Currently in game";
|
||||||
|
presence.startTimestamp = start_time;
|
||||||
|
Discord_UpdatePresence(&presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiscordImpl::Update() {
|
||||||
|
const std::string default_text = "yuzu is an emulator for the Nintendo Switch";
|
||||||
|
const std::string default_image = "yuzu_logo";
|
||||||
|
|
||||||
if (system.IsPoweredOn()) {
|
if (system.IsPoweredOn()) {
|
||||||
system.GetAppLoader().ReadTitle(title);
|
system.GetAppLoader().ReadTitle(game_title);
|
||||||
|
|
||||||
// Used to format Icon URL for yuzu website game compatibility page
|
// Used to format Icon URL for yuzu website game compatibility page
|
||||||
std::string icon_name = GetGameString(title);
|
std::string icon_name = GetGameString(game_title);
|
||||||
|
game_url = fmt::format("https://yuzu-emu.org/images/game/boxart/{}.png", icon_name);
|
||||||
|
|
||||||
// New Check for game cover
|
QNetworkAccessManager manager;
|
||||||
httplib::Client cli(game_cover_url);
|
QNetworkRequest request;
|
||||||
cli.set_connection_timeout(std::chrono::seconds(3));
|
request.setUrl(QUrl(QString::fromStdString(game_url)));
|
||||||
cli.set_read_timeout(std::chrono::seconds(3));
|
request.setTransferTimeout(3000);
|
||||||
|
QNetworkReply* reply = manager.head(request);
|
||||||
if (auto res = cli.Head(fmt::format("/images/game/boxart/{}.png", icon_name))) {
|
QEventLoop request_event_loop;
|
||||||
if (res->status == 200) {
|
QObject::connect(reply, &QNetworkReply::finished, &request_event_loop, &QEventLoop::quit);
|
||||||
game_cover_url += fmt::format("/images/game/boxart/{}.png", icon_name);
|
request_event_loop.exec();
|
||||||
} else {
|
UpdateGameStatus(reply->error());
|
||||||
game_cover_url = "yuzu_logo";
|
return;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
game_cover_url = "yuzu_logo";
|
|
||||||
}
|
|
||||||
|
|
||||||
presence.largeImageKey = game_cover_url.c_str();
|
|
||||||
presence.largeImageText = title.c_str();
|
|
||||||
|
|
||||||
presence.smallImageKey = default_image.c_str();
|
|
||||||
presence.smallImageText = default_text.c_str();
|
|
||||||
presence.state = title.c_str();
|
|
||||||
presence.details = "Currently in game";
|
|
||||||
} else {
|
|
||||||
presence.largeImageKey = default_image.c_str();
|
|
||||||
presence.largeImageText = default_text.c_str();
|
|
||||||
presence.details = "Currently not in game";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s64 start_time = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
DiscordRichPresence presence{};
|
||||||
|
presence.largeImageKey = default_image.c_str();
|
||||||
|
presence.largeImageText = default_text.c_str();
|
||||||
|
presence.details = "Currently not in game";
|
||||||
presence.startTimestamp = start_time;
|
presence.startTimestamp = start_time;
|
||||||
Discord_UpdatePresence(&presence);
|
Discord_UpdatePresence(&presence);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,13 @@ public:
|
|||||||
void Pause() override;
|
void Pause() override;
|
||||||
void Update() override;
|
void Update() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string GetGameString(const std::string& title);
|
||||||
|
void UpdateGameStatus(bool use_default);
|
||||||
|
|
||||||
|
std::string game_url{};
|
||||||
|
std::string game_title{};
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ GameListWorker::~GameListWorker() = default;
|
|||||||
void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
||||||
using namespace FileSys;
|
using namespace FileSys;
|
||||||
|
|
||||||
const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider());
|
const auto& cache = system.GetContentProviderUnion();
|
||||||
|
|
||||||
auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
|
auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
|
||||||
ContentRecordType::Program);
|
ContentRecordType::Program);
|
||||||
@ -265,7 +265,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
|
|||||||
std::vector<u8> icon;
|
std::vector<u8> icon;
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 program_id = 0;
|
u64 program_id = 0;
|
||||||
loader->ReadProgramId(program_id);
|
const auto result = loader->ReadProgramId(program_id);
|
||||||
|
|
||||||
|
if (result != Loader::ResultStatus::Success) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const PatchManager patch{program_id, system.GetFileSystemController(),
|
const PatchManager patch{program_id, system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
|
Reference in New Issue
Block a user