Compare commits
42 Commits
0.16.0-p2
...
hid_refact
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b18db914c | ||
|
|
b69bf07d9c | ||
|
|
09978eafb9 | ||
|
|
8070de693d | ||
|
|
72671d39ab | ||
|
|
a4c4cf22c9 | ||
|
|
6ea1955e94 | ||
|
|
e81025af2e | ||
|
|
791638e6ba | ||
|
|
2e0378c724 | ||
|
|
59ada14680 | ||
|
|
25e944f519 | ||
|
|
3e87b8ff17 | ||
|
|
55502fcd0c | ||
|
|
d3e3292bb8 | ||
|
|
33c568963d | ||
|
|
c374f1c5ce | ||
|
|
825e2df2e0 | ||
|
|
b3efdebeaf | ||
|
|
b393f8f348 | ||
|
|
74e0ea1033 | ||
|
|
1738a308c4 | ||
|
|
8fe7373ad2 | ||
|
|
83dd25b894 | ||
|
|
5217a78637 | ||
|
|
2f0470ff1c | ||
|
|
e6733fb2d4 | ||
|
|
5be5be9e5c | ||
|
|
f86d23cb2c | ||
|
|
a7bc540fed | ||
|
|
0f7853417a | ||
|
|
11f90f03d9 | ||
|
|
7e2449b347 | ||
|
|
abe57ac5b2 | ||
|
|
8d458b44d7 | ||
|
|
1352690ece | ||
|
|
ac6fc7b965 | ||
|
|
d0e6fdb3da | ||
|
|
4c581d21f6 | ||
|
|
1365814b8d | ||
|
|
f63d79d8f9 | ||
|
|
14d50c0e39 |
7
Makefile
7
Makefile
@@ -141,16 +141,15 @@ dist: dist-no-debug
|
||||
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
|
||||
cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.elf
|
||||
cp stratosphere/eclct.stub/eclct.stub.elf atmosphere-$(AMSVER)-debug/eclct.stub.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/fatal/fatal.elf atmosphere-$(AMSVER)-debug/fatal.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/loader/loader.elf atmosphere-$(AMSVER)-debug/loader.elf
|
||||
cp stratosphere/ncm/ncm.elf atmosphere-$(AMSVER)-debug/ncm.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp stratosphere/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf
|
||||
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
||||
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf
|
||||
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||
rm -r atmosphere-$(AMSVER)-debug
|
||||
|
||||
@@ -1,38 +1,4 @@
|
||||
# Changelog
|
||||
## 0.16.0
|
||||
+ Support was added for 11.0.0.
|
||||
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ `loader`, `sm`, `boot`, `pgl` were updated to reflect the latest official behaviors.
|
||||
+ **Please Note**: 11.0.0 implements an opt-in version of the atmosphère `sm` extension that allows for closing session without unregistering services.
|
||||
+ Correspondingly, the extension will be deprecated in favor of the new official opt-in command. In 0.17.0, it will be removed entirely.
|
||||
+ If your custom system module relies on this extension (however unlikely that seems to me), please update it accordingly.
|
||||
+ `erpt` was partially updated to provide compatibility with 11.0.0.
|
||||
+ The latest firmware attaches additional fields and context information to logs.
|
||||
+ A future atmosphère update will implement this logic, so that users who are interested can also get the new information when examining their logs.
|
||||
+ **Please Note**: 11.0.0 introduced breaking changes to the `usb` system module's `usb:ds` API.
|
||||
+ Homebrew which uses the `usb:ds` service should rebuild with the latest libnx version to support running on 11.0.0.
|
||||
+ The `boot` system module was rewritten to reflect the huge driver changes introduced in 8.0.0.
|
||||
+ This includes a number of improvements to both logo display and battery management logic.
|
||||
+ Support was added for configuring the address space width for `hbl`.
|
||||
+ The `hbl_config!override_address_space_(#)` and `hbl_config!override_any_app_address_space` can now be set to `39_bit`, `36_bit`, or `32_bit` to control the address space for hbl on a per-override basis.
|
||||
+ If a configuration has not been set, hbl will now default to 39-bit address space.
|
||||
+ Previously, a legacy 36-bit address space was always used to maintain compatibility with 1.0.0.
|
||||
+ A new loader extension was added to support 39-bit whenever possible (including mesosphere-on-1.0.0), with fallback to 36-bit when unavailable.
|
||||
+ Support was added to a number of components for running on Mariko hardware.
|
||||
+ The `boot` system module can now safely be run on mariko hardware, performing correct hardware initialization.
|
||||
+ Daybreak (and generally, system update logic) were updated to be usable on Mariko.
|
||||
+ Boot0 protection/management logic was updated to perform correct actions on Mariko.
|
||||
+ Reboot to payload does not and cannot work on Mariko. Correspondingly, A "fatal error" handler was written, to display and save fatal errors from within TrustZone.
|
||||
+ **Please Note:** Atmosphere is still not properly usable on Mariko hardware.
|
||||
+ In particular, wake-from-sleep will not properly function (the magic numbers aren't set correctly), among a few other minor issues.
|
||||
+ `exosphère` received support for building under debug configuration.
|
||||
+ A small (otherwise unused) portion of IRAM is now reserved for debug-only exosphere code (this region is unused/untouched under release config).
|
||||
+ This enables logging (including printf) to uart from the secure monitor, for those interested.
|
||||
+ A number of bugs were fixed, including:
|
||||
+ Minor issues in a number of filesystem related code were fixed.
|
||||
+ An issue was fixed that could cause NCM to abort on consoles which came with 3.0.x and were never updated.
|
||||
+ Several issues were fixed, and usability and stability were improved.
|
||||
## 0.15.0
|
||||
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
|
||||
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/m4xw/emuMMC
|
||||
branch = develop
|
||||
commit = 5eed18eb527bbaa63aee5323c26de5b0cca6d28e
|
||||
parent = 021b29d2dbc8ed0469bc822393e58c9f0d174d57
|
||||
commit = 25075973d31a5be6f2e769f1ea0fff44daf0cdfa
|
||||
parent = 8ba513fefbcfd8278a433090e59017963ba9887f
|
||||
method = rebase
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
||||
|
||||
### Supported Horizon Versions
|
||||
**1.0.0 - 11.0.0**
|
||||
**1.0.0 - 10.0.0**
|
||||
|
||||
## Features
|
||||
* Arbitrary SDMMC backend selection
|
||||
|
||||
@@ -71,7 +71,6 @@ static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \
|
||||
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
|
||||
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
|
||||
.sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \
|
||||
.sdmmc_accessor_controller_open = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_OPEN, \
|
||||
.sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \
|
||||
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
|
||||
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
|
||||
|
||||
@@ -41,7 +41,6 @@ typedef struct {
|
||||
// Misc funcs
|
||||
uintptr_t lock_mutex;
|
||||
uintptr_t unlock_mutex;
|
||||
uintptr_t sdmmc_accessor_controller_open;
|
||||
uintptr_t sdmmc_accessor_controller_close;
|
||||
// Misc data
|
||||
uintptr_t sd_mutex;
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef struct sdmmc_accessor_vt
|
||||
void *dtor;
|
||||
void *map_device_addr_space;
|
||||
void *unmap_device_addr_space;
|
||||
uint64_t (*sdmmc_accessor_controller_open)(void *);
|
||||
void *controller_open;
|
||||
uint64_t (*sdmmc_accessor_controller_close)(void *);
|
||||
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
|
||||
// More not included because we don't use it.
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_100_LOCK_MUTEX 0x2884
|
||||
#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0
|
||||
|
||||
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
|
||||
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
|
||||
|
||||
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1100_LOCK_MUTEX 0x28FF0
|
||||
#define FS_OFFSET_1100_UNLOCK_MUTEX 0x29040
|
||||
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
|
||||
#define FS_OFFSET_1100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_1100_EXFAT_LOCK_MUTEX 0x28FF0
|
||||
#define FS_OFFSET_1100_EXFAT_UNLOCK_MUTEX 0x29040
|
||||
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x14B840
|
||||
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14B8F0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_200_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_210_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
|
||||
#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0
|
||||
|
||||
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC
|
||||
#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638
|
||||
|
||||
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
|
||||
#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638
|
||||
|
||||
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_301_LOCK_MUTEX 0x3638
|
||||
#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4
|
||||
|
||||
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
|
||||
#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4
|
||||
|
||||
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
|
||||
// Misc Data
|
||||
#define FS_OFFSET_410_SD_MUTEX 0xE80268
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
|
||||
#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C
|
||||
|
||||
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_500_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_510_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
|
||||
#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0
|
||||
|
||||
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
|
||||
#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310
|
||||
|
||||
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
|
||||
#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10
|
||||
|
||||
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90
|
||||
#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0
|
||||
|
||||
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
|
||||
#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090
|
||||
|
||||
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
|
||||
#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720
|
||||
|
||||
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
|
||||
#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0
|
||||
|
||||
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
|
||||
#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720
|
||||
|
||||
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
|
||||
#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0
|
||||
|
||||
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_900_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_910_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280
|
||||
#define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0
|
||||
|
||||
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||
|
||||
// Misc Data
|
||||
|
||||
@@ -271,7 +271,7 @@ int sdmmc_nand_get_active_partition_index()
|
||||
|
||||
static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned int num_sectors, bool is_write)
|
||||
{
|
||||
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw))
|
||||
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD))
|
||||
{
|
||||
// raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset.
|
||||
sector += emuMMC_ctx.EMMC_StoragePartitionOffset;
|
||||
@@ -318,31 +318,6 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
|
||||
return res;
|
||||
}
|
||||
|
||||
// Controller open wrapper
|
||||
uint64_t sdmmc_wrapper_controller_open(int mmc_id)
|
||||
{
|
||||
uint64_t result;
|
||||
sdmmc_accessor_t *_this;
|
||||
_this = sdmmc_accessor_get(mmc_id);
|
||||
|
||||
if (_this != NULL)
|
||||
{
|
||||
// Lock eMMC xfer while SD card is being initialized by FS.
|
||||
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
|
||||
mutex_lock_handler(FS_SDMMC_EMMC); // Recursive Mutex, handler will lock SD as well if custom_driver
|
||||
|
||||
result = _this->vtab->sdmmc_accessor_controller_open(_this);
|
||||
|
||||
// Unlock eMMC.
|
||||
if (_this == sdmmc_accessor_get(FS_SDMMC_SD))
|
||||
mutex_unlock_handler(FS_SDMMC_EMMC);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fatal_abort(Fatal_OpenAccessor);
|
||||
}
|
||||
|
||||
// Controller close wrapper
|
||||
uint64_t sdmmc_wrapper_controller_close(int mmc_id)
|
||||
{
|
||||
@@ -414,7 +389,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
||||
if (first_sd_read)
|
||||
{
|
||||
first_sd_read = false;
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
||||
{
|
||||
// Because some SD cards have issues with emuMMC's driver
|
||||
// we currently swap to FS's driver after first SD read
|
||||
@@ -425,7 +400,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
||||
}
|
||||
}
|
||||
|
||||
// Call hekate's driver.
|
||||
// Call hekates driver.
|
||||
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
|
||||
{
|
||||
mutex_unlock_handler(mmc_id);
|
||||
|
||||
@@ -52,7 +52,6 @@ void mutex_lock_handler(int mmc_id);
|
||||
void mutex_unlock_handler(int mmc_id);
|
||||
|
||||
// Hooks
|
||||
uint64_t sdmmc_wrapper_controller_open(int mmc_id);
|
||||
uint64_t sdmmc_wrapper_controller_close(int mmc_id);
|
||||
uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned int sector, unsigned int num_sectors);
|
||||
uint64_t sdmmc_wrapper_write(int mmc_id, unsigned int sector, unsigned int num_sectors, void *buf, uint64_t bufSize);
|
||||
|
||||
@@ -30,7 +30,7 @@ enum emuMMC_Type
|
||||
emuMMC_EMMC = 0,
|
||||
|
||||
// SD Device raw
|
||||
emuMMC_SD_Raw,
|
||||
emuMMC_SD,
|
||||
// SD Device File
|
||||
emuMMC_SD_File,
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ volatile __attribute__((aligned(0x1000))) emuMMC_ctx_t emuMMC_ctx = {
|
||||
.fs_ver = FS_VER_MAX,
|
||||
|
||||
// SD Default Metadata
|
||||
.SD_Type = emuMMC_SD_Raw,
|
||||
.SD_Type = emuMMC_SD,
|
||||
.SD_StoragePartitionOffset = 0,
|
||||
|
||||
// EMMC Default Metadata
|
||||
@@ -285,9 +285,6 @@ void setup_hooks(void)
|
||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
|
||||
// sdmmc_wrapper_write hook
|
||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write);
|
||||
// sdmmc_wrapper_controller_open hook
|
||||
if (fs_offsets->sdmmc_accessor_controller_open)
|
||||
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_open, sdmmc_wrapper_controller_open);
|
||||
// sdmmc_wrapper_controller_close hook
|
||||
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
|
||||
|
||||
@@ -349,7 +346,7 @@ static void load_emummc_ctx(void)
|
||||
emuMMC_ctx.id = config.base_cfg.id;
|
||||
emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type;
|
||||
emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version;
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
||||
{
|
||||
emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector;
|
||||
}
|
||||
|
||||
@@ -72,9 +72,6 @@ namespace ams::secmon::boot {
|
||||
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
|
||||
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
|
||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
|
||||
|
||||
/* TODO: Fix to ensure correct scratch contents on mariko, as otherwise wb is broken. */
|
||||
AMS_ABORT_UNLESS(fuse::GetSocType() != fuse::SocType_Mariko);
|
||||
}
|
||||
|
||||
/* This function derives the master kek and device keys using the tsec root key. */
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_IcosaSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaMicron4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveHynix1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
|
||||
[fuse::DramId_CopperHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperMicron4GB] = pkg1::MemorySize_4GB,
|
||||
@@ -66,13 +66,9 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBY] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y8GBY] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBA] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
};
|
||||
|
||||
constexpr const pkg1::MemoryMode MemoryModes[] = {
|
||||
|
||||
@@ -543,8 +543,8 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9B
|
||||
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x80]
|
||||
mov w10, #3
|
||||
ldr x11, [sp, #0x90]
|
||||
mov w10, w28
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
@@ -567,11 +567,11 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9B
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send)[] = {0xE0, 0x03, 0x15, 0xAA, 0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0x88, 0x4A, 0x3C, 0x8B, 0x09, 0xFC, 0x60, 0xD3, 0x00, 0x25, 0x00, 0x29};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9BF2FEA, 0xF94043EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9BF2FEA, 0xF9404BEB, 0x2A1C03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54FFFFA0, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0xE0]
|
||||
mov w10, #3
|
||||
ldr w10, [sp, #0xC0]
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
@@ -594,7 +594,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9B
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x7F, 0x40, 0xF9, 0x09, 0xFC, 0x60, 0xD3, 0xEA, 0x5B, 0x40, 0xF9};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)[] = {0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)[] = {0xA9BF2FEA, 0xF94073EB, 0xB940C3EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54FFFFA0, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/* svcControlCodeMemory Patches */
|
||||
/* b.eq -> nop */
|
||||
@@ -1090,7 +1090,7 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
||||
|
||||
uint8_t *pattern_loc = search_pattern(kernel, *kernel_size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||
if (pattern_loc == NULL) {
|
||||
fatal_error("kernel_patcher: failed to identify patch location!\n");
|
||||
/* TODO: Should we print an error/abort here? */
|
||||
continue;
|
||||
}
|
||||
/* Patch kernel to branch to our hook at the desired place. */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = 2c3ccef17e9b267a5d9d232f1aba689f2c591b95
|
||||
parent = d2f48d5e36cb2ba4e8cc014238457bd75df81797
|
||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace ams::fuse {
|
||||
DramId_IcosaSamsung4GB = 0,
|
||||
DramId_IcosaHynix4GB = 1,
|
||||
DramId_IcosaMicron4GB = 2,
|
||||
DramId_FiveHynix1y4GB = 3,
|
||||
DramId_CopperSamsung4GB = 3,
|
||||
DramId_IcosaSamsung6GB = 4,
|
||||
DramId_CopperHynix4GB = 5,
|
||||
DramId_CopperMicron4GB = 6,
|
||||
@@ -70,13 +70,9 @@ namespace ams::fuse {
|
||||
DramId_HoagSamsung1y4GBX = 19,
|
||||
DramId_IowaSamsung1y4GBY = 20,
|
||||
DramId_IowaSamsung1y8GBY = 21,
|
||||
DramId_FiveSamsung1y4GB = 22,
|
||||
DramId_HoagSamsung1y8GBX = 23,
|
||||
DramId_IowaSamsung1y4GBA = 22,
|
||||
DramId_FiveSamsung1y8GBX = 23,
|
||||
DramId_FiveSamsung1y4GBX = 24,
|
||||
DramId_IowaMicron1y4GB = 25,
|
||||
DramId_HoagMicron1y4GB = 26,
|
||||
DramId_FiveMicron1y4GB = 27,
|
||||
DramId_FiveSamsung1y8GBX = 28,
|
||||
|
||||
DramId_Count,
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
@@ -77,8 +77,6 @@
|
||||
#include <mesosphere/kern_select_debug.hpp>
|
||||
#include <mesosphere/kern_k_process.hpp>
|
||||
#include <mesosphere/kern_k_resource_limit.hpp>
|
||||
#include <mesosphere/kern_k_alpha.hpp>
|
||||
#include <mesosphere/kern_k_beta.hpp>
|
||||
|
||||
/* More Miscellaneous objects. */
|
||||
#include <mesosphere/kern_k_object_name.hpp>
|
||||
|
||||
@@ -668,7 +668,6 @@ namespace ams::kern::arch::arm64::init {
|
||||
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
||||
cpu::StoreEntireCacheForInit();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
|
||||
public:
|
||||
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE void Lock() {
|
||||
void Lock() {
|
||||
u32 tmp0, tmp1, tmp2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
@@ -52,7 +52,7 @@ namespace ams::kern::arch::arm64 {
|
||||
);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
void Unlock() {
|
||||
const u32 value = this->packed_tickets + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[packed_tickets]\n"
|
||||
@@ -71,7 +71,7 @@ namespace ams::kern::arch::arm64 {
|
||||
public:
|
||||
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE void Lock() {
|
||||
void Lock() {
|
||||
u32 tmp0, tmp1, got_lock;
|
||||
|
||||
__asm__ __volatile__(
|
||||
@@ -94,7 +94,7 @@ namespace ams::kern::arch::arm64 {
|
||||
);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
void Unlock() {
|
||||
const u32 value = this->current_ticket + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[current_ticket]\n"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern::board::nintendo::nx::impl::cpu {
|
||||
|
||||
/* Virtual to Physical core map. */
|
||||
constexpr inline const s32 VirtualToPhysicalCoreMap[BITSIZEOF(u64)] = {
|
||||
0, 1, 2, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -34,8 +34,6 @@ namespace ams::kern::init {
|
||||
size_t num_KObjectName;
|
||||
size_t num_KResourceLimit;
|
||||
size_t num_KDebug;
|
||||
size_t num_KAlpha;
|
||||
size_t num_KBeta;
|
||||
};
|
||||
|
||||
NOINLINE void InitializeSlabResourceCounts();
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KAlpha final : public KAutoObjectWithSlabHeapAndContainer<KAlpha, KAutoObjectWithList> {
|
||||
MESOSPHERE_AUTOOBJECT_TRAITS(KAlpha, KAutoObject);
|
||||
private:
|
||||
/* NOTE: Official KAlpha has size 0x50, corresponding to 0x20 bytes of fields. */
|
||||
/* TODO: Add these fields, if KAlpha is ever instantiable in the NX kernel. */
|
||||
public:
|
||||
explicit KAlpha() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~KAlpha() { /* ... */ }
|
||||
|
||||
/* virtual void Finalize() override; */
|
||||
|
||||
virtual bool IsInitialized() const override { return false /* TODO */; }
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -198,7 +198,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
~KScopedAutoObject() {
|
||||
ALWAYS_INLINE ~KScopedAutoObject() {
|
||||
if (this->obj != nullptr) {
|
||||
this->obj->Close();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
template<typename U> requires (std::derived_from<T, U> || std::derived_from<U, T>)
|
||||
constexpr KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
||||
constexpr ALWAYS_INLINE KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
||||
if constexpr (std::derived_from<U, T>) {
|
||||
/* Upcast. */
|
||||
this->obj = rhs.obj;
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KProcess;
|
||||
|
||||
class KBeta final : public KAutoObjectWithSlabHeapAndContainer<KBeta, KAutoObjectWithList> {
|
||||
MESOSPHERE_AUTOOBJECT_TRAITS(KBeta, KAutoObject);
|
||||
private:
|
||||
friend class KProcess;
|
||||
private:
|
||||
/* NOTE: Official KBeta has size 0x88, corresponding to 0x58 bytes of fields. */
|
||||
/* TODO: Add these fields, if KBeta is ever instantiable in the NX kernel. */
|
||||
util::IntrusiveListNode process_list_node;
|
||||
public:
|
||||
explicit KBeta()
|
||||
: process_list_node()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~KBeta() { /* ... */ }
|
||||
|
||||
/* virtual void Finalize() override; */
|
||||
|
||||
virtual bool IsInitialized() const override { return false /* TODO */; }
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -112,10 +112,6 @@ namespace ams::kern {
|
||||
KSessionRequest,
|
||||
KCodeMemory,
|
||||
|
||||
/* NOTE: True order for these has not been determined yet. */
|
||||
KAlpha,
|
||||
KBeta,
|
||||
|
||||
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
extern KThread g_cv_arbiter_compare_thread;
|
||||
|
||||
class KConditionVariable {
|
||||
public:
|
||||
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;
|
||||
|
||||
@@ -160,16 +160,14 @@ namespace ams::kern {
|
||||
return this->template GetObjectWithoutPseudoHandle<T>(handle);
|
||||
}
|
||||
|
||||
KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
||||
ALWAYS_INLINE KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
||||
/* Lock and look up in table. */
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
|
||||
KAutoObject *obj = this->GetObjectImpl(handle);
|
||||
if (AMS_LIKELY(obj != nullptr)) {
|
||||
if (AMS_UNLIKELY(obj->DynamicCast<KInterruptEvent *>() != nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (obj->DynamicCast<KInterruptEvent *>() != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
||||
@@ -112,9 +112,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) {
|
||||
const auto ®ion = Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
return region.GetEndAddress();
|
||||
return Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))).GetEndAddress();
|
||||
}
|
||||
public:
|
||||
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
|
||||
|
||||
@@ -70,13 +70,11 @@ namespace ams::kern {
|
||||
public:
|
||||
Impl() : heap(), page_reference_counts(), management_region(), pool(), next(), prev() { /* ... */ }
|
||||
|
||||
size_t Initialize(uintptr_t address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p);
|
||||
size_t Initialize(const KMemoryRegion *region, Pool pool, KVirtualAddress management_region, KVirtualAddress management_region_end);
|
||||
|
||||
KVirtualAddress AllocateBlock(s32 index, bool random) { return this->heap.AllocateBlock(index, random); }
|
||||
void Free(KVirtualAddress addr, size_t num_pages) { this->heap.Free(addr, num_pages); }
|
||||
|
||||
void UpdateUsedHeapSize() { this->heap.UpdateUsedSize(); }
|
||||
|
||||
void InitializeOptimizedMemory() { std::memset(GetVoidPointer(this->management_region), 0, CalculateOptimizedProcessOverheadSize(this->heap.GetSize())); }
|
||||
|
||||
void TrackUnoptimizedAllocation(KVirtualAddress block, size_t num_pages);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace ams::kern {
|
||||
private:
|
||||
uintptr_t address;
|
||||
uintptr_t pair_address;
|
||||
uintptr_t last_address;
|
||||
size_t region_size;
|
||||
u32 attributes;
|
||||
u32 type_id;
|
||||
public:
|
||||
@@ -43,18 +43,18 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), last_address(0), attributes(0), type_id(0) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) :
|
||||
address(a), pair_address(p), last_address(la), attributes(r), type_id(t)
|
||||
constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), region_size(0), attributes(0), type_id(0) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, uintptr_t p, u32 r, u32 t) :
|
||||
address(a), pair_address(p), region_size(rs), attributes(r), type_id(t)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, u32 r, u32 t) : KMemoryRegion(a, la, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, u32 r, u32 t) : KMemoryRegion(a, rs, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
|
||||
private:
|
||||
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t la, uintptr_t p, u32 r, u32 t) {
|
||||
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t rs, uintptr_t p, u32 r, u32 t) {
|
||||
this->address = a;
|
||||
this->pair_address = p;
|
||||
this->last_address = la;
|
||||
this->region_size = rs;
|
||||
this->attributes = r;
|
||||
this->type_id = t;
|
||||
}
|
||||
@@ -67,16 +67,16 @@ namespace ams::kern {
|
||||
return this->pair_address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->last_address;
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->region_size;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||
return this->GetLastAddress() + 1;
|
||||
return this->GetAddress() + this->GetSize();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->GetEndAddress() - this->GetAddress();
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->GetEndAddress() - 1;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetAttributes() const {
|
||||
@@ -93,7 +93,6 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(this->GetEndAddress() != 0);
|
||||
return this->GetAddress() <= address && address <= this->GetLastAddress();
|
||||
}
|
||||
|
||||
@@ -131,17 +130,17 @@ namespace ams::kern {
|
||||
return this->first_region->GetAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->last_region->GetLastAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||
return this->GetLastAddress() + 1;
|
||||
return this->last_region->GetEndAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->GetEndAddress() - this->GetAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->GetEndAddress() - 1;
|
||||
}
|
||||
};
|
||||
private:
|
||||
using TreeType = util::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
|
||||
@@ -161,7 +160,7 @@ namespace ams::kern {
|
||||
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
|
||||
public:
|
||||
KMemoryRegion *FindModifiable(uintptr_t address) {
|
||||
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) {
|
||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) {
|
||||
return std::addressof(*it);
|
||||
} else {
|
||||
return nullptr;
|
||||
@@ -169,7 +168,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
const KMemoryRegion *Find(uintptr_t address) const {
|
||||
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) {
|
||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) {
|
||||
return std::addressof(*it);
|
||||
} else {
|
||||
return nullptr;
|
||||
@@ -235,7 +234,7 @@ namespace ams::kern {
|
||||
return extents;
|
||||
}
|
||||
public:
|
||||
NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr = 0, u32 type_id = 0);
|
||||
NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0);
|
||||
NOINLINE bool Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
|
||||
|
||||
NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <mesosphere/kern_k_thread.hpp>
|
||||
#include <mesosphere/kern_k_thread_local_page.hpp>
|
||||
#include <mesosphere/kern_k_shared_memory_info.hpp>
|
||||
#include <mesosphere/kern_k_beta.hpp>
|
||||
#include <mesosphere/kern_k_worker_task.hpp>
|
||||
#include <mesosphere/kern_select_page_table.hpp>
|
||||
#include <mesosphere/kern_k_condition_variable.hpp>
|
||||
@@ -53,7 +52,6 @@ namespace ams::kern {
|
||||
static constexpr size_t AslrAlignment = KernelAslrAlignment;
|
||||
private:
|
||||
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
||||
using BetaList = util::IntrusiveListMemberTraits<&KBeta::process_list_node>::ListType;
|
||||
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
||||
using TLPIterator = TLPTree::iterator;
|
||||
private:
|
||||
@@ -97,7 +95,6 @@ namespace ams::kern {
|
||||
KThread *exception_thread{};
|
||||
ThreadList thread_list{};
|
||||
SharedMemoryInfoList shared_memory_list{};
|
||||
BetaList beta_list{};
|
||||
bool is_suspended{};
|
||||
bool is_jit_debug{};
|
||||
ams::svc::DebugEvent jit_debug_event_type{};
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace ams::kern {
|
||||
return this->owner_thread == GetCurrentThreadPointer();
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
ALWAYS_INLINE void Lock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->IsLockedByCurrentThread()) {
|
||||
@@ -67,7 +67,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||
MESOSPHERE_ASSERT(this->lock_count > 0);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ams::kern {
|
||||
*out_timer = this->timer;
|
||||
}
|
||||
|
||||
~KScopedSchedulerLockAndSleep() {
|
||||
ALWAYS_INLINE ~KScopedSchedulerLockAndSleep() {
|
||||
/* Register the sleep. */
|
||||
if (this->timeout_tick > 0) {
|
||||
this->timer->RegisterAbsoluteTask(this->thread, this->timeout_tick);
|
||||
|
||||
@@ -45,10 +45,10 @@ namespace ams::kern {
|
||||
this->state = st;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetClientAddress() const { return this->client_address; }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetServerAddress() const { return this->server_address; }
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const { return this->size; }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetMemoryState() const { return this->state; }
|
||||
constexpr KProcessAddress GetClientAddress() const { return this->client_address; }
|
||||
constexpr KProcessAddress GetServerAddress() const { return this->server_address; }
|
||||
constexpr size_t GetSize() const { return this->size; }
|
||||
constexpr KMemoryState GetMemoryState() const { return this->state; }
|
||||
};
|
||||
private:
|
||||
Mapping static_mappings[NumStaticMappings];
|
||||
@@ -62,32 +62,32 @@ namespace ams::kern {
|
||||
void Initialize() { /* ... */ }
|
||||
void Finalize();
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSendCount() const { return this->num_send; }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveCount() const { return this->num_recv; }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeCount() const { return this->num_exch; }
|
||||
constexpr size_t GetSendCount() const { return this->num_send; }
|
||||
constexpr size_t GetReceiveCount() const { return this->num_recv; }
|
||||
constexpr size_t GetExchangeCount() const { return this->num_exch; }
|
||||
|
||||
Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendClientAddress(size_t i) const { return GetSendMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendServerAddress(size_t i) const { return GetSendMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetSendSize(size_t i) const { return GetSendMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetSendMemoryState(size_t i) const { return GetSendMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetSendClientAddress(size_t i) const { return GetSendMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetSendServerAddress(size_t i) const { return GetSendMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetSendSize(size_t i) const { return GetSendMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetSendMemoryState(size_t i) const { return GetSendMapping(i).GetMemoryState(); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveClientAddress(size_t i) const { return GetReceiveMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveServerAddress(size_t i) const { return GetReceiveMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveSize(size_t i) const { return GetReceiveMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetReceiveMemoryState(size_t i) const { return GetReceiveMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetReceiveClientAddress(size_t i) const { return GetReceiveMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetReceiveServerAddress(size_t i) const { return GetReceiveMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetReceiveSize(size_t i) const { return GetReceiveMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetReceiveMemoryState(size_t i) const { return GetReceiveMapping(i).GetMemoryState(); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeClientAddress(size_t i) const { return GetExchangeMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeServerAddress(size_t i) const { return GetExchangeMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeSize(size_t i) const { return GetExchangeMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetExchangeMemoryState(size_t i) const { return GetExchangeMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetExchangeClientAddress(size_t i) const { return GetExchangeMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetExchangeServerAddress(size_t i) const { return GetExchangeMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetExchangeSize(size_t i) const { return GetExchangeMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetExchangeMemoryState(size_t i) const { return GetExchangeMapping(i).GetMemoryState(); }
|
||||
private:
|
||||
Result PushMap(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state, size_t index);
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetSendMapping(size_t i) const {
|
||||
constexpr const Mapping &GetSendMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_send);
|
||||
|
||||
const size_t index = i;
|
||||
@@ -98,7 +98,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetReceiveMapping(size_t i) const {
|
||||
constexpr const Mapping &GetReceiveMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_recv);
|
||||
|
||||
const size_t index = this->num_send + i;
|
||||
@@ -109,7 +109,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetExchangeMapping(size_t i) const {
|
||||
constexpr const Mapping &GetExchangeMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_exch);
|
||||
|
||||
const size_t index = this->num_send + this->num_recv + i;
|
||||
@@ -176,50 +176,50 @@ namespace ams::kern {
|
||||
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
|
||||
constexpr ALWAYS_INLINE KThread *GetThread() const { return this->thread; }
|
||||
constexpr ALWAYS_INLINE KWritableEvent *GetEvent() const { return this->event; }
|
||||
constexpr ALWAYS_INLINE uintptr_t GetAddress() const { return this->address; }
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const { return this->size; }
|
||||
constexpr ALWAYS_INLINE KProcess *GetServerProcess() const { return this->server; }
|
||||
constexpr KThread *GetThread() const { return this->thread; }
|
||||
constexpr KWritableEvent *GetEvent() const { return this->event; }
|
||||
constexpr uintptr_t GetAddress() const { return this->address; }
|
||||
constexpr size_t GetSize() const { return this->size; }
|
||||
constexpr KProcess *GetServerProcess() const { return this->server; }
|
||||
|
||||
void ALWAYS_INLINE SetServerProcess(KProcess *process) {
|
||||
void SetServerProcess(KProcess *process) {
|
||||
this->server = process;
|
||||
this->server->Open();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void ClearThread() { this->thread = nullptr; }
|
||||
constexpr ALWAYS_INLINE void ClearEvent() { this->event = nullptr; }
|
||||
constexpr void ClearThread() { this->thread = nullptr; }
|
||||
constexpr void ClearEvent() { this->event = nullptr; }
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSendCount() const { return this->mappings.GetSendCount(); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveCount() const { return this->mappings.GetReceiveCount(); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeCount() const { return this->mappings.GetExchangeCount(); }
|
||||
constexpr size_t GetSendCount() const { return this->mappings.GetSendCount(); }
|
||||
constexpr size_t GetReceiveCount() const { return this->mappings.GetReceiveCount(); }
|
||||
constexpr size_t GetExchangeCount() const { return this->mappings.GetExchangeCount(); }
|
||||
|
||||
ALWAYS_INLINE Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushSend(client, server, size, state);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushReceive(client, server, size, state);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushExchange(client, server, size, state);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendClientAddress(size_t i) const { return this->mappings.GetSendClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendServerAddress(size_t i) const { return this->mappings.GetSendServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetSendSize(size_t i) const { return this->mappings.GetSendSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetSendMemoryState(size_t i) const { return this->mappings.GetSendMemoryState(i); }
|
||||
constexpr KProcessAddress GetSendClientAddress(size_t i) const { return this->mappings.GetSendClientAddress(i); }
|
||||
constexpr KProcessAddress GetSendServerAddress(size_t i) const { return this->mappings.GetSendServerAddress(i); }
|
||||
constexpr size_t GetSendSize(size_t i) const { return this->mappings.GetSendSize(i); }
|
||||
constexpr KMemoryState GetSendMemoryState(size_t i) const { return this->mappings.GetSendMemoryState(i); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveClientAddress(size_t i) const { return this->mappings.GetReceiveClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveServerAddress(size_t i) const { return this->mappings.GetReceiveServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveSize(size_t i) const { return this->mappings.GetReceiveSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetReceiveMemoryState(size_t i) const { return this->mappings.GetReceiveMemoryState(i); }
|
||||
constexpr KProcessAddress GetReceiveClientAddress(size_t i) const { return this->mappings.GetReceiveClientAddress(i); }
|
||||
constexpr KProcessAddress GetReceiveServerAddress(size_t i) const { return this->mappings.GetReceiveServerAddress(i); }
|
||||
constexpr size_t GetReceiveSize(size_t i) const { return this->mappings.GetReceiveSize(i); }
|
||||
constexpr KMemoryState GetReceiveMemoryState(size_t i) const { return this->mappings.GetReceiveMemoryState(i); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeClientAddress(size_t i) const { return this->mappings.GetExchangeClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeServerAddress(size_t i) const { return this->mappings.GetExchangeServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeSize(size_t i) const { return this->mappings.GetExchangeSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetExchangeMemoryState(size_t i) const { return this->mappings.GetExchangeMemoryState(i); }
|
||||
constexpr KProcessAddress GetExchangeClientAddress(size_t i) const { return this->mappings.GetExchangeClientAddress(i); }
|
||||
constexpr KProcessAddress GetExchangeServerAddress(size_t i) const { return this->mappings.GetExchangeServerAddress(i); }
|
||||
constexpr size_t GetExchangeSize(size_t i) const { return this->mappings.GetExchangeSize(i); }
|
||||
constexpr KMemoryState GetExchangeMemoryState(size_t i) const { return this->mappings.GetExchangeMemoryState(i); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -124,21 +124,7 @@ namespace ams::kern {
|
||||
static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles));
|
||||
|
||||
struct ConditionVariableComparator {
|
||||
struct LightCompareType {
|
||||
uintptr_t cv_key;
|
||||
s32 priority;
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetConditionVariableKey() const {
|
||||
return this->cv_key;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE s32 GetPriority() const {
|
||||
return this->priority;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, LightCompareType>)
|
||||
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
|
||||
static constexpr ALWAYS_INLINE int Compare(const KThread &lhs, const KThread &rhs) {
|
||||
const uintptr_t l_key = lhs.GetConditionVariableKey();
|
||||
const uintptr_t r_key = rhs.GetConditionVariableKey();
|
||||
|
||||
@@ -153,8 +139,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
};
|
||||
static_assert(ams::util::HasLightCompareType<ConditionVariableComparator>);
|
||||
static_assert(std::same_as<ams::util::LightCompareType<ConditionVariableComparator, void>, ConditionVariableComparator::LightCompareType>);
|
||||
private:
|
||||
static inline std::atomic<u64> s_next_thread_id = 0;
|
||||
private:
|
||||
@@ -168,8 +152,7 @@ namespace ams::kern {
|
||||
|
||||
ConditionVariableThreadTree *condvar_tree{};
|
||||
uintptr_t condvar_key{};
|
||||
u64 virtual_affinity_mask{};
|
||||
KAffinityMask physical_affinity_mask{};
|
||||
KAffinityMask affinity_mask{};
|
||||
u64 thread_id{};
|
||||
std::atomic<s64> cpu_time{};
|
||||
KSynchronizationObject *synced_object{};
|
||||
@@ -198,13 +181,12 @@ namespace ams::kern {
|
||||
Result wait_result;
|
||||
Result debug_exception_result;
|
||||
s32 base_priority{};
|
||||
s32 physical_ideal_core_id{};
|
||||
s32 virtual_ideal_core_id{};
|
||||
s32 ideal_core_id{};
|
||||
s32 num_kernel_waiters{};
|
||||
s32 current_core_id{};
|
||||
s32 core_id{};
|
||||
KAffinityMask original_physical_affinity_mask{};
|
||||
s32 original_physical_ideal_core_id{};
|
||||
KAffinityMask original_affinity_mask{};
|
||||
s32 original_ideal_core_id{};
|
||||
s32 num_core_migration_disables{};
|
||||
ThreadState thread_state{};
|
||||
std::atomic<bool> termination_requested{};
|
||||
@@ -220,21 +202,21 @@ namespace ams::kern {
|
||||
|
||||
virtual ~KThread() { /* ... */ }
|
||||
|
||||
Result Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type);
|
||||
Result Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type);
|
||||
|
||||
private:
|
||||
static Result InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type);
|
||||
static Result InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type);
|
||||
public:
|
||||
static Result InitializeKernelThread(KThread *thread, KThreadFunction func, uintptr_t arg, s32 prio, s32 virt_core) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, prio, virt_core, nullptr, ThreadType_Kernel);
|
||||
static Result InitializeKernelThread(KThread *thread, KThreadFunction func, uintptr_t arg, s32 prio, s32 core) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, prio, core, nullptr, ThreadType_Kernel);
|
||||
}
|
||||
|
||||
static Result InitializeHighPriorityThread(KThread *thread, KThreadFunction func, uintptr_t arg) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, 0, GetCurrentCoreId(), nullptr, ThreadType_HighPriority);
|
||||
}
|
||||
|
||||
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner) {
|
||||
return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType_User);
|
||||
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner) {
|
||||
return InitializeThread(thread, func, arg, user_stack_top, prio, core, owner, ThreadType_User);
|
||||
}
|
||||
|
||||
static void ResumeThreadsSuspendedForInit();
|
||||
@@ -341,14 +323,10 @@ namespace ams::kern {
|
||||
constexpr KThreadContext &GetContext() { return this->thread_context; }
|
||||
constexpr const KThreadContext &GetContext() const { return this->thread_context; }
|
||||
|
||||
constexpr u64 GetVirtualAffinityMask() const { return this->virtual_affinity_mask; }
|
||||
constexpr const KAffinityMask &GetAffinityMask() const { return this->physical_affinity_mask; }
|
||||
|
||||
constexpr const KAffinityMask &GetAffinityMask() const { return this->affinity_mask; }
|
||||
Result GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
Result SetCoreMask(int32_t ideal_core, u64 affinity_mask);
|
||||
|
||||
Result GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
|
||||
constexpr ThreadState GetState() const { return static_cast<ThreadState>(this->thread_state & ThreadState_Mask); }
|
||||
constexpr ThreadState GetRawState() const { return this->thread_state; }
|
||||
NOINLINE void SetState(ThreadState state);
|
||||
@@ -358,6 +336,11 @@ namespace ams::kern {
|
||||
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
|
||||
constexpr uintptr_t GetAddressArbiterKey() const { return this->condvar_key; }
|
||||
|
||||
constexpr void SetupForConditionVariableCompare(uintptr_t cv_key, int priority) {
|
||||
this->condvar_key = cv_key;
|
||||
this->priority = priority;
|
||||
}
|
||||
|
||||
constexpr void SetConditionVariable(ConditionVariableThreadTree *tree, KProcessAddress address, uintptr_t cv_key, u32 value) {
|
||||
this->condvar_tree = tree;
|
||||
this->condvar_key = cv_key;
|
||||
@@ -373,6 +356,11 @@ namespace ams::kern {
|
||||
return this->condvar_tree != nullptr;
|
||||
}
|
||||
|
||||
constexpr void SetupForAddressArbiterCompare(uintptr_t address, int priority) {
|
||||
this->condvar_key = address;
|
||||
this->priority = priority;
|
||||
}
|
||||
|
||||
constexpr void SetAddressArbiter(ConditionVariableThreadTree *tree, uintptr_t address) {
|
||||
this->condvar_tree = tree;
|
||||
this->condvar_key = address;
|
||||
@@ -386,9 +374,7 @@ namespace ams::kern {
|
||||
return this->condvar_tree != nullptr;
|
||||
}
|
||||
|
||||
constexpr s32 GetIdealVirtualCore() const { return this->virtual_ideal_core_id; }
|
||||
constexpr s32 GetIdealPhysicalCore() const { return this->physical_ideal_core_id; }
|
||||
|
||||
constexpr s32 GetIdealCore() const { return this->ideal_core_id; }
|
||||
constexpr s32 GetActiveCore() const { return this->core_id; }
|
||||
constexpr void SetActiveCore(s32 core) { this->core_id = core; }
|
||||
|
||||
|
||||
@@ -28,24 +28,3 @@
|
||||
#else
|
||||
#error "Unknown architecture for CPU"
|
||||
#endif
|
||||
|
||||
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
|
||||
|
||||
#include <mesosphere/board/nintendo/nx/kern_cpu_map.hpp>
|
||||
|
||||
namespace ams::kern::cpu {
|
||||
|
||||
using namespace ams::kern::board::nintendo::nx::impl::cpu;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Unknown board for CPU Map"
|
||||
#endif
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
static_assert(cpu::NumCores <= static_cast<s32>(BITSIZEOF(u64)));
|
||||
static_assert(util::size(cpu::VirtualToPhysicalCoreMap) == BITSIZEOF(u64));
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ams::kern {
|
||||
u32 prev_intr_state;
|
||||
public:
|
||||
ALWAYS_INLINE KScopedInterruptDisable() : prev_intr_state(KInterruptManager::DisableInterrupts()) { /* ... */ }
|
||||
ALWAYS_INLINE ~KScopedInterruptDisable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
~KScopedInterruptDisable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
};
|
||||
|
||||
class KScopedInterruptEnable {
|
||||
@@ -52,7 +52,7 @@ namespace ams::kern {
|
||||
u32 prev_intr_state;
|
||||
public:
|
||||
ALWAYS_INLINE KScopedInterruptEnable() : prev_intr_state(KInterruptManager::EnableInterrupts()) { /* ... */ }
|
||||
ALWAYS_INLINE ~KScopedInterruptEnable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
~KScopedInterruptEnable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ namespace ams::kern::svc {
|
||||
|
||||
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O2")
|
||||
#pragma GCC optimize ("omit-frame-pointer")
|
||||
|
||||
AMS_SVC_FOREACH_KERN_DEFINITION(DECLARE_SVC_STRUCT, _)
|
||||
|
||||
@@ -182,9 +182,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const KMemoryRegion *region = KMemoryLayout::Find(KPhysicalAddress(address));
|
||||
if (AMS_LIKELY(region != nullptr)) {
|
||||
if (AMS_LIKELY(region->IsDerivedFrom(KMemoryRegionType_MemoryController))) {
|
||||
/* Check the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Get the offset within the region. */
|
||||
const size_t offset = address - region->GetAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(offset < region->GetSize());
|
||||
@@ -213,9 +210,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
region->IsDerivedFrom(KMemoryRegionType_MemoryController0) ||
|
||||
region->IsDerivedFrom(KMemoryRegionType_MemoryController1))
|
||||
{
|
||||
/* Check the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Get the offset within the region. */
|
||||
const size_t offset = address - region->GetAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(offset < region->GetSize());
|
||||
@@ -455,8 +449,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Configure the Kernel Carveout region. */
|
||||
{
|
||||
const auto carveout = KMemoryLayout::GetCarveoutRegionExtents();
|
||||
MESOSPHERE_ABORT_UNLESS(carveout.GetEndAddress() != 0);
|
||||
|
||||
smc::ConfigureCarveout(0, carveout.GetAddress(), carveout.GetSize());
|
||||
}
|
||||
|
||||
@@ -553,12 +545,12 @@ namespace ams::kern::board::nintendo::nx {
|
||||
if (arg != nullptr) {
|
||||
/* Get the address of the legacy IRAM region. */
|
||||
const KVirtualAddress iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 64_KB;
|
||||
constexpr size_t RebootPayloadSize = 0x24000;
|
||||
constexpr size_t RebootPayloadSize = 0x2E000;
|
||||
|
||||
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
||||
/* generate a fatal error report using it. */
|
||||
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + 0x2E000);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + RebootPayloadSize);
|
||||
|
||||
/* Clear the fatal context. */
|
||||
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
||||
|
||||
@@ -58,30 +58,28 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
/* Disable interrupts while making the call. */
|
||||
KScopedInterruptDisable intr_disable;
|
||||
|
||||
{
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
}
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
void CallUserSecureMonitorFunction(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||
@@ -100,30 +98,28 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
/* Disable interrupts while making the call. */
|
||||
KScopedInterruptDisable intr_disable;
|
||||
|
||||
{
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
|
||||
__asm__ __volatile__("smc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
__asm__ __volatile__("smc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args->r[0] = x0;
|
||||
args->r[1] = x1;
|
||||
args->r[2] = x2;
|
||||
args->r[3] = x3;
|
||||
args->r[4] = x4;
|
||||
args->r[5] = x5;
|
||||
args->r[6] = x6;
|
||||
args->r[7] = x7;
|
||||
}
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
}
|
||||
|
||||
/* Store arguments to output. */
|
||||
args->r[0] = x0;
|
||||
args->r[1] = x1;
|
||||
args->r[2] = x2;
|
||||
args->r[3] = x3;
|
||||
args->r[4] = x4;
|
||||
args->r[5] = x5;
|
||||
args->r[6] = x6;
|
||||
args->r[7] = x7;
|
||||
}
|
||||
|
||||
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
||||
|
||||
@@ -39,9 +39,7 @@ namespace ams::kern::init {
|
||||
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
|
||||
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
|
||||
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||
HANDLER(KAlpha, (SLAB_COUNT(KAlpha)), ## __VA_ARGS__) \
|
||||
HANDLER(KBeta, (SLAB_COUNT(KBeta)), ## __VA_ARGS__)
|
||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__)
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -70,8 +68,6 @@ namespace ams::kern::init {
|
||||
constexpr size_t SlabCountKObjectName = 7;
|
||||
constexpr size_t SlabCountKResourceLimit = 5;
|
||||
constexpr size_t SlabCountKDebug = cpu::NumCores;
|
||||
constexpr size_t SlabCountKAlpha = 1;
|
||||
constexpr size_t SlabCountKBeta = 6;
|
||||
|
||||
constexpr size_t SlabCountExtraKThread = 160;
|
||||
|
||||
@@ -98,8 +94,6 @@ namespace ams::kern::init {
|
||||
.num_KObjectName = SlabCountKObjectName,
|
||||
.num_KResourceLimit = SlabCountKResourceLimit,
|
||||
.num_KDebug = SlabCountKDebug,
|
||||
.num_KAlpha = SlabCountKAlpha,
|
||||
.num_KBeta = SlabCountKBeta,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -51,22 +51,37 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
bool KDebugLogImpl::Initialize() {
|
||||
/* Get the uart memory region. */
|
||||
const KMemoryRegion *uart_region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_Uart);
|
||||
if (uart_region == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the uart register base address. */
|
||||
g_uart_address = uart_region->GetPairAddress();
|
||||
if (g_uart_address == Null<KVirtualAddress>) {
|
||||
return false;
|
||||
}
|
||||
g_uart_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_Uart);
|
||||
|
||||
/* NOTE: We assume here that UART init/config has been done by the Secure Monitor. */
|
||||
/* As such, we only need to disable interrupts. */
|
||||
/* Parameters for uart. */
|
||||
constexpr u32 BaudRate = 115200;
|
||||
constexpr u32 Pllp = 408000000;
|
||||
constexpr u32 Rate = 16 * BaudRate;
|
||||
constexpr u32 Divisor = (Pllp + Rate / 2) / Rate;
|
||||
|
||||
/* Initialize the UART registers. */
|
||||
/* Set Divisor Latch Access bit, to allow access to DLL/DLH */
|
||||
WriteUartRegister(UartRegister_LCR, 0x80);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Program the divisor into DLL/DLH. */
|
||||
WriteUartRegister(UartRegister_DLL, Divisor & 0xFF);
|
||||
WriteUartRegister(UartRegister_DLH, (Divisor >> 8) & 0xFF);
|
||||
ReadUartRegister(UartRegister_DLH);
|
||||
|
||||
/* Set word length to 3, clear Divisor Latch Access. */
|
||||
WriteUartRegister(UartRegister_LCR, 0x03);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Disable UART interrupts. */
|
||||
WriteUartRegister(UartRegister_IER, 0x00);
|
||||
|
||||
/* Configure the FIFO to be enabled and clear receive. */
|
||||
WriteUartRegister(UartRegister_FCR, 0x03);
|
||||
WriteUartRegister(UartRegister_IRDA_CSR, 0x02);
|
||||
ReadUartRegister(UartRegister_FCR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,7 @@ namespace ams::kern {
|
||||
};
|
||||
|
||||
KVirtualAddress GetInitialProcessBinaryAddress() {
|
||||
const uintptr_t end_address = KMemoryLayout::GetPageTableHeapRegion().GetEndAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(end_address != 0);
|
||||
return end_address - InitialProcessBinarySizeMax;
|
||||
return KMemoryLayout::GetPageTableHeapRegion().GetEndAddress() - InitialProcessBinarySizeMax;
|
||||
}
|
||||
|
||||
void LoadInitialProcessBinaryHeader(InitialProcessBinaryHeader *header) {
|
||||
@@ -99,11 +97,8 @@ namespace ams::kern {
|
||||
/* Ensure that we do not leak pages. */
|
||||
ON_SCOPE_EXIT { pg.Close(); };
|
||||
|
||||
/* Get the temporary region. */
|
||||
const auto &temp_region = KMemoryLayout::GetTempRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(temp_region.GetEndAddress() != 0);
|
||||
|
||||
/* Map the process's memory into the temporary region. */
|
||||
const auto &temp_region = KMemoryLayout::GetTempRegion();
|
||||
KProcessAddress temp_address = Null<KProcessAddress>;
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().MapPageGroup(std::addressof(temp_address), pg, temp_region.GetAddress(), temp_region.GetSize() / PageSize, KMemoryState_Kernel, KMemoryPermission_KernelReadWrite));
|
||||
|
||||
|
||||
@@ -50,8 +50,9 @@ namespace ams::kern {
|
||||
s32 num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
@@ -78,7 +79,10 @@ namespace ams::kern {
|
||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
@@ -99,8 +103,10 @@ namespace ams::kern {
|
||||
s32 num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
/* Determine the updated value. */
|
||||
s32 new_value;
|
||||
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
constinit KThread g_cv_arbiter_compare_thread;
|
||||
|
||||
namespace {
|
||||
|
||||
ALWAYS_INLINE bool ReadFromUser(u32 *out, KProcessAddress address) {
|
||||
@@ -177,8 +179,9 @@ namespace ams::kern {
|
||||
int num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForConditionVariableCompare(cv_key, -1);
|
||||
|
||||
auto it = this->tree.nfind_light({ cv_key, -1 });
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
|
||||
@@ -194,12 +197,6 @@ namespace ams::kern {
|
||||
target_thread->ClearConditionVariable();
|
||||
++num_waiters;
|
||||
}
|
||||
|
||||
/* If we have no waiters, clear the has waiter flag. */
|
||||
if (it == this->tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||
const u32 has_waiter_flag = 0;
|
||||
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
||||
}
|
||||
}
|
||||
|
||||
/* Close threads in the array. */
|
||||
@@ -250,13 +247,6 @@ namespace ams::kern {
|
||||
next_owner_thread->Wakeup();
|
||||
}
|
||||
|
||||
/* Write to the cv key. */
|
||||
{
|
||||
const u32 has_waiter_flag = 1;
|
||||
WriteToUser(key, std::addressof(has_waiter_flag));
|
||||
cpu::DataMemoryBarrier();
|
||||
}
|
||||
|
||||
/* Write the value to userspace. */
|
||||
if (!WriteToUser(addr, std::addressof(next_value))) {
|
||||
slp.CancelSleep();
|
||||
|
||||
@@ -55,7 +55,6 @@ namespace ams::kern {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(start, size, phys_type, attr));
|
||||
const KMemoryRegion *phys = KMemoryLayout::GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(phys_type, attr);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(phys != nullptr);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(phys->GetEndAddress() != 0);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size, virt_type, attr));
|
||||
}
|
||||
|
||||
@@ -105,7 +104,6 @@ namespace ams::kern {
|
||||
void SetupPoolPartitionMemoryRegions() {
|
||||
/* Start by identifying the extents of the DRAM memory region. */
|
||||
const auto dram_extents = KMemoryLayout::GetMainMemoryPhysicalExtents();
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(dram_extents.GetEndAddress() != 0);
|
||||
|
||||
/* Determine the end of the pool region. */
|
||||
const uintptr_t pool_end = dram_extents.GetEndAddress() - KTraceBufferSize;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ams::kern {
|
||||
NON_COPYABLE(KMemoryRegionAllocator);
|
||||
NON_MOVEABLE(KMemoryRegionAllocator);
|
||||
public:
|
||||
static constexpr size_t MaxMemoryRegions = 200;
|
||||
static constexpr size_t MaxMemoryRegions = 1000;
|
||||
private:
|
||||
KMemoryRegion region_heap[MaxMemoryRegions];
|
||||
size_t num_regions;
|
||||
@@ -40,6 +40,8 @@ namespace ams::kern {
|
||||
new (region) KMemoryRegion(std::forward<Args>(args)...);
|
||||
|
||||
return region;
|
||||
|
||||
return &this->region_heap[this->num_regions++];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,8 +55,8 @@ namespace ams::kern {
|
||||
|
||||
}
|
||||
|
||||
void KMemoryRegionTree::InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr, u32 type_id) {
|
||||
this->insert(*AllocateRegion(address, last_address, attr, type_id));
|
||||
void KMemoryRegionTree::InsertDirectly(uintptr_t address, size_t size, u32 attr, u32 type_id) {
|
||||
this->insert(*AllocateRegion(address, size, attr, type_id));
|
||||
}
|
||||
|
||||
bool KMemoryRegionTree::Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) {
|
||||
@@ -80,7 +82,9 @@ namespace ams::kern {
|
||||
|
||||
/* Cache information from the region before we remove it. */
|
||||
const uintptr_t old_address = found->GetAddress();
|
||||
const uintptr_t old_last = found->GetLastAddress();
|
||||
const size_t old_size = found->GetSize();
|
||||
const uintptr_t old_end = old_address + old_size;
|
||||
const uintptr_t old_last = old_end - 1;
|
||||
const uintptr_t old_pair = found->GetPairAddress();
|
||||
const u32 old_type = found->GetType();
|
||||
|
||||
@@ -88,24 +92,24 @@ namespace ams::kern {
|
||||
this->erase(this->iterator_to(*found));
|
||||
|
||||
/* Insert the new region into the tree. */
|
||||
const uintptr_t new_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (address - old_address) : old_pair;
|
||||
if (old_address == address) {
|
||||
/* Reuse the old object for the new region, if we can. */
|
||||
found->Reset(address, inserted_region_last, old_pair, new_attr, type_id);
|
||||
found->Reset(address, size, new_pair, new_attr, type_id);
|
||||
this->insert(*found);
|
||||
} else {
|
||||
/* If we can't re-use, adjust the old region. */
|
||||
found->Reset(old_address, address - 1, old_pair, old_attr, old_type);
|
||||
found->Reset(old_address, address - old_address, old_pair, old_attr, old_type);
|
||||
this->insert(*found);
|
||||
|
||||
/* Insert a new region for the split. */
|
||||
const uintptr_t new_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (address - old_address) : old_pair;
|
||||
this->insert(*AllocateRegion(address, inserted_region_last, new_pair, new_attr, type_id));
|
||||
this->insert(*AllocateRegion(address, size, new_pair, new_attr, type_id));
|
||||
}
|
||||
|
||||
/* If we need to insert a region after the region, do so. */
|
||||
if (old_last != inserted_region_last) {
|
||||
const uintptr_t after_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (inserted_region_end - old_address) : old_pair;
|
||||
this->insert(*AllocateRegion(inserted_region_end, old_last, after_pair, old_attr, old_type));
|
||||
this->insert(*AllocateRegion(inserted_region_end, old_end - inserted_region_end, after_pair, old_attr, old_type));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -121,11 +125,8 @@ namespace ams::kern {
|
||||
const uintptr_t first_address = extents.GetAddress();
|
||||
const uintptr_t last_address = extents.GetLastAddress();
|
||||
|
||||
const uintptr_t first_index = first_address / alignment;
|
||||
const uintptr_t last_index = last_address / alignment;
|
||||
|
||||
while (true) {
|
||||
const uintptr_t candidate = KSystemControl::Init::GenerateRandomRange(first_index, last_index) * alignment;
|
||||
const uintptr_t candidate = util::AlignDown(KSystemControl::Init::GenerateRandomRange(first_address, last_address), alignment);
|
||||
|
||||
/* Ensure that the candidate doesn't overflow with the size. */
|
||||
if (!(candidate < candidate + size)) {
|
||||
@@ -156,13 +157,13 @@ namespace ams::kern {
|
||||
/* Initialize linear trees. */
|
||||
for (auto ®ion : GetPhysicalMemoryRegionTree()) {
|
||||
if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
|
||||
GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType());
|
||||
GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ®ion : GetVirtualMemoryRegionTree()) {
|
||||
if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
|
||||
GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType());
|
||||
GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,12 @@ namespace ams::kern {
|
||||
namespace {
|
||||
|
||||
constexpr KMemoryManager::Pool GetPoolFromMemoryRegionType(u32 type) {
|
||||
if ((type | KMemoryRegionType_VirtualDramApplicationPool) == type) {
|
||||
return KMemoryManager::Pool_Application;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramAppletPool) == type) {
|
||||
return KMemoryManager::Pool_Applet;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramSystemPool) == type) {
|
||||
return KMemoryManager::Pool_System;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramSystemNonSecurePool) == type) {
|
||||
return KMemoryManager::Pool_SystemNonSecure;
|
||||
} else {
|
||||
MESOSPHERE_PANIC("InvalidMemoryRegionType for conversion to Pool");
|
||||
switch (type) {
|
||||
case KMemoryRegionType_VirtualDramApplicationPool: return KMemoryManager::Pool_Application;
|
||||
case KMemoryRegionType_VirtualDramAppletPool: return KMemoryManager::Pool_Applet;
|
||||
case KMemoryRegionType_VirtualDramSystemPool: return KMemoryManager::Pool_System;
|
||||
case KMemoryRegionType_VirtualDramSystemNonSecurePool: return KMemoryManager::Pool_SystemNonSecure;
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +37,9 @@ namespace ams::kern {
|
||||
std::memset(GetVoidPointer(management_region), 0, management_region_size);
|
||||
|
||||
/* Traverse the virtual memory layout tree, initializing each manager as appropriate. */
|
||||
while (this->num_managers != MaxManagerCount) {
|
||||
while (true) {
|
||||
/* Locate the region that should initialize the current manager. */
|
||||
uintptr_t region_address = 0;
|
||||
size_t region_size = 0;
|
||||
Pool region_pool = Pool_Count;
|
||||
const KMemoryRegion *region = nullptr;
|
||||
for (const auto &it : KMemoryLayout::GetVirtualMemoryRegionTree()) {
|
||||
/* We only care about regions that we need to create managers for. */
|
||||
if (!it.IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)) {
|
||||
@@ -57,62 +51,39 @@ namespace ams::kern {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Validate the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(it.GetEndAddress() != 0);
|
||||
MESOSPHERE_ASSERT(it.GetAddress() != Null<decltype(it.GetAddress())>);
|
||||
MESOSPHERE_ASSERT(it.GetSize() > 0);
|
||||
|
||||
/* Update the region's extents. */
|
||||
if (region_address == 0) {
|
||||
region_address = it.GetAddress();
|
||||
region_size = it.GetSize();
|
||||
region_pool = GetPoolFromMemoryRegionType(it.GetType());
|
||||
} else {
|
||||
MESOSPHERE_ASSERT(it.GetAddress() == region_address + region_size);
|
||||
|
||||
/* Update the size. */
|
||||
region_size = it.GetEndAddress() - region_address;
|
||||
MESOSPHERE_ABORT_UNLESS(GetPoolFromMemoryRegionType(it.GetType()) == region_pool);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we didn't find a region, we're done. */
|
||||
if (region_size == 0) {
|
||||
region = std::addressof(it);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't find a region, then we're done initializing managers. */
|
||||
if (region == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure that the region is correct. */
|
||||
MESOSPHERE_ASSERT(region->GetAddress() != Null<decltype(region->GetAddress())>);
|
||||
MESOSPHERE_ASSERT(region->GetSize() > 0);
|
||||
MESOSPHERE_ASSERT(region->GetEndAddress() >= region->GetAddress());
|
||||
MESOSPHERE_ASSERT(region->IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool));
|
||||
MESOSPHERE_ASSERT(region->GetAttributes() == this->num_managers);
|
||||
|
||||
/* Initialize a new manager for the region. */
|
||||
const Pool pool = GetPoolFromMemoryRegionType(region->GetType());
|
||||
Impl *manager = std::addressof(this->managers[this->num_managers++]);
|
||||
MESOSPHERE_ABORT_UNLESS(this->num_managers <= util::size(this->managers));
|
||||
|
||||
const size_t cur_size = manager->Initialize(region_address, region_size, management_region, management_region_end, region_pool);
|
||||
const size_t cur_size = manager->Initialize(region, pool, management_region, management_region_end);
|
||||
management_region += cur_size;
|
||||
MESOSPHERE_ABORT_UNLESS(management_region <= management_region_end);
|
||||
|
||||
/* Insert the manager into the pool list. */
|
||||
if (this->pool_managers_tail[region_pool] == nullptr) {
|
||||
this->pool_managers_head[region_pool] = manager;
|
||||
if (this->pool_managers_tail[pool] == nullptr) {
|
||||
this->pool_managers_head[pool] = manager;
|
||||
} else {
|
||||
this->pool_managers_tail[region_pool]->SetNext(manager);
|
||||
manager->SetPrev(this->pool_managers_tail[region_pool]);
|
||||
this->pool_managers_tail[pool]->SetNext(manager);
|
||||
manager->SetPrev(this->pool_managers_tail[pool]);
|
||||
}
|
||||
this->pool_managers_tail[region_pool] = manager;
|
||||
}
|
||||
|
||||
/* Free each region to its corresponding heap. */
|
||||
for (const auto &it : KMemoryLayout::GetVirtualMemoryRegionTree()) {
|
||||
if (it.IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)) {
|
||||
/* Check the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(it.GetEndAddress() != 0);
|
||||
|
||||
/* Free the memory to the heap. */
|
||||
this->managers[it.GetAttributes()].Free(it.GetAddress(), it.GetSize() / PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the used size for all managers. */
|
||||
for (size_t i = 0; i < this->num_managers; ++i) {
|
||||
this->managers[i].UpdateUsedHeapSize();
|
||||
this->pool_managers_tail[pool] = manager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,12 +354,12 @@ namespace ams::kern {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
size_t KMemoryManager::Impl::Initialize(uintptr_t address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p) {
|
||||
size_t KMemoryManager::Impl::Initialize(const KMemoryRegion *region, Pool p, KVirtualAddress management, KVirtualAddress management_end) {
|
||||
/* Calculate management sizes. */
|
||||
const size_t ref_count_size = (size / PageSize) * sizeof(u16);
|
||||
const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(size);
|
||||
const size_t ref_count_size = (region->GetSize() / PageSize) * sizeof(u16);
|
||||
const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(region->GetSize());
|
||||
const size_t manager_size = util::AlignUp(optimize_map_size + ref_count_size, PageSize);
|
||||
const size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(size);
|
||||
const size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(region->GetSize());
|
||||
const size_t total_management_size = manager_size + page_heap_size;
|
||||
MESOSPHERE_ABORT_UNLESS(manager_size <= total_management_size);
|
||||
MESOSPHERE_ABORT_UNLESS(management + total_management_size <= management_end);
|
||||
@@ -401,7 +372,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(this->management_region), PageSize));
|
||||
|
||||
/* Initialize the manager's KPageHeap. */
|
||||
this->heap.Initialize(address, size, management + manager_size, page_heap_size);
|
||||
this->heap.Initialize(region->GetAddress(), region->GetSize(), management + manager_size, page_heap_size);
|
||||
|
||||
/* Free the memory to the heap. */
|
||||
this->heap.Free(region->GetAddress(), region->GetSize() / PageSize);
|
||||
|
||||
/* Update the heap's used size. */
|
||||
this->heap.UpdateUsedSize();
|
||||
|
||||
return total_management_size;
|
||||
}
|
||||
|
||||
@@ -908,7 +908,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Check if we're done. */
|
||||
if (dst_address + size - 1 <= info.GetLastAddress()) {
|
||||
if (dst_address + size - 1 > info.GetLastAddress()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1807,9 +1807,6 @@ namespace ams::kern {
|
||||
const KMemoryRegion *region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(region_type);
|
||||
R_UNLESS(region != nullptr, svc::ResultOutOfRange());
|
||||
|
||||
/* Check that the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Map the region. */
|
||||
R_TRY_CATCH(this->MapStatic(region->GetAddress(), region->GetSize(), perm)) {
|
||||
R_CONVERT(svc::ResultInvalidAddress, svc::ResultOutOfRange())
|
||||
@@ -3054,9 +3051,6 @@ namespace ams::kern {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
Result KPageTableBase::SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state) {
|
||||
/* Validate pre-conditions. */
|
||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||
@@ -3710,8 +3704,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
|
||||
/* Lock the physical memory lock. */
|
||||
KScopedLightLock phys_lk(this->map_physical_memory_lock);
|
||||
|
||||
@@ -129,17 +129,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
/* Close all references to our betas. */
|
||||
{
|
||||
auto it = this->beta_list.begin();
|
||||
while (it != this->beta_list.end()) {
|
||||
KBeta *beta = std::addressof(*it);
|
||||
it = this->beta_list.erase(it);
|
||||
|
||||
beta->Close();
|
||||
}
|
||||
}
|
||||
|
||||
/* Our thread local page list must be empty at this point. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->partially_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(this->fully_used_tlp_tree.empty());
|
||||
@@ -933,7 +922,7 @@ namespace ams::kern {
|
||||
mem_reservation.Commit();
|
||||
|
||||
/* Note for debug that we're running a new process. */
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetVirtualAffinityMask(), main_thread->GetIdealVirtualCore(), main_thread->GetActiveCore());
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetAffinityMask().GetAffinityMask(), main_thread->GetIdealCore(), main_thread->GetActiveCore());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
namespace ipc {
|
||||
|
||||
using MessageBuffer = ams::svc::ipc::MessageBuffer;
|
||||
@@ -1365,6 +1362,4 @@ namespace ams::kern {
|
||||
this->NotifyAvailable(svc::ResultSessionClosed());
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -38,17 +38,13 @@ namespace ams::kern {
|
||||
|
||||
}
|
||||
|
||||
Result KThread::Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type) {
|
||||
Result KThread::Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type) {
|
||||
/* Assert parameters are valid. */
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(kern_stack_top != nullptr);
|
||||
MESOSPHERE_ASSERT((type == ThreadType_Main) || (ams::svc::HighestThreadPriority <= prio && prio <= ams::svc::LowestThreadPriority));
|
||||
MESOSPHERE_ASSERT((owner != nullptr) || (type != ThreadType_User));
|
||||
MESOSPHERE_ASSERT(0 <= virt_core && virt_core < static_cast<s32>(BITSIZEOF(u64)));
|
||||
|
||||
/* Convert the virtual core to a physical core. */
|
||||
const s32 phys_core = cpu::VirtualToPhysicalCoreMap[virt_core];
|
||||
MESOSPHERE_ASSERT(0 <= phys_core && phys_core < static_cast<s32>(cpu::NumCores));
|
||||
MESOSPHERE_ASSERT(0 <= core && core < static_cast<s32>(cpu::NumCores));
|
||||
|
||||
/* First, clear the TLS address. */
|
||||
this->tls_address = Null<KProcessAddress>;
|
||||
@@ -63,8 +59,8 @@ namespace ams::kern {
|
||||
}
|
||||
[[fallthrough]];
|
||||
case ThreadType_HighPriority:
|
||||
if (type != ThreadType_Main) {
|
||||
MESOSPHERE_ASSERT(phys_core == GetCurrentCoreId());
|
||||
{
|
||||
MESOSPHERE_ASSERT(core == GetCurrentCoreId());
|
||||
}
|
||||
[[fallthrough]];
|
||||
case ThreadType_Kernel:
|
||||
@@ -75,8 +71,8 @@ namespace ams::kern {
|
||||
[[fallthrough]];
|
||||
case ThreadType_User:
|
||||
{
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ul << virt_core)) == owner->GetCoreMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetPriorityMask() | (1ul << prio)) == owner->GetPriorityMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ul << core)) == owner->GetCoreMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetPriorityMask() | (1ul << prio)) == owner->GetPriorityMask()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -85,10 +81,8 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the ideal core ID and affinity mask. */
|
||||
this->virtual_ideal_core_id = virt_core;
|
||||
this->physical_ideal_core_id = phys_core;
|
||||
this->virtual_affinity_mask = (static_cast<u64>(1) << virt_core);
|
||||
this->physical_affinity_mask.SetAffinity(phys_core, true);
|
||||
this->ideal_core_id = core;
|
||||
this->affinity_mask.SetAffinity(core, true);
|
||||
|
||||
/* Set the thread state. */
|
||||
this->thread_state = (type == ThreadType_Main) ? ThreadState_Runnable : ThreadState_Initialized;
|
||||
@@ -109,7 +103,7 @@ namespace ams::kern {
|
||||
this->cancellable = false;
|
||||
|
||||
/* Set core ID and wait result. */
|
||||
this->core_id = phys_core;
|
||||
this->core_id = this->ideal_core_id;
|
||||
this->wait_result = svc::ResultNoSynchronizationObject();
|
||||
|
||||
/* Set the stack top. */
|
||||
@@ -147,7 +141,7 @@ namespace ams::kern {
|
||||
this->num_kernel_waiters = 0;
|
||||
|
||||
/* Set our current core id. */
|
||||
this->current_core_id = phys_core;
|
||||
this->current_core_id = core;
|
||||
|
||||
/* We haven't released our resource limit hint, and we've spent no time on the cpu. */
|
||||
this->resource_limit_release_hint = 0;
|
||||
@@ -207,7 +201,6 @@ namespace ams::kern {
|
||||
Result KThread::InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type) {
|
||||
/* Get stack region for the thread. */
|
||||
const auto &stack_region = KMemoryLayout::GetKernelStackRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(stack_region.GetEndAddress() != 0);
|
||||
|
||||
/* Allocate a page to use as the thread. */
|
||||
KPageBuffer *page = KPageBuffer::Allocate();
|
||||
@@ -397,19 +390,20 @@ namespace ams::kern {
|
||||
++this->num_core_migration_disables;
|
||||
|
||||
/* Save our ideal state to restore when we're unpinned. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
this->original_ideal_core_id = this->ideal_core_id;
|
||||
this->original_affinity_mask = this->affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
const s32 current_core = GetCurrentCoreId();
|
||||
|
||||
this->SetActiveCore(current_core);
|
||||
this->physical_ideal_core_id = current_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
this->ideal_core_id = current_core;
|
||||
|
||||
if (active_core != current_core || this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
this->affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
|
||||
if (active_core != current_core || this->affinity_mask.GetAffinityMask() != this->original_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,19 +438,19 @@ namespace ams::kern {
|
||||
--this->num_core_migration_disables;
|
||||
|
||||
/* Restore our original state. */
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
this->ideal_core_id = this->original_ideal_core_id;
|
||||
this->affinity_mask = this->original_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -498,16 +492,16 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
if ((this->num_core_migration_disables++) == 0) {
|
||||
/* Save our ideal state to restore when we can migrate again. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
this->original_ideal_core_id = this->ideal_core_id;
|
||||
this->original_affinity_mask = this->affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
this->physical_ideal_core_id = active_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
this->ideal_core_id = active_core;
|
||||
this->affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
if (this->affinity_mask.GetAffinityMask() != this->original_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -519,20 +513,20 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables > 0);
|
||||
if ((--this->num_core_migration_disables) == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
/* Restore our ideals. */
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
this->ideal_core_id = this->original_ideal_core_id;
|
||||
this->affinity_mask = this->original_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -541,19 +535,6 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
Result KThread::GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Get the virtual mask. */
|
||||
*out_ideal_core = this->virtual_ideal_core_id;
|
||||
*out_affinity_mask = this->virtual_affinity_mask;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KThread::GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
@@ -561,72 +542,63 @@ namespace ams::kern {
|
||||
|
||||
/* Select between core mask and original core mask. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
*out_ideal_core = this->physical_ideal_core_id;
|
||||
*out_affinity_mask = this->physical_affinity_mask.GetAffinityMask();
|
||||
*out_ideal_core = this->ideal_core_id;
|
||||
*out_affinity_mask = this->affinity_mask.GetAffinityMask();
|
||||
} else {
|
||||
*out_ideal_core = this->original_physical_ideal_core_id;
|
||||
*out_affinity_mask = this->original_physical_affinity_mask.GetAffinityMask();
|
||||
*out_ideal_core = this->original_ideal_core_id;
|
||||
*out_affinity_mask = this->original_affinity_mask.GetAffinityMask();
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KThread::SetCoreMask(int32_t core_id, u64 v_affinity_mask) {
|
||||
Result KThread::SetCoreMask(int32_t ideal_core, u64 affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->parent != nullptr);
|
||||
MESOSPHERE_ASSERT(v_affinity_mask != 0);
|
||||
MESOSPHERE_ASSERT(affinity_mask != 0);
|
||||
KScopedLightLock lk(this->activity_pause_lock);
|
||||
|
||||
/* Set the core mask. */
|
||||
u64 p_affinity_mask = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
|
||||
/* If the core id is no-update magic, preserve the ideal core id. */
|
||||
if (core_id == ams::svc::IdealCoreNoUpdate) {
|
||||
core_id = this->virtual_ideal_core_id;
|
||||
R_UNLESS(((1ul << core_id) & v_affinity_mask) != 0, svc::ResultInvalidCombination());
|
||||
}
|
||||
if (ideal_core == ams::svc::IdealCoreNoUpdate) {
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
ideal_core = this->ideal_core_id;
|
||||
} else {
|
||||
ideal_core = this->original_ideal_core_id;
|
||||
}
|
||||
|
||||
/* Set the virtual core/affinity mask. */
|
||||
this->virtual_ideal_core_id = core_id;
|
||||
this->virtual_affinity_mask = v_affinity_mask;
|
||||
|
||||
/* Translate the virtual core to a physical core. */
|
||||
if (core_id >= 0) {
|
||||
core_id = cpu::VirtualToPhysicalCoreMap[core_id];
|
||||
}
|
||||
|
||||
/* Translate the virtual affinity mask to a physical one. */
|
||||
while (v_affinity_mask != 0) {
|
||||
const u64 next = __builtin_ctzll(v_affinity_mask);
|
||||
v_affinity_mask &= ~(1ul << next);
|
||||
p_affinity_mask |= (1ul << cpu::VirtualToPhysicalCoreMap[next]);
|
||||
R_UNLESS(((1ul << ideal_core) & affinity_mask) != 0, svc::ResultInvalidCombination());
|
||||
}
|
||||
|
||||
/* If we haven't disabled migration, perform an affinity change. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
/* Set our new ideals. */
|
||||
this->physical_ideal_core_id = core_id;
|
||||
this->physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
this->ideal_core_id = ideal_core;
|
||||
this->affinity_mask.SetAffinityMask(affinity_mask);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (active_core >= 0 && !this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
const s32 new_core = this->physical_ideal_core_id >= 0 ? this->physical_ideal_core_id : BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask());
|
||||
this->SetActiveCore(new_core);
|
||||
if (active_core >= 0) {
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
}
|
||||
} else {
|
||||
/* Otherwise, we edit the original affinity for restoration later. */
|
||||
this->original_physical_ideal_core_id = core_id;
|
||||
this->original_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
this->original_ideal_core_id = ideal_core;
|
||||
this->original_affinity_mask.SetAffinityMask(affinity_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,7 +627,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If the thread is currently running, check whether it's no longer allowed under the new mask. */
|
||||
if (thread_is_current && ((1ul << thread_core) & p_affinity_mask) == 0) {
|
||||
if (thread_is_current && ((1ul << thread_core) & affinity_mask) == 0) {
|
||||
/* If the thread is pinned, we want to wait until it's not pinned. */
|
||||
if (this->GetStackParameters().is_pinned) {
|
||||
/* Verify that the current thread isn't terminating. */
|
||||
@@ -1155,7 +1127,7 @@ namespace ams::kern {
|
||||
|
||||
/* If the thread is runnable, send a termination interrupt to other cores. */
|
||||
if (this->GetState() == ThreadState_Runnable) {
|
||||
if (const u64 core_mask = this->physical_affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
if (const u64 core_mask = this->affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_ThreadTerminate, core_mask);
|
||||
}
|
||||
|
||||
@@ -52,8 +52,6 @@ namespace ams::kern {
|
||||
/* Initialize the memory manager and the KPageBuffer slabheap. */
|
||||
{
|
||||
const auto &management_region = KMemoryLayout::GetPoolManagementRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(management_region.GetEndAddress() != 0);
|
||||
|
||||
Kernel::GetMemoryManager().Initialize(management_region.GetAddress(), management_region.GetSize());
|
||||
init::InitializeKPageBufferSlabHeap();
|
||||
}
|
||||
@@ -70,8 +68,6 @@ namespace ams::kern {
|
||||
/* Initialize the Dynamic Slab Heaps. */
|
||||
{
|
||||
const auto &pt_heap_region = KMemoryLayout::GetPageTableHeapRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(pt_heap_region.GetEndAddress() != 0);
|
||||
|
||||
Kernel::InitializeResourceManagers(pt_heap_region.GetAddress(), pt_heap_region.GetSize());
|
||||
}
|
||||
}
|
||||
@@ -128,13 +124,6 @@ namespace ams::kern {
|
||||
|
||||
/* Resume all threads suspended while we initialized. */
|
||||
KThread::ResumeThreadsSuspendedForInit();
|
||||
|
||||
/* Validate that all reserved dram blocks are valid. */
|
||||
for (const auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
|
||||
if (region.IsDerivedFrom(KMemoryRegionType_DramReservedBase)) {
|
||||
MESOSPHERE_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
|
||||
@@ -92,9 +92,6 @@ namespace ams::kern::svc {
|
||||
/* Ensure that we found the region. */
|
||||
R_UNLESS(region != nullptr, svc::ResultNotFound());
|
||||
|
||||
/* Chcek that the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
R_TRY(pt.QueryStaticMapping(std::addressof(found_address), region->GetAddress(), region->GetSize()));
|
||||
found_size = region->GetSize();
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
/* ============================= Common ============================= */
|
||||
|
||||
namespace {
|
||||
|
||||
Result Unknown39() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown3A() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown46() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown47() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ============================= 64 ABI ============================= */
|
||||
|
||||
Result Unknown3964() {
|
||||
return Unknown39();
|
||||
}
|
||||
|
||||
Result Unknown3A64() {
|
||||
/* NOTE: From official stubs, true API to this is something like Unknown3A(u64 *, u32_or_u64, u64, u64, u64_or_u32, u64_or_u32); */
|
||||
return Unknown3A();
|
||||
}
|
||||
|
||||
Result Unknown4664() {
|
||||
return Unknown46();
|
||||
}
|
||||
|
||||
Result Unknown4764() {
|
||||
return Unknown47();
|
||||
}
|
||||
|
||||
/* ============================= 64From32 ABI ============================= */
|
||||
|
||||
Result Unknown3964From32() {
|
||||
return Unknown39();
|
||||
}
|
||||
|
||||
Result Unknown3A64From32() {
|
||||
return Unknown3A();
|
||||
}
|
||||
|
||||
Result Unknown4664From32() {
|
||||
return Unknown46();
|
||||
}
|
||||
|
||||
Result Unknown4764From32() {
|
||||
return Unknown47();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -363,11 +363,7 @@ namespace ams::kern::svc {
|
||||
case ams::svc::DebugThreadParam_IdealCore:
|
||||
{
|
||||
/* Get the ideal core. */
|
||||
s32 core_id;
|
||||
u64 affinity_mask;
|
||||
thread->GetPhysicalCoreMask(std::addressof(core_id), std::addressof(affinity_mask));
|
||||
|
||||
*out_32 = core_id;
|
||||
*out_32 = thread->GetIdealCore();
|
||||
}
|
||||
break;
|
||||
case ams::svc::DebugThreadParam_CurrentCore:
|
||||
@@ -379,11 +375,7 @@ namespace ams::kern::svc {
|
||||
case ams::svc::DebugThreadParam_AffinityMask:
|
||||
{
|
||||
/* Get the affinity mask. */
|
||||
s32 core_id;
|
||||
u64 affinity_mask;
|
||||
thread->GetPhysicalCoreMask(std::addressof(core_id), std::addressof(affinity_mask));
|
||||
|
||||
*out_32 = affinity_mask;
|
||||
*out_32 = thread->GetAffinityMask().GetAffinityMask();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -206,35 +206,28 @@ namespace ams::kern::svc {
|
||||
case ams::svc::InfoType_ThreadTickCount:
|
||||
{
|
||||
/* Verify the requested core is valid. */
|
||||
const bool core_valid = (info_subtype == static_cast<u64>(-1ul)) || (info_subtype < util::size(cpu::VirtualToPhysicalCoreMap));
|
||||
const bool core_valid = (info_subtype == static_cast<u64>(-1ul)) || (info_subtype < cpu::NumCores);
|
||||
R_UNLESS(core_valid, svc::ResultInvalidCombination());
|
||||
|
||||
/* Get the thread from its handle. */
|
||||
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(handle);
|
||||
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Disable interrupts while we get the tick count. */
|
||||
/* Get the tick count. */
|
||||
s64 tick_count;
|
||||
{
|
||||
KScopedInterruptDisable di;
|
||||
|
||||
if (info_subtype == static_cast<u64>(-1ul)) {
|
||||
tick_count = thread->GetCpuTime();
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
} else {
|
||||
const s32 phys_core = cpu::VirtualToPhysicalCoreMap[info_subtype];
|
||||
MESOSPHERE_ABORT_UNLESS(phys_core < static_cast<s32>(cpu::NumCores));
|
||||
|
||||
tick_count = thread->GetCpuTime(phys_core);
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe() && phys_core == GetCurrentCoreId()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
if (info_subtype == static_cast<u64>(-1ul)) {
|
||||
tick_count = thread->GetCpuTime();
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
} else {
|
||||
tick_count = thread->GetCpuTime(static_cast<s32>(info_subtype));
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe() && static_cast<s32>(info_subtype) == GetCurrentCoreId()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
/* ============================= Common ============================= */
|
||||
|
||||
namespace {
|
||||
@@ -307,6 +304,4 @@ namespace ams::kern::svc {
|
||||
return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -22,31 +22,7 @@ namespace ams::kern::svc {
|
||||
namespace {
|
||||
|
||||
int32_t GetCurrentProcessorNumber() {
|
||||
/* Setup variables to track affinity information. */
|
||||
s32 current_phys_core;
|
||||
u64 v_affinity_mask = 0;
|
||||
|
||||
/* Forever try to get the affinity. */
|
||||
while (true) {
|
||||
/* Update affinity information if we've run out. */
|
||||
while (v_affinity_mask == 0) {
|
||||
current_phys_core = GetCurrentCoreId();
|
||||
v_affinity_mask = GetCurrentThread().GetVirtualAffinityMask();
|
||||
if ((v_affinity_mask & (1ul << current_phys_core)) != 0) {
|
||||
return current_phys_core;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the next virtual bit. */
|
||||
do {
|
||||
const s32 next_virt_core = static_cast<s32>(__builtin_ctzll(v_affinity_mask));
|
||||
if (current_phys_core == cpu::VirtualToPhysicalCoreMap[next_virt_core]) {
|
||||
return next_virt_core;
|
||||
}
|
||||
|
||||
v_affinity_mask &= ~(1ul << next_virt_core);
|
||||
} while (v_affinity_mask != 0);
|
||||
}
|
||||
return GetCurrentCoreId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ams::kern::svc {
|
||||
R_UNLESS(resource_limit.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Get the peak value. */
|
||||
*out_peak_value = resource_limit->GetPeakValue(which);
|
||||
*out_peak_value = resource_limit->GetCurrentValue(which);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@
|
||||
HANDLER(UsbStateInfo, 123) \
|
||||
HANDLER(NvHostErrInfo, 124) \
|
||||
HANDLER(RunningUlaInfo, 125) \
|
||||
HANDLER(InternalPanelInfo, 126) \
|
||||
HANDLER(ResourceLimitLimitInfo, 127) \
|
||||
HANDLER(ResourceLimitPeakInfo, 128) \
|
||||
HANDLER(TouchScreenInfo, 129) \
|
||||
HANDLER(Category_Unknown126, 126) \
|
||||
HANDLER(Category_Unknown127, 127) \
|
||||
HANDLER(Category_Unknown128, 128) \
|
||||
HANDLER(Category_Unknown129, 129) \
|
||||
|
||||
#define AMS_ERPT_FOREACH_FIELD(HANDLER) \
|
||||
HANDLER(TestU64, 0, Test, FieldType_NumericU64, FieldFlag_None ) \
|
||||
@@ -782,22 +782,22 @@
|
||||
HANDLER(NANDTotalSizeOfSystem, 609, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(NANDFreeSpaceOfSystem, 610, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(AccessPointSSIDAsHex, 611, AccessPointInfo, FieldType_String, FieldFlag_None ) \
|
||||
HANDLER(PanelVendorId, 612, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelRevisionId, 613, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelModelId, 614, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelVendorId, 612, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelRevisionId, 613, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelModelId, 614, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(ErrorContext, 615, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \
|
||||
HANDLER(ErrorContextSize, 616, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(ErrorContextTotalSize, 617, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryLimit, 618, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountLimit, 619, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountLimit, 620, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountLimit, 621, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountLimit, 622, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryPeak, 623, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountPeak, 624, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountPeak, 625, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountPeak, 626, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountPeak, 627, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryLimit, 618, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountLimit, 619, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountLimit, 620, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountLimit, 621, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountLimit, 622, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryPeak, 623, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountPeak, 624, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountPeak, 625, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountPeak, 626, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountPeak, 627, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(GpuCrashHash, 628, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||
HANDLER(TouchScreenPanelGpioValue, 629, TouchScreenInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(TouchScreenPanelGpioValue, 629, Category_Unknown129, FieldType_NumericU8, FieldFlag_None ) \
|
||||
|
||||
|
||||
@@ -25,17 +25,17 @@ namespace ams::erpt::sf {
|
||||
#define AMS_ERPT_I_CONTEXT_INTERFACE_INFO(C, H) \
|
||||
AMS_SF_METHOD_INFO(C, H, 0, Result, SubmitContext, (const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 1, Result, CreateReportV0, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer)) \
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInitialLaunchSettingsCompletionTime, (const time::SteadyClockTimePoint &time_point), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, ClearInitialLaunchSettingsCompletionTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, UpdatePowerOnTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, UpdateAwakeTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, SubmitMultipleCategoryContext, (const MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer), hos::Version_5_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, Result, UpdateApplicationLaunchTime, (), hos::Version_6_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, ClearApplicationLaunchTime, (), hos::Version_6_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachment, (ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), hos::Version_8_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer), hos::Version_8_0_0, hos::Version_10_2_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachments, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, Result result), hos::Version_11_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 11, Result, CreateReport, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, Result result), hos::Version_11_0_0)
|
||||
AMS_SF_METHOD_INFO(C, H, 2, Result, SetInitialLaunchSettingsCompletionTime, (const time::SteadyClockTimePoint &time_point), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 3, Result, ClearInitialLaunchSettingsCompletionTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 4, Result, UpdatePowerOnTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 5, Result, UpdateAwakeTime, (), hos::Version_3_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 6, Result, SubmitMultipleCategoryContext, (const MultipleCategoryContextEntry &ctx_entry, const ams::sf::InBuffer &str_buffer), hos::Version_5_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 7, Result, UpdateApplicationLaunchTime, (), hos::Version_6_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 8, Result, ClearApplicationLaunchTime, (), hos::Version_6_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 9, Result, SubmitAttachment, (ams::sf::Out<AttachmentId> out, const ams::sf::InBuffer &attachment_name, const ams::sf::InBuffer &attachment_data), hos::Version_8_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachmentsDeprecated, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer), hos::Version_8_0_0, hos::Version_10_2_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 10, Result, CreateReportWithAttachments, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &attachment_ids_buffer, u32 context), hos::Version_11_0_0) \
|
||||
AMS_SF_METHOD_INFO(C, H, 11, Result, CreateReport, (ReportType report_type, const ams::sf::InBuffer &ctx_buffer, const ams::sf::InBuffer &str_buffer, const ams::sf::InBuffer &meta_buffer, u32 context), hos::Version_11_0_0)
|
||||
|
||||
|
||||
AMS_SF_DEFINE_INTERFACE(IContext, AMS_ERPT_I_CONTEXT_INTERFACE_INFO)
|
||||
|
||||
@@ -42,52 +42,4 @@ namespace ams::err {
|
||||
static_assert(sizeof(ErrorContext) == 0x200);
|
||||
static_assert(util::is_pod<ErrorContext>::value);
|
||||
|
||||
struct ContextDescriptor {
|
||||
int value;
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator==(const ContextDescriptor &rhs) const { return this->value == rhs.value; }
|
||||
constexpr ALWAYS_INLINE bool operator!=(const ContextDescriptor &rhs) const { return this->value != rhs.value; }
|
||||
constexpr ALWAYS_INLINE bool operator< (const ContextDescriptor &rhs) const { return this->value < rhs.value; }
|
||||
constexpr ALWAYS_INLINE bool operator<=(const ContextDescriptor &rhs) const { return this->value <= rhs.value; }
|
||||
constexpr ALWAYS_INLINE bool operator> (const ContextDescriptor &rhs) const { return this->value > rhs.value; }
|
||||
constexpr ALWAYS_INLINE bool operator>=(const ContextDescriptor &rhs) const { return this->value >= rhs.value; }
|
||||
};
|
||||
|
||||
constexpr inline const ContextDescriptor InvalidContextDescriptor{ -1 };
|
||||
|
||||
namespace impl {
|
||||
|
||||
constexpr inline const ContextDescriptor ContextDescriptorMin{ 0x001 };
|
||||
constexpr inline const ContextDescriptor ContextDescriptorMax{ 0x1FF };
|
||||
|
||||
}
|
||||
|
||||
constexpr Result MakeResultWithContextDescriptor(Result result, ContextDescriptor descriptor) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(R_FAILED(result));
|
||||
AMS_ASSERT(descriptor != InvalidContextDescriptor);
|
||||
AMS_ASSERT(impl::ContextDescriptorMin <= descriptor && descriptor <= impl::ContextDescriptorMax);
|
||||
|
||||
return result::impl::ResultInternalAccessor::MergeReserved(result, descriptor.value | 0x200);
|
||||
}
|
||||
|
||||
constexpr ContextDescriptor GetContextDescriptorFromResult(Result result) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(R_FAILED(result));
|
||||
|
||||
/* Get reserved bits. */
|
||||
const auto reserved = result::impl::ResultInternalAccessor::GetReserved(result);
|
||||
if ((reserved & 0x200) != 0x200) {
|
||||
return InvalidContextDescriptor;
|
||||
}
|
||||
|
||||
/* Check the descriptor value. */
|
||||
const ContextDescriptor descriptor{static_cast<decltype(ContextDescriptor{}.value)>(reserved & ~0x200)};
|
||||
if (!(impl::ContextDescriptorMin <= descriptor && descriptor <= impl::ContextDescriptorMax)) {
|
||||
return InvalidContextDescriptor;
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user