Compare commits

...

35 Commits

Author SHA1 Message Date
ff3fba0610 Android #25 2023-07-31 00:58:23 +00:00
689dc4a17b Merge pull request #11155 from liamwhite/memory3
memory: check page against address space size
2023-07-28 09:29:21 -04:00
9352a0f2e6 Merge pull request #11156 from 8bitDream/localize
android: Only label language with language
2023-07-28 09:29:11 -04:00
b1730d3c72 Merge pull request #11163 from Moonlacer/revert-10946-amdBlending
Revert "Blacklist EDS3 blending from new AMD drivers"
2023-07-28 09:29:00 -04:00
4007142b91 Revert "Blacklist EDS3 blending from new AMD drivers" 2023-07-26 15:02:48 -05:00
a1c355051e Merge pull request #11128 from german77/discord
yuzu: Replace httplib with QtNetworkRequest
2023-07-26 11:04:57 -04:00
d3da1e6517 Merge pull request #10990 from comex/ubsan
Fixes and workarounds to make UBSan happier on macOS
2023-07-26 10:33:28 -04:00
6ffcc3d5d2 Merge pull request #11142 from german77/avoid_crash
yuzu: Avoid reading broken games
2023-07-26 10:33:14 -04:00
01b379fe20 Address feedback 2023-07-26 00:41:24 -04:00
4742627744 Merge pull request #11157 from lat9nq/nasm
cmake: Download nasm from our external repo
2023-07-25 13:35:02 -04:00
43920aa1a0 cmake: Download nasm from our external repo
This package download has intermittent failures due to host Internet
issues (presumably), so download it ourselves from our own hosting.
2023-07-25 15:47:44 -04:00
e2ea46f6ef android: Only label language with language 2023-07-25 10:38:30 -04:00
07f71e2620 memory: check page against address space size 2023-07-25 09:51:06 -04:00
18000df5e9 Merge pull request #11095 from liamwhite/memory2
memory: cleanup
2023-07-24 13:47:11 -04:00
bb0edb53ae Merge pull request #11135 from liamwhite/getaddrinfo
core: implement GetGaiStringErrorRequest, IContextRegistrar
2023-07-24 13:47:02 -04:00
099295d7c6 Merge pull request #11136 from liamwhite/sp3shader
ssa_rewrite_pass: use proper maps
2023-07-24 13:46:53 -04:00
a0ed0e4e10 yuzu: Avoid reading broken games 2023-07-24 08:59:14 -06:00
dad0d076ee ssa_rewrite_pass: use proper maps 2023-07-23 11:38:01 -04:00
3e3294e1c2 core: implement GetGaiStringErrorRequest, IContextRegistrar 2023-07-22 23:29:45 -04:00
9f3f615e05 core: reduce TOCTTOU memory access 2023-07-22 11:19:29 -04:00
d144168442 memory: minimize dependency on process 2023-07-22 11:19:29 -04:00
3e4029b238 Merge pull request #11042 from lat9nq/wayland-appimage
ci/linux: Target deploy script from appimage path
2023-07-22 11:17:48 -04:00
b1aed2c5b7 Merge pull request #11094 from liamwhite/get
kernel: misc cleanup of page table accessors
2023-07-22 11:17:36 -04:00
0ea138fb5b Merge pull request #11098 from GPUCode/texel-buffers
buffer_cache: Increase number of texture buffers
2023-07-22 11:17:27 -04:00
482c957f5d Merge pull request #11113 from liamwhite/nsd1
nsd: add GetApplicationServerEnvironmentType
2023-07-21 21:24:36 -07:00
39edd2ff82 Merge pull request #11129 from liamwhite/dynamic_cast
general: remove uses of dynamic_cast
2023-07-21 21:22:51 -07:00
05bc024260 core: remove remaining uses of dynamic_cast 2023-07-21 19:37:29 -04:00
4bee333d84 general: reduce use of dynamic_cast 2023-07-21 19:22:14 -04:00
c067046387 yuzu: Replace httplib with QtNetworkRequest 2023-07-21 16:53:06 -06:00
8f1d48fda6 nsd: add GetApplicationServerEnvironmentType 2023-07-17 21:34:23 -04:00
4347dd26c6 buffer_cache: Increase number of texture buffers 2023-07-15 23:09:58 +03:00
d7c532d889 Fixes and workarounds to make UBSan happier on macOS
There are still some other issues not addressed here, but it's a start.

Workarounds for false-positive reports:

- `RasterizerAccelerated`: Put a gigantic array behind a `unique_ptr`,
  because UBSan has a [hardcoded limit](https://stackoverflow.com/questions/64531383/c-runtime-error-using-fsanitize-undefined-object-has-a-possibly-invalid-vp)
  of how big it thinks objects can be, specifically when dealing with
  offset-to-top values used with multiple inheritance.  Hopefully this
  doesn't have a performance impact.

- `QueryCacheBase::QueryCacheBase`: Avoid an operation that UBSan thinks
  is UB even though it at least arguably isn't.  See the link in the
  comment for more information.

Fixes for correct reports:

- `PageTable`, `Memory`: Use `uintptr_t` values instead of pointers to
  avoid UB from pointer overflow (when pointer arithmetic wraps around
  the address space).

- `KScheduler::Reload`: `thread->GetOwnerProcess()` can be `nullptr`;
  avoid calling methods on it in this case.  (The existing code returns
  a garbage reference to a field, which is then passed into
  `LoadWatchpointArray`, and apparently it's never used, so it's
  harmless in practice but still triggers UBSan.)

- `KAutoObject::Close`: This function calls `this->Destroy()`, which
  overwrites the beginning of the object with junk (specifically a free
  list pointer).  Then it calls `this->UnregisterWithKernel()`.  UBSan
  complains about a type mismatch because the vtable has been
  overwritten, and I believe this is indeed UB.  `UnregisterWithKernel`
  also loads `m_kernel` from the 'freed' object, which seems to be
  technically safe (the overwriting doesn't extend as far as that
  field), but seems dubious.  Switch to a `static` method and load
  `m_kernel` in advance.
2023-07-15 12:00:28 -07:00
474db2d8da kernel: reduce page table region checking 2023-07-14 22:33:10 -04:00
a85ce8ea56 k_process: PageTable -> GetPageTable 2023-07-14 21:43:15 -04:00
b417b8562e ci/linux: Target deploy script from appimage path
Includes AppImage changes so that the needed Qt Wayland libraries are
included.
2023-07-06 20:53:22 -04:00
85 changed files with 514 additions and 639 deletions

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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;

View File

@ -235,26 +235,6 @@
<string name="region_korea">Korea</string> <string name="region_korea">Korea</string>
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names -->
<string name="language_japanese">Japanisch (日本語)</string>
<string name="language_english">Englisch</string>
<string name="language_french">Französisch (Français)</string>
<string name="langauge_german">Deutsch (German)</string>
<string name="language_italian">Italienisch (Italiano)</string>
<string name="language_spanish">Spanisch (Español)</string>
<string name="language_chinese">Chinesisch (简体中文)</string>
<string name="language_korean">Koreanisch (한국어)</string>
<string name="language_dutch">Niederländisch (Nederlands)</string>
<string name="language_portuguese">Portugiesisch (Português)</string>
<string name="language_russian">Russisch (Русский)</string>
<string name="language_taiwanese">Taiwanesisch (台湾)</string>
<string name="language_british_english">Britisches Englisch</string>
<string name="language_canadian_french">Kanadisches Französisch (Français canadien)</string>
<string name="language_latin_american_spanish">Lateinamerikanisches Spanisch (Español latinoamericano)</string>
<string name="language_simplified_chinese">Vereinfachtes Chinesisch (简体中文)</string>
<string name="language_traditional_chinese">Traditionelles Chinesisch (正體中文)</string>
<string name="language_brazilian_portuguese">Brasilianisches Portugiesisch (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>
<string name="renderer_none">Keiner</string> <string name="renderer_none">Keiner</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taiwán</string> <string name="region_taiwan">Taiwán</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japonés (日本語)</string>
<string name="language_english">Inglés (English)</string>
<string name="language_french">Francés (Français)</string>
<string name="langauge_german">Alemán (deutsch)</string>
<string name="language_italian">Italiano (Italiano)</string>
<string name="language_spanish">Español (Español)</string>
<string name="language_chinese">Chino (简体中文)</string>
<string name="language_korean">Coreano (한국어)</string>
<string name="language_dutch">Holandés (nederlands)</string>
<string name="language_portuguese">Portugués (Português)</string>
<string name="language_russian">Ruso (Русский)</string>
<string name="language_taiwanese">Taiwanés (台湾)</string>
<string name="language_british_english">Inglés británico</string>
<string name="language_canadian_french">Francés Canadiense (Français canadien)</string>
<string name="language_latin_american_spanish">Español Latinoamericano (Español latinoamericano)</string>
<string name="language_simplified_chinese">Chino Simplificado (简体中文)</string>
<string name="language_traditional_chinese">Chino tradicional (正體中文)</string>
<string name="language_brazilian_portuguese">Portugués Brasileño (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taïwan</string> <string name="region_taiwan">Taïwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japonais (日本語)</string>
<string name="language_english">Anglais</string>
<string name="language_french">Français (Français)</string>
<string name="langauge_german">Allemand (Deutsch)</string>
<string name="language_italian">Italien (Italiano)</string>
<string name="language_spanish">Espagnol (Español)</string>
<string name="language_chinese">Chinois (简体中文)</string>
<string name="language_korean">Coréen (한국어)</string>
<string name="language_dutch">Néerlandais (Nederlands)</string>
<string name="language_portuguese">Portugais (Português)</string>
<string name="language_russian">Russe (Русский)</string>
<string name="language_taiwanese">Taïwanais (台湾)</string>
<string name="language_british_english">Anglais Britannique</string>
<string name="language_canadian_french">Français canadien (Français canadien)</string>
<string name="language_latin_american_spanish">Espagnol latino-américain (Español latinoamericano)</string>
<string name="language_simplified_chinese">Chinois simplifié (简体中文)</string>
<string name="language_traditional_chinese">Chinois Traditionnel (正體中文)</string>
<string name="language_brazilian_portuguese">Portugais brésilien (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Giapponese (日本語)</string>
<string name="language_english">Inglese (English)</string>
<string name="language_french">Francese (Français)</string>
<string name="langauge_german">Tedesco (Deutsch)</string>
<string name="language_italian">Italiano (Italiano)</string>
<string name="language_spanish">Spagnolo (Español)</string>
<string name="language_chinese">Cinese (简体中文)</string>
<string name="language_korean">Coreano (한국어)</string>
<string name="language_dutch">Olandese (Nederlands)</string>
<string name="language_portuguese">Portoghese (Português)</string>
<string name="language_russian">Russo (Русский)</string>
<string name="language_taiwanese">Taiwanese (台湾)</string>
<string name="language_british_english">Inglese britannico</string>
<string name="language_canadian_french">Francese Canadese (Français canadien)</string>
<string name="language_latin_american_spanish">Spagnolo Latino Americano (Español latinoamericano)</string>
<string name="language_simplified_chinese">Cinese Semplificato (简体中文)</string>
<string name="language_traditional_chinese">Cinese tradizionale (正體中文)</string>
<string name="language_brazilian_portuguese">Portoghese (Português)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -239,24 +239,6 @@
<string name="region_taiwan">台湾</string> <string name="region_taiwan">台湾</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">日本語</string>
<string name="language_english">英語</string>
<string name="language_french">フランス語 (Français)</string>
<string name="langauge_german">ドイツ語 (Deutsch)</string>
<string name="language_italian">イタリア語 (Italiano)</string>
<string name="language_spanish">スペイン語 (Español)</string>
<string name="language_chinese">中国語 (简体中文)</string>
<string name="language_korean">韓国語 (한국어)</string>
<string name="language_dutch">オランダ語 (Nederlands)</string>
<string name="language_portuguese">ポルトガル語 (Português)</string>
<string name="language_russian">ロシア語 (Русский)</string>
<string name="language_taiwanese">台湾語 (台湾)</string>
<string name="language_british_english">イギリス英語</string>
<string name="language_canadian_french">フランス語(カナダ) (Français canadien)</string>
<string name="language_latin_american_spanish">スペイン語(ラテンアメリカ) (Español latinoamericano)</string>
<string name="language_simplified_chinese">中国語 (简体中文)</string>
<string name="language_traditional_chinese">繁体字中国語 (正體中文)</string>
<string name="language_brazilian_portuguese">ポルトガル語(ブラジル) (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">타이완</string> <string name="region_taiwan">타이완</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">일본어 (日本語)</string>
<string name="language_english">영어 (English)</string>
<string name="language_french">프랑스어 (Français)</string>
<string name="langauge_german">독일어(Deutsch)</string>
<string name="language_italian">이탈리아어 (Italiano)</string>
<string name="language_spanish">스페인어 (Español)</string>
<string name="language_chinese">중국어 (简体中文)</string>
<string name="language_korean">한국어 (Korean)</string>
<string name="language_dutch">네덜란드어 (Nederlands)</string>
<string name="language_portuguese">포르투갈어 (Português)</string>
<string name="language_russian">러시아어 (Русский)</string>
<string name="language_taiwanese">대만어 (台湾)</string>
<string name="language_british_english">영어 (British English)</string>
<string name="language_canadian_french">캐나다 프랑스어 (Français canadien)</string>
<string name="language_latin_american_spanish">라틴 아메리카 스페인어 (Español latinoamericano)</string>
<string name="language_simplified_chinese">중국어 간체 (简体中文)</string>
<string name="language_traditional_chinese">중국어 번체 (正體中文)</string>
<string name="language_brazilian_portuguese">브라질 포르투갈어 (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">불칸</string> <string name="renderer_vulkan">불칸</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japansk (日本語)</string>
<string name="language_english">Engelsk</string>
<string name="language_french">Fransk (Français)</string>
<string name="langauge_german">Tysk (Deutsch)</string>
<string name="language_italian">Italiensk (Italiano)</string>
<string name="language_spanish">Spansk (Español)</string>
<string name="language_chinese">Kinesisk (简体中文)</string>
<string name="language_korean">Koreansk (한국어)</string>
<string name="language_dutch">Nederlandsk (Nederlands)</string>
<string name="language_portuguese">Portugisisk (Português)</string>
<string name="language_russian">Russisk (Русский)</string>
<string name="language_taiwanese">Taiwansk (台湾)</string>
<string name="language_british_english">Britisk Engelsk</string>
<string name="language_canadian_french">Kanadisk fransk (Français canadien)</string>
<string name="language_latin_american_spanish">Latinamerikansk spansk (Español latinoamericano)</string>
<string name="language_simplified_chinese">Forenklet kinesisk (简体中文)</string>
<string name="language_traditional_chinese">Tradisjonell Kinesisk (正體中文)</string>
<string name="language_brazilian_portuguese">Brasiliansk portugisisk (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Tajwan</string> <string name="region_taiwan">Tajwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japoński (日本語)</string>
<string name="language_english">Angielski</string>
<string name="language_french">Francuski (Francja)</string>
<string name="langauge_german">Niemiecki (Niemcy)</string>
<string name="language_italian">Włoski (Włochy)</string>
<string name="language_spanish">Hiszpański (Hiszpania)</string>
<string name="language_chinese">Chiński (简体中文)</string>
<string name="language_korean">Koreański (한국어)</string>
<string name="language_dutch">Duński (Holandia)</string>
<string name="language_portuguese">Portugalski (Portugalia)</string>
<string name="language_russian">Rosyjski (Русский)</string>
<string name="language_taiwanese">Tajwański (台湾)</string>
<string name="language_british_english">Angielski Brytyjski</string>
<string name="language_canadian_french">Francuski (Kanada)</string>
<string name="language_latin_american_spanish">Hiszpański (Ameryka Latynoska)</string>
<string name="language_simplified_chinese">Chiński uproszczony (简体中文)</string>
<string name="language_traditional_chinese">Chiński tradycyjny (正體中文)</string>
<string name="language_brazilian_portuguese">Portugalski (Brazylia)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japônes (日本語)</string>
<string name="language_english">Português do Brasil</string>
<string name="language_french">Francês (Français)</string>
<string name="langauge_german">Alemão (Deutsch)</string>
<string name="language_italian">Italiano (Italiano)</string>
<string name="language_spanish">Espanhol (Español)</string>
<string name="language_chinese">Mandarim (简体中文)</string>
<string name="language_korean">Coreano (한국어)</string>
<string name="language_dutch">Holandês (Nederlands)</string>
<string name="language_portuguese">Português (Português)</string>
<string name="language_russian">Russo (Русский)</string>
<string name="language_taiwanese">Taiwanês (台湾)</string>
<string name="language_british_english">Inglês britânico (British English)</string>
<string name="language_canadian_french">Fracês Canadiano (Français canadien)</string>
<string name="language_latin_american_spanish">Espanhol da América Latina (Español latino-americano)</string>
<string name="language_simplified_chinese">Chinês Simplificado (简体中文)</string>
<string name="language_traditional_chinese">Chinês tradicional (正體中文)</string>
<string name="language_brazilian_portuguese">Português do Brasil (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulcano</string> <string name="renderer_vulkan">Vulcano</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japonês (日本語)</string>
<string name="language_english">Inglês</string>
<string name="language_french">Francês (Français)</string>
<string name="langauge_german">Alemão (Deutsch)</string>
<string name="language_italian">Italiano (Italiano)</string>
<string name="language_spanish">Espanhol (Español)</string>
<string name="language_chinese">Chinês simplificado (简体中文)</string>
<string name="language_korean">Coreano (한국어)</string>
<string name="language_dutch">Holandês (Nederlands)</string>
<string name="language_portuguese">Português (Português)</string>
<string name="language_russian">Russo (Русский)</string>
<string name="language_taiwanese">Taiwanês (台湾)</string>
<string name="language_british_english">Inglês Britânico</string>
<string name="language_canadian_french">Fracês Canadiano (Français canadien)</string>
<string name="language_latin_american_spanish">Espanhol da América Latina (Español latino-americano)</string>
<string name="language_simplified_chinese">Chinês Simplificado (简体中文)</string>
<string name="language_traditional_chinese">Chinês Tradicional (正 體 中文)</string>
<string name="language_brazilian_portuguese">Português do Brasil (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulcano</string> <string name="renderer_vulkan">Vulcano</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Тайвань</string> <string name="region_taiwan">Тайвань</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Японский (日本語)</string>
<string name="language_english">Английский (English)</string>
<string name="language_french">Французский (Français)</string>
<string name="langauge_german">Немецкий (Deutsch)</string>
<string name="language_italian">Итальянский (Italiano)</string>
<string name="language_spanish">Испанский (Español)</string>
<string name="language_chinese">Китайский (简体中文)</string>
<string name="language_korean">Корейский (한국어)</string>
<string name="language_dutch">Голландский (Nederlands)</string>
<string name="language_portuguese">Португальский (Português)</string>
<string name="language_russian">Русский</string>
<string name="language_taiwanese">Тайваньский (台湾)</string>
<string name="language_british_english">Британский английский</string>
<string name="language_canadian_french">Канадский французский (Français canadien)</string>
<string name="language_latin_american_spanish">Латиноамериканский испанский (Español latinoamericano)</string>
<string name="language_simplified_chinese">Упрощенный китайский (简体中文)</string>
<string name="language_traditional_chinese">Традиционный китайский (正體中文)</string>
<string name="language_brazilian_portuguese">Бразильский португальский (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">Тайвань</string> <string name="region_taiwan">Тайвань</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Японська (日本語)</string>
<string name="language_english">Англійська (English)</string>
<string name="language_french">Французька (Français)</string>
<string name="langauge_german">Німецька (Deutsch)</string>
<string name="language_italian">Італійська (Italiano)</string>
<string name="language_spanish">Іспанська (Español)</string>
<string name="language_chinese">Китайскька (简体中文)</string>
<string name="language_korean">Корейська (한국어)</string>
<string name="language_dutch">Голландська (Nederlands)</string>
<string name="language_portuguese">Португальська (Português)</string>
<string name="language_russian">Російська (Русский)</string>
<string name="language_taiwanese">Тайванська (台湾)</string>
<string name="language_british_english">Британська англійська</string>
<string name="language_canadian_french">Канадська французька (Français canadien)</string>
<string name="language_latin_american_spanish">Латиноамериканська іспанська (Español latinoamericano)</string>
<string name="language_simplified_chinese">Спрощена китайська (简体中文)</string>
<string name="language_traditional_chinese">Традиційна китайська (正體中文)</string>
<string name="language_brazilian_portuguese">Бразильська португальська (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">中国台湾</string> <string name="region_taiwan">中国台湾</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">日语 (日本語)</string>
<string name="language_english">英语 (English)</string>
<string name="language_french">法语 (Français)</string>
<string name="langauge_german">德语 (Deutsch)</string>
<string name="language_italian">意大利语 (Italiano)</string>
<string name="language_spanish">西班牙语 (Español)</string>
<string name="language_chinese">中文 (简体中文)</string>
<string name="language_korean">韩语 (한국어)</string>
<string name="language_dutch">荷兰语 (Nederlands)</string>
<string name="language_portuguese">葡萄牙语 (Português)</string>
<string name="language_russian">俄语 (Русский)</string>
<string name="language_taiwanese">台湾中文 (台灣)</string>
<string name="language_british_english">英式英语</string>
<string name="language_canadian_french">加拿大法语 (Français canadien)</string>
<string name="language_latin_american_spanish">拉丁美洲西班牙语 (Español latinoamericano)</string>
<string name="language_simplified_chinese">简体中文 (简体中文)</string>
<string name="language_traditional_chinese">繁体中文 (正體中文)</string>
<string name="language_brazilian_portuguese">巴西葡萄牙语 (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -241,24 +241,6 @@
<string name="region_taiwan">台灣</string> <string name="region_taiwan">台灣</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">日文 (日本語)</string>
<string name="language_english">英文</string>
<string name="language_french">法文 (Français)</string>
<string name="langauge_german">德文 (Deutsch)</string>
<string name="language_italian">義大利文 (Italiano)</string>
<string name="language_spanish">西班牙文 (Español)</string>
<string name="language_chinese">中文 (简体中文)</string>
<string name="language_korean">韓文 (한국어)</string>
<string name="language_dutch">荷蘭文 (Nederlands)</string>
<string name="language_portuguese">葡萄牙文 (Português)</string>
<string name="language_russian">俄文 (Русский)</string>
<string name="language_taiwanese">台文 (台灣)</string>
<string name="language_british_english">英式英文</string>
<string name="language_canadian_french">加拿大法文 (Français canadien)</string>
<string name="language_latin_american_spanish">拉丁美洲西班牙文 (Español latinoamericano)</string>
<string name="language_simplified_chinese">簡體中文 (简体中文)</string>
<string name="language_traditional_chinese">正體中文 (正體中文)</string>
<string name="language_brazilian_portuguese">巴西葡萄牙文 (Português do Brasil)</string>
<!-- Renderer APIs --> <!-- Renderer APIs -->
<string name="renderer_vulkan">Vulkan</string> <string name="renderer_vulkan">Vulkan</string>

View File

@ -287,24 +287,24 @@
<string name="region_taiwan">Taiwan</string> <string name="region_taiwan">Taiwan</string>
<!-- Language Names --> <!-- Language Names -->
<string name="language_japanese">Japanese (日本語)</string> <string name="language_japanese" translatable="false">日本語</string>
<string name="language_english">English</string> <string name="language_english" translatable="false">English</string>
<string name="language_french">French (Français)</string> <string name="language_french" translatable="false">Français</string>
<string name="langauge_german">German (Deutsch)</string> <string name="langauge_german" translatable="false">Deutsch</string>
<string name="language_italian">Italian (Italiano)</string> <string name="language_italian" translatable="false">Italiano</string>
<string name="language_spanish">Spanish (Español)</string> <string name="language_spanish" translatable="false">Español</string>
<string name="language_chinese">Chinese (简体中文)</string> <string name="language_chinese" translatable="false">简体中文</string>
<string name="language_korean">Korean (한국어)</string> <string name="language_korean" translatable="false">한국어</string>
<string name="language_dutch">Dutch (Nederlands)</string> <string name="language_dutch" translatable="false">Nederlands</string>
<string name="language_portuguese">Portuguese (Português)</string> <string name="language_portuguese" translatable="false">Português</string>
<string name="language_russian">Russian (Русский)</string> <string name="language_russian" translatable="false">Русский</string>
<string name="language_taiwanese">Taiwanese (台湾)</string> <string name="language_taiwanese" translatable="false">台湾</string>
<string name="language_british_english">British English</string> <string name="language_british_english" translatable="false">British English</string>
<string name="language_canadian_french">Canadian French (Français canadien)</string> <string name="language_canadian_french" translatable="false">Français canadien</string>
<string name="language_latin_american_spanish">Latin American Spanish (Español latinoamericano)</string> <string name="language_latin_american_spanish" translatable="false">Español latinoamericano</string>
<string name="language_simplified_chinese">Simplified Chinese (简体中文)</string> <string name="language_simplified_chinese" translatable="false">简体中文</string>
<string name="language_traditional_chinese">Traditional Chinese (正體中文)</string> <string name="language_traditional_chinese" translatable="false">正體中文</string>
<string name="language_brazilian_portuguese">Brazilian Portuguese (Português do Brasil)</string> <string name="language_brazilian_portuguese" translatable="false">Português do Brasil</string>
<!-- Memory Sizes --> <!-- Memory Sizes -->
<string name="memory_byte">Byte</string> <string name="memory_byte">Byte</string>

View File

@ -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

View File

@ -217,8 +217,8 @@ void ARM_Interface::Run() {
} }
} }
void ARM_Interface::LoadWatchpointArray(const WatchpointArray& wp) { void ARM_Interface::LoadWatchpointArray(const WatchpointArray* wp) {
watchpoints = &wp; watchpoints = wp;
} }
const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint( const Kernel::DebugWatchpoint* ARM_Interface::MatchingWatchpoint(

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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_);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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());

View File

@ -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;

View File

@ -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();
} }

View File

@ -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

View File

@ -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:

View File

@ -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));

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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));

View File

@ -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:

View File

@ -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>(

View File

@ -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()) {

View File

@ -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);

View File

@ -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);

View File

@ -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));
} }

View File

@ -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));

View File

@ -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);

View File

@ -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>(

View File

@ -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);

View File

@ -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));

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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());
} }

View File

@ -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};
} }

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -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);

View File

@ -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()};

View File

@ -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);

View File

@ -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;
} }

View File

@ -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, {}};
} }

View File

@ -24,6 +24,16 @@
namespace Core::Memory { namespace Core::Memory {
namespace {
bool AddressSpaceContains(const Common::PageTable& table, const Common::ProcessAddress addr,
const std::size_t size) {
const Common::ProcessAddress max_addr = 1ULL << table.GetAddressSpaceBits();
return addr + size >= addr && addr + size <= max_addr;
}
} // namespace
// Implementation class used to keep the specifics of the memory subsystem hidden // Implementation class used to keep the specifics of the memory subsystem hidden
// from outside classes. This also allows modification to the internals of the memory // from outside classes. This also allows modification to the internals of the memory
// subsystem without needing to rebuild all files that make use of the memory interface. // subsystem without needing to rebuild all files that make use of the memory interface.
@ -31,10 +41,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 +83,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 +94,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 +193,18 @@ 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;
if (!AddressSpaceContains(page_table, addr, size)) [[unlikely]] {
on_unmapped(size, addr);
return false;
}
while (remaining_size) { while (remaining_size) {
const std::size_t copy_amount = const std::size_t copy_amount =
@ -200,11 +215,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 +244,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 +275,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 +302,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 +327,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 +357,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 +382,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,41 +405,38 @@ 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) {
if (vaddr == 0) { if (vaddr == 0 || !AddressSpaceContains(*current_page_table, vaddr, size)) {
return; return;
} }
@ -448,7 +463,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 +481,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:
@ -477,7 +493,7 @@ struct Memory::Impl {
} }
void RasterizerMarkRegionCached(u64 vaddr, u64 size, bool cached) { void RasterizerMarkRegionCached(u64 vaddr, u64 size, bool cached) {
if (vaddr == 0) { if (vaddr == 0 || !AddressSpaceContains(*current_page_table, vaddr, size)) {
return; return;
} }
@ -506,7 +522,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 +550,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 +601,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 +610,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;
@ -612,15 +630,15 @@ struct Memory::Impl {
// AARCH64 masks the upper 16 bit of all memory accesses // AARCH64 masks the upper 16 bit of all memory accesses
vaddr = vaddr & 0xffffffffffffULL; vaddr = vaddr & 0xffffffffffffULL;
if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { if (!AddressSpaceContains(*current_page_table, vaddr, 1)) [[unlikely]] {
on_unmapped(); on_unmapped();
return nullptr; return nullptr;
} }
// 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 +826,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 +917,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 +935,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 +959,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) {

View File

@ -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

View File

@ -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(),

View File

@ -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) {

View File

@ -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;
}; };

View File

@ -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) {

View File

@ -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>;

View File

@ -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
} }

View File

@ -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!");

View File

@ -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;
}; };

View File

@ -554,14 +554,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
} }
sets_per_pool = 64; sets_per_pool = 64;
if (extensions.extended_dynamic_state3 && is_amd_driver &&
properties.properties.driverVersion >= VK_MAKE_API_VERSION(0, 2, 0, 270)) {
LOG_WARNING(Render_Vulkan,
"AMD drivers after 23.5.2 have broken extendedDynamicState3ColorBlendEquation");
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEquation = false;
dynamic_state3_blending = false;
}
if (is_amd_driver) { if (is_amd_driver) {
// AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2. // AMD drivers need a higher amount of Sets per Pool in certain circumstances like in XC2.
sets_per_pool = 96; sets_per_pool = 96;

View File

@ -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);
} }

View File

@ -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;
}; };

View File

@ -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()};