Compare commits
94 Commits
hid_refact
...
0.16.0-p2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7336dc2b7a | ||
|
|
d2f48d5e36 | ||
|
|
422e9434d8 | ||
|
|
2b93bbd9ee | ||
|
|
021b29d2db | ||
|
|
6da28f4a27 | ||
|
|
bba99d49da | ||
|
|
e760a9d4b0 | ||
|
|
ee91f3fde0 | ||
|
|
f72475872a | ||
|
|
199a9aec8b | ||
|
|
1b83f5169a | ||
|
|
7bb77f44af | ||
|
|
801ce24622 | ||
|
|
1d778b2dc8 | ||
|
|
7c9608021d | ||
|
|
b8fbd0baff | ||
|
|
525da05629 | ||
|
|
2e9db4d113 | ||
|
|
4f1a4e7499 | ||
|
|
972283032a | ||
|
|
57f935391d | ||
|
|
4804e1e1e0 | ||
|
|
4ae74b9b4e | ||
|
|
726d7b6e4d | ||
|
|
390bdc7b6b | ||
|
|
2d8acf9c64 | ||
|
|
9743f63f0d | ||
|
|
ccd2798ae2 | ||
|
|
f3dbab4876 | ||
|
|
41a53075e5 | ||
|
|
ab8de72db0 | ||
|
|
331fa1d00d | ||
|
|
fd745ab2d3 | ||
|
|
972b396f61 | ||
|
|
3c8e7de915 | ||
|
|
1b164613a6 | ||
|
|
3d4ab95ab2 | ||
|
|
152def19c0 | ||
|
|
63974d9bce | ||
|
|
2b483866c7 | ||
|
|
7e1da15f6e | ||
|
|
0a1465f198 | ||
|
|
748893fe77 | ||
|
|
1ca64cf2a1 | ||
|
|
aac8af8bf5 | ||
|
|
5da6b60008 | ||
|
|
e400e2afc7 | ||
|
|
56c6e4244a | ||
|
|
c8ebd7eea0 | ||
|
|
550f5690bf | ||
|
|
28f9b534b6 | ||
|
|
3fd59b61bc | ||
|
|
f86059de70 | ||
|
|
a03ee7b148 | ||
|
|
8b2ed36698 | ||
|
|
1852fe8612 | ||
|
|
b60054dba1 | ||
|
|
c7f37f81ee | ||
|
|
19a279ce45 | ||
|
|
783f1077be | ||
|
|
b0debd72a7 | ||
|
|
24d545701c | ||
|
|
aae565629e | ||
|
|
bee629b8ad | ||
|
|
5cb237d030 | ||
|
|
a4e09fc6c4 | ||
|
|
73d9d5ff47 | ||
|
|
08cfee54fa | ||
|
|
7b279ab863 | ||
|
|
6a85f7225d | ||
|
|
f469dfbeb3 | ||
|
|
cc11d452e5 | ||
|
|
3bce008170 | ||
|
|
3383509da6 | ||
|
|
281dcf232a | ||
|
|
71a2fe1bb6 | ||
|
|
4a216dc928 | ||
|
|
18099e19b1 | ||
|
|
a0a45853dd | ||
|
|
fe9a4cd2fc | ||
|
|
88a66c89e2 | ||
|
|
93128b6b17 | ||
|
|
db2de8ef31 | ||
|
|
05832cec73 | ||
|
|
632c8984c8 | ||
|
|
694e3b579e | ||
|
|
20eba0dc98 | ||
|
|
730ef6d6db | ||
|
|
7cb24713ab | ||
|
|
a685842804 | ||
|
|
ad6dd60474 | ||
|
|
05af215191 | ||
|
|
e06b73aafa |
7
Makefile
7
Makefile
@@ -141,15 +141,16 @@ dist: dist-no-debug
|
|||||||
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
|
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
|
||||||
cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.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/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/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/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/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf
|
||||||
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
||||||
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
||||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.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
|
cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf
|
||||||
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||||
rm -r atmosphere-$(AMSVER)-debug
|
rm -r atmosphere-$(AMSVER)-debug
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,38 @@
|
|||||||
# Changelog
|
# 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
|
## 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.
|
+ 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.
|
+ 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]
|
[subrepo]
|
||||||
remote = https://github.com/m4xw/emuMMC
|
remote = https://github.com/m4xw/emuMMC
|
||||||
branch = develop
|
branch = develop
|
||||||
commit = 25075973d31a5be6f2e769f1ea0fff44daf0cdfa
|
commit = 5eed18eb527bbaa63aee5323c26de5b0cca6d28e
|
||||||
parent = 8ba513fefbcfd8278a433090e59017963ba9887f
|
parent = 021b29d2dbc8ed0469bc822393e58c9f0d174d57
|
||||||
method = rebase
|
method = rebase
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
|
||||||
|
|
||||||
### Supported Horizon Versions
|
### Supported Horizon Versions
|
||||||
**1.0.0 - 10.0.0**
|
**1.0.0 - 11.0.0**
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
* Arbitrary SDMMC backend selection
|
* Arbitrary SDMMC backend selection
|
||||||
|
|||||||
@@ -49,6 +49,8 @@
|
|||||||
#include "offsets/1000_exfat.h"
|
#include "offsets/1000_exfat.h"
|
||||||
#include "offsets/1020.h"
|
#include "offsets/1020.h"
|
||||||
#include "offsets/1020_exfat.h"
|
#include "offsets/1020_exfat.h"
|
||||||
|
#include "offsets/1100.h"
|
||||||
|
#include "offsets/1100_exfat.h"
|
||||||
#include "../utils/fatal.h"
|
#include "../utils/fatal.h"
|
||||||
|
|
||||||
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
|
||||||
@@ -69,6 +71,7 @@ static const fs_offsets_t GET_OFFSET_STRUCT_NAME(vers) = { \
|
|||||||
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
|
.nand_mutex = FS_OFFSET##vers##_NAND_MUTEX, \
|
||||||
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
|
.active_partition = FS_OFFSET##vers##_ACTIVE_PARTITION, \
|
||||||
.sdmmc_das_handle = FS_OFFSET##vers##_SDMMC_DAS_HANDLE, \
|
.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, \
|
.sdmmc_accessor_controller_close = FS_OFFSET##vers##_SDMMC_WRAPPER_CONTROLLER_CLOSE, \
|
||||||
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
|
.sd_das_init = FS_OFFSET##vers##_SD_DAS_INIT, \
|
||||||
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
|
.nintendo_paths = FS_OFFSET##vers##_NINTENDO_PATHS, \
|
||||||
@@ -108,6 +111,8 @@ DEFINE_OFFSET_STRUCT(_1000);
|
|||||||
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
|
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
|
||||||
DEFINE_OFFSET_STRUCT(_1020);
|
DEFINE_OFFSET_STRUCT(_1020);
|
||||||
DEFINE_OFFSET_STRUCT(_1020_EXFAT);
|
DEFINE_OFFSET_STRUCT(_1020_EXFAT);
|
||||||
|
DEFINE_OFFSET_STRUCT(_1100);
|
||||||
|
DEFINE_OFFSET_STRUCT(_1100_EXFAT);
|
||||||
|
|
||||||
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
||||||
switch (version) {
|
switch (version) {
|
||||||
@@ -177,6 +182,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
|
|||||||
return &(GET_OFFSET_STRUCT_NAME(_1020));
|
return &(GET_OFFSET_STRUCT_NAME(_1020));
|
||||||
case FS_VER_10_2_0_EXFAT:
|
case FS_VER_10_2_0_EXFAT:
|
||||||
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
|
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
|
||||||
|
case FS_VER_11_0_0:
|
||||||
|
return &(GET_OFFSET_STRUCT_NAME(_1100));
|
||||||
|
case FS_VER_11_0_0_EXFAT:
|
||||||
|
return &(GET_OFFSET_STRUCT_NAME(_1100_EXFAT));
|
||||||
default:
|
default:
|
||||||
fatal_abort(Fatal_UnknownVersion);
|
fatal_abort(Fatal_UnknownVersion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ typedef struct {
|
|||||||
// Misc funcs
|
// Misc funcs
|
||||||
uintptr_t lock_mutex;
|
uintptr_t lock_mutex;
|
||||||
uintptr_t unlock_mutex;
|
uintptr_t unlock_mutex;
|
||||||
|
uintptr_t sdmmc_accessor_controller_open;
|
||||||
uintptr_t sdmmc_accessor_controller_close;
|
uintptr_t sdmmc_accessor_controller_close;
|
||||||
// Misc data
|
// Misc data
|
||||||
uintptr_t sd_mutex;
|
uintptr_t sd_mutex;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ typedef struct sdmmc_accessor_vt
|
|||||||
void *dtor;
|
void *dtor;
|
||||||
void *map_device_addr_space;
|
void *map_device_addr_space;
|
||||||
void *unmap_device_addr_space;
|
void *unmap_device_addr_space;
|
||||||
void *controller_open;
|
uint64_t (*sdmmc_accessor_controller_open)(void *);
|
||||||
uint64_t (*sdmmc_accessor_controller_close)(void *);
|
uint64_t (*sdmmc_accessor_controller_close)(void *);
|
||||||
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
|
uint64_t (*read_write)(void *, uint64_t, uint64_t, void *, uint64_t, uint64_t);
|
||||||
// More not included because we don't use it.
|
// More not included because we don't use it.
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ enum FS_VER
|
|||||||
FS_VER_10_2_0,
|
FS_VER_10_2_0,
|
||||||
FS_VER_10_2_0_EXFAT,
|
FS_VER_10_2_0_EXFAT,
|
||||||
|
|
||||||
|
FS_VER_11_0_0,
|
||||||
|
FS_VER_11_0_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_100_LOCK_MUTEX 0x2884
|
#define FS_OFFSET_100_LOCK_MUTEX 0x2884
|
||||||
#define FS_OFFSET_100_UNLOCK_MUTEX 0x28F0
|
#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
|
#define FS_OFFSET_100_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x6A8AC
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910
|
#define FS_OFFSET_1000_LOCK_MUTEX 0x28910
|
||||||
#define FS_OFFSET_1000_UNLOCK_MUTEX 0x28960
|
#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
|
#define FS_OFFSET_1000_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
|
#define FS_OFFSET_1000_EXFAT_LOCK_MUTEX 0x28910
|
||||||
#define FS_OFFSET_1000_EXFAT_UNLOCK_MUTEX 0x28960
|
#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
|
#define FS_OFFSET_1000_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1422E0
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
|
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
|
||||||
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
|
#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
|
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
|
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
|
||||||
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
|
#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
|
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
59
emummc/source/FS/offsets/1100.h
Normal file
59
emummc/source/FS/offsets/1100.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||||
|
* Copyright (c) 2019 Atmosphere-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/>.
|
||||||
|
*/
|
||||||
|
#ifndef __FS_1100_H__
|
||||||
|
#define __FS_1100_H__
|
||||||
|
|
||||||
|
// Accessor vtable getters
|
||||||
|
#define FS_OFFSET_1100_SDMMC_ACCESSOR_GC 0x156D90
|
||||||
|
#define FS_OFFSET_1100_SDMMC_ACCESSOR_SD 0x154F40
|
||||||
|
#define FS_OFFSET_1100_SDMMC_ACCESSOR_NAND 0x1500F0
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
#define FS_OFFSET_1100_SDMMC_WRAPPER_READ 0x14B990
|
||||||
|
#define FS_OFFSET_1100_SDMMC_WRAPPER_WRITE 0x14BA70
|
||||||
|
#define FS_OFFSET_1100_RTLD 0x688
|
||||||
|
#define FS_OFFSET_1100_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
|
||||||
|
|
||||||
|
#define FS_OFFSET_1100_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
|
||||||
|
|
||||||
|
// Misc funcs
|
||||||
|
#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
|
||||||
|
#define FS_OFFSET_1100_SD_MUTEX 0xE323E8
|
||||||
|
#define FS_OFFSET_1100_NAND_MUTEX 0xE2D338
|
||||||
|
#define FS_OFFSET_1100_ACTIVE_PARTITION 0xE2D378
|
||||||
|
#define FS_OFFSET_1100_SDMMC_DAS_HANDLE 0xE15D40
|
||||||
|
|
||||||
|
// NOPs
|
||||||
|
#define FS_OFFSET_1100_SD_DAS_INIT 0x273B4
|
||||||
|
|
||||||
|
// Nintendo Paths
|
||||||
|
#define FS_OFFSET_1100_NINTENDO_PATHS \
|
||||||
|
{ \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __FS_1100_H__
|
||||||
59
emummc/source/FS/offsets/1100_exfat.h
Normal file
59
emummc/source/FS/offsets/1100_exfat.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
|
||||||
|
* Copyright (c) 2019 Atmosphere-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/>.
|
||||||
|
*/
|
||||||
|
#ifndef __FS_1100_EXFAT_H__
|
||||||
|
#define __FS_1100_EXFAT_H__
|
||||||
|
|
||||||
|
// Accessor vtable getters
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_GC 0x156D90
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_SD 0x154F40
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_ACCESSOR_NAND 0x1500F0
|
||||||
|
|
||||||
|
// Hooks
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_READ 0x14B990
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_WRAPPER_WRITE 0x14BA70
|
||||||
|
#define FS_OFFSET_1100_EXFAT_RTLD 0x688
|
||||||
|
#define FS_OFFSET_1100_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
|
||||||
|
|
||||||
|
#define FS_OFFSET_1100_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x14AC40
|
||||||
|
|
||||||
|
// Misc funcs
|
||||||
|
#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
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SD_MUTEX 0xE403E8
|
||||||
|
#define FS_OFFSET_1100_EXFAT_NAND_MUTEX 0xE3B338
|
||||||
|
#define FS_OFFSET_1100_EXFAT_ACTIVE_PARTITION 0xE3B378
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SDMMC_DAS_HANDLE 0xE23D40
|
||||||
|
|
||||||
|
// NOPs
|
||||||
|
#define FS_OFFSET_1100_EXFAT_SD_DAS_INIT 0x273B4
|
||||||
|
|
||||||
|
// Nintendo Paths
|
||||||
|
#define FS_OFFSET_1100_EXFAT_NINTENDO_PATHS \
|
||||||
|
{ \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0006D944, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x0007A3C0, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 3, .adrp_offset = 0x00080708, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 4, .adrp_offset = 0x00092198, .add_rel_offset = 0x00000004}, \
|
||||||
|
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __FS_1100_EXFAT_H__
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_200_LOCK_MUTEX 0x3264
|
#define FS_OFFSET_200_LOCK_MUTEX 0x3264
|
||||||
#define FS_OFFSET_200_UNLOCK_MUTEX 0x32D0
|
#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
|
#define FS_OFFSET_200_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
|
#define FS_OFFSET_200_EXFAT_LOCK_MUTEX 0x3264
|
||||||
#define FS_OFFSET_200_EXFAT_UNLOCK_MUTEX 0x32D0
|
#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
|
#define FS_OFFSET_200_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x733F4
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_210_LOCK_MUTEX 0x3264
|
#define FS_OFFSET_210_LOCK_MUTEX 0x3264
|
||||||
#define FS_OFFSET_210_UNLOCK_MUTEX 0x32D0
|
#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
|
#define FS_OFFSET_210_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
|
#define FS_OFFSET_210_EXFAT_LOCK_MUTEX 0x3264
|
||||||
#define FS_OFFSET_210_EXFAT_UNLOCK_MUTEX 0x32D0
|
#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
|
#define FS_OFFSET_210_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x737D4
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC
|
#define FS_OFFSET_300_LOCK_MUTEX 0x35CC
|
||||||
#define FS_OFFSET_300_UNLOCK_MUTEX 0x3638
|
#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
|
#define FS_OFFSET_300_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
|
#define FS_OFFSET_300_EXFAT_LOCK_MUTEX 0x35CC
|
||||||
#define FS_OFFSET_300_EXFAT_UNLOCK_MUTEX 0x3638
|
#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
|
#define FS_OFFSET_300_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A270
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_301_LOCK_MUTEX 0x3638
|
#define FS_OFFSET_301_LOCK_MUTEX 0x3638
|
||||||
#define FS_OFFSET_301_UNLOCK_MUTEX 0x36A4
|
#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
|
#define FS_OFFSET_301_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
|
#define FS_OFFSET_301_EXFAT_LOCK_MUTEX 0x3638
|
||||||
#define FS_OFFSET_301_EXFAT_UNLOCK_MUTEX 0x36A4
|
#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
|
#define FS_OFFSET_301_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x8A32C
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0
|
#define FS_OFFSET_400_LOCK_MUTEX 0x39A0
|
||||||
#define FS_OFFSET_400_UNLOCK_MUTEX 0x3A0C
|
#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
|
#define FS_OFFSET_400_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
|
#define FS_OFFSET_400_EXFAT_LOCK_MUTEX 0x39A0
|
||||||
#define FS_OFFSET_400_EXFAT_UNLOCK_MUTEX 0x3A0C
|
#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
|
#define FS_OFFSET_400_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DB48
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,7 +34,8 @@
|
|||||||
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0
|
#define FS_OFFSET_410_LOCK_MUTEX 0x39A0
|
||||||
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
|
#define FS_OFFSET_410_UNLOCK_MUTEX 0x3A0C
|
||||||
|
|
||||||
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_OPEN 0
|
||||||
|
#define FS_OFFSET_410_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
#define FS_OFFSET_410_SD_MUTEX 0xE80268
|
#define FS_OFFSET_410_SD_MUTEX 0xE80268
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
|
#define FS_OFFSET_410_EXFAT_LOCK_MUTEX 0x39A0
|
||||||
#define FS_OFFSET_410_EXFAT_UNLOCK_MUTEX 0x3A0C
|
#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
|
#define FS_OFFSET_410_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x9DBAC
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_500_LOCK_MUTEX 0x4080
|
#define FS_OFFSET_500_LOCK_MUTEX 0x4080
|
||||||
#define FS_OFFSET_500_UNLOCK_MUTEX 0x40D0
|
#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
|
#define FS_OFFSET_500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
|
#define FS_OFFSET_500_EXFAT_LOCK_MUTEX 0x4080
|
||||||
#define FS_OFFSET_500_EXFAT_UNLOCK_MUTEX 0x40D0
|
#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
|
#define FS_OFFSET_500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9380
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_510_LOCK_MUTEX 0x4080
|
#define FS_OFFSET_510_LOCK_MUTEX 0x4080
|
||||||
#define FS_OFFSET_510_UNLOCK_MUTEX 0x40D0
|
#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
|
#define FS_OFFSET_510_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
|
#define FS_OFFSET_510_EXFAT_LOCK_MUTEX 0x4080
|
||||||
#define FS_OFFSET_510_EXFAT_UNLOCK_MUTEX 0x40D0
|
#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
|
#define FS_OFFSET_510_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0xC9750
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
|
#define FS_OFFSET_600_LOCK_MUTEX 0x1412C0
|
||||||
#define FS_OFFSET_600_UNLOCK_MUTEX 0x141310
|
#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
|
#define FS_OFFSET_600_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x148500
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
|
#define FS_OFFSET_600_EXFAT_LOCK_MUTEX 0x14C9C0
|
||||||
#define FS_OFFSET_600_EXFAT_UNLOCK_MUTEX 0x14CA10
|
#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
|
#define FS_OFFSET_600_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x153C00
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90
|
#define FS_OFFSET_700_LOCK_MUTEX 0x148A90
|
||||||
#define FS_OFFSET_700_UNLOCK_MUTEX 0x148AE0
|
#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
|
#define FS_OFFSET_700_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x14FD50
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
|
#define FS_OFFSET_700_EXFAT_LOCK_MUTEX 0x154040
|
||||||
#define FS_OFFSET_700_EXFAT_UNLOCK_MUTEX 0x154090
|
#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
|
#define FS_OFFSET_700_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15B300
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
|
#define FS_OFFSET_800_LOCK_MUTEX 0x14B6D0
|
||||||
#define FS_OFFSET_800_UNLOCK_MUTEX 0x14B720
|
#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
|
#define FS_OFFSET_800_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
|
#define FS_OFFSET_800_EXFAT_LOCK_MUTEX 0x156C80
|
||||||
#define FS_OFFSET_800_EXFAT_UNLOCK_MUTEX 0x156CD0
|
#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
|
#define FS_OFFSET_800_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
|
#define FS_OFFSET_810_LOCK_MUTEX 0x14B6D0
|
||||||
#define FS_OFFSET_810_UNLOCK_MUTEX 0x14B720
|
#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
|
#define FS_OFFSET_810_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x1529E0
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
|
#define FS_OFFSET_810_EXFAT_LOCK_MUTEX 0x156C80
|
||||||
#define FS_OFFSET_810_EXFAT_UNLOCK_MUTEX 0x156CD0
|
#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
|
#define FS_OFFSET_810_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x15DF90
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_900_LOCK_MUTEX 0x25280
|
#define FS_OFFSET_900_LOCK_MUTEX 0x25280
|
||||||
#define FS_OFFSET_900_UNLOCK_MUTEX 0x252D0
|
#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
|
#define FS_OFFSET_900_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
|
#define FS_OFFSET_900_EXFAT_LOCK_MUTEX 0x25280
|
||||||
#define FS_OFFSET_900_EXFAT_UNLOCK_MUTEX 0x252D0
|
#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
|
#define FS_OFFSET_900_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137740
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_910_LOCK_MUTEX 0x25280
|
#define FS_OFFSET_910_LOCK_MUTEX 0x25280
|
||||||
#define FS_OFFSET_910_UNLOCK_MUTEX 0x252D0
|
#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
|
#define FS_OFFSET_910_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||||
|
|
||||||
// Misc Data
|
// Misc Data
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280
|
#define FS_OFFSET_910_EXFAT_LOCK_MUTEX 0x25280
|
||||||
#define FS_OFFSET_910_EXFAT_UNLOCK_MUTEX 0x252D0
|
#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
|
#define FS_OFFSET_910_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x137750
|
||||||
|
|
||||||
// Misc Data
|
// 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)
|
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))
|
if ((emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw))
|
||||||
{
|
{
|
||||||
// raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset.
|
// raw partition sector offset: emuMMC_ctx.EMMC_StoragePartitionOffset.
|
||||||
sector += emuMMC_ctx.EMMC_StoragePartitionOffset;
|
sector += emuMMC_ctx.EMMC_StoragePartitionOffset;
|
||||||
@@ -318,6 +318,31 @@ static uint64_t emummc_read_write_inner(void *buf, unsigned int sector, unsigned
|
|||||||
return res;
|
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
|
// Controller close wrapper
|
||||||
uint64_t sdmmc_wrapper_controller_close(int mmc_id)
|
uint64_t sdmmc_wrapper_controller_close(int mmc_id)
|
||||||
{
|
{
|
||||||
@@ -389,7 +414,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
|||||||
if (first_sd_read)
|
if (first_sd_read)
|
||||||
{
|
{
|
||||||
first_sd_read = false;
|
first_sd_read = false;
|
||||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||||
{
|
{
|
||||||
// Because some SD cards have issues with emuMMC's driver
|
// Because some SD cards have issues with emuMMC's driver
|
||||||
// we currently swap to FS's driver after first SD read
|
// we currently swap to FS's driver after first SD read
|
||||||
@@ -400,7 +425,7 @@ uint64_t sdmmc_wrapper_read(void *buf, uint64_t bufSize, int mmc_id, unsigned in
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call hekates driver.
|
// Call hekate's driver.
|
||||||
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
|
if (sdmmc_storage_read(&sd_storage, sector, num_sectors, buf))
|
||||||
{
|
{
|
||||||
mutex_unlock_handler(mmc_id);
|
mutex_unlock_handler(mmc_id);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ void mutex_lock_handler(int mmc_id);
|
|||||||
void mutex_unlock_handler(int mmc_id);
|
void mutex_unlock_handler(int mmc_id);
|
||||||
|
|
||||||
// Hooks
|
// Hooks
|
||||||
|
uint64_t sdmmc_wrapper_controller_open(int mmc_id);
|
||||||
uint64_t sdmmc_wrapper_controller_close(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_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);
|
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,
|
emuMMC_EMMC = 0,
|
||||||
|
|
||||||
// SD Device raw
|
// SD Device raw
|
||||||
emuMMC_SD,
|
emuMMC_SD_Raw,
|
||||||
// SD Device File
|
// SD Device File
|
||||||
emuMMC_SD_File,
|
emuMMC_SD_File,
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ volatile __attribute__((aligned(0x1000))) emuMMC_ctx_t emuMMC_ctx = {
|
|||||||
.fs_ver = FS_VER_MAX,
|
.fs_ver = FS_VER_MAX,
|
||||||
|
|
||||||
// SD Default Metadata
|
// SD Default Metadata
|
||||||
.SD_Type = emuMMC_SD,
|
.SD_Type = emuMMC_SD_Raw,
|
||||||
.SD_StoragePartitionOffset = 0,
|
.SD_StoragePartitionOffset = 0,
|
||||||
|
|
||||||
// EMMC Default Metadata
|
// EMMC Default Metadata
|
||||||
@@ -285,6 +285,9 @@ void setup_hooks(void)
|
|||||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
|
INJECT_HOOK(fs_offsets->sdmmc_wrapper_read, sdmmc_wrapper_read);
|
||||||
// sdmmc_wrapper_write hook
|
// sdmmc_wrapper_write hook
|
||||||
INJECT_HOOK(fs_offsets->sdmmc_wrapper_write, sdmmc_wrapper_write);
|
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
|
// sdmmc_wrapper_controller_close hook
|
||||||
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
|
INJECT_HOOK(fs_offsets->sdmmc_accessor_controller_close, sdmmc_wrapper_controller_close);
|
||||||
|
|
||||||
@@ -346,7 +349,7 @@ static void load_emummc_ctx(void)
|
|||||||
emuMMC_ctx.id = config.base_cfg.id;
|
emuMMC_ctx.id = config.base_cfg.id;
|
||||||
emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type;
|
emuMMC_ctx.EMMC_Type = (enum emuMMC_Type)config.base_cfg.type;
|
||||||
emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version;
|
emuMMC_ctx.fs_ver = (enum FS_VER)config.base_cfg.fs_version;
|
||||||
if (emuMMC_ctx.EMMC_Type == emuMMC_SD)
|
if (emuMMC_ctx.EMMC_Type == emuMMC_SD_Raw)
|
||||||
{
|
{
|
||||||
emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector;
|
emuMMC_ctx.EMMC_StoragePartitionOffset = config.partition_cfg.start_sector;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ namespace ams::secmon::boot {
|
|||||||
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
|
/* 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. */
|
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
|
||||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
|
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. */
|
/* 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_IcosaSamsung4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_IcosaHynix4GB] = pkg1::MemorySize_4GB,
|
[fuse::DramId_IcosaHynix4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_IcosaMicron4GB] = pkg1::MemorySize_4GB,
|
[fuse::DramId_IcosaMicron4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_CopperSamsung4GB] = pkg1::MemorySize_4GB,
|
[fuse::DramId_FiveHynix1y4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
|
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
|
||||||
[fuse::DramId_CopperHynix4GB] = pkg1::MemorySize_4GB,
|
[fuse::DramId_CopperHynix4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_CopperMicron4GB] = pkg1::MemorySize_4GB,
|
[fuse::DramId_CopperMicron4GB] = pkg1::MemorySize_4GB,
|
||||||
@@ -66,9 +66,13 @@ namespace ams::secmon::smc {
|
|||||||
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_IowaSamsung1y4GBY] = pkg1::MemorySize_4GB,
|
[fuse::DramId_IowaSamsung1y4GBY] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_IowaSamsung1y8GBY] = pkg1::MemorySize_8GB,
|
[fuse::DramId_IowaSamsung1y8GBY] = pkg1::MemorySize_8GB,
|
||||||
[fuse::DramId_IowaSamsung1y4GBA] = pkg1::MemorySize_4GB,
|
[fuse::DramId_FiveSamsung1y4GB] = pkg1::MemorySize_4GB,
|
||||||
[fuse::DramId_FiveSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
[fuse::DramId_HoagSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
[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_FiveSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr const pkg1::MemoryMode MemoryModes[] = {
|
constexpr const pkg1::MemoryMode MemoryModes[] = {
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ typedef enum {
|
|||||||
FS_VER_10_2_0,
|
FS_VER_10_2_0,
|
||||||
FS_VER_10_2_0_EXFAT,
|
FS_VER_10_2_0_EXFAT,
|
||||||
|
|
||||||
|
FS_VER_11_0_0,
|
||||||
|
FS_VER_11_0_0_EXFAT,
|
||||||
|
|
||||||
FS_VER_MAX,
|
FS_VER_MAX,
|
||||||
} emummc_fs_ver_t;
|
} emummc_fs_ver_t;
|
||||||
|
|
||||||
|
|||||||
@@ -423,6 +423,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
|
|||||||
|
|
||||||
"\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", /* FS_VER_10_2_0 */
|
"\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", /* FS_VER_10_2_0 */
|
||||||
"\x16\x0D\x3E\x10\x4E\xAD\x61\x76", /* FS_VER_10_2_0_EXFAT */
|
"\x16\x0D\x3E\x10\x4E\xAD\x61\x76", /* FS_VER_10_2_0_EXFAT */
|
||||||
|
|
||||||
|
"\xE3\x99\x15\x6E\x84\x4E\xB0\xAA", /* FS_VER_11_0_0 */
|
||||||
|
"\x0B\xA1\x5B\xB3\x04\xB5\x05\x63", /* FS_VER_11_0_0_EXFAT */
|
||||||
};
|
};
|
||||||
|
|
||||||
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {
|
||||||
|
|||||||
@@ -541,6 +541,60 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_send)[] = {0xA9B
|
|||||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1000, proc_id_recv)[] = {0x88, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1C, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x87, 0x40, 0xF9, 0x08, 0x49, 0x3A, 0x8B, 0x09, 0xFC, 0x60, 0xD3};
|
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1000, proc_id_recv)[] = {0x88, 0x03, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0xE0, 0x03, 0x1C, 0xAA, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x87, 0x40, 0xF9, 0x08, 0x49, 0x3A, 0x8B, 0x09, 0xFC, 0x60, 0xD3};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9BF2FEA, 0xF94067EB, 0x2A1A03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400388, 0xF9401D08, 0xAA1C03E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||||
|
|
||||||
|
/*
|
||||||
|
stp x10, x11, [sp, #-0x10]!
|
||||||
|
ldr x11, [sp, #0x80]
|
||||||
|
mov w10, #3
|
||||||
|
lsl x10, x10, #2
|
||||||
|
ldr x10, [x11, x10]
|
||||||
|
mov x9, #0x0000ffffffffffff
|
||||||
|
and x8, x10, x9
|
||||||
|
mov x9, #0xffff000000000000
|
||||||
|
and x10, x10, x9
|
||||||
|
mov x9, #0xfffe000000000000
|
||||||
|
cmp x10, x9
|
||||||
|
beq #0x20
|
||||||
|
|
||||||
|
stp x8, x9, [sp, #-0x10]!
|
||||||
|
ldr x8, [x21]
|
||||||
|
ldr x8, [x8, #0x38]
|
||||||
|
mov x0, x21
|
||||||
|
blr x8
|
||||||
|
ldp x8, x9, [sp],#0x10
|
||||||
|
mov x8, x0
|
||||||
|
|
||||||
|
ldp x10, x11, [sp],#0x10
|
||||||
|
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};
|
||||||
|
/*
|
||||||
|
stp x10, x11, [sp, #-0x10]!
|
||||||
|
ldr x11, [sp, #0xE0]
|
||||||
|
mov w10, #3
|
||||||
|
lsl x10, x10, #2
|
||||||
|
ldr x10, [x11, x10]
|
||||||
|
mov x9, #0x0000ffffffffffff
|
||||||
|
and x8, x10, x9
|
||||||
|
mov x9, #0xffff000000000000
|
||||||
|
and x10, x10, x9
|
||||||
|
mov x9, #0xfffe000000000000
|
||||||
|
cmp x10, x9
|
||||||
|
beq #0x20
|
||||||
|
|
||||||
|
stp x8, x9, [sp, #-0x10]!
|
||||||
|
ldr x8, [x24]
|
||||||
|
ldr x8, [x8, #0x38]
|
||||||
|
mov x0, x24
|
||||||
|
blr x8
|
||||||
|
ldp x8, x9, [sp],#0x10
|
||||||
|
mov x8, x0
|
||||||
|
|
||||||
|
ldp x10, x11, [sp],#0x10
|
||||||
|
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};
|
||||||
|
|
||||||
/* svcControlCodeMemory Patches */
|
/* svcControlCodeMemory Patches */
|
||||||
/* b.eq -> nop */
|
/* b.eq -> nop */
|
||||||
@@ -550,6 +604,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(700, svc_control_codememory)[
|
|||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory)[] = {MAKE_NOP};
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory)[] = {MAKE_NOP};
|
||||||
|
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, system_memory_increase)[] = {0x52A3C008}; /* MOV W8, #0x1E000000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(500, system_memory_increase)[] = {0x52A3C008}; /* MOV W8, #0x1E000000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(600, system_memory_increase)[] = {0x52A3B008}; /* MOV W8, #0x1D800000 */
|
||||||
@@ -557,6 +612,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(700, system_memory_increase)[
|
|||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(800, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(900, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, system_memory_increase)[] = {0x52A3B013}; /* MOV W19, #0x1D800000 */
|
||||||
|
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase)[] = {0x52A3B015}; /* MOV W21, #0x1D800000 */
|
||||||
|
|
||||||
/* Hook Definitions. */
|
/* Hook Definitions. */
|
||||||
static const kernel_patch_t g_kernel_patches_100[] = {
|
static const kernel_patch_t g_kernel_patches_100[] = {
|
||||||
@@ -821,6 +877,35 @@ static const kernel_patch_t g_kernel_patches_1000[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const kernel_patch_t g_kernel_patches_1100[] = {
|
||||||
|
{ /* Send Message Process ID Patch. */
|
||||||
|
.pattern_size = 0x1C,
|
||||||
|
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send),
|
||||||
|
.pattern_hook_offset = 0x0,
|
||||||
|
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_send))/sizeof(instruction_t),
|
||||||
|
.branch_back_offset = 0x10,
|
||||||
|
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)
|
||||||
|
},
|
||||||
|
{ /* Receive Message Process ID Patch. */
|
||||||
|
.pattern_size = 0x1C,
|
||||||
|
.pattern = MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv),
|
||||||
|
.pattern_hook_offset = 0x0,
|
||||||
|
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv))/sizeof(instruction_t),
|
||||||
|
.branch_back_offset = 0x10,
|
||||||
|
.payload = MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)
|
||||||
|
},
|
||||||
|
{ /* svcControlCodeMemory Patch. */
|
||||||
|
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory))/sizeof(instruction_t),
|
||||||
|
.payload = MAKE_KERNEL_PATCH_NAME(1100, svc_control_codememory),
|
||||||
|
.patch_offset = 0x2FCE0,
|
||||||
|
},
|
||||||
|
{ /* System Memory Increase Patch. */
|
||||||
|
.payload_num_instructions = sizeof(MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase))/sizeof(instruction_t),
|
||||||
|
.payload = MAKE_KERNEL_PATCH_NAME(1100, system_memory_increase),
|
||||||
|
.patch_offset = 0x490C4,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
#define KERNEL_PATCHES(vers) .num_patches = sizeof(g_kernel_patches_##vers)/sizeof(kernel_patch_t), .patches = g_kernel_patches_##vers,
|
||||||
|
|
||||||
/* Kernel Infos. */
|
/* Kernel Infos. */
|
||||||
@@ -906,6 +991,15 @@ static const kernel_info_t g_kernel_infos[] = {
|
|||||||
.embedded_ini_ptr = 0x178,
|
.embedded_ini_ptr = 0x178,
|
||||||
.free_code_space_offset = 0x67790,
|
.free_code_space_offset = 0x67790,
|
||||||
KERNEL_PATCHES(1000)
|
KERNEL_PATCHES(1000)
|
||||||
|
},
|
||||||
|
{ /* 11.0.0. */
|
||||||
|
.hash = {0xC2, 0x0E, 0xB3, 0x1B, 0xBF, 0x0B, 0x82, 0xF3, 0x3D, 0xFD, 0x47, 0x04, 0xB4, 0x44, 0x38, 0x47, 0x64, 0xAB, 0xD8, 0x70, 0x2F, 0x0E, 0x0C, 0x37, 0x82, 0x28, 0x02, 0x24, 0xB8, 0x6E, 0xCE, 0x05, },
|
||||||
|
.hash_offset = 0x1C4,
|
||||||
|
.hash_size = 0x69000 - 0x1C4,
|
||||||
|
.embedded_ini_offset = 0x69000,
|
||||||
|
.embedded_ini_ptr = 0x180,
|
||||||
|
.free_code_space_offset = 0x49EE8,
|
||||||
|
KERNEL_PATCHES(1100)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -967,13 +1061,6 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (kernel_info->embedded_ini_offset != 0) {
|
if (kernel_info->embedded_ini_offset != 0) {
|
||||||
/* Copy in our kernel loader. */
|
|
||||||
const uint32_t kernel_ldr_offset = *((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr + 8));
|
|
||||||
memcpy((void *)((uintptr_t)_kernel + kernel_ldr_offset), kernel_ldr_bin, kernel_ldr_bin_size);
|
|
||||||
|
|
||||||
/* Update size. */
|
|
||||||
*kernel_size = kernel_ldr_offset + kernel_ldr_bin_size;
|
|
||||||
|
|
||||||
/* Set output INI ptr. */
|
/* Set output INI ptr. */
|
||||||
*out_ini1 = (void *)((uintptr_t)_kernel + kernel_info->embedded_ini_offset);
|
*out_ini1 = (void *)((uintptr_t)_kernel + kernel_info->embedded_ini_offset);
|
||||||
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)*kernel_size;
|
*((volatile uint64_t *)((uintptr_t)_kernel + kernel_info->embedded_ini_ptr)) = (uint64_t)*kernel_size;
|
||||||
@@ -1003,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);
|
uint8_t *pattern_loc = search_pattern(kernel, *kernel_size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||||
if (pattern_loc == NULL) {
|
if (pattern_loc == NULL) {
|
||||||
/* TODO: Should we print an error/abort here? */
|
fatal_error("kernel_patcher: failed to identify patch location!\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Patch kernel to branch to our hook at the desired place. */
|
/* Patch kernel to branch to our hook at the desired place. */
|
||||||
|
|||||||
@@ -239,7 +239,9 @@ static bool is_nca_present(const char *nca_name) {
|
|||||||
static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
|
static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
|
||||||
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
|
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
|
||||||
|
|
||||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
|
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_11_0_0) {
|
||||||
|
CHECK_NCA("594c90bcdbcccad6b062eadba0cd0e7e", 11_0_0);
|
||||||
|
} else if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
|
||||||
CHECK_NCA("26325de4db3909e0ef2379787c7e671d", 10_2_0);
|
CHECK_NCA("26325de4db3909e0ef2379787c7e671d", 10_2_0);
|
||||||
CHECK_NCA("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
|
CHECK_NCA("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
|
||||||
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
|
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
|
||||||
@@ -337,6 +339,8 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
|||||||
return ATMOSPHERE_TARGET_FIRMWARE_9_1_0;
|
return ATMOSPHERE_TARGET_FIRMWARE_9_1_0;
|
||||||
} else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) {
|
} else if (memcmp(package1loader_header->build_timestamp, "20200303", 8) == 0) {
|
||||||
return ATMOSPHERE_TARGET_FIRMWARE_10_0_0;
|
return ATMOSPHERE_TARGET_FIRMWARE_10_0_0;
|
||||||
|
} else if (memcmp(package1loader_header->build_timestamp, "20201030", 8) == 0) {
|
||||||
|
return ATMOSPHERE_TARGET_FIRMWARE_11_0_0;
|
||||||
} else {
|
} else {
|
||||||
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
fatal_error("[NXBOOT] Unable to identify package1!\n");
|
||||||
}
|
}
|
||||||
@@ -521,6 +525,10 @@ static void nxboot_configure_stratosphere(uint32_t target_firmware) {
|
|||||||
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) {
|
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_9_0_0 && !(fuse_get_reserved_odm(7) & ~0x000003FF)) {
|
||||||
kip_patches_set_enable_nogc();
|
kip_patches_set_enable_nogc();
|
||||||
}
|
}
|
||||||
|
/* Check if the fuses are < 11.0.0, but firmware is >= 11.0.0 */
|
||||||
|
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_11_0_0 && !(fuse_get_reserved_odm(7) & ~0x00001FFF)) {
|
||||||
|
kip_patches_set_enable_nogc();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ static bool package2_validate_metadata(package2_meta_t *metadata, uint8_t data[]
|
|||||||
|
|
||||||
/* Perform version checks. */
|
/* Perform version checks. */
|
||||||
/* We will be compatible with all package2s released before current, but not newer ones. */
|
/* We will be compatible with all package2s released before current, but not newer ones. */
|
||||||
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1000_CURRENT) {
|
if (metadata->version_max >= PACKAGE2_MINVER_THEORETICAL && metadata->version_min < PACKAGE2_MAXVER_1100_CURRENT) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,8 @@
|
|||||||
#define PACKAGE2_MAXVER_810 0xB
|
#define PACKAGE2_MAXVER_810 0xB
|
||||||
#define PACKAGE2_MAXVER_900 0xC
|
#define PACKAGE2_MAXVER_900 0xC
|
||||||
#define PACKAGE2_MAXVER_910_920 0xD
|
#define PACKAGE2_MAXVER_910_920 0xD
|
||||||
#define PACKAGE2_MAXVER_1000_CURRENT 0xE
|
#define PACKAGE2_MAXVER_1000 0xE
|
||||||
|
#define PACKAGE2_MAXVER_1100_CURRENT 0xF
|
||||||
|
|
||||||
#define PACKAGE2_MINVER_100 0x3
|
#define PACKAGE2_MINVER_100 0x3
|
||||||
#define PACKAGE2_MINVER_200 0x4
|
#define PACKAGE2_MINVER_200 0x4
|
||||||
@@ -54,7 +55,8 @@
|
|||||||
#define PACKAGE2_MINVER_810 0xC
|
#define PACKAGE2_MINVER_810 0xC
|
||||||
#define PACKAGE2_MINVER_900 0xD
|
#define PACKAGE2_MINVER_900 0xD
|
||||||
#define PACKAGE2_MINVER_910_920 0xE
|
#define PACKAGE2_MINVER_910_920 0xE
|
||||||
#define PACKAGE2_MINVER_1000_CURRENT 0xF
|
#define PACKAGE2_MINVER_1000 0xF
|
||||||
|
#define PACKAGE2_MINVER_1100_CURRENT 0x10
|
||||||
|
|
||||||
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
#define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull))
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||||
branch = master
|
branch = master
|
||||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
commit = 2c3ccef17e9b267a5d9d232f1aba689f2c591b95
|
||||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
parent = d2f48d5e36cb2ba4e8cc014238457bd75df81797
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.1
|
cmdver = 0.4.1
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
|||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
export SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace ams::fuse {
|
|||||||
DramId_IcosaSamsung4GB = 0,
|
DramId_IcosaSamsung4GB = 0,
|
||||||
DramId_IcosaHynix4GB = 1,
|
DramId_IcosaHynix4GB = 1,
|
||||||
DramId_IcosaMicron4GB = 2,
|
DramId_IcosaMicron4GB = 2,
|
||||||
DramId_CopperSamsung4GB = 3,
|
DramId_FiveHynix1y4GB = 3,
|
||||||
DramId_IcosaSamsung6GB = 4,
|
DramId_IcosaSamsung6GB = 4,
|
||||||
DramId_CopperHynix4GB = 5,
|
DramId_CopperHynix4GB = 5,
|
||||||
DramId_CopperMicron4GB = 6,
|
DramId_CopperMicron4GB = 6,
|
||||||
@@ -70,9 +70,13 @@ namespace ams::fuse {
|
|||||||
DramId_HoagSamsung1y4GBX = 19,
|
DramId_HoagSamsung1y4GBX = 19,
|
||||||
DramId_IowaSamsung1y4GBY = 20,
|
DramId_IowaSamsung1y4GBY = 20,
|
||||||
DramId_IowaSamsung1y8GBY = 21,
|
DramId_IowaSamsung1y8GBY = 21,
|
||||||
DramId_IowaSamsung1y4GBA = 22,
|
DramId_FiveSamsung1y4GB = 22,
|
||||||
DramId_FiveSamsung1y8GBX = 23,
|
DramId_HoagSamsung1y8GBX = 23,
|
||||||
DramId_FiveSamsung1y4GBX = 24,
|
DramId_FiveSamsung1y4GBX = 24,
|
||||||
|
DramId_IowaMicron1y4GB = 25,
|
||||||
|
DramId_HoagMicron1y4GB = 26,
|
||||||
|
DramId_FiveMicron1y4GB = 27,
|
||||||
|
DramId_FiveSamsung1y8GBX = 28,
|
||||||
|
|
||||||
DramId_Count,
|
DramId_Count,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace ams::pkg2 {
|
|||||||
constexpr inline int PayloadCount = 3;
|
constexpr inline int PayloadCount = 3;
|
||||||
|
|
||||||
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x10 in Nintendo's code. */
|
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x10 in Nintendo's code. */
|
||||||
constexpr inline int CurrentBootloaderVersion = 0xD;
|
constexpr inline int CurrentBootloaderVersion = 0xE;
|
||||||
|
|
||||||
struct Package2Meta {
|
struct Package2Meta {
|
||||||
using Magic = util::FourCC<'P','K','2','1'>;
|
using Magic = util::FourCC<'P','K','2','1'>;
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ namespace ams::fuse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
|
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
|
||||||
|
TargetFirmware_11_0_0,
|
||||||
TargetFirmware_10_0_0,
|
TargetFirmware_10_0_0,
|
||||||
TargetFirmware_9_1_0,
|
TargetFirmware_9_1_0,
|
||||||
TargetFirmware_9_0_0,
|
TargetFirmware_9_0_0,
|
||||||
@@ -207,7 +208,7 @@ namespace ams::fuse {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_10_0_0) == 13);
|
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_11_0_0) == 14);
|
||||||
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_1_0_0) == 1);
|
static_assert(GetExpectedFuseVersionImpl(TargetFirmware_1_0_0) == 1);
|
||||||
static_assert(GetExpectedFuseVersionImpl(static_cast<TargetFirmware>(0)) == 0);
|
static_assert(GetExpectedFuseVersionImpl(static_cast<TargetFirmware>(0)) == 0);
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ include $(CURRENT_DIRECTORY)/../config/common.mk
|
|||||||
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||||
|
|
||||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
|
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
|
||||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||||
|
|||||||
@@ -48,7 +48,6 @@
|
|||||||
#include <mesosphere/kern_k_spin_lock.hpp>
|
#include <mesosphere/kern_k_spin_lock.hpp>
|
||||||
#include <mesosphere/kern_k_memory_manager.hpp>
|
#include <mesosphere/kern_k_memory_manager.hpp>
|
||||||
#include <mesosphere/kern_k_interrupt_task_manager.hpp>
|
#include <mesosphere/kern_k_interrupt_task_manager.hpp>
|
||||||
#include <mesosphere/kern_k_core_local_region.hpp>
|
|
||||||
#include <mesosphere/kern_k_slab_heap.hpp>
|
#include <mesosphere/kern_k_slab_heap.hpp>
|
||||||
#include <mesosphere/kern_k_light_lock.hpp>
|
#include <mesosphere/kern_k_light_lock.hpp>
|
||||||
#include <mesosphere/kern_k_dpc_manager.hpp>
|
#include <mesosphere/kern_k_dpc_manager.hpp>
|
||||||
@@ -78,7 +77,8 @@
|
|||||||
#include <mesosphere/kern_select_debug.hpp>
|
#include <mesosphere/kern_select_debug.hpp>
|
||||||
#include <mesosphere/kern_k_process.hpp>
|
#include <mesosphere/kern_k_process.hpp>
|
||||||
#include <mesosphere/kern_k_resource_limit.hpp>
|
#include <mesosphere/kern_k_resource_limit.hpp>
|
||||||
#include <mesosphere/kern_k_synchronization.hpp>
|
#include <mesosphere/kern_k_alpha.hpp>
|
||||||
|
#include <mesosphere/kern_k_beta.hpp>
|
||||||
|
|
||||||
/* More Miscellaneous objects. */
|
/* More Miscellaneous objects. */
|
||||||
#include <mesosphere/kern_k_object_name.hpp>
|
#include <mesosphere/kern_k_object_name.hpp>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ namespace ams::kern::init {
|
|||||||
u64 entrypoint;
|
u64 entrypoint;
|
||||||
u64 argument;
|
u64 argument;
|
||||||
u64 setup_function;
|
u64 setup_function;
|
||||||
|
u64 exception_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
|
|
||||||
/* Can we make an L1 block? */
|
/* Can we make an L1 block? */
|
||||||
if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && size >= L1BlockSize) {
|
if (util::IsAligned(GetInteger(virt_addr), L1BlockSize) && util::IsAligned(GetInteger(phys_addr), L1BlockSize) && size >= L1BlockSize) {
|
||||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
|
|
||||||
virt_addr += L1BlockSize;
|
virt_addr += L1BlockSize;
|
||||||
@@ -327,7 +327,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
/* Can we make a contiguous L2 block? */
|
/* Can we make a contiguous L2 block? */
|
||||||
if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && size >= L2ContiguousBlockSize) {
|
if (util::IsAligned(GetInteger(virt_addr), L2ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L2ContiguousBlockSize) && size >= L2ContiguousBlockSize) {
|
||||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, true);
|
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, true);
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
|
|
||||||
virt_addr += L2BlockSize;
|
virt_addr += L2BlockSize;
|
||||||
@@ -339,7 +339,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
|
|
||||||
/* Can we make an L2 block? */
|
/* Can we make an L2 block? */
|
||||||
if (util::IsAligned(GetInteger(virt_addr), L2BlockSize) && util::IsAligned(GetInteger(phys_addr), L2BlockSize) && size >= L2BlockSize) {
|
if (util::IsAligned(GetInteger(virt_addr), L2BlockSize) && util::IsAligned(GetInteger(phys_addr), L2BlockSize) && size >= L2BlockSize) {
|
||||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
|
|
||||||
virt_addr += L2BlockSize;
|
virt_addr += L2BlockSize;
|
||||||
@@ -361,7 +361,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
/* Can we make a contiguous L3 block? */
|
/* Can we make a contiguous L3 block? */
|
||||||
if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && size >= L3ContiguousBlockSize) {
|
if (util::IsAligned(GetInteger(virt_addr), L3ContiguousBlockSize) && util::IsAligned(GetInteger(phys_addr), L3ContiguousBlockSize) && size >= L3ContiguousBlockSize) {
|
||||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, true);
|
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, true);
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
|
|
||||||
virt_addr += L3BlockSize;
|
virt_addr += L3BlockSize;
|
||||||
@@ -372,7 +372,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Make an L3 block. */
|
/* Make an L3 block. */
|
||||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, false);
|
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, attr, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
virt_addr += L3BlockSize;
|
virt_addr += L3BlockSize;
|
||||||
phys_addr += L3BlockSize;
|
phys_addr += L3BlockSize;
|
||||||
@@ -542,7 +542,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
const KPhysicalAddress block = l1_entry->GetBlock();
|
const KPhysicalAddress block = l1_entry->GetBlock();
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L1BlockSize);
|
MESOSPHERE_INIT_ABORT_UNLESS(size >= L1BlockSize);
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, false));
|
MESOSPHERE_INIT_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||||
|
|
||||||
/* Invalidate the existing L1 block. */
|
/* Invalidate the existing L1 block. */
|
||||||
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
|
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
|
||||||
@@ -550,7 +550,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
cpu::InvalidateEntireTlb();
|
cpu::InvalidateEntireTlb();
|
||||||
|
|
||||||
/* Create new L1 block. */
|
/* Create new L1 block. */
|
||||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
|
|
||||||
virt_addr += L1BlockSize;
|
virt_addr += L1BlockSize;
|
||||||
size -= L1BlockSize;
|
size -= L1BlockSize;
|
||||||
@@ -573,7 +573,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
/* Invalidate the existing contiguous L2 block. */
|
/* Invalidate the existing contiguous L2 block. */
|
||||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||||
/* Ensure that the entry is valid. */
|
/* Ensure that the entry is valid. */
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, true));
|
||||||
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
|
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
|
||||||
}
|
}
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
@@ -581,7 +581,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
|
|
||||||
/* Create a new contiguous L2 block. */
|
/* Create a new contiguous L2 block. */
|
||||||
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
|
||||||
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, block + L2BlockSize * i, attr_after, true);
|
l2_entry[i] = L2PageTableEntry(PageTableEntry::BlockTag{}, block + L2BlockSize * i, attr_after, PageTableEntry::SoftwareReservedBit_None, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_addr += L2ContiguousBlockSize;
|
virt_addr += L2ContiguousBlockSize;
|
||||||
@@ -591,7 +591,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize));
|
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize));
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize));
|
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize));
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L2BlockSize);
|
MESOSPHERE_INIT_ABORT_UNLESS(size >= L2BlockSize);
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, false));
|
MESOSPHERE_INIT_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||||
|
|
||||||
/* Invalidate the existing L2 block. */
|
/* Invalidate the existing L2 block. */
|
||||||
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
|
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
|
||||||
@@ -599,7 +599,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
cpu::InvalidateEntireTlb();
|
cpu::InvalidateEntireTlb();
|
||||||
|
|
||||||
/* Create new L2 block. */
|
/* Create new L2 block. */
|
||||||
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
*l2_entry = L2PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
|
|
||||||
virt_addr += L2BlockSize;
|
virt_addr += L2BlockSize;
|
||||||
size -= L2BlockSize;
|
size -= L2BlockSize;
|
||||||
@@ -625,7 +625,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
/* Invalidate the existing contiguous L3 block. */
|
/* Invalidate the existing contiguous L3 block. */
|
||||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||||
/* Ensure that the entry is valid. */
|
/* Ensure that the entry is valid. */
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, true));
|
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, true));
|
||||||
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
|
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
|
||||||
}
|
}
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
@@ -633,7 +633,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
|
|
||||||
/* Create a new contiguous L3 block. */
|
/* Create a new contiguous L3 block. */
|
||||||
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
|
||||||
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, block + L3BlockSize * i, attr_after, true);
|
l3_entry[i] = L3PageTableEntry(PageTableEntry::BlockTag{}, block + L3BlockSize * i, attr_after, PageTableEntry::SoftwareReservedBit_None, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_addr += L3ContiguousBlockSize;
|
virt_addr += L3ContiguousBlockSize;
|
||||||
@@ -643,7 +643,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize));
|
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize));
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize));
|
MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize));
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(size >= L3BlockSize);
|
MESOSPHERE_INIT_ABORT_UNLESS(size >= L3BlockSize);
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, false));
|
MESOSPHERE_INIT_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, PageTableEntry::SoftwareReservedBit_None, false));
|
||||||
|
|
||||||
/* Invalidate the existing L3 block. */
|
/* Invalidate the existing L3 block. */
|
||||||
*static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry;
|
*static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry;
|
||||||
@@ -651,7 +651,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
cpu::InvalidateEntireTlb();
|
cpu::InvalidateEntireTlb();
|
||||||
|
|
||||||
/* Create new L3 block. */
|
/* Create new L3 block. */
|
||||||
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, false);
|
*l3_entry = L3PageTableEntry(PageTableEntry::BlockTag{}, block, attr_after, PageTableEntry::SoftwareReservedBit_None, false);
|
||||||
|
|
||||||
virt_addr += L3BlockSize;
|
virt_addr += L3BlockSize;
|
||||||
size -= L3BlockSize;
|
size -= L3BlockSize;
|
||||||
@@ -668,6 +668,7 @@ namespace ams::kern::arch::arm64::init {
|
|||||||
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
||||||
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
||||||
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
||||||
|
cpu::StoreEntireCacheForInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -220,16 +220,19 @@ namespace ams::kern::arch::arm64::cpu {
|
|||||||
DataSynchronizationBarrier();
|
DataSynchronizationBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE uintptr_t GetCoreLocalRegionAddress() {
|
ALWAYS_INLINE uintptr_t GetCurrentThreadPointerValue() {
|
||||||
register uintptr_t x18 asm("x18");
|
register uintptr_t x18 asm("x18");
|
||||||
__asm__ __volatile__("" : [x18]"=r"(x18));
|
__asm__ __volatile__("" : [x18]"=r"(x18));
|
||||||
return x18;
|
return x18;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void SetCoreLocalRegionAddress(uintptr_t value) {
|
ALWAYS_INLINE void SetCurrentThreadPointerValue(uintptr_t value) {
|
||||||
register uintptr_t x18 asm("x18") = value;
|
register uintptr_t x18 asm("x18") = value;
|
||||||
__asm__ __volatile__("":: [x18]"r"(x18));
|
__asm__ __volatile__("":: [x18]"r"(x18));
|
||||||
SetTpidrEl1(value);
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE void SetExceptionThreadStackTop(uintptr_t top) {
|
||||||
|
SetTpidrEl1(top);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void SwitchThreadLocalRegion(uintptr_t tlr) {
|
ALWAYS_INLINE void SwitchThreadLocalRegion(uintptr_t tlr) {
|
||||||
|
|||||||
@@ -19,18 +19,14 @@
|
|||||||
|
|
||||||
namespace ams::kern::arch::arm64 {
|
namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
namespace impl {
|
class KHardwareTimer : public KInterruptTask, public KHardwareTimerBase {
|
||||||
|
private:
|
||||||
class KHardwareTimerInterruptTask;
|
s64 maximum_time;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class KHardwareTimer : public KHardwareTimerBase {
|
|
||||||
public:
|
public:
|
||||||
constexpr KHardwareTimer() : KHardwareTimerBase() { /* ... */ }
|
constexpr KHardwareTimer() : KInterruptTask(), KHardwareTimerBase(), maximum_time(std::numeric_limits<s64>::max()) { /* ... */ }
|
||||||
public:
|
public:
|
||||||
/* Public API. */
|
/* Public API. */
|
||||||
NOINLINE void Initialize(s32 core_id);
|
NOINLINE void Initialize();
|
||||||
NOINLINE void Finalize();
|
NOINLINE void Finalize();
|
||||||
|
|
||||||
static s64 GetTick() {
|
static s64 GetTick() {
|
||||||
@@ -42,13 +38,12 @@ namespace ams::kern::arch::arm64 {
|
|||||||
KScopedSpinLock lk(this->GetLock());
|
KScopedSpinLock lk(this->GetLock());
|
||||||
|
|
||||||
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
|
||||||
SetCompareValue(task_time);
|
if (task_time <= this->maximum_time) {
|
||||||
EnableInterrupt();
|
SetCompareValue(task_time);
|
||||||
|
EnableInterrupt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
friend class impl::KHardwareTimerInterruptTask;
|
|
||||||
NOINLINE void DoInterruptTask();
|
|
||||||
private:
|
private:
|
||||||
/* Hardware register accessors. */
|
/* Hardware register accessors. */
|
||||||
static ALWAYS_INLINE void InitializeGlobalTimer() {
|
static ALWAYS_INLINE void InitializeGlobalTimer() {
|
||||||
@@ -88,7 +83,13 @@ namespace ams::kern::arch::arm64 {
|
|||||||
static ALWAYS_INLINE void SetCompareValue(s64 value) {
|
static ALWAYS_INLINE void SetCompareValue(s64 value) {
|
||||||
cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor(0).SetCompareValue(static_cast<u64>(value)).Store();
|
cpu::CounterTimerPhysicalTimerCompareValueRegisterAccessor(0).SetCompareValue(static_cast<u64>(value)).Store();
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override {
|
||||||
|
MESOSPHERE_UNUSED(interrupt_id);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void DoTask() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,23 +47,23 @@ namespace ams::kern::arch::arm64 {
|
|||||||
constexpr KGlobalInterruptEntry() : handler(nullptr), manually_cleared(false), needs_clear(false) { /* ... */ }
|
constexpr KGlobalInterruptEntry() : handler(nullptr), manually_cleared(false), needs_clear(false) { /* ... */ }
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
static KSpinLock s_lock;
|
KCoreLocalInterruptEntry core_local_interrupts[cpu::NumCores][KInterruptController::NumLocalInterrupts]{};
|
||||||
static std::array<KGlobalInterruptEntry, KInterruptController::NumGlobalInterrupts> s_global_interrupts;
|
KInterruptController interrupt_controller{};
|
||||||
static KInterruptController::GlobalState s_global_state;
|
KInterruptController::LocalState local_states[cpu::NumCores]{};
|
||||||
static bool s_global_state_saved;
|
bool local_state_saved[cpu::NumCores]{};
|
||||||
|
mutable KSpinLock global_interrupt_lock{};
|
||||||
|
KGlobalInterruptEntry global_interrupts[KInterruptController::NumGlobalInterrupts]{};
|
||||||
|
KInterruptController::GlobalState global_state{};
|
||||||
|
bool global_state_saved{};
|
||||||
private:
|
private:
|
||||||
KCoreLocalInterruptEntry core_local_interrupts[KInterruptController::NumLocalInterrupts];
|
ALWAYS_INLINE KSpinLock &GetGlobalInterruptLock() const { return this->global_interrupt_lock; }
|
||||||
KInterruptController interrupt_controller;
|
ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return this->global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
|
||||||
KInterruptController::LocalState local_state;
|
ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return this->core_local_interrupts[GetCurrentCoreId()][KInterruptController::GetLocalInterruptIndex(irq)]; }
|
||||||
bool local_state_saved;
|
|
||||||
private:
|
|
||||||
static ALWAYS_INLINE KSpinLock &GetLock() { return s_lock; }
|
|
||||||
static ALWAYS_INLINE KGlobalInterruptEntry &GetGlobalInterruptEntry(s32 irq) { return s_global_interrupts[KInterruptController::GetGlobalInterruptIndex(irq)]; }
|
|
||||||
ALWAYS_INLINE KCoreLocalInterruptEntry &GetLocalInterruptEntry(s32 irq) { return this->core_local_interrupts[KInterruptController::GetLocalInterruptIndex(irq)]; }
|
|
||||||
|
|
||||||
bool OnHandleInterrupt();
|
bool OnHandleInterrupt();
|
||||||
public:
|
public:
|
||||||
constexpr KInterruptManager() : core_local_interrupts(), interrupt_controller(), local_state(), local_state_saved(false) { /* ... */ }
|
constexpr KInterruptManager() = default;
|
||||||
|
|
||||||
NOINLINE void Initialize(s32 core_id);
|
NOINLINE void Initialize(s32 core_id);
|
||||||
NOINLINE void Finalize(s32 core_id);
|
NOINLINE void Finalize(s32 core_id);
|
||||||
|
|
||||||
|
|||||||
@@ -134,9 +134,6 @@ namespace ams::kern::arch::arm64 {
|
|||||||
entry.SetUserExecuteNever(true);
|
entry.SetUserExecuteNever(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set can be contiguous. */
|
|
||||||
entry.SetContiguousAllowed(!properties.non_contiguous);
|
|
||||||
|
|
||||||
/* Set AP[1] based on perm. */
|
/* Set AP[1] based on perm. */
|
||||||
switch (properties.perm & KMemoryPermission_UserReadWrite) {
|
switch (properties.perm & KMemoryPermission_UserReadWrite) {
|
||||||
case KMemoryPermission_UserReadWrite:
|
case KMemoryPermission_UserReadWrite:
|
||||||
@@ -179,19 +176,19 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
|
||||||
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager);
|
NOINLINE Result InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager);
|
||||||
Result Finalize();
|
Result Finalize();
|
||||||
private:
|
private:
|
||||||
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
Result MapL1Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
Result MapL2Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
Result MapL2Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
Result MapL3Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
Result MapL3Blocks(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
|
|
||||||
Result Unmap(KProcessAddress virt_addr, size_t num_pages, PageLinkedList *page_list, bool force, bool reuse_ll);
|
Result Unmap(KProcessAddress virt_addr, size_t num_pages, PageLinkedList *page_list, bool force, bool reuse_ll);
|
||||||
|
|
||||||
Result Map(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, size_t page_size, PageLinkedList *page_list, bool reuse_ll) {
|
Result Map(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, size_t page_size, PageLinkedList *page_list, bool reuse_ll) {
|
||||||
switch (page_size) {
|
switch (page_size) {
|
||||||
case L1BlockSize:
|
case L1BlockSize:
|
||||||
return this->MapL1Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
return this->MapL1Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||||
case L2ContiguousBlockSize:
|
case L2ContiguousBlockSize:
|
||||||
entry_template.SetContiguous(true);
|
entry_template.SetContiguous(true);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
@@ -199,25 +196,25 @@ namespace ams::kern::arch::arm64 {
|
|||||||
case L2TegraSmmuBlockSize:
|
case L2TegraSmmuBlockSize:
|
||||||
#endif
|
#endif
|
||||||
case L2BlockSize:
|
case L2BlockSize:
|
||||||
return this->MapL2Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
return this->MapL2Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||||
case L3ContiguousBlockSize:
|
case L3ContiguousBlockSize:
|
||||||
entry_template.SetContiguous(true);
|
entry_template.SetContiguous(true);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case L3BlockSize:
|
case L3BlockSize:
|
||||||
return this->MapL3Blocks(virt_addr, phys_addr, num_pages, entry_template, page_list, reuse_ll);
|
return this->MapL3Blocks(virt_addr, phys_addr, num_pages, entry_template, disable_head_merge, page_list, reuse_ll);
|
||||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, PageLinkedList *page_list, bool reuse_ll);
|
Result MapGroup(KProcessAddress virt_addr, const KPageGroup &pg, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
|
||||||
|
|
||||||
bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list);
|
bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list);
|
||||||
|
|
||||||
ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
||||||
Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll);
|
||||||
|
|
||||||
Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll);
|
Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll);
|
||||||
|
|
||||||
static void PteDataSynchronizationBarrier() {
|
static void PteDataSynchronizationBarrier() {
|
||||||
cpu::DataSynchronizationBarrierInnerShareable();
|
cpu::DataSynchronizationBarrierInnerShareable();
|
||||||
|
|||||||
@@ -69,9 +69,23 @@ namespace ams::kern::arch::arm64 {
|
|||||||
MappingFlag_Mapped = (1 << 0),
|
MappingFlag_Mapped = (1 << 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SoftwareReservedBit : u8 {
|
||||||
|
SoftwareReservedBit_None = 0,
|
||||||
|
SoftwareReservedBit_DisableMergeHead = (1u << 0),
|
||||||
|
SoftwareReservedBit_DisableMergeHeadAndBody = (1u << 1),
|
||||||
|
SoftwareReservedBit_DisableMergeHeadTail = (1u << 2),
|
||||||
|
SoftwareReservedBit_Valid = (1u << 3),
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr ALWAYS_INLINE std::underlying_type<SoftwareReservedBit>::type EncodeSoftwareReservedBits(bool head, bool head_body, bool tail) {
|
||||||
|
return (head ? SoftwareReservedBit_DisableMergeHead : SoftwareReservedBit_None) | (head_body ? SoftwareReservedBit_DisableMergeHeadAndBody : SoftwareReservedBit_None) | (tail ? SoftwareReservedBit_DisableMergeHeadTail : SoftwareReservedBit_None);
|
||||||
|
}
|
||||||
|
|
||||||
enum ExtensionFlag : u64 {
|
enum ExtensionFlag : u64 {
|
||||||
ExtensionFlag_NotContiguous = (1ul << 55),
|
ExtensionFlag_DisableMergeHead = (static_cast<u64>(SoftwareReservedBit_DisableMergeHead) << 55),
|
||||||
ExtensionFlag_Valid = (1ul << 56),
|
ExtensionFlag_DisableMergeHeadAndBody = (static_cast<u64>(SoftwareReservedBit_DisableMergeHeadAndBody) << 55),
|
||||||
|
ExtensionFlag_DisableMergeTail = (static_cast<u64>(SoftwareReservedBit_DisableMergeHeadTail) << 55),
|
||||||
|
ExtensionFlag_Valid = (static_cast<u64>(SoftwareReservedBit_Valid) << 55),
|
||||||
|
|
||||||
ExtensionFlag_ValidAndMapped = (ExtensionFlag_Valid | MappingFlag_Mapped),
|
ExtensionFlag_ValidAndMapped = (ExtensionFlag_Valid | MappingFlag_Mapped),
|
||||||
ExtensionFlag_TestTableMask = (ExtensionFlag_Valid | (1ul << 1)),
|
ExtensionFlag_TestTableMask = (ExtensionFlag_Valid | (1ul << 1)),
|
||||||
@@ -138,23 +152,26 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE bool IsContiguousAllowed() const { return this->GetBits(55, 1) == 0; }
|
constexpr ALWAYS_INLINE u8 GetSoftwareReservedBits() const { return this->GetBits(55, 3); }
|
||||||
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsHeadMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHead) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsHeadAndBodyMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHeadAndBody) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsTailMergeDisabled() const { return (this->GetSoftwareReservedBits() & SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; }
|
constexpr ALWAYS_INLINE bool IsHeadOrHeadAndBodyMergeDisabled() const { return (this->GetSoftwareReservedBits() & (SoftwareReservedBit_DisableMergeHead | SoftwareReservedBit_DisableMergeHeadAndBody)) != 0; }
|
||||||
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); }
|
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); }
|
constexpr ALWAYS_INLINE bool IsPrivilegedExecuteNever() const { return this->GetBits(53, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); }
|
constexpr ALWAYS_INLINE bool IsContiguous() const { return this->GetBits(52, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsGlobal() const { return this->GetBits(11, 1) == 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
constexpr ALWAYS_INLINE AccessFlag GetAccessFlag() const { return static_cast<AccessFlag>(this->GetBits(10, 1)); }
|
||||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
constexpr ALWAYS_INLINE Shareable GetShareable() const { return static_cast<Shareable>(this->GetBits(8, 2)); }
|
||||||
constexpr ALWAYS_INLINE bool IsBlock() const { return (this->attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
constexpr ALWAYS_INLINE PageAttribute GetPageAttribute() const { return static_cast<PageAttribute>(this->GetBits(2, 3)); }
|
||||||
constexpr ALWAYS_INLINE bool IsTable() const { return (this->attributes & ExtensionFlag_TestTableMask) == 2; }
|
constexpr ALWAYS_INLINE bool IsReadOnly() const { return this->GetBits(7, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsEmpty() const { return (this->attributes & ExtensionFlag_TestTableMask) == 0; }
|
constexpr ALWAYS_INLINE bool IsUserAccessible() const { return this->GetBits(6, 1) != 0; }
|
||||||
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 0; }
|
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBits(5, 1) != 0; }
|
||||||
|
constexpr ALWAYS_INLINE bool IsBlock() const { return (this->attributes & ExtensionFlag_TestTableMask) == ExtensionFlag_Valid; }
|
||||||
|
constexpr ALWAYS_INLINE bool IsTable() const { return (this->attributes & ExtensionFlag_TestTableMask) == 2; }
|
||||||
|
constexpr ALWAYS_INLINE bool IsEmpty() const { return (this->attributes & ExtensionFlag_TestTableMask) == 0; }
|
||||||
|
constexpr ALWAYS_INLINE bool IsMapped() const { return this->GetBits(0, 1) != 0; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetContiguousAllowed(bool en) { this->SetBit(55, !en); return *this; }
|
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetUserExecuteNever(bool en) { this->SetBit(54, en); return *this; }
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetPrivilegedExecuteNever(bool en) { this->SetBit(53, en); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetPrivilegedExecuteNever(bool en) { this->SetBit(53, en); return *this; }
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetContiguous(bool en) { this->SetBit(52, en); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetContiguous(bool en) { this->SetBit(52, en); return *this; }
|
||||||
@@ -166,13 +183,14 @@ namespace ams::kern::arch::arm64 {
|
|||||||
constexpr ALWAYS_INLINE decltype(auto) SetPageAttribute(PageAttribute a) { this->SetBitsDirect(2, 3, a); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetPageAttribute(PageAttribute a) { this->SetBitsDirect(2, 3, a); return *this; }
|
||||||
constexpr ALWAYS_INLINE decltype(auto) SetMapped(bool m) { static_assert(static_cast<u64>(MappingFlag_Mapped == (1 << 0))); this->SetBit(0, m); return *this; }
|
constexpr ALWAYS_INLINE decltype(auto) SetMapped(bool m) { static_assert(static_cast<u64>(MappingFlag_Mapped == (1 << 0))); this->SetBit(0, m); return *this; }
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetEntryTemplate() const {
|
constexpr ALWAYS_INLINE u64 GetEntryTemplateForMerge() const {
|
||||||
constexpr u64 Mask = (0xFFF0000000000FFFul & ~u64((0x1ul << 52) | ExtensionFlag_TestTableMask));
|
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||||
return this->attributes & Mask;
|
return this->attributes & BaseMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool Is(u64 attr) const {
|
constexpr ALWAYS_INLINE bool IsForMerge(u64 attr) const {
|
||||||
return this->attributes == attr;
|
constexpr u64 BaseMaskForMerge = ~static_cast<u64>(ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail);
|
||||||
|
return (this->attributes & BaseMaskForMerge) == attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
constexpr ALWAYS_INLINE u64 GetRawAttributesUnsafeForSwap() const {
|
||||||
@@ -207,8 +225,8 @@ namespace ams::kern::arch::arm64 {
|
|||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr explicit ALWAYS_INLINE L1PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr explicit ALWAYS_INLINE L1PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -230,9 +248,26 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2BlockMask(size_t idx) {
|
||||||
|
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||||
|
if (idx == 0) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < L2ContiguousBlockSize / L2BlockSize) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < (L1BlockSize - L2ContiguousBlockSize) / L2BlockSize) {
|
||||||
|
return BaseMask;
|
||||||
|
} else {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2Block(size_t idx) const {
|
||||||
|
return this->attributes & GetEntryTemplateForL2BlockMask(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||||
return L1PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
return L1PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -252,8 +287,8 @@ namespace ams::kern::arch::arm64 {
|
|||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr explicit ALWAYS_INLINE L2PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr explicit ALWAYS_INLINE L2PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | PageTableEntry::ExtensionFlag_Valid)
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -275,9 +310,41 @@ namespace ams::kern::arch::arm64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2BlockMask(size_t idx) {
|
||||||
|
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||||
|
if (idx == 0) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < (L2ContiguousBlockSize / L2BlockSize) - 1) {
|
||||||
|
return BaseMask;
|
||||||
|
} else {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL2Block(size_t idx) const {
|
||||||
|
return this->attributes & GetEntryTemplateForL2BlockMask(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3BlockMask(size_t idx) {
|
||||||
|
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||||
|
if (idx == 0) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < L3ContiguousBlockSize / L3BlockSize) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < (L2BlockSize - L3ContiguousBlockSize) / L3BlockSize) {
|
||||||
|
return BaseMask;
|
||||||
|
} else {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3Block(size_t idx) const {
|
||||||
|
return this->attributes & GetEntryTemplateForL3BlockMask(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||||
return L2PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
return L2PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -285,8 +352,8 @@ namespace ams::kern::arch::arm64 {
|
|||||||
public:
|
public:
|
||||||
constexpr explicit ALWAYS_INLINE L3PageTableEntry(InvalidTag) : PageTableEntry(InvalidTag{}) { /* ... */ }
|
constexpr explicit ALWAYS_INLINE L3PageTableEntry(InvalidTag) : PageTableEntry(InvalidTag{}) { /* ... */ }
|
||||||
|
|
||||||
constexpr explicit ALWAYS_INLINE L3PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
|
constexpr explicit ALWAYS_INLINE L3PageTableEntry(BlockTag, KPhysicalAddress phys_addr, const PageTableEntry &attr, u8 sw_reserved_bits, bool contig)
|
||||||
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | static_cast<u64>(ExtensionFlag_TestTableMask))
|
: PageTableEntry(attr, (static_cast<u64>(sw_reserved_bits) << 55) | (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | static_cast<u64>(ExtensionFlag_TestTableMask))
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -297,9 +364,24 @@ namespace ams::kern::arch::arm64 {
|
|||||||
return this->SelectBits(12, 36);
|
return this->SelectBits(12, 36);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
|
static constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3BlockMask(size_t idx) {
|
||||||
|
constexpr u64 BaseMask = (0xFFF0000000000FFFul & ~static_cast<u64>((0x1ul << 52) | ExtensionFlag_TestTableMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody | ExtensionFlag_DisableMergeTail));
|
||||||
|
if (idx == 0) {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeHead | ExtensionFlag_DisableMergeHeadAndBody;
|
||||||
|
} else if (idx < (L3ContiguousBlockSize / L3BlockSize) - 1) {
|
||||||
|
return BaseMask;
|
||||||
|
} else {
|
||||||
|
return BaseMask | ExtensionFlag_DisableMergeTail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE u64 GetEntryTemplateForL3Block(size_t idx) const {
|
||||||
|
return this->attributes & GetEntryTemplateForL3BlockMask(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, u8 sw_reserved_bits, bool contig) const {
|
||||||
/* Check whether this has the same permission/etc as the desired attributes. */
|
/* Check whether this has the same permission/etc as the desired attributes. */
|
||||||
return L3PageTableEntry(BlockTag{}, this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
|
return L3PageTableEntry(BlockTag{}, this->GetBlock(), rhs, sw_reserved_bits, contig).GetRawAttributes() == this->GetRawAttributes();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ namespace ams::kern::arch::arm64 {
|
|||||||
struct TraversalEntry {
|
struct TraversalEntry {
|
||||||
KPhysicalAddress phys_addr;
|
KPhysicalAddress phys_addr;
|
||||||
size_t block_size;
|
size_t block_size;
|
||||||
|
u8 sw_reserved_bits;
|
||||||
|
|
||||||
|
constexpr bool IsHeadMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHead) != 0; }
|
||||||
|
constexpr bool IsHeadAndBodyMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadAndBody) != 0; }
|
||||||
|
constexpr bool IsTailMergeDisabled() const { return (this->sw_reserved_bits & PageTableEntry::SoftwareReservedBit_DisableMergeHeadTail) != 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TraversalContext {
|
struct TraversalContext {
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ namespace ams::kern::arch::arm64 {
|
|||||||
this->page_table.Activate(id);
|
this->page_table.Activate(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
||||||
return this->page_table.InitializeForProcess(id, as_type, enable_aslr, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
return this->page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Finalize() { this->page_table.Finalize(); }
|
void Finalize() { this->page_table.Finalize(); }
|
||||||
@@ -128,10 +128,6 @@ namespace ams::kern::arch::arm64 {
|
|||||||
return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) {
|
|
||||||
return this->page_table.MakeAndOpenPageGroupContiguous(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result InvalidateProcessDataCache(KProcessAddress address, size_t size) {
|
Result InvalidateProcessDataCache(KProcessAddress address, size_t size) {
|
||||||
return this->page_table.InvalidateProcessDataCache(address, size);
|
return this->page_table.InvalidateProcessDataCache(address, size);
|
||||||
}
|
}
|
||||||
@@ -152,6 +148,14 @@ namespace ams::kern::arch::arm64 {
|
|||||||
return this->page_table.UnlockForDeviceAddressSpace(address, size);
|
return this->page_table.UnlockForDeviceAddressSpace(address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result MakePageGroupForUnmapDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size) {
|
||||||
|
return this->page_table.MakePageGroupForUnmapDeviceAddressSpace(out, address, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size, size_t mapped_size) {
|
||||||
|
return this->page_table.UnlockForDeviceAddressSpacePartialMap(address, size, mapped_size);
|
||||||
|
}
|
||||||
|
|
||||||
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size) {
|
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size) {
|
||||||
return this->page_table.LockForIpcUserBuffer(out, address, size);
|
return this->page_table.LockForIpcUserBuffer(out, address, size);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
public:
|
public:
|
||||||
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
||||||
|
|
||||||
void Lock() {
|
ALWAYS_INLINE void Lock() {
|
||||||
u32 tmp0, tmp1, tmp2;
|
u32 tmp0, tmp1, tmp2;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
@@ -52,7 +52,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unlock() {
|
ALWAYS_INLINE void Unlock() {
|
||||||
const u32 value = this->packed_tickets + 1;
|
const u32 value = this->packed_tickets + 1;
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" stlrh %w[value], %[packed_tickets]\n"
|
" stlrh %w[value], %[packed_tickets]\n"
|
||||||
@@ -71,7 +71,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
public:
|
public:
|
||||||
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
||||||
|
|
||||||
void Lock() {
|
ALWAYS_INLINE void Lock() {
|
||||||
u32 tmp0, tmp1, got_lock;
|
u32 tmp0, tmp1, got_lock;
|
||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
@@ -94,7 +94,7 @@ namespace ams::kern::arch::arm64 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unlock() {
|
ALWAYS_INLINE void Unlock() {
|
||||||
const u32 value = this->current_ticket + 1;
|
const u32 value = this->current_ticket + 1;
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" stlrh %w[value], %[current_ticket]\n"
|
" stlrh %w[value], %[current_ticket]\n"
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -71,6 +71,10 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
|
|
||||||
Result Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings);
|
Result Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings);
|
||||||
Result Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address);
|
Result Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address);
|
||||||
|
|
||||||
|
void Unmap(KDeviceVirtualAddress device_address, size_t size) {
|
||||||
|
return this->UnmapImpl(device_address, size, false);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
Result MapDevicePage(size_t *out_mapped_size, s32 &num_pt, s32 max_pt, KPhysicalAddress phys_addr, u64 size, KDeviceVirtualAddress address, ams::svc::MemoryPermission device_perm);
|
Result MapDevicePage(size_t *out_mapped_size, s32 &num_pt, s32 max_pt, KPhysicalAddress phys_addr, u64 size, KDeviceVirtualAddress address, ams::svc::MemoryPermission device_perm);
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,5 @@
|
|||||||
namespace ams::kern::init {
|
namespace ams::kern::init {
|
||||||
|
|
||||||
KPhysicalAddress GetInitArgumentsAddress(s32 core_id);
|
KPhysicalAddress GetInitArgumentsAddress(s32 core_id);
|
||||||
void SetInitArguments(s32 core_id, KPhysicalAddress address, uintptr_t arg);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ namespace ams::kern::init {
|
|||||||
size_t num_KObjectName;
|
size_t num_KObjectName;
|
||||||
size_t num_KResourceLimit;
|
size_t num_KResourceLimit;
|
||||||
size_t num_KDebug;
|
size_t num_KDebug;
|
||||||
|
size_t num_KAlpha;
|
||||||
|
size_t num_KBeta;
|
||||||
};
|
};
|
||||||
|
|
||||||
NOINLINE void InitializeSlabResourceCounts();
|
NOINLINE void InitializeSlabResourceCounts();
|
||||||
|
|||||||
41
libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp
Normal file
41
libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE ~KScopedAutoObject() {
|
~KScopedAutoObject() {
|
||||||
if (this->obj != nullptr) {
|
if (this->obj != nullptr) {
|
||||||
this->obj->Close();
|
this->obj->Close();
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename U> requires (std::derived_from<T, U> || std::derived_from<U, T>)
|
template<typename U> requires (std::derived_from<T, U> || std::derived_from<U, T>)
|
||||||
constexpr ALWAYS_INLINE KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
constexpr KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
||||||
if constexpr (std::derived_from<U, T>) {
|
if constexpr (std::derived_from<U, T>) {
|
||||||
/* Upcast. */
|
/* Upcast. */
|
||||||
this->obj = rhs.obj;
|
this->obj = rhs.obj;
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ namespace ams::kern {
|
|||||||
void Initialize() { MESOSPHERE_ASSERT_THIS(); }
|
void Initialize() { MESOSPHERE_ASSERT_THIS(); }
|
||||||
void Finalize() { MESOSPHERE_ASSERT_THIS(); }
|
void Finalize() { MESOSPHERE_ASSERT_THIS(); }
|
||||||
|
|
||||||
Result Register(KAutoObjectWithList *obj);
|
void Register(KAutoObjectWithList *obj);
|
||||||
Result Unregister(KAutoObjectWithList *obj);
|
void Unregister(KAutoObjectWithList *obj);
|
||||||
size_t GetOwnedCount(KProcess *owner);
|
size_t GetOwnedCount(KProcess *owner);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
48
libraries/libmesosphere/include/mesosphere/kern_k_beta.hpp
Normal file
48
libraries/libmesosphere/include/mesosphere/kern_k_beta.hpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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,6 +112,10 @@ namespace ams::kern {
|
|||||||
KSessionRequest,
|
KSessionRequest,
|
||||||
KCodeMemory,
|
KCodeMemory,
|
||||||
|
|
||||||
|
/* NOTE: True order for these has not been determined yet. */
|
||||||
|
KAlpha,
|
||||||
|
KBeta,
|
||||||
|
|
||||||
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@
|
|||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
extern KThread g_cv_arbiter_compare_thread;
|
|
||||||
|
|
||||||
class KConditionVariable {
|
class KConditionVariable {
|
||||||
public:
|
public:
|
||||||
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;
|
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;
|
||||||
|
|||||||
@@ -1,61 +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_select_cpu.hpp>
|
|
||||||
#include <mesosphere/kern_k_current_context.hpp>
|
|
||||||
#include <mesosphere/kern_k_scheduler.hpp>
|
|
||||||
#include <mesosphere/kern_k_interrupt_task_manager.hpp>
|
|
||||||
#include <mesosphere/kern_select_interrupt_manager.hpp>
|
|
||||||
#include <mesosphere/kern_select_hardware_timer.hpp>
|
|
||||||
#include <mesosphere/kern_k_memory_manager.hpp>
|
|
||||||
|
|
||||||
namespace ams::kern {
|
|
||||||
|
|
||||||
struct KCoreLocalContext {
|
|
||||||
KCurrentContext current;
|
|
||||||
KScheduler scheduler;
|
|
||||||
KInterruptTaskManager interrupt_task_manager;
|
|
||||||
KInterruptManager interrupt_manager;
|
|
||||||
KHardwareTimer hardware_timer;
|
|
||||||
/* Everything after this point is for debugging. */
|
|
||||||
/* Retail kernel doesn't even consistently update these fields. */
|
|
||||||
u64 num_sw_interrupts;
|
|
||||||
u64 num_hw_interrupts;
|
|
||||||
std::atomic<u64> num_svc;
|
|
||||||
u64 num_process_switches;
|
|
||||||
u64 num_thread_switches;
|
|
||||||
u64 num_fpu_switches;
|
|
||||||
u64 num_scheduler_updates;
|
|
||||||
u64 num_invoked_scheduler_updates;
|
|
||||||
std::atomic<u64> num_specific_svc[0x80];
|
|
||||||
u32 perf_counters[6];
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KCoreLocalContext) < PageSize);
|
|
||||||
|
|
||||||
struct KCoreLocalPage {
|
|
||||||
KCoreLocalContext context;
|
|
||||||
u8 padding[PageSize - sizeof(KCoreLocalContext)];
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KCoreLocalPage) == PageSize);
|
|
||||||
|
|
||||||
struct KCoreLocalRegion {
|
|
||||||
KCoreLocalPage current;
|
|
||||||
KCoreLocalPage absolute[cpu::NumCores];
|
|
||||||
};
|
|
||||||
static_assert(sizeof(KCoreLocalRegion) == PageSize * (1 + cpu::NumCores));
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -21,80 +21,24 @@ namespace ams::kern {
|
|||||||
class KThread;
|
class KThread;
|
||||||
class KProcess;
|
class KProcess;
|
||||||
class KScheduler;
|
class KScheduler;
|
||||||
class KInterruptTaskManager;
|
|
||||||
|
|
||||||
struct KCurrentContext {
|
|
||||||
std::atomic<KThread *> current_thread;
|
|
||||||
std::atomic<KProcess *> current_process;
|
|
||||||
KScheduler *scheduler;
|
|
||||||
KInterruptTaskManager *interrupt_task_manager;
|
|
||||||
s32 core_id;
|
|
||||||
void *exception_stack_top;
|
|
||||||
ams::svc::ThreadLocalRegion *tlr;
|
|
||||||
};
|
|
||||||
static_assert(std::is_standard_layout<KCurrentContext>::value && std::is_trivially_destructible<KCurrentContext>::value);
|
|
||||||
static_assert(sizeof(KCurrentContext) <= cpu::DataCacheLineSize);
|
|
||||||
static_assert(sizeof(std::atomic<KThread *>) == sizeof(KThread *));
|
|
||||||
static_assert(sizeof(std::atomic<KProcess *>) == sizeof(KProcess *));
|
|
||||||
|
|
||||||
namespace impl {
|
|
||||||
|
|
||||||
ALWAYS_INLINE KCurrentContext &GetCurrentContext() {
|
|
||||||
return *reinterpret_cast<KCurrentContext *>(cpu::GetCoreLocalRegionAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KThread *GetCurrentThreadPointer() {
|
ALWAYS_INLINE KThread *GetCurrentThreadPointer() {
|
||||||
return impl::GetCurrentContext().current_thread.load(std::memory_order_relaxed);
|
return reinterpret_cast<KThread *>(cpu::GetCurrentThreadPointerValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE KThread &GetCurrentThread() {
|
ALWAYS_INLINE KThread &GetCurrentThread() {
|
||||||
return *GetCurrentThreadPointer();
|
return *GetCurrentThreadPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE KProcess *GetCurrentProcessPointer() {
|
|
||||||
return impl::GetCurrentContext().current_process.load(std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KProcess &GetCurrentProcess() {
|
|
||||||
return *GetCurrentProcessPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KScheduler *GetCurrentSchedulerPointer() {
|
|
||||||
return impl::GetCurrentContext().scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KScheduler &GetCurrentScheduler() {
|
|
||||||
return *GetCurrentSchedulerPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KInterruptTaskManager *GetCurrentInterruptTaskManagerPointer() {
|
|
||||||
return impl::GetCurrentContext().interrupt_task_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE KInterruptTaskManager &GetCurrentInterruptTaskManager() {
|
|
||||||
return *GetCurrentInterruptTaskManagerPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE s32 GetCurrentCoreId() {
|
|
||||||
return impl::GetCurrentContext().core_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE ams::svc::ThreadLocalRegion *GetCurrentThreadLocalRegion() {
|
|
||||||
return impl::GetCurrentContext().tlr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE void SetCurrentThread(KThread *new_thread) {
|
ALWAYS_INLINE void SetCurrentThread(KThread *new_thread) {
|
||||||
impl::GetCurrentContext().current_thread = new_thread;
|
cpu::SetCurrentThreadPointerValue(reinterpret_cast<uintptr_t>(new_thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void SetCurrentProcess(KProcess *new_process) {
|
ALWAYS_INLINE KProcess *GetCurrentProcessPointer();
|
||||||
impl::GetCurrentContext().current_process = new_process;
|
ALWAYS_INLINE KProcess &GetCurrentProcess();
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE void SetCurrentThreadLocalRegion(void *address) {
|
ALWAYS_INLINE s32 GetCurrentCoreId();
|
||||||
impl::GetCurrentContext().tlr = static_cast<ams::svc::ThreadLocalRegion *>(address);
|
|
||||||
}
|
ALWAYS_INLINE KScheduler &GetCurrentScheduler();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ namespace ams::kern {
|
|||||||
struct InfoCreateThread {
|
struct InfoCreateThread {
|
||||||
u32 thread_id;
|
u32 thread_id;
|
||||||
uintptr_t tls_address;
|
uintptr_t tls_address;
|
||||||
uintptr_t entrypoint;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InfoExitProcess {
|
struct InfoExitProcess {
|
||||||
|
|||||||
@@ -160,14 +160,16 @@ namespace ams::kern {
|
|||||||
return this->template GetObjectWithoutPseudoHandle<T>(handle);
|
return this->template GetObjectWithoutPseudoHandle<T>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
||||||
/* Lock and look up in table. */
|
/* Lock and look up in table. */
|
||||||
KScopedDisableDispatch dd;
|
KScopedDisableDispatch dd;
|
||||||
KScopedSpinLock lk(this->lock);
|
KScopedSpinLock lk(this->lock);
|
||||||
|
|
||||||
KAutoObject *obj = this->GetObjectImpl(handle);
|
KAutoObject *obj = this->GetObjectImpl(handle);
|
||||||
if (obj->DynamicCast<KInterruptEvent *>() != nullptr) {
|
if (AMS_LIKELY(obj != nullptr)) {
|
||||||
return nullptr;
|
if (AMS_UNLIKELY(obj->DynamicCast<KInterruptEvent *>() != nullptr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|||||||
@@ -27,11 +27,10 @@ namespace ams::kern {
|
|||||||
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
|
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
|
||||||
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
|
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
|
||||||
private:
|
private:
|
||||||
KInterruptEventTask *task;
|
|
||||||
s32 interrupt_id;
|
s32 interrupt_id;
|
||||||
bool is_initialized;
|
bool is_initialized;
|
||||||
public:
|
public:
|
||||||
constexpr KInterruptEvent() : task(nullptr), interrupt_id(-1), is_initialized(false) { /* ... */ }
|
constexpr KInterruptEvent() : interrupt_id(-1), is_initialized(false) { /* ... */ }
|
||||||
virtual ~KInterruptEvent() { /* ... */ }
|
virtual ~KInterruptEvent() { /* ... */ }
|
||||||
|
|
||||||
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
|
Result Initialize(int32_t interrupt_name, ams::svc::InterruptType type);
|
||||||
@@ -49,17 +48,19 @@ namespace ams::kern {
|
|||||||
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
|
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
|
||||||
private:
|
private:
|
||||||
KInterruptEvent *event;
|
KInterruptEvent *event;
|
||||||
s32 interrupt_id;
|
KLightLock lock;
|
||||||
public:
|
public:
|
||||||
constexpr KInterruptEventTask() : event(nullptr), interrupt_id(-1) { /* ... */ }
|
constexpr KInterruptEventTask() : event(nullptr), lock() { /* ... */ }
|
||||||
~KInterruptEventTask() { /* ... */ }
|
~KInterruptEventTask() { /* ... */ }
|
||||||
|
|
||||||
|
KLightLock &GetLock() { return this->lock; }
|
||||||
|
|
||||||
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
|
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
|
||||||
virtual void DoTask() override;
|
virtual void DoTask() override;
|
||||||
|
|
||||||
void Unregister();
|
void Unregister(s32 interrupt_id);
|
||||||
public:
|
public:
|
||||||
static Result Register(KInterruptEventTask **out, s32 interrupt_id, bool level, KInterruptEvent *event);
|
static Result Register(s32 interrupt_id, bool level, KInterruptEvent *event);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,28 +165,42 @@ namespace ams::kern {
|
|||||||
|
|
||||||
enum KMemoryAttribute : u8 {
|
enum KMemoryAttribute : u8 {
|
||||||
KMemoryAttribute_None = 0x00,
|
KMemoryAttribute_None = 0x00,
|
||||||
KMemoryAttribute_UserMask = 0x7F,
|
|
||||||
KMemoryAttribute_All = 0xFF,
|
KMemoryAttribute_All = 0xFF,
|
||||||
|
KMemoryAttribute_UserMask = KMemoryAttribute_All,
|
||||||
|
|
||||||
KMemoryAttribute_Locked = ams::svc::MemoryAttribute_Locked,
|
KMemoryAttribute_Locked = ams::svc::MemoryAttribute_Locked,
|
||||||
KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked,
|
KMemoryAttribute_IpcLocked = ams::svc::MemoryAttribute_IpcLocked,
|
||||||
KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared,
|
KMemoryAttribute_DeviceShared = ams::svc::MemoryAttribute_DeviceShared,
|
||||||
KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached,
|
KMemoryAttribute_Uncached = ams::svc::MemoryAttribute_Uncached,
|
||||||
|
|
||||||
KMemoryAttribute_AnyLocked = 0x80,
|
|
||||||
|
|
||||||
KMemoryAttribute_SetMask = KMemoryAttribute_Uncached,
|
KMemoryAttribute_SetMask = KMemoryAttribute_Uncached,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum KMemoryBlockDisableMergeAttribute : u8 {
|
||||||
|
KMemoryBlockDisableMergeAttribute_None = 0,
|
||||||
|
KMemoryBlockDisableMergeAttribute_Normal = (1u << 0),
|
||||||
|
KMemoryBlockDisableMergeAttribute_DeviceLeft = (1u << 1),
|
||||||
|
KMemoryBlockDisableMergeAttribute_IpcLeft = (1u << 2),
|
||||||
|
KMemoryBlockDisableMergeAttribute_Locked = (1u << 3),
|
||||||
|
KMemoryBlockDisableMergeAttribute_DeviceRight = (1u << 4),
|
||||||
|
|
||||||
|
KMemoryBlockDisableMergeAttribute_AllLeft = KMemoryBlockDisableMergeAttribute_Normal | KMemoryBlockDisableMergeAttribute_DeviceLeft | KMemoryBlockDisableMergeAttribute_IpcLeft | KMemoryBlockDisableMergeAttribute_Locked,
|
||||||
|
KMemoryBlockDisableMergeAttribute_AllRight = KMemoryBlockDisableMergeAttribute_DeviceRight,
|
||||||
|
};
|
||||||
|
|
||||||
struct KMemoryInfo {
|
struct KMemoryInfo {
|
||||||
uintptr_t address;
|
uintptr_t address;
|
||||||
size_t size;
|
size_t size;
|
||||||
KMemoryState state;
|
KMemoryState state;
|
||||||
|
u16 device_disable_merge_left_count;
|
||||||
|
u16 device_disable_merge_right_count;
|
||||||
|
u16 ipc_lock_count;
|
||||||
|
u16 device_use_count;
|
||||||
|
u16 ipc_disable_merge_count;
|
||||||
KMemoryPermission perm;
|
KMemoryPermission perm;
|
||||||
KMemoryAttribute attribute;
|
KMemoryAttribute attribute;
|
||||||
KMemoryPermission original_perm;
|
KMemoryPermission original_perm;
|
||||||
u16 ipc_lock_count;
|
KMemoryBlockDisableMergeAttribute disable_merge_attribute;
|
||||||
u16 device_use_count;
|
|
||||||
|
|
||||||
constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const {
|
constexpr ams::svc::MemoryInfo GetSvcMemoryInfo() const {
|
||||||
return {
|
return {
|
||||||
@@ -225,6 +239,10 @@ namespace ams::kern {
|
|||||||
return this->ipc_lock_count;
|
return this->ipc_lock_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr u16 GetIpcDisableMergeCount() const {
|
||||||
|
return this->ipc_disable_merge_count;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr KMemoryState GetState() const {
|
constexpr KMemoryState GetState() const {
|
||||||
return this->state;
|
return this->state;
|
||||||
}
|
}
|
||||||
@@ -240,18 +258,26 @@ namespace ams::kern {
|
|||||||
constexpr KMemoryAttribute GetAttribute() const {
|
constexpr KMemoryAttribute GetAttribute() const {
|
||||||
return this->attribute;
|
return this->attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr KMemoryBlockDisableMergeAttribute GetDisableMergeAttribute() const {
|
||||||
|
return this->disable_merge_attribute;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class KMemoryBlock : public util::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> {
|
class KMemoryBlock : public util::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> {
|
||||||
private:
|
private:
|
||||||
|
u16 device_disable_merge_left_count;
|
||||||
|
u16 device_disable_merge_right_count;
|
||||||
KProcessAddress address;
|
KProcessAddress address;
|
||||||
size_t num_pages;
|
size_t num_pages;
|
||||||
KMemoryState memory_state;
|
KMemoryState memory_state;
|
||||||
u16 ipc_lock_count;
|
u16 ipc_lock_count;
|
||||||
u16 device_use_count;
|
u16 device_use_count;
|
||||||
|
u16 ipc_disable_merge_count;
|
||||||
KMemoryPermission perm;
|
KMemoryPermission perm;
|
||||||
KMemoryPermission original_perm;
|
KMemoryPermission original_perm;
|
||||||
KMemoryAttribute attribute;
|
KMemoryAttribute attribute;
|
||||||
|
KMemoryBlockDisableMergeAttribute disable_merge_attribute;
|
||||||
public:
|
public:
|
||||||
static constexpr ALWAYS_INLINE int Compare(const KMemoryBlock &lhs, const KMemoryBlock &rhs) {
|
static constexpr ALWAYS_INLINE int Compare(const KMemoryBlock &lhs, const KMemoryBlock &rhs) {
|
||||||
if (lhs.GetAddress() < rhs.GetAddress()) {
|
if (lhs.GetAddress() < rhs.GetAddress()) {
|
||||||
@@ -287,6 +313,10 @@ namespace ams::kern {
|
|||||||
return this->ipc_lock_count;
|
return this->ipc_lock_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr u16 GetIpcDisableMergeCount() const {
|
||||||
|
return this->ipc_disable_merge_count;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr KMemoryPermission GetPermission() const {
|
constexpr KMemoryPermission GetPermission() const {
|
||||||
return this->perm;
|
return this->perm;
|
||||||
}
|
}
|
||||||
@@ -301,25 +331,29 @@ namespace ams::kern {
|
|||||||
|
|
||||||
constexpr KMemoryInfo GetMemoryInfo() const {
|
constexpr KMemoryInfo GetMemoryInfo() const {
|
||||||
return {
|
return {
|
||||||
.address = GetInteger(this->GetAddress()),
|
.address = GetInteger(this->GetAddress()),
|
||||||
.size = this->GetSize(),
|
.size = this->GetSize(),
|
||||||
.state = this->memory_state,
|
.state = this->memory_state,
|
||||||
.perm = this->perm,
|
.device_disable_merge_left_count = this->device_disable_merge_left_count,
|
||||||
.attribute = this->attribute,
|
.device_disable_merge_right_count = this->device_disable_merge_right_count,
|
||||||
.original_perm = this->original_perm,
|
.ipc_lock_count = this->ipc_lock_count,
|
||||||
.ipc_lock_count = this->ipc_lock_count,
|
.device_use_count = this->device_use_count,
|
||||||
.device_use_count = this->device_use_count,
|
.ipc_disable_merge_count = this->ipc_disable_merge_count,
|
||||||
|
.perm = this->perm,
|
||||||
|
.attribute = this->attribute,
|
||||||
|
.original_perm = this->original_perm,
|
||||||
|
.disable_merge_attribute = this->disable_merge_attribute,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
constexpr KMemoryBlock()
|
constexpr KMemoryBlock()
|
||||||
: address(), num_pages(), memory_state(KMemoryState_None), ipc_lock_count(), device_use_count(), perm(), original_perm(), attribute()
|
: device_disable_merge_left_count(), device_disable_merge_right_count(), address(), num_pages(), memory_state(KMemoryState_None), ipc_lock_count(), device_use_count(), ipc_disable_merge_count(), perm(), original_perm(), attribute(), disable_merge_attribute()
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr KMemoryBlock(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p, KMemoryAttribute attr)
|
constexpr KMemoryBlock(KProcessAddress addr, size_t np, KMemoryState ms, KMemoryPermission p, KMemoryAttribute attr)
|
||||||
: address(addr), num_pages(np), memory_state(ms), ipc_lock_count(0), device_use_count(0), perm(p), original_perm(KMemoryPermission_None), attribute(attr)
|
: device_disable_merge_left_count(), device_disable_merge_right_count(), address(addr), num_pages(np), memory_state(ms), ipc_lock_count(0), device_use_count(0), ipc_disable_merge_count(), perm(p), original_perm(KMemoryPermission_None), attribute(attr), disable_merge_attribute()
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@@ -353,21 +387,29 @@ namespace ams::kern {
|
|||||||
this->device_use_count == rhs.device_use_count;
|
this->device_use_count == rhs.device_use_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr bool CanMergeWith(const KMemoryBlock &rhs) const {
|
||||||
|
return this->HasSameProperties(rhs) &&
|
||||||
|
(this->disable_merge_attribute & KMemoryBlockDisableMergeAttribute_AllRight) == 0 &&
|
||||||
|
(rhs.disable_merge_attribute & KMemoryBlockDisableMergeAttribute_AllLeft) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool Contains(KProcessAddress addr) const {
|
constexpr bool Contains(KProcessAddress addr) const {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
return this->GetAddress() <= addr && addr <= this->GetEndAddress();
|
return this->GetAddress() <= addr && addr <= this->GetEndAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void Add(size_t np) {
|
constexpr void Add(const KMemoryBlock &added_block) {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
MESOSPHERE_ASSERT(np > 0);
|
MESOSPHERE_ASSERT(added_block.GetNumPages() > 0);
|
||||||
MESOSPHERE_ASSERT(this->GetAddress() + np * PageSize - 1 < this->GetEndAddress() + np * PageSize - 1);
|
MESOSPHERE_ASSERT(this->GetAddress() + added_block.GetSize() - 1 < this->GetEndAddress() + added_block.GetSize() - 1);
|
||||||
|
|
||||||
this->num_pages += np;
|
this->num_pages += added_block.GetNumPages();
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute | added_block.disable_merge_attribute);
|
||||||
|
this->device_disable_merge_right_count = added_block.device_disable_merge_right_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void Update(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) {
|
constexpr void Update(KMemoryState s, KMemoryPermission p, KMemoryAttribute a, bool set_disable_merge_attr, u8 set_mask, u8 clear_mask) {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
MESOSPHERE_ASSERT(this->original_perm == KMemoryPermission_None);
|
MESOSPHERE_ASSERT(this->original_perm == KMemoryPermission_None);
|
||||||
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == 0);
|
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == 0);
|
||||||
@@ -375,6 +417,13 @@ namespace ams::kern {
|
|||||||
this->memory_state = s;
|
this->memory_state = s;
|
||||||
this->perm = p;
|
this->perm = p;
|
||||||
this->attribute = static_cast<KMemoryAttribute>(a | (this->attribute & (KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared)));
|
this->attribute = static_cast<KMemoryAttribute>(a | (this->attribute & (KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared)));
|
||||||
|
|
||||||
|
if (set_disable_merge_attr && set_mask != 0) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute | set_mask);
|
||||||
|
}
|
||||||
|
if (clear_mask != 0) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & ~clear_mask);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void Split(KMemoryBlock *block, KProcessAddress addr) {
|
constexpr void Split(KMemoryBlock *block, KProcessAddress addr) {
|
||||||
@@ -383,20 +432,55 @@ namespace ams::kern {
|
|||||||
MESOSPHERE_ASSERT(this->Contains(addr));
|
MESOSPHERE_ASSERT(this->Contains(addr));
|
||||||
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(addr), PageSize));
|
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(addr), PageSize));
|
||||||
|
|
||||||
block->address = this->address;
|
block->address = this->address;
|
||||||
block->num_pages = (addr - this->GetAddress()) / PageSize;
|
block->num_pages = (addr - this->GetAddress()) / PageSize;
|
||||||
block->memory_state = this->memory_state;
|
block->memory_state = this->memory_state;
|
||||||
block->ipc_lock_count = this->ipc_lock_count;
|
block->ipc_lock_count = this->ipc_lock_count;
|
||||||
block->device_use_count = this->device_use_count;
|
block->device_use_count = this->device_use_count;
|
||||||
block->perm = this->perm;
|
block->perm = this->perm;
|
||||||
block->original_perm = this->original_perm;
|
block->original_perm = this->original_perm;
|
||||||
block->attribute = this->attribute;
|
block->attribute = this->attribute;
|
||||||
|
block->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & KMemoryBlockDisableMergeAttribute_AllLeft);
|
||||||
|
block->ipc_disable_merge_count = this->ipc_disable_merge_count;
|
||||||
|
block->device_disable_merge_left_count = this->device_disable_merge_left_count;
|
||||||
|
block->device_disable_merge_right_count = 0;
|
||||||
|
|
||||||
this->address = addr;
|
this->address = addr;
|
||||||
this->num_pages -= block->num_pages;
|
this->num_pages -= block->num_pages;
|
||||||
|
|
||||||
|
this->ipc_disable_merge_count = 0;
|
||||||
|
this->device_disable_merge_left_count = 0;
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & KMemoryBlockDisableMergeAttribute_AllRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void ShareToDevice(KMemoryPermission new_perm) {
|
constexpr void UpdateDeviceDisableMergeStateForShareLeft(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
/* New permission/right aren't used. */
|
||||||
|
MESOSPHERE_UNUSED(new_perm, right);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute | KMemoryBlockDisableMergeAttribute_DeviceLeft);
|
||||||
|
const u16 new_device_disable_merge_left_count = ++this->device_disable_merge_left_count;
|
||||||
|
MESOSPHERE_ABORT_UNLESS(new_device_disable_merge_left_count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void UpdateDeviceDisableMergeStateForShareRight(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
/* New permission/left aren't used. */
|
||||||
|
MESOSPHERE_UNUSED(new_perm, left);
|
||||||
|
|
||||||
|
if (right) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute | KMemoryBlockDisableMergeAttribute_DeviceRight);
|
||||||
|
const u16 new_device_disable_merge_right_count = ++this->device_disable_merge_right_count;
|
||||||
|
MESOSPHERE_ABORT_UNLESS(new_device_disable_merge_right_count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void UpdateDeviceDisableMergeStateForShare(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
this->UpdateDeviceDisableMergeStateForShareLeft(new_perm, left, right);
|
||||||
|
this->UpdateDeviceDisableMergeStateForShareRight(new_perm, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void ShareToDevice(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
/* New permission isn't used. */
|
/* New permission isn't used. */
|
||||||
MESOSPHERE_UNUSED(new_perm);
|
MESOSPHERE_UNUSED(new_perm);
|
||||||
|
|
||||||
@@ -408,9 +492,47 @@ namespace ams::kern {
|
|||||||
MESOSPHERE_ABORT_UNLESS(new_count > 0);
|
MESOSPHERE_ABORT_UNLESS(new_count > 0);
|
||||||
|
|
||||||
this->attribute = static_cast<KMemoryAttribute>(this->attribute | KMemoryAttribute_DeviceShared);
|
this->attribute = static_cast<KMemoryAttribute>(this->attribute | KMemoryAttribute_DeviceShared);
|
||||||
|
|
||||||
|
this->UpdateDeviceDisableMergeStateForShare(new_perm, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void UnshareToDevice(KMemoryPermission new_perm) {
|
constexpr void UpdateDeviceDisableMergeStateForUnshareLeft(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
/* New permission/right aren't used. */
|
||||||
|
MESOSPHERE_UNUSED(new_perm, right);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
if (!this->device_disable_merge_left_count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
--this->device_disable_merge_left_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->device_disable_merge_left_count = std::min(this->device_disable_merge_left_count, this->device_use_count);
|
||||||
|
|
||||||
|
if (this->device_disable_merge_left_count == 0) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute_DeviceLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void UpdateDeviceDisableMergeStateForUnshareRight(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
/* New permission/left aren't used. */
|
||||||
|
MESOSPHERE_UNUSED(new_perm, left);
|
||||||
|
|
||||||
|
if (right) {
|
||||||
|
const u16 old_device_disable_merge_right_count = this->device_disable_merge_right_count--;
|
||||||
|
MESOSPHERE_ASSERT(old_device_disable_merge_right_count > 0);
|
||||||
|
if (old_device_disable_merge_right_count == 1) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute_DeviceRight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void UpdateDeviceDisableMergeStateForUnshare(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
this->UpdateDeviceDisableMergeStateForUnshareLeft(new_perm, left, right);
|
||||||
|
this->UpdateDeviceDisableMergeStateForUnshareRight(new_perm, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void UnshareToDevice(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
/* New permission isn't used. */
|
/* New permission isn't used. */
|
||||||
MESOSPHERE_UNUSED(new_perm);
|
MESOSPHERE_UNUSED(new_perm);
|
||||||
|
|
||||||
@@ -424,9 +546,29 @@ namespace ams::kern {
|
|||||||
if (old_count == 1) {
|
if (old_count == 1) {
|
||||||
this->attribute = static_cast<KMemoryAttribute>(this->attribute & ~KMemoryAttribute_DeviceShared);
|
this->attribute = static_cast<KMemoryAttribute>(this->attribute & ~KMemoryAttribute_DeviceShared);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->UpdateDeviceDisableMergeStateForUnshare(new_perm, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void LockForIpc(KMemoryPermission new_perm) {
|
constexpr void UnshareToDeviceRight(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
|
/* New permission isn't used. */
|
||||||
|
MESOSPHERE_UNUSED(new_perm);
|
||||||
|
|
||||||
|
/* We must be shared. */
|
||||||
|
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_DeviceShared) == KMemoryAttribute_DeviceShared);
|
||||||
|
|
||||||
|
/* Unhare. */
|
||||||
|
const u16 old_count = this->device_use_count--;
|
||||||
|
MESOSPHERE_ABORT_UNLESS(old_count > 0);
|
||||||
|
|
||||||
|
if (old_count == 1) {
|
||||||
|
this->attribute = static_cast<KMemoryAttribute>(this->attribute & ~KMemoryAttribute_DeviceShared);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->UpdateDeviceDisableMergeStateForUnshareRight(new_perm, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void LockForIpc(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
/* We must either be locked or have a zero lock count. */
|
/* We must either be locked or have a zero lock count. */
|
||||||
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == KMemoryAttribute_IpcLocked || this->ipc_lock_count == 0);
|
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == KMemoryAttribute_IpcLocked || this->ipc_lock_count == 0);
|
||||||
|
|
||||||
@@ -443,9 +585,16 @@ namespace ams::kern {
|
|||||||
this->perm = static_cast<KMemoryPermission>((new_perm & KMemoryPermission_IpcLockChangeMask) | (this->original_perm & ~KMemoryPermission_IpcLockChangeMask));
|
this->perm = static_cast<KMemoryPermission>((new_perm & KMemoryPermission_IpcLockChangeMask) | (this->original_perm & ~KMemoryPermission_IpcLockChangeMask));
|
||||||
}
|
}
|
||||||
this->attribute = static_cast<KMemoryAttribute>(this->attribute | KMemoryAttribute_IpcLocked);
|
this->attribute = static_cast<KMemoryAttribute>(this->attribute | KMemoryAttribute_IpcLocked);
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute | KMemoryBlockDisableMergeAttribute_IpcLeft);
|
||||||
|
const u16 new_ipc_disable_merge_count = ++this->ipc_disable_merge_count;
|
||||||
|
MESOSPHERE_ABORT_UNLESS(new_ipc_disable_merge_count > 0);
|
||||||
|
}
|
||||||
|
MESOSPHERE_UNUSED(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr void UnlockForIpc(KMemoryPermission new_perm) {
|
constexpr void UnlockForIpc(KMemoryPermission new_perm, bool left, bool right) {
|
||||||
/* New permission isn't used. */
|
/* New permission isn't used. */
|
||||||
MESOSPHERE_UNUSED(new_perm);
|
MESOSPHERE_UNUSED(new_perm);
|
||||||
|
|
||||||
@@ -463,6 +612,19 @@ namespace ams::kern {
|
|||||||
this->original_perm = KMemoryPermission_None;
|
this->original_perm = KMemoryPermission_None;
|
||||||
this->attribute = static_cast<KMemoryAttribute>(this->attribute & ~KMemoryAttribute_IpcLocked);
|
this->attribute = static_cast<KMemoryAttribute>(this->attribute & ~KMemoryAttribute_IpcLocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
const u16 old_ipc_disable_merge_count = this->ipc_disable_merge_count--;
|
||||||
|
MESOSPHERE_ASSERT(old_ipc_disable_merge_count > 0);
|
||||||
|
if (old_ipc_disable_merge_count == 1) {
|
||||||
|
this->disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(this->disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute_IpcLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MESOSPHERE_UNUSED(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr KMemoryBlockDisableMergeAttribute GetDisableMergeAttribute() const {
|
||||||
|
return this->disable_merge_attribute;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivially_destructible<KMemoryBlock>::value);
|
static_assert(std::is_trivially_destructible<KMemoryBlock>::value);
|
||||||
|
|||||||
@@ -22,39 +22,40 @@ namespace ams::kern {
|
|||||||
|
|
||||||
class KMemoryBlockManagerUpdateAllocator {
|
class KMemoryBlockManagerUpdateAllocator {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t NumBlocks = 2;
|
static constexpr size_t MaxBlocks = 2;
|
||||||
private:
|
private:
|
||||||
KMemoryBlock *blocks[NumBlocks];
|
KMemoryBlock *blocks[MaxBlocks];
|
||||||
size_t index;
|
size_t index;
|
||||||
KMemoryBlockSlabManager *slab_manager;
|
KMemoryBlockSlabManager *slab_manager;
|
||||||
Result result;
|
|
||||||
public:
|
public:
|
||||||
explicit KMemoryBlockManagerUpdateAllocator(KMemoryBlockSlabManager *sm) : blocks(), index(), slab_manager(sm), result(svc::ResultOutOfResource()) {
|
constexpr explicit KMemoryBlockManagerUpdateAllocator(KMemoryBlockSlabManager *sm) : blocks(), index(MaxBlocks), slab_manager(sm) { /* ... */ }
|
||||||
for (size_t i = 0; i < NumBlocks; i++) {
|
|
||||||
this->blocks[i] = this->slab_manager->Allocate();
|
|
||||||
if (this->blocks[i] == nullptr) {
|
|
||||||
this->result = svc::ResultOutOfResource();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->result = ResultSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
~KMemoryBlockManagerUpdateAllocator() {
|
~KMemoryBlockManagerUpdateAllocator() {
|
||||||
for (size_t i = 0; i < NumBlocks; i++) {
|
for (const auto &block : this->blocks) {
|
||||||
if (this->blocks[i] != nullptr) {
|
if (block != nullptr) {
|
||||||
this->slab_manager->Free(this->blocks[i]);
|
this->slab_manager->Free(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetResult() const {
|
Result Initialize(size_t num_blocks) {
|
||||||
return this->result;
|
/* Check num blocks. */
|
||||||
|
MESOSPHERE_ASSERT(num_blocks <= MaxBlocks);
|
||||||
|
|
||||||
|
/* Set index. */
|
||||||
|
this->index = MaxBlocks - num_blocks;
|
||||||
|
|
||||||
|
/* Allocate the blocks. */
|
||||||
|
for (size_t i = 0; i < num_blocks && i < MaxBlocks; ++i) {
|
||||||
|
this->blocks[this->index + i] = this->slab_manager->Allocate();
|
||||||
|
R_UNLESS(this->blocks[this->index + i] != nullptr, svc::ResultOutOfResource());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
KMemoryBlock *Allocate() {
|
KMemoryBlock *Allocate() {
|
||||||
MESOSPHERE_ABORT_UNLESS(this->index < NumBlocks);
|
MESOSPHERE_ABORT_UNLESS(this->index < MaxBlocks);
|
||||||
MESOSPHERE_ABORT_UNLESS(this->blocks[this->index] != nullptr);
|
MESOSPHERE_ABORT_UNLESS(this->blocks[this->index] != nullptr);
|
||||||
KMemoryBlock *block = nullptr;
|
KMemoryBlock *block = nullptr;
|
||||||
std::swap(block, this->blocks[this->index++]);
|
std::swap(block, this->blocks[this->index++]);
|
||||||
@@ -62,7 +63,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Free(KMemoryBlock *block) {
|
void Free(KMemoryBlock *block) {
|
||||||
MESOSPHERE_ABORT_UNLESS(this->index <= NumBlocks);
|
MESOSPHERE_ABORT_UNLESS(this->index <= MaxBlocks);
|
||||||
MESOSPHERE_ABORT_UNLESS(block != nullptr);
|
MESOSPHERE_ABORT_UNLESS(block != nullptr);
|
||||||
if (this->index == 0) {
|
if (this->index == 0) {
|
||||||
this->slab_manager->Free(block);
|
this->slab_manager->Free(block);
|
||||||
@@ -75,12 +76,15 @@ namespace ams::kern {
|
|||||||
class KMemoryBlockManager {
|
class KMemoryBlockManager {
|
||||||
public:
|
public:
|
||||||
using MemoryBlockTree = util::IntrusiveRedBlackTreeBaseTraits<KMemoryBlock>::TreeType<KMemoryBlock>;
|
using MemoryBlockTree = util::IntrusiveRedBlackTreeBaseTraits<KMemoryBlock>::TreeType<KMemoryBlock>;
|
||||||
|
using MemoryBlockLockFunction = void (KMemoryBlock::*)(KMemoryPermission new_perm, bool left, bool right);
|
||||||
using iterator = MemoryBlockTree::iterator;
|
using iterator = MemoryBlockTree::iterator;
|
||||||
using const_iterator = MemoryBlockTree::const_iterator;
|
using const_iterator = MemoryBlockTree::const_iterator;
|
||||||
private:
|
private:
|
||||||
MemoryBlockTree memory_block_tree;
|
MemoryBlockTree memory_block_tree;
|
||||||
KProcessAddress start_address;
|
KProcessAddress start_address;
|
||||||
KProcessAddress end_address;
|
KProcessAddress end_address;
|
||||||
|
private:
|
||||||
|
void CoalesceForUpdate(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages);
|
||||||
public:
|
public:
|
||||||
constexpr KMemoryBlockManager() : memory_block_tree(), start_address(), end_address() { /* ... */ }
|
constexpr KMemoryBlockManager() : memory_block_tree(), start_address(), end_address() { /* ... */ }
|
||||||
|
|
||||||
@@ -93,8 +97,8 @@ namespace ams::kern {
|
|||||||
|
|
||||||
KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const;
|
KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const;
|
||||||
|
|
||||||
void Update(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr);
|
void Update(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr, KMemoryBlockDisableMergeAttribute set_disable_attr, KMemoryBlockDisableMergeAttribute clear_disable_attr);
|
||||||
void UpdateLock(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, void (KMemoryBlock::*lock_func)(KMemoryPermission new_perm), KMemoryPermission perm);
|
void UpdateLock(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, MemoryBlockLockFunction lock_func, KMemoryPermission perm);
|
||||||
|
|
||||||
void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr);
|
void UpdateIfMatch(KMemoryBlockManagerUpdateAllocator *allocator, KProcessAddress address, size_t num_pages, KMemoryState test_state, KMemoryPermission test_perm, KMemoryAttribute test_attr, KMemoryState state, KMemoryPermission perm, KMemoryAttribute attr);
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,9 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) {
|
static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) {
|
||||||
return Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))).GetEndAddress();
|
const auto ®ion = Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
|
||||||
|
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||||
|
return region.GetEndAddress();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
|
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
|
||||||
@@ -134,7 +136,6 @@ namespace ams::kern {
|
|||||||
static NOINLINE KVirtualAddress GetExceptionStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); }
|
static NOINLINE KVirtualAddress GetExceptionStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); }
|
||||||
|
|
||||||
static NOINLINE KVirtualAddress GetSlabRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)).GetAddress(); }
|
static NOINLINE KVirtualAddress GetSlabRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)).GetAddress(); }
|
||||||
static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)).GetAddress(); }
|
|
||||||
|
|
||||||
static NOINLINE const KMemoryRegion &GetDeviceRegion(KMemoryRegionType type) { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); }
|
static NOINLINE const KMemoryRegion &GetDeviceRegion(KMemoryRegionType type) { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); }
|
||||||
static KPhysicalAddress GetDevicePhysicalAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetAddress(); }
|
static KPhysicalAddress GetDevicePhysicalAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetAddress(); }
|
||||||
@@ -144,7 +145,6 @@ namespace ams::kern {
|
|||||||
static NOINLINE const KMemoryRegion &GetPageTableHeapRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap)); }
|
static NOINLINE const KMemoryRegion &GetPageTableHeapRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap)); }
|
||||||
static NOINLINE const KMemoryRegion &GetKernelStackRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); }
|
static NOINLINE const KMemoryRegion &GetKernelStackRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); }
|
||||||
static NOINLINE const KMemoryRegion &GetTempRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); }
|
static NOINLINE const KMemoryRegion &GetTempRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); }
|
||||||
static NOINLINE const KMemoryRegion &GetCoreLocalRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)); }
|
|
||||||
|
|
||||||
static NOINLINE const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); }
|
static NOINLINE const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); }
|
||||||
|
|
||||||
@@ -216,7 +216,6 @@ namespace ams::kern {
|
|||||||
namespace init {
|
namespace init {
|
||||||
|
|
||||||
/* These should be generic, regardless of board. */
|
/* These should be generic, regardless of board. */
|
||||||
void SetupCoreLocalRegionMemoryRegions(KInitialPageTable &page_table, KInitialPageAllocator &page_allocator);
|
|
||||||
void SetupPoolPartitionMemoryRegions();
|
void SetupPoolPartitionMemoryRegions();
|
||||||
|
|
||||||
/* These may be implemented in a board-specific manner. */
|
/* These may be implemented in a board-specific manner. */
|
||||||
|
|||||||
@@ -70,11 +70,13 @@ namespace ams::kern {
|
|||||||
public:
|
public:
|
||||||
Impl() : heap(), page_reference_counts(), management_region(), pool(), next(), prev() { /* ... */ }
|
Impl() : heap(), page_reference_counts(), management_region(), pool(), next(), prev() { /* ... */ }
|
||||||
|
|
||||||
size_t Initialize(const KMemoryRegion *region, Pool pool, KVirtualAddress management_region, KVirtualAddress management_region_end);
|
size_t Initialize(uintptr_t address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p);
|
||||||
|
|
||||||
KVirtualAddress AllocateBlock(s32 index, bool random) { return this->heap.AllocateBlock(index, random); }
|
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 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 InitializeOptimizedMemory() { std::memset(GetVoidPointer(this->management_region), 0, CalculateOptimizedProcessOverheadSize(this->heap.GetSize())); }
|
||||||
|
|
||||||
void TrackUnoptimizedAllocation(KVirtualAddress block, size_t num_pages);
|
void TrackUnoptimizedAllocation(KVirtualAddress block, size_t num_pages);
|
||||||
@@ -96,12 +98,23 @@ namespace ams::kern {
|
|||||||
constexpr Impl *GetNext() const { return this->next; }
|
constexpr Impl *GetNext() const { return this->next; }
|
||||||
constexpr Impl *GetPrev() const { return this->prev; }
|
constexpr Impl *GetPrev() const { return this->prev; }
|
||||||
|
|
||||||
|
void OpenFirst(KVirtualAddress address, size_t num_pages) {
|
||||||
|
size_t index = this->GetPageOffset(address);
|
||||||
|
const size_t end = index + num_pages;
|
||||||
|
while (index < end) {
|
||||||
|
const RefCount ref_count = (++this->page_reference_counts[index]);
|
||||||
|
MESOSPHERE_ABORT_UNLESS(ref_count == 1);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Open(KVirtualAddress address, size_t num_pages) {
|
void Open(KVirtualAddress address, size_t num_pages) {
|
||||||
size_t index = this->GetPageOffset(address);
|
size_t index = this->GetPageOffset(address);
|
||||||
const size_t end = index + num_pages;
|
const size_t end = index + num_pages;
|
||||||
while (index < end) {
|
while (index < end) {
|
||||||
const RefCount ref_count = (++this->page_reference_counts[index]);
|
const RefCount ref_count = (++this->page_reference_counts[index]);
|
||||||
MESOSPHERE_ABORT_UNLESS(ref_count > 0);
|
MESOSPHERE_ABORT_UNLESS(ref_count > 1);
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -178,9 +191,9 @@ namespace ams::kern {
|
|||||||
NOINLINE Result InitializeOptimizedMemory(u64 process_id, Pool pool);
|
NOINLINE Result InitializeOptimizedMemory(u64 process_id, Pool pool);
|
||||||
NOINLINE void FinalizeOptimizedMemory(u64 process_id, Pool pool);
|
NOINLINE void FinalizeOptimizedMemory(u64 process_id, Pool pool);
|
||||||
|
|
||||||
NOINLINE KVirtualAddress AllocateContinuous(size_t num_pages, size_t align_pages, u32 option);
|
NOINLINE KVirtualAddress AllocateAndOpenContinuous(size_t num_pages, size_t align_pages, u32 option);
|
||||||
NOINLINE Result Allocate(KPageGroup *out, size_t num_pages, u32 option);
|
NOINLINE Result AllocateAndOpen(KPageGroup *out, size_t num_pages, u32 option);
|
||||||
NOINLINE Result AllocateForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern);
|
NOINLINE Result AllocateAndOpenForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern);
|
||||||
|
|
||||||
void Open(KVirtualAddress address, size_t num_pages) {
|
void Open(KVirtualAddress address, size_t num_pages) {
|
||||||
/* Repeatedly open references until we've done so for all pages. */
|
/* Repeatedly open references until we've done so for all pages. */
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace ams::kern {
|
|||||||
private:
|
private:
|
||||||
uintptr_t address;
|
uintptr_t address;
|
||||||
uintptr_t pair_address;
|
uintptr_t pair_address;
|
||||||
size_t region_size;
|
uintptr_t last_address;
|
||||||
u32 attributes;
|
u32 attributes;
|
||||||
u32 type_id;
|
u32 type_id;
|
||||||
public:
|
public:
|
||||||
@@ -43,18 +43,18 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), region_size(0), attributes(0), type_id(0) { /* ... */ }
|
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 rs, uintptr_t p, u32 r, u32 t) :
|
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) :
|
||||||
address(a), pair_address(p), region_size(rs), attributes(r), type_id(t)
|
address(a), pair_address(p), last_address(la), attributes(r), type_id(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) { /* ... */ }
|
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) { /* ... */ }
|
||||||
private:
|
private:
|
||||||
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t rs, uintptr_t p, u32 r, u32 t) {
|
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t la, uintptr_t p, u32 r, u32 t) {
|
||||||
this->address = a;
|
this->address = a;
|
||||||
this->pair_address = p;
|
this->pair_address = p;
|
||||||
this->region_size = rs;
|
this->last_address = la;
|
||||||
this->attributes = r;
|
this->attributes = r;
|
||||||
this->type_id = t;
|
this->type_id = t;
|
||||||
}
|
}
|
||||||
@@ -67,16 +67,16 @@ namespace ams::kern {
|
|||||||
return this->pair_address;
|
return this->pair_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||||
return this->region_size;
|
return this->last_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||||
return this->GetAddress() + this->GetSize();
|
return this->GetLastAddress() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
return this->GetEndAddress() - 1;
|
return this->GetEndAddress() - this->GetAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE u32 GetAttributes() const {
|
constexpr ALWAYS_INLINE u32 GetAttributes() const {
|
||||||
@@ -93,6 +93,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
|
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
|
||||||
|
MESOSPHERE_INIT_ABORT_UNLESS(this->GetEndAddress() != 0);
|
||||||
return this->GetAddress() <= address && address <= this->GetLastAddress();
|
return this->GetAddress() <= address && address <= this->GetLastAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,17 +131,17 @@ namespace ams::kern {
|
|||||||
return this->first_region->GetAddress();
|
return this->first_region->GetAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||||
|
return this->last_region->GetLastAddress();
|
||||||
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||||
return this->last_region->GetEndAddress();
|
return this->GetLastAddress() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||||
return this->GetEndAddress() - this->GetAddress();
|
return this->GetEndAddress() - this->GetAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
|
||||||
return this->GetEndAddress() - 1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
using TreeType = util::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
|
using TreeType = util::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
|
||||||
@@ -160,7 +161,7 @@ namespace ams::kern {
|
|||||||
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
|
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
|
||||||
public:
|
public:
|
||||||
KMemoryRegion *FindModifiable(uintptr_t address) {
|
KMemoryRegion *FindModifiable(uintptr_t address) {
|
||||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) {
|
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) {
|
||||||
return std::addressof(*it);
|
return std::addressof(*it);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -168,7 +169,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const KMemoryRegion *Find(uintptr_t address) const {
|
const KMemoryRegion *Find(uintptr_t address) const {
|
||||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) {
|
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) {
|
||||||
return std::addressof(*it);
|
return std::addressof(*it);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -234,7 +235,7 @@ namespace ams::kern {
|
|||||||
return extents;
|
return extents;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0);
|
NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, 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 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);
|
NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
|
||||||
|
|||||||
@@ -156,12 +156,13 @@ namespace ams::kern {
|
|||||||
|
|
||||||
constexpr inline const auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
|
constexpr inline const auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
|
||||||
|
|
||||||
constexpr inline const auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
|
constexpr inline const auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
|
||||||
constexpr inline const auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
|
constexpr inline const auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
|
||||||
constexpr inline const auto KMemoryRegionType_CoreLocalRegion = KMemoryRegionType_None.DeriveInitial(2).Finalize();
|
static_assert(KMemoryRegionType_Kernel.GetValue() == 0x1);
|
||||||
static_assert(KMemoryRegionType_Kernel .GetValue() == 0x1);
|
static_assert(KMemoryRegionType_Dram .GetValue() == 0x2);
|
||||||
static_assert(KMemoryRegionType_Dram .GetValue() == 0x2);
|
|
||||||
static_assert(KMemoryRegionType_CoreLocalRegion.GetValue() == 0x4);
|
/* constexpr inline const auto KMemoryRegionType_CoreLocalRegion = KMemoryRegionType_None.DeriveInitial(2).Finalize(); */
|
||||||
|
/* static_assert(KMemoryRegionType_CoreLocalRegion.GetValue() == 0x4); */
|
||||||
|
|
||||||
constexpr inline const auto KMemoryRegionType_DramKernelBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 0).SetAttribute(KMemoryRegionAttr_NoUserMap).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
|
constexpr inline const auto KMemoryRegionType_DramKernelBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 0).SetAttribute(KMemoryRegionAttr_NoUserMap).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
|
||||||
constexpr inline const auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
|
constexpr inline const auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
|
||||||
@@ -274,15 +275,15 @@ namespace ams::kern {
|
|||||||
/* UNUSED: .Derive(7, 0); */
|
/* UNUSED: .Derive(7, 0); */
|
||||||
constexpr inline const auto KMemoryRegionType_KernelMiscMainStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
|
constexpr inline const auto KMemoryRegionType_KernelMiscMainStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
|
||||||
constexpr inline const auto KMemoryRegionType_KernelMiscMappedDevice = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
|
constexpr inline const auto KMemoryRegionType_KernelMiscMappedDevice = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
|
||||||
constexpr inline const auto KMemoryRegionType_KernelMiscIdleStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
|
constexpr inline const auto KMemoryRegionType_KernelMiscExceptionStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
|
||||||
constexpr inline const auto KMemoryRegionType_KernelMiscUnknownDebug = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
|
constexpr inline const auto KMemoryRegionType_KernelMiscUnknownDebug = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
|
||||||
/* UNUSED: .Derive(7, 5); */
|
/* UNUSED: .Derive(7, 5); */
|
||||||
constexpr inline const auto KMemoryRegionType_KernelMiscExceptionStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
|
constexpr inline const auto KMemoryRegionType_KernelMiscIdleStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
|
||||||
static_assert(KMemoryRegionType_KernelMiscMainStack .GetValue() == 0xB49);
|
static_assert(KMemoryRegionType_KernelMiscMainStack .GetValue() == 0xB49);
|
||||||
static_assert(KMemoryRegionType_KernelMiscMappedDevice .GetValue() == 0xD49);
|
static_assert(KMemoryRegionType_KernelMiscMappedDevice .GetValue() == 0xD49);
|
||||||
static_assert(KMemoryRegionType_KernelMiscIdleStack .GetValue() == 0x1349);
|
static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x1349);
|
||||||
static_assert(KMemoryRegionType_KernelMiscUnknownDebug .GetValue() == 0x1549);
|
static_assert(KMemoryRegionType_KernelMiscUnknownDebug .GetValue() == 0x1549);
|
||||||
static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x2349);
|
static_assert(KMemoryRegionType_KernelMiscIdleStack .GetValue() == 0x2349);
|
||||||
|
|
||||||
constexpr inline const auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
|
constexpr inline const auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
|
||||||
static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
|
static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
|
||||||
|
|||||||
@@ -24,13 +24,28 @@
|
|||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
enum DisableMergeAttribute : u8 {
|
||||||
|
DisableMergeAttribute_None = (0u << 0),
|
||||||
|
|
||||||
|
DisableMergeAttribute_DisableHead = (1u << 0),
|
||||||
|
DisableMergeAttribute_DisableHeadAndBody = (1u << 1),
|
||||||
|
DisableMergeAttribute_EnableHeadAndBody = (1u << 2),
|
||||||
|
DisableMergeAttribute_DisableTail = (1u << 3),
|
||||||
|
DisableMergeAttribute_EnableTail = (1u << 4),
|
||||||
|
DisableMergeAttribute_EnableAndMergeHeadBodyTail = (1u << 5),
|
||||||
|
|
||||||
|
DisableMergeAttribute_EnableHeadBodyTail = DisableMergeAttribute_EnableHeadAndBody | DisableMergeAttribute_EnableTail,
|
||||||
|
DisableMergeAttribute_DisableHeadBodyTail = DisableMergeAttribute_DisableHeadAndBody | DisableMergeAttribute_DisableTail,
|
||||||
|
};
|
||||||
|
|
||||||
struct KPageProperties {
|
struct KPageProperties {
|
||||||
KMemoryPermission perm;
|
KMemoryPermission perm;
|
||||||
bool io;
|
bool io;
|
||||||
bool uncached;
|
bool uncached;
|
||||||
bool non_contiguous;
|
DisableMergeAttribute disable_merge_attributes;
|
||||||
};
|
};
|
||||||
static_assert(std::is_trivial<KPageProperties>::value);
|
static_assert(std::is_trivial<KPageProperties>::value);
|
||||||
|
static_assert(sizeof(KPageProperties) == sizeof(u32));
|
||||||
|
|
||||||
class KPageTableBase {
|
class KPageTableBase {
|
||||||
NON_COPYABLE(KPageTableBase);
|
NON_COPYABLE(KPageTableBase);
|
||||||
@@ -143,6 +158,7 @@ namespace ams::kern {
|
|||||||
u32 address_space_width;
|
u32 address_space_width;
|
||||||
bool is_kernel;
|
bool is_kernel;
|
||||||
bool enable_aslr;
|
bool enable_aslr;
|
||||||
|
bool enable_device_address_space_merge;
|
||||||
KMemoryBlockSlabManager *memory_block_slab_manager;
|
KMemoryBlockSlabManager *memory_block_slab_manager;
|
||||||
KBlockInfoManager *block_info_manager;
|
KBlockInfoManager *block_info_manager;
|
||||||
const KMemoryRegion *cached_physical_linear_region;
|
const KMemoryRegion *cached_physical_linear_region;
|
||||||
@@ -157,15 +173,15 @@ namespace ams::kern {
|
|||||||
alias_region_start(), alias_region_end(), stack_region_start(), stack_region_end(), kernel_map_region_start(),
|
alias_region_start(), alias_region_end(), stack_region_start(), stack_region_end(), kernel_map_region_start(),
|
||||||
kernel_map_region_end(), alias_code_region_start(), alias_code_region_end(), code_region_start(), code_region_end(),
|
kernel_map_region_end(), alias_code_region_start(), alias_code_region_end(), code_region_start(), code_region_end(),
|
||||||
max_heap_size(), mapped_physical_memory_size(), mapped_unsafe_physical_memory(), general_lock(), map_physical_memory_lock(),
|
max_heap_size(), mapped_physical_memory_size(), mapped_unsafe_physical_memory(), general_lock(), map_physical_memory_lock(),
|
||||||
impl(), memory_block_manager(), allocate_option(), address_space_width(), is_kernel(), enable_aslr(), memory_block_slab_manager(),
|
impl(), memory_block_manager(), allocate_option(), address_space_width(), is_kernel(), enable_aslr(), enable_device_address_space_merge(),
|
||||||
block_info_manager(), cached_physical_linear_region(), cached_physical_heap_region(), cached_virtual_heap_region(),
|
memory_block_slab_manager(), block_info_manager(), cached_physical_linear_region(), cached_physical_heap_region(), cached_virtual_heap_region(),
|
||||||
heap_fill_value(), ipc_fill_value(), stack_fill_value()
|
heap_fill_value(), ipc_fill_value(), stack_fill_value()
|
||||||
{
|
{
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
|
NOINLINE Result InitializeForKernel(bool is_64_bit, void *table, KVirtualAddress start, KVirtualAddress end);
|
||||||
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager);
|
NOINLINE Result InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager);
|
||||||
|
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
@@ -251,12 +267,18 @@ namespace ams::kern {
|
|||||||
constexpr size_t GetNumGuardPages() const { return this->IsKernel() ? 1 : 4; }
|
constexpr size_t GetNumGuardPages() const { return this->IsKernel() ? 1 : 4; }
|
||||||
ALWAYS_INLINE KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const;
|
ALWAYS_INLINE KProcessAddress FindFreeArea(KProcessAddress region_start, size_t region_num_pages, size_t num_pages, size_t alignment, size_t offset, size_t guard_pages) const;
|
||||||
|
|
||||||
Result CheckMemoryStateContiguous(KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) const;
|
Result CheckMemoryStateContiguous(size_t *out_blocks_needed, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) const;
|
||||||
|
Result CheckMemoryStateContiguous(KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) const {
|
||||||
|
return this->CheckMemoryStateContiguous(nullptr, addr, size, state_mask, state, perm_mask, perm, attr_mask, attr);
|
||||||
|
}
|
||||||
|
|
||||||
Result CheckMemoryState(const KMemoryInfo &info, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) const;
|
Result CheckMemoryState(const KMemoryInfo &info, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) const;
|
||||||
Result CheckMemoryState(KMemoryState *out_state, KMemoryPermission *out_perm, KMemoryAttribute *out_attr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, u32 ignore_attr = DefaultMemoryIgnoreAttr) const;
|
Result CheckMemoryState(KMemoryState *out_state, KMemoryPermission *out_perm, KMemoryAttribute *out_attr, size_t *out_blocks_needed, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, u32 ignore_attr = DefaultMemoryIgnoreAttr) const;
|
||||||
|
Result CheckMemoryState(size_t *out_blocks_needed, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, u32 ignore_attr = DefaultMemoryIgnoreAttr) const {
|
||||||
|
return this->CheckMemoryState(nullptr, nullptr, nullptr, out_blocks_needed, addr, size, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr);
|
||||||
|
}
|
||||||
Result CheckMemoryState(KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, u32 ignore_attr = DefaultMemoryIgnoreAttr) const {
|
Result CheckMemoryState(KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, u32 ignore_attr = DefaultMemoryIgnoreAttr) const {
|
||||||
return this->CheckMemoryState(nullptr, nullptr, nullptr, addr, size, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr);
|
return this->CheckMemoryState(nullptr, addr, size, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LockMemoryAndOpen(KPageGroup *out_pg, KPhysicalAddress *out_paddr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, KMemoryPermission new_perm, u32 lock_attr);
|
Result LockMemoryAndOpen(KPageGroup *out_pg, KPhysicalAddress *out_paddr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, KMemoryPermission new_perm, u32 lock_attr);
|
||||||
@@ -266,17 +288,19 @@ namespace ams::kern {
|
|||||||
|
|
||||||
Result QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, KMemoryState state) const;
|
Result QueryMappingImpl(KProcessAddress *out, KPhysicalAddress address, size_t size, KMemoryState state) const;
|
||||||
|
|
||||||
Result AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, const KPageProperties properties);
|
Result AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, KMemoryPermission perm);
|
||||||
Result MapPageGroupImpl(PageLinkedList *page_list, KProcessAddress address, const KPageGroup &pg, const KPageProperties properties, bool reuse_ll);
|
Result MapPageGroupImpl(PageLinkedList *page_list, KProcessAddress address, const KPageGroup &pg, const KPageProperties properties, bool reuse_ll);
|
||||||
|
|
||||||
|
void RemapPageGroup(PageLinkedList *page_list, KProcessAddress address, size_t size, const KPageGroup &pg);
|
||||||
|
|
||||||
Result MakePageGroup(KPageGroup &pg, KProcessAddress addr, size_t num_pages);
|
Result MakePageGroup(KPageGroup &pg, KProcessAddress addr, size_t num_pages);
|
||||||
bool IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages);
|
bool IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages);
|
||||||
|
|
||||||
NOINLINE Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
|
NOINLINE Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
|
||||||
|
|
||||||
Result SetupForIpcClient(PageLinkedList *page_list, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state);
|
Result SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state);
|
||||||
Result SetupForIpcServer(KProcessAddress *out_addr, size_t size, KProcessAddress src_addr, KMemoryPermission test_perm, KMemoryState dst_state, KPageTableBase &src_page_table, bool send);
|
Result SetupForIpcServer(KProcessAddress *out_addr, size_t size, KProcessAddress src_addr, KMemoryPermission test_perm, KMemoryState dst_state, KPageTableBase &src_page_table, bool send);
|
||||||
Result CleanupForIpcClientOnServerSetupFailure(PageLinkedList *page_list, KProcessAddress address, size_t size, KMemoryPermission test_perm);
|
void CleanupForIpcClientOnServerSetupFailure(PageLinkedList *page_list, KProcessAddress address, size_t size, KMemoryPermission prot_perm);
|
||||||
public:
|
public:
|
||||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress virt_addr) const {
|
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress virt_addr) const {
|
||||||
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
||||||
@@ -321,7 +345,6 @@ namespace ams::kern {
|
|||||||
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state);
|
Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state);
|
||||||
|
|
||||||
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
||||||
Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr);
|
|
||||||
|
|
||||||
Result InvalidateProcessDataCache(KProcessAddress address, size_t size);
|
Result InvalidateProcessDataCache(KProcessAddress address, size_t size);
|
||||||
|
|
||||||
@@ -330,6 +353,10 @@ namespace ams::kern {
|
|||||||
|
|
||||||
Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned);
|
Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned);
|
||||||
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
|
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
|
||||||
|
|
||||||
|
Result MakePageGroupForUnmapDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size);
|
||||||
|
Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size, size_t mapped_size);
|
||||||
|
|
||||||
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size);
|
Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size);
|
||||||
Result UnlockForIpcUserBuffer(KProcessAddress address, size_t size);
|
Result UnlockForIpcUserBuffer(KProcessAddress address, size_t size);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <mesosphere/kern_k_thread.hpp>
|
#include <mesosphere/kern_k_thread.hpp>
|
||||||
#include <mesosphere/kern_k_thread_local_page.hpp>
|
#include <mesosphere/kern_k_thread_local_page.hpp>
|
||||||
#include <mesosphere/kern_k_shared_memory_info.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_k_worker_task.hpp>
|
||||||
#include <mesosphere/kern_select_page_table.hpp>
|
#include <mesosphere/kern_select_page_table.hpp>
|
||||||
#include <mesosphere/kern_k_condition_variable.hpp>
|
#include <mesosphere/kern_k_condition_variable.hpp>
|
||||||
@@ -52,6 +53,7 @@ namespace ams::kern {
|
|||||||
static constexpr size_t AslrAlignment = KernelAslrAlignment;
|
static constexpr size_t AslrAlignment = KernelAslrAlignment;
|
||||||
private:
|
private:
|
||||||
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
||||||
|
using BetaList = util::IntrusiveListMemberTraits<&KBeta::process_list_node>::ListType;
|
||||||
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
||||||
using TLPIterator = TLPTree::iterator;
|
using TLPIterator = TLPTree::iterator;
|
||||||
private:
|
private:
|
||||||
@@ -95,6 +97,7 @@ namespace ams::kern {
|
|||||||
KThread *exception_thread{};
|
KThread *exception_thread{};
|
||||||
ThreadList thread_list{};
|
ThreadList thread_list{};
|
||||||
SharedMemoryInfoList shared_memory_list{};
|
SharedMemoryInfoList shared_memory_list{};
|
||||||
|
BetaList beta_list{};
|
||||||
bool is_suspended{};
|
bool is_suspended{};
|
||||||
bool is_jit_debug{};
|
bool is_jit_debug{};
|
||||||
ams::svc::DebugEvent jit_debug_event_type{};
|
ams::svc::DebugEvent jit_debug_event_type{};
|
||||||
@@ -361,9 +364,6 @@ namespace ams::kern {
|
|||||||
static void Switch(KProcess *cur_process, KProcess *next_process) {
|
static void Switch(KProcess *cur_process, KProcess *next_process) {
|
||||||
MESOSPHERE_UNUSED(cur_process);
|
MESOSPHERE_UNUSED(cur_process);
|
||||||
|
|
||||||
/* Set the current process pointer. */
|
|
||||||
SetCurrentProcess(next_process);
|
|
||||||
|
|
||||||
/* Update the current page table. */
|
/* Update the current page table. */
|
||||||
if (next_process) {
|
if (next_process) {
|
||||||
next_process->GetPageTable().Activate(next_process->GetProcessId());
|
next_process->GetPageTable().Activate(next_process->GetProcessId());
|
||||||
|
|||||||
@@ -28,11 +28,12 @@ namespace ams::kern {
|
|||||||
s64 limit_values[ams::svc::LimitableResource_Count];
|
s64 limit_values[ams::svc::LimitableResource_Count];
|
||||||
s64 current_values[ams::svc::LimitableResource_Count];
|
s64 current_values[ams::svc::LimitableResource_Count];
|
||||||
s64 current_hints[ams::svc::LimitableResource_Count];
|
s64 current_hints[ams::svc::LimitableResource_Count];
|
||||||
|
s64 peak_values[ams::svc::LimitableResource_Count];
|
||||||
mutable KLightLock lock;
|
mutable KLightLock lock;
|
||||||
s32 waiter_count;
|
s32 waiter_count;
|
||||||
KLightConditionVariable cond_var;
|
KLightConditionVariable cond_var;
|
||||||
public:
|
public:
|
||||||
constexpr ALWAYS_INLINE KResourceLimit() : limit_values(), current_values(), current_hints(), lock(), waiter_count(), cond_var() { /* ... */ }
|
constexpr ALWAYS_INLINE KResourceLimit() : limit_values(), current_values(), current_hints(), peak_values(), lock(), waiter_count(), cond_var() { /* ... */ }
|
||||||
virtual ~KResourceLimit() { /* ... */ }
|
virtual ~KResourceLimit() { /* ... */ }
|
||||||
|
|
||||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||||
@@ -42,6 +43,7 @@ namespace ams::kern {
|
|||||||
|
|
||||||
s64 GetLimitValue(ams::svc::LimitableResource which) const;
|
s64 GetLimitValue(ams::svc::LimitableResource which) const;
|
||||||
s64 GetCurrentValue(ams::svc::LimitableResource which) const;
|
s64 GetCurrentValue(ams::svc::LimitableResource which) const;
|
||||||
|
s64 GetPeakValue(ams::svc::LimitableResource which) const;
|
||||||
s64 GetFreeValue(ams::svc::LimitableResource which) const;
|
s64 GetFreeValue(ams::svc::LimitableResource which) const;
|
||||||
|
|
||||||
Result SetLimitValue(ams::svc::LimitableResource which, s64 value);
|
Result SetLimitValue(ams::svc::LimitableResource which, s64 value);
|
||||||
|
|||||||
@@ -56,9 +56,10 @@ namespace ams::kern {
|
|||||||
KThread *prev_thread;
|
KThread *prev_thread;
|
||||||
s64 last_context_switch_time;
|
s64 last_context_switch_time;
|
||||||
KThread *idle_thread;
|
KThread *idle_thread;
|
||||||
|
std::atomic<KThread *> current_thread;
|
||||||
public:
|
public:
|
||||||
constexpr KScheduler()
|
constexpr KScheduler()
|
||||||
: state(), is_active(false), core_id(0), prev_thread(nullptr), last_context_switch_time(0), idle_thread(nullptr)
|
: state(), is_active(false), core_id(0), prev_thread(nullptr), last_context_switch_time(0), idle_thread(nullptr), current_thread(nullptr)
|
||||||
{
|
{
|
||||||
this->state.needs_scheduling = true;
|
this->state.needs_scheduling = true;
|
||||||
this->state.interrupt_task_thread_runnable = false;
|
this->state.interrupt_task_thread_runnable = false;
|
||||||
@@ -96,6 +97,10 @@ namespace ams::kern {
|
|||||||
return this->prev_thread;
|
return this->prev_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE KThread *GetSchedulerCurrentThread() const {
|
||||||
|
return this->current_thread;
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE s64 GetLastContextSwitchTime() const {
|
ALWAYS_INLINE s64 GetLastContextSwitchTime() const {
|
||||||
return this->last_context_switch_time;
|
return this->last_context_switch_time;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace ams::kern {
|
|||||||
return this->owner_thread == GetCurrentThreadPointer();
|
return this->owner_thread == GetCurrentThreadPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void Lock() {
|
void Lock() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
if (this->IsLockedByCurrentThread()) {
|
if (this->IsLockedByCurrentThread()) {
|
||||||
@@ -67,7 +67,7 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE void Unlock() {
|
void Unlock() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||||
MESOSPHERE_ASSERT(this->lock_count > 0);
|
MESOSPHERE_ASSERT(this->lock_count > 0);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user