Compare commits

..

41 Commits

Author SHA1 Message Date
Michael Scire
003f369238 docs: add basic changelog for 1.3.0 2022-03-23 09:07:51 -07:00
Michael Scire
56050a2195 exo: fix typo causing mishandling of carveouts 2022-03-23 08:49:18 -07:00
Michael Scire
e15bcc10a8 emummc: add 14.0.0 patches 2022-03-23 04:32:08 -07:00
Michael Scire
caf0be85fa kern: turns out changing base address gives pretty elfs but breaks relocs 2022-03-23 00:45:48 -07:00
Michael Scire
8c955587f4 os/dd: add missing semicolon to new cache logic 2022-03-23 00:29:49 -07:00
Michael Scire
253ce776cb exo: right, Mariko* is a wiki-ism 2022-03-23 00:04:14 -07:00
Michael Scire
bec0c7ec2f exo: update for new dram ids 2022-03-23 00:03:18 -07:00
Michael Scire
ae09c45f6b kern: codegen tweaks, now that we're no longer -Os 2022-03-22 23:58:39 -07:00
Michael Scire
059a005647 kern: good night sweet prince 2022-03-22 23:13:50 -07:00
Michael Scire
b7091df796 kern: on second thought, gcc built ins are for chumps 2022-03-22 23:10:09 -07:00
Michael Scire
bb0be4de8e kern: implement revised IPI/SGI semantics 2022-03-22 23:02:10 -07:00
Michael Scire
7454507467 kern: update for new hw maintenance semantics 2022-03-22 21:33:43 -07:00
Michael Scire
79dbc22cb2 kern: implement new thread context/fpu semantics 2022-03-22 19:59:39 -07:00
hexkyz
0896d47a92 fusee: add unused mtc table 2022-03-22 23:28:32 +00:00
hexkyz
4288b12f37 fusee: add new sdram params 2022-03-22 23:14:00 +00:00
hexkyz
599c4ebf42 fusee: add new mtc tables 2022-03-22 22:51:29 +00:00
Michael Scire
abede65264 kern: implement additional randomness in KPageHeap allocations 2022-03-22 15:29:55 -07:00
Michael Scire
fee7a4b774 kern: enforce end of dram == end of partitions (move our probably outdated KTraceBuffer to new location) 2022-03-22 15:01:22 -07:00
Michael Scire
a39448905a kern: add new KCapability checks before creating process 2022-03-22 14:45:29 -07:00
Michael Scire
29a53bc572 kern: add InfoType_IsSvcPermitted 2022-03-22 14:29:02 -07:00
Michael Scire
262a066c8c kern: enforce maximum secure region size 2022-03-22 14:16:02 -07:00
Michael Scire
de6d8d4ab4 kern: print kernel backtrace on panic 2022-03-22 14:11:35 -07:00
Michael Scire
dc7184c01f ncm: hot take, uninitialized data bad 2022-03-22 14:02:14 -07:00
Michael Scire
b428e77c16 fs/sprof/build: fix minor issues 2022-03-22 13:27:05 -07:00
Michael Scire
30ff0254a4 pm: grant access to GetResourceLimitPeakValue 2022-03-22 11:10:02 -07:00
Michael Scire
c04ebf10a0 boot2: launch omm before am 2022-03-22 11:09:46 -07:00
Michael Scire
f466f9e825 pgl: style nitpick 2022-03-22 10:29:18 -07:00
Michael Scire
7498958a06 pgl: hook up logic for enabling extra system threads 2022-03-22 10:27:03 -07:00
Michael Scire
f804793fdf pm: hook up the new libnx apis 2022-03-22 10:21:47 -07:00
Michael Scire
0a81889967 fusee: update static_assert on key generation 2022-03-22 10:09:23 -07:00
Michael Scire
cd83a3bd08 pm: loosen restriction on resource limit boost 2022-03-22 09:59:09 -07:00
Michael Scire
11e3d4a620 erpt: update id map 2022-03-22 08:20:45 -07:00
Michael Scire
c593b1be89 sf: add another sanity assert 2022-03-22 05:22:44 -07:00
Michael Scire
36ab24f93a sf: add new debug-interface-id in cmif out header 2022-03-22 05:19:18 -07:00
Michael Scire
41e2c24101 sprofile: fix/simplify import count calculation 2022-03-22 01:00:53 -07:00
Michael Scire
b06ada6ac8 libstrat: misc fixes for unused arg warnings 2022-03-22 01:00:39 -07:00
Michael Scire
b2413b7464 fatal: update for new 14.0.0 command 2022-03-22 00:52:48 -07:00
Michael Scire
fa330deeba kern: update version (note: actual 14-kernel diff/impl todo) 2022-03-21 23:56:54 -07:00
Michael Scire
df1b133bc7 pm/kern: update for 14.0.0 2022-03-21 23:52:16 -07:00
Michael Scire
40601cc74c sprofile: update for 14.0.0 (orphaned profiles now deleted on import) 2022-03-21 23:20:31 -07:00
Michael Scire
9acf48ba5f exo/fusee: first pass at updating enums for 14.0.0 2022-03-21 18:37:48 -07:00
849 changed files with 7650 additions and 14072 deletions

View File

@@ -1,32 +1,4 @@
# Changelog
## 1.4.0
+ Support was added for 15.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
+ `ncm` was updated to reflect the latest official kernel behavior.
+ A number of minor issues were fixed and improvements were made, including:
+ The capacity limit on registered add-on contents was fixed in NCM to reflect the increase that occurred in 12.0.0.
+ An off-by-one was fixed in mesosphere when computing the new value for an address arbiter signaled with ModifyByWaitingCountIfEqual.
+ dmnt.gen2's gdbstub now sanitizes thread names to prevent invalid characters from breaking gdb.
+ dmnt.gen2's gdbstub now reports the architecture tag correctly when attached to 32-bit processes.
+ Support for program-specific html manual content overrides was added for non-hbl takeover context.
+ A bug was fixed in how emummc constructed the alternate Nintendo directory path.
+ Previously, this was using `/*/Nintendo/Nintendo` instead of `/*/Nintendo`.
+ Code was added to automatically move the old folders to the new ones when booting into emummc.
+ A bug was fixed in boot that caused an incorrectly low input voltage limit to be set.
+ General system stability improvements to enhance the user's experience.
## 1.3.2
+ Support was improved for 14.0.0+.
+ `loader` was updated to reflect the latest official behaviors.
+ `ro` was updated to reflect the latest official behaviors.
+ A number of minor issues were fixed and improvements were made, including:
+ A memory leak was fixed in filesystem path management; this could cause a crash when launching games ~100 times, or when deleting/re-downloading games.
+ A bug was fixed that could cause threads to not see a newly signaled semaphore.
+ A number of minor inaccuracies were fixed in the updated FileSystem APIs.
+ General system stability improvements to enhance the user's experience.
## 1.3.1
+ Support was added for 14.1.0.
+ A number of minor under the hood improvements to accuracy were made to better reflect latest official system module behavior, particularly around FS apis.
+ General system stability improvements to enhance the user's experience.
## 1.3.0
+ Support was added for 14.0.0.
+ `mesosphère` was updated to reflect the latest official kernel behavior.
@@ -43,10 +15,9 @@
+ If you are a developer interested in adding support for another target, please reach out to `SciresM#0524` on discord.
+ This is intended to finally allow sanely testing Atmosphère's code, by allowing most of it to run on a PC (with access to a debugger) instead of on game console hardware.
+ In addition, this will allow making PC tools which reuse code written for Atmosphère directly..
+ **Please Note**: This has no relation to interacting with official software on PC whatsoever. This really allows for making tests and self-contained atmosphère-based command-line tools; the Atmosphère project continues to have zero interest in attempting to run official software of any kind.
+ In the course of adding this support (and working on tooling using it), a number of fairly major revisions were made to stratosphere (particularly surrounding filesystem code).
+ **Please Note**: A number of changes made for this (and ones necessary in the process of adding support for 14.0.0) are api-breaking.
+ If you're a developer and any of this caused your code to break, please feel free to contact `SciresM#0524` for help updating your program.
+ **Please Note**: This has no relation to interacting with official software on PC whatsoever. This does not and is not intended to enable anything with official software, it only really allows for making tests and self-contained atmosphère-based tools.
+ In the course of adding this support (and working on tooling using it), a number of major revisions were added to stratosphere:
+
+ General system stability improvements to enhance the user's experience.
## 1.2.6
+ Support was added for 13.2.1.

6
emummc/.gitrepo vendored
View File

@@ -4,9 +4,9 @@
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = https://github.com/m4xw/emummc
remote = https://github.com/m4xw/emuMMC
branch = develop
commit = 4714b2df9eaf68fb85516b35f7f4265ab0413825
parent = 99f6a96845b6097d50f5059eea9245d27876f26a
commit = a9d56959460fc794ce2cb6405402c25a3e89c47f
parent = ff719641396c635b735873fb2b020c910f768a04
method = merge
cmdver = 0.4.1

2
emummc/README.md vendored
View File

@@ -2,7 +2,7 @@
*A SDMMC driver replacement for Nintendo's Filesystem Services, by **m4xw***
### Supported Horizon Versions
**1.0.0 - 15.0.0**
**1.0.0 - 13.1.0**
## Features
* Arbitrary SDMMC backend selection

View File

@@ -61,8 +61,6 @@
#include "offsets/1310_exfat.h"
#include "offsets/1400.h"
#include "offsets/1400_exfat.h"
#include "offsets/1500.h"
#include "offsets/1500_exfat.h"
#include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -135,8 +133,6 @@ DEFINE_OFFSET_STRUCT(_1310);
DEFINE_OFFSET_STRUCT(_1310_EXFAT);
DEFINE_OFFSET_STRUCT(_1400);
DEFINE_OFFSET_STRUCT(_1400_EXFAT);
DEFINE_OFFSET_STRUCT(_1500);
DEFINE_OFFSET_STRUCT(_1500_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) {
@@ -230,10 +226,6 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1400));
case FS_VER_14_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1400_EXFAT));
case FS_VER_15_0_0:
return &(GET_OFFSET_STRUCT_NAME(_1500));
case FS_VER_15_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1500_EXFAT));
default:
fatal_abort(Fatal_UnknownVersion);
}

View File

@@ -89,9 +89,6 @@ enum FS_VER
FS_VER_14_0_0,
FS_VER_14_0_0_EXFAT,
FS_VER_15_0_0,
FS_VER_15_0_0_EXFAT,
FS_VER_MAX,
};

View File

@@ -1,59 +0,0 @@
/*
* 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_1500_H__
#define __FS_1500_H__
// Accessor vtable getters
#define FS_OFFSET_1500_SDMMC_ACCESSOR_GC 0x183E20
#define FS_OFFSET_1500_SDMMC_ACCESSOR_SD 0x185AA0
#define FS_OFFSET_1500_SDMMC_ACCESSOR_NAND 0x1842E0
// Hooks
#define FS_OFFSET_1500_SDMMC_WRAPPER_READ 0x17FCF0
#define FS_OFFSET_1500_SDMMC_WRAPPER_WRITE 0x17FD50
#define FS_OFFSET_1500_RTLD 0x26518
#define FS_OFFSET_1500_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1500_CLKRST_SET_MIN_V_CLK_RATE 0x1A0870
// Misc funcs
#define FS_OFFSET_1500_LOCK_MUTEX 0x1791A0
#define FS_OFFSET_1500_UNLOCK_MUTEX 0x1791F0
#define FS_OFFSET_1500_SDMMC_WRAPPER_CONTROLLER_OPEN 0x17FCB0
#define FS_OFFSET_1500_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x17FCD0
// Misc Data
#define FS_OFFSET_1500_SD_MUTEX 0xFF33F0
#define FS_OFFSET_1500_NAND_MUTEX 0xFEE2E8
#define FS_OFFSET_1500_ACTIVE_PARTITION 0xFEE328
#define FS_OFFSET_1500_SDMMC_DAS_HANDLE 0xFD38D8
// NOPs
#define FS_OFFSET_1500_SD_DAS_INIT 0x25454
// Nintendo Paths
#define FS_OFFSET_1500_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063050, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0006FDE8, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000768D4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00089364, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1500_H__

View File

@@ -1,59 +0,0 @@
/*
* 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_1500_EXFAT_H__
#define __FS_1500_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_GC 0x18EDB0
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_SD 0x190A30
#define FS_OFFSET_1500_EXFAT_SDMMC_ACCESSOR_NAND 0x18F270
// Hooks
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_READ 0x18AC80
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_WRITE 0x18ACE0
#define FS_OFFSET_1500_EXFAT_RTLD 0x26518
#define FS_OFFSET_1500_EXFAT_RTLD_DESTINATION ((uintptr_t)(INT64_C(-0x3C)))
#define FS_OFFSET_1500_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x1AB800
// Misc funcs
#define FS_OFFSET_1500_EXFAT_LOCK_MUTEX 0x184130
#define FS_OFFSET_1500_EXFAT_UNLOCK_MUTEX 0x184180
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_CONTROLLER_OPEN 0x18AC40
#define FS_OFFSET_1500_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x18AC60
// Misc Data
#define FS_OFFSET_1500_EXFAT_SD_MUTEX 0x10053F0
#define FS_OFFSET_1500_EXFAT_NAND_MUTEX 0x10002E8
#define FS_OFFSET_1500_EXFAT_ACTIVE_PARTITION 0x1000328
#define FS_OFFSET_1500_EXFAT_SDMMC_DAS_HANDLE 0xFE08D8
// NOPs
#define FS_OFFSET_1500_EXFAT_SD_DAS_INIT 0x25454
// Nintendo Paths
#define FS_OFFSET_1500_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x00063050, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0006FDE8, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x000768D4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x00089364, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1500_EXFAT_H__

View File

@@ -27,10 +27,6 @@ CODE_BEGIN armDCacheFlush
bic x8, x0, x10
mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheFlush_L0:
dc civac, x8
add x8, x8, x9
@@ -38,9 +34,6 @@ armDCacheFlush_L0:
bcc armDCacheFlush_L0
dsb sy
strb wzr, [x0, #0x104]
ret
CODE_END
@@ -55,10 +48,6 @@ CODE_BEGIN armDCacheClean
bic x8, x0, x10
mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheClean_L0:
dc cvac, x8
add x8, x8, x9
@@ -66,9 +55,6 @@ armDCacheClean_L0:
bcc armDCacheClean_L0
dsb sy
strb wzr, [x0, #0x104]
ret
CODE_END
@@ -82,10 +68,6 @@ CODE_BEGIN armICacheInvalidate
bic x8, x0, x10
mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armICacheInvalidate_L0:
ic ivau, x8
add x8, x8, x9
@@ -93,9 +75,6 @@ armICacheInvalidate_L0:
bcc armICacheInvalidate_L0
dsb sy
strb wzr, [x0, #0x104]
ret
CODE_END
@@ -110,10 +89,6 @@ CODE_BEGIN armDCacheZero
bic x8, x0, x10
mov x10, x1
mov w1, #1
mrs x0, tpidrro_el0
strb w1, [x0, #0x104]
armDCacheZero_L0:
dc zva, x8
add x8, x8, x9
@@ -121,8 +96,5 @@ armDCacheZero_L0:
bcc armDCacheZero_L0
dsb sy
strb wzr, [x0, #0x104]
ret
CODE_END

View File

@@ -62,7 +62,7 @@ namespace ams::secmon::fatal {
/* Write the context to the file. */
R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush));
R_SUCCEED();
return ResultSuccess();
}
}

View File

@@ -48,11 +48,11 @@ namespace ams::secmon::fatal {
//sdmmc::Deactivate(Port);
R_TRY(sdmmc::Activate(Port));
R_SUCCEED();
return ResultSuccess();
}
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
R_RETURN(sdmmc::CheckSdCardConnection(out_sm, out_bw, Port));
return sdmmc::CheckSdCardConnection(out_sm, out_bw, Port);
}
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) {
@@ -78,7 +78,7 @@ namespace ams::secmon::fatal {
sector_count -= cur_sectors;
}
R_SUCCEED();
return ResultSuccess();
}
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) {
@@ -104,7 +104,7 @@ namespace ams::secmon::fatal {
sector_count -= cur_sectors;
}
R_SUCCEED();
return ResultSuccess();
}
}

View File

@@ -34,45 +34,45 @@ namespace ams::fs {
Result TranslateFatFsError(FRESULT res) {
switch (res) {
case FR_OK:
R_SUCCEED();
return ResultSuccess();
case FR_DISK_ERR:
R_THROW(fs::ResultMmcAccessFailed());
return fs::ResultMmcAccessFailed();
case FR_INT_ERR:
R_THROW(fs::ResultPreconditionViolation());
return fs::ResultPreconditionViolation();
case FR_NOT_READY:
R_THROW(fs::ResultMmcAccessFailed());
return fs::ResultMmcAccessFailed();
case FR_NO_FILE:
R_THROW(fs::ResultPathNotFound());
return fs::ResultPathNotFound();
case FR_NO_PATH:
R_THROW(fs::ResultPathNotFound());
return fs::ResultPathNotFound();
case FR_INVALID_NAME:
R_THROW(fs::ResultInvalidPath());
return fs::ResultInvalidPath();
case FR_DENIED:
R_THROW(fs::ResultPermissionDenied());
return fs::ResultPermissionDenied();
case FR_EXIST:
R_THROW(fs::ResultPathAlreadyExists());
return fs::ResultPathAlreadyExists();
case FR_INVALID_OBJECT:
R_THROW(fs::ResultInvalidArgument());
return fs::ResultInvalidArgument();
case FR_WRITE_PROTECTED:
R_THROW(fs::ResultWriteNotPermitted());
return fs::ResultWriteNotPermitted();
case FR_INVALID_DRIVE:
R_THROW(fs::ResultInvalidMountName());
return fs::ResultInvalidMountName();
case FR_NOT_ENABLED:
R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
return fs::ResultInvalidMountName(); /* BAD/TODO */
case FR_NO_FILESYSTEM:
R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
return fs::ResultInvalidMountName(); /* BAD/TODO */
case FR_TIMEOUT:
R_THROW(fs::ResultTargetLocked()); /* BAD/TODO */
return fs::ResultTargetLocked(); /* BAD/TODO */
case FR_LOCKED:
R_THROW(fs::ResultTargetLocked());
return fs::ResultTargetLocked();
case FR_NOT_ENOUGH_CORE:
R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
return fs::ResultPreconditionViolation(); /* BAD/TODO */
case FR_TOO_MANY_OPEN_FILES:
R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
return fs::ResultPreconditionViolation(); /* BAD/TODO */
case FR_INVALID_PARAMETER:
R_THROW(fs::ResultInvalidArgument());
return fs::ResultInvalidArgument();
default:
R_THROW(fs::ResultInternal());
return fs::ResultInternal();
}
}
@@ -125,11 +125,11 @@ namespace ams::fs {
/* Expand the file. */
R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1)));
R_SUCCEED();
return ResultSuccess();
}
Result CreateDirectory(const char *path) {
R_RETURN(TranslateFatFsError(f_mkdir(path)));
return TranslateFatFsError(f_mkdir(path));
}
Result OpenFile(FileHandle *out_file, const char *path, int mode) {
@@ -144,10 +144,10 @@ namespace ams::fs {
out_file->_handle = fp;
g_files_opened[i] = true;
g_open_modes[i] = mode;
R_SUCCEED();
return ResultSuccess();
}
}
R_THROW(fs::ResultOpenCountLimit());
return fs::ResultOpenCountLimit();
}
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -164,11 +164,11 @@ namespace ams::fs {
/* Check that we read the correct amount. */
R_UNLESS(br == size, fs::ResultOutOfRange());
R_SUCCEED();
return ResultSuccess();
}
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) {
R_RETURN(ReadFile(handle, offset, buffer, size, fs::ReadOption::None));
return ReadFile(handle, offset, buffer, size, fs::ReadOption::None);
}
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -185,21 +185,21 @@ namespace ams::fs {
/* Set the output size. */
*out = br;
R_SUCCEED();
return ResultSuccess();
}
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) {
R_RETURN(ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None));
return ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None);
}
Result GetFileSize(s64 *out, FileHandle handle) {
FIL *fp = GetInternalFile(handle);
*out = f_size(fp);
R_SUCCEED();
return ResultSuccess();
}
Result FlushFile(FileHandle handle) {
R_RETURN(TranslateFatFsError(f_sync(GetInternalFile(handle))));
return TranslateFatFsError(f_sync(GetInternalFile(handle)));
}
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
@@ -218,7 +218,7 @@ namespace ams::fs {
R_TRY(FlushFile(handle));
}
R_SUCCEED();
return ResultSuccess();
}
Result SetFileSize(FileHandle handle, s64 size) {
@@ -242,7 +242,7 @@ namespace ams::fs {
/* Check that our expansion succeeded. */
AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size));
R_SUCCEED();
return ResultSuccess();
}
int GetFileOpenMode(FileHandle handle) {

View File

@@ -85,10 +85,10 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
/* We can get away with only including latest because exosphere supports newer-than-expected master key in engine. */
/* TODO: Update on next change of keys. */
/* Mariko Development Master Kek Source. */
.byte 0x18, 0xA5, 0x6F, 0xEF, 0x72, 0x11, 0x62, 0xC5, 0x1A, 0x14, 0xF1, 0x8C, 0x21, 0x83, 0x27, 0xB7
.byte 0xEC, 0x5E, 0xB5, 0x11, 0xD5, 0x43, 0x1E, 0x6A, 0x4E, 0x54, 0x6F, 0xD4, 0xD3, 0x22, 0xCE, 0x87
/* Mariko Production Master Kek Source. */
.byte 0xEC, 0x61, 0xBC, 0x82, 0x1E, 0x0F, 0x5A, 0xC3, 0x2B, 0x64, 0x3F, 0x9D, 0xD6, 0x19, 0x22, 0x2D
.byte 0xD2, 0x68, 0xC6, 0x53, 0x9D, 0x94, 0xF9, 0xA8, 0xA5, 0xA8, 0xA7, 0xC8, 0x8F, 0x53, 0x4B, 0x7A
/* Development Master Key Vectors. */
.byte 0x46, 0x22, 0xB4, 0x51, 0x9A, 0x7E, 0xA7, 0x7F, 0x62, 0xA1, 0x1F, 0x8F, 0xC5, 0x3A, 0xDB, 0xFE /* Zeroes encrypted with Master Key 00. */
@@ -105,7 +105,6 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C /* Master key 0A encrypted with Master key 0B. */
.byte 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 /* Master key 0B encrypted with Master key 0C. */
.byte 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 /* Master key 0C encrypted with Master key 0D. */
.byte 0xD6, 0x80, 0x98, 0xC0, 0xFA, 0xC7, 0x13, 0xCB, 0x93, 0xD2, 0x0B, 0x82, 0x4C, 0xA1, 0x7B, 0x8D /* Master key 0D encrypted with Master key 0E. */
/* Production Master Key Vectors. */
.byte 0x0C, 0xF0, 0x59, 0xAC, 0x85, 0xF6, 0x26, 0x65, 0xE1, 0xE9, 0x19, 0x55, 0xE6, 0xF2, 0x67, 0x3D /* Zeroes encrypted with Master Key 00. */
@@ -122,7 +121,6 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 /* Master key 0A encrypted with Master key 0B. */
.byte 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 /* Master key 0B encrypted with Master key 0C. */
.byte 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 /* Master key 0C encrypted with Master key 0D. */
.byte 0xB1, 0x81, 0xA6, 0x0D, 0x72, 0xC7, 0xEE, 0x15, 0x21, 0xF3, 0xC0, 0xB5, 0x6B, 0x61, 0x6D, 0xE7 /* Master key 0D encrypted with Master key 0E. */
/* Device Master Key Source Sources. */
.byte 0x8B, 0x4E, 0x1C, 0x22, 0x42, 0x07, 0xC8, 0x73, 0x56, 0x94, 0x08, 0x8B, 0xCC, 0x47, 0x0F, 0x5D /* 4.0.0 Device Master Key Source Source. */
@@ -136,7 +134,6 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 /* 12.1.0 Device Master Key Source Source. */
.byte 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F /* 13.0.0 Device Master Key Source Source. */
.byte 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D /* 14.0.0 Device Master Key Source Source. */
.byte 0x5E, 0xC9, 0xC5, 0x0A, 0xD0, 0x5F, 0x8B, 0x7B, 0xA7, 0x39, 0xEA, 0xBC, 0x60, 0x0F, 0x74, 0xE6 /* 15.0.0 Device Master Key Source Source. */
/* Development Device Master Kek Sources. */
.byte 0xD6, 0xBD, 0x9F, 0xC6, 0x18, 0x09, 0xE1, 0x96, 0x20, 0x39, 0x60, 0xD2, 0x89, 0x83, 0x31, 0x34 /* 4.0.0 Device Master Kek Source. */
@@ -150,7 +147,6 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB /* 12.1.0 Device Master Kek Source. */
.byte 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F /* 13.0.0 Device Master Kek Source. */
.byte 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA /* 14.0.0 Device Master Kek Source. */
.byte 0xAE, 0x05, 0x48, 0x65, 0xAB, 0x17, 0x9D, 0x3D, 0x51, 0xB7, 0x56, 0xBD, 0x9B, 0x0B, 0x5B, 0x6E /* 15.0.0 Device Master Kek Source. */
/* Production Device Master Kek Sources. */
.byte 0x88, 0x62, 0x34, 0x6E, 0xFA, 0xF7, 0xD8, 0x3F, 0xE1, 0x30, 0x39, 0x50, 0xF0, 0xB7, 0x5D, 0x5D /* 4.0.0 Device Master Kek Source. */
@@ -164,4 +160,3 @@ _ZN3ams6secmon4boot15VolatileKeyDataE:
.byte 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 /* 12.1.0 Device Master Kek Source. */
.byte 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 /* 13.0.0 Device Master Kek Source. */
.byte 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 /* 14.0.0 Device Master Kek Source. */
.byte 0x7C, 0x30, 0xED, 0x8B, 0x39, 0x25, 0x2C, 0x08, 0x8F, 0x48, 0xDC, 0x28, 0xE6, 0x1A, 0x6B, 0x49 /* 15.0.0 Device Master Kek Source. */

View File

@@ -94,7 +94,7 @@ namespace ams::secmon::boot {
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 15);
static_assert(pkg1::KeyGeneration_Count == 14);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}

View File

@@ -52,7 +52,7 @@ namespace ams::secmon::smc {
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
[fuse::DramId_HoagHynix1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaHynix1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_Deprecated7] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSansung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung8GB] = pkg1::MemorySize_8GB,
[fuse::DramId_IowaHynix4GB] = pkg1::MemorySize_4GB,
@@ -61,7 +61,7 @@ namespace ams::secmon::smc {
[fuse::DramId_HoagSamsung8GB] = pkg1::MemorySize_8GB,
[fuse::DramId_HoagHynix4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagMicron4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_Deprecated16] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung4GBY] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung1y4GBX] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung1y8GBX] = pkg1::MemorySize_8GB,
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
@@ -74,12 +74,6 @@ namespace ams::secmon::smc {
[fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaMicron1y4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaSamsung1y8GBX] = pkg1::MemorySize_8GB,
[fuse::DramId_IowaX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaX1X2Samsung4GB] = pkg1::MemorySize_4GB,
[fuse::DramId_IowaSamsung4GBY] = pkg1::MemorySize_4GB,
[fuse::DramId_HoagSamsung4GBY] = pkg1::MemorySize_4GB,
[fuse::DramId_AulaSamsung4GBY] = pkg1::MemorySize_4GB,
};
constexpr const pkg1::MemoryMode MemoryModes[] = {

View File

@@ -39,45 +39,45 @@ namespace ams::fs {
Result TranslateFatFsError(FRESULT res) {
switch (res) {
case FR_OK:
R_SUCCEED();
return ResultSuccess();
case FR_DISK_ERR:
R_THROW(fs::ResultMmcAccessFailed());
return fs::ResultMmcAccessFailed();
case FR_INT_ERR:
R_THROW(fs::ResultPreconditionViolation());
return fs::ResultPreconditionViolation();
case FR_NOT_READY:
R_THROW(fs::ResultMmcAccessFailed());
return fs::ResultMmcAccessFailed();
case FR_NO_FILE:
R_THROW(fs::ResultPathNotFound());
return fs::ResultPathNotFound();
case FR_NO_PATH:
R_THROW(fs::ResultPathNotFound());
return fs::ResultPathNotFound();
case FR_INVALID_NAME:
R_THROW(fs::ResultInvalidPath());
return fs::ResultInvalidPath();
case FR_DENIED:
R_THROW(fs::ResultPermissionDenied());
return fs::ResultPermissionDenied();
case FR_EXIST:
R_THROW(fs::ResultPathAlreadyExists());
return fs::ResultPathAlreadyExists();
case FR_INVALID_OBJECT:
R_THROW(fs::ResultInvalidArgument());
return fs::ResultInvalidArgument();
case FR_WRITE_PROTECTED:
R_THROW(fs::ResultWriteNotPermitted());
return fs::ResultWriteNotPermitted();
case FR_INVALID_DRIVE:
R_THROW(fs::ResultInvalidMountName());
return fs::ResultInvalidMountName();
case FR_NOT_ENABLED:
R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
return fs::ResultInvalidMountName(); /* BAD/TODO */
case FR_NO_FILESYSTEM:
R_THROW(fs::ResultInvalidMountName()); /* BAD/TODO */
return fs::ResultInvalidMountName(); /* BAD/TODO */
case FR_TIMEOUT:
R_THROW(fs::ResultTargetLocked()); /* BAD/TODO */
return fs::ResultTargetLocked(); /* BAD/TODO */
case FR_LOCKED:
R_THROW(fs::ResultTargetLocked());
return fs::ResultTargetLocked();
case FR_NOT_ENOUGH_CORE:
R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
return fs::ResultPreconditionViolation(); /* BAD/TODO */
case FR_TOO_MANY_OPEN_FILES:
R_THROW(fs::ResultPreconditionViolation()); /* BAD/TODO */
return fs::ResultPreconditionViolation(); /* BAD/TODO */
case FR_INVALID_PARAMETER:
R_THROW(fs::ResultInvalidArgument());
return fs::ResultInvalidArgument();
default:
R_THROW(fs::ResultInternal());
return fs::ResultInternal();
}
}
@@ -138,7 +138,7 @@ namespace ams::fs {
*out_entry_type = (info.fattrib & AM_DIR) ? DirectoryEntryType_Directory : DirectoryEntryType_File;
*out_archive = (info.fattrib & AM_ARC);
R_SUCCEED();
return ResultSuccess();
}
Result CreateFile(const char *path, s64 size) {
@@ -152,11 +152,11 @@ namespace ams::fs {
/* Expand the file. */
R_TRY(TranslateFatFsError(f_expand(std::addressof(fp), size, 1)));
R_SUCCEED();
return ResultSuccess();
}
Result CreateDirectory(const char *path) {
R_RETURN(TranslateFatFsError(f_mkdir(path)));
return TranslateFatFsError(f_mkdir(path));
}
Result OpenFile(FileHandle *out_file, const char *path, int mode) {
@@ -171,10 +171,10 @@ namespace ams::fs {
out_file->_handle = fp;
g_files_opened[i] = true;
g_open_modes[i] = mode;
R_SUCCEED();
return ResultSuccess();
}
}
R_THROW(fs::ResultOpenCountLimit());
return fs::ResultOpenCountLimit();
}
Result OpenDirectory(DirectoryHandle *out_dir, const char *path) {
@@ -188,10 +188,10 @@ namespace ams::fs {
/* Set the output. */
out_dir->_handle = dp;
g_dirs_opened[i] = true;
R_SUCCEED();
return ResultSuccess();
}
}
R_THROW(fs::ResultOpenCountLimit());
return fs::ResultOpenCountLimit();
}
Result ReadDirectory(s64 *out_count, DirectoryEntry *out_entries, DirectoryHandle handle, s64 max_entries) {
@@ -209,7 +209,7 @@ namespace ams::fs {
}
*out_count = count;
R_SUCCEED();
return ResultSuccess();
}
void CloseDirectory(DirectoryHandle handle) {
@@ -232,11 +232,11 @@ namespace ams::fs {
/* Check that we read the correct amount. */
R_UNLESS(br == size, fs::ResultOutOfRange());
R_SUCCEED();
return ResultSuccess();
}
Result ReadFile(FileHandle handle, s64 offset, void *buffer, size_t size) {
R_RETURN(ReadFile(handle, offset, buffer, size, fs::ReadOption::None));
return ReadFile(handle, offset, buffer, size, fs::ReadOption::None);
}
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size, const fs::ReadOption &option) {
@@ -253,21 +253,21 @@ namespace ams::fs {
/* Set the output size. */
*out = br;
R_SUCCEED();
return ResultSuccess();
}
Result ReadFile(size_t *out, FileHandle handle, s64 offset, void *buffer, size_t size) {
R_RETURN(ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None));
return ReadFile(out, handle, offset, buffer, size, fs::ReadOption::None);
}
Result GetFileSize(s64 *out, FileHandle handle) {
FIL *fp = GetInternalFile(handle);
*out = f_size(fp);
R_SUCCEED();
return ResultSuccess();
}
Result FlushFile(FileHandle handle) {
R_RETURN(TranslateFatFsError(f_sync(GetInternalFile(handle))));
return TranslateFatFsError(f_sync(GetInternalFile(handle)));
}
Result WriteFile(FileHandle handle, s64 offset, const void *buffer, size_t size, const fs::WriteOption &option) {
@@ -286,7 +286,7 @@ namespace ams::fs {
R_TRY(FlushFile(handle));
}
R_SUCCEED();
return ResultSuccess();
}
Result SetFileSize(FileHandle handle, s64 size) {
@@ -310,7 +310,7 @@ namespace ams::fs {
/* Check that our expansion succeeded. */
AMS_ASSERT(f_size(fp) == static_cast<FSIZE_t>(size));
R_SUCCEED();
return ResultSuccess();
}
int GetFileOpenMode(FileHandle handle) {

View File

@@ -20,7 +20,7 @@ namespace ams::fs {
Result FileHandleStorage::UpdateSize() {
R_SUCCEED_IF(m_size != InvalidSize);
R_RETURN(GetFileSize(std::addressof(m_size), m_handle));
return GetFileSize(std::addressof(m_size), m_handle);
}
Result FileHandleStorage::Read(s64 offset, void *buffer, size_t size) {
@@ -34,9 +34,9 @@ namespace ams::fs {
R_TRY(this->UpdateSize());
/* Ensure our access is valid. */
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
R_RETURN(ReadFile(m_handle, offset, buffer, size, fs::ReadOption()));
return ReadFile(m_handle, offset, buffer, size, fs::ReadOption());
}
Result FileHandleStorage::Write(s64 offset, const void *buffer, size_t size) {
@@ -50,24 +50,24 @@ namespace ams::fs {
R_TRY(this->UpdateSize());
/* Ensure our access is valid. */
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
R_RETURN(WriteFile(m_handle, offset, buffer, size, fs::WriteOption()));
return WriteFile(m_handle, offset, buffer, size, fs::WriteOption());
}
Result FileHandleStorage::Flush() {
R_RETURN(FlushFile(m_handle));
return FlushFile(m_handle);
}
Result FileHandleStorage::GetSize(s64 *out_size) {
R_TRY(this->UpdateSize());
*out_size = m_size;
R_SUCCEED();
return ResultSuccess();
}
Result FileHandleStorage::SetSize(s64 size) {
m_size = InvalidSize;
R_RETURN(SetFileSize(m_handle, size));
return SetFileSize(m_handle, size);
}
}

View File

@@ -31,38 +31,25 @@ namespace ams::fs {
virtual Result GetSize(s64 *out) = 0;
public:
static inline Result CheckAccessRange(s64 offset, s64 size, s64 total_size) {
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
R_UNLESS(size >= 0, fs::ResultInvalidSize());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_UNLESS(offset + size <= total_size, fs::ResultOutOfRange());
R_SUCCEED();
static inline bool CheckAccessRange(s64 offset, s64 size, s64 total_size) {
return offset >= 0 &&
size >= 0 &&
size <= total_size &&
offset <= (total_size - size);
}
static ALWAYS_INLINE Result CheckAccessRange(s64 offset, size_t size, s64 total_size) {
R_RETURN(CheckAccessRange(offset, static_cast<s64>(size), total_size));
static inline bool CheckAccessRange(s64 offset, size_t size, s64 total_size) {
return CheckAccessRange(offset, static_cast<s64>(size), total_size);
}
static inline Result CheckOffsetAndSize(s64 offset, s64 size) {
R_UNLESS(offset >= 0, fs::ResultInvalidOffset());
R_UNLESS(size >= 0, fs::ResultInvalidSize());
R_UNLESS(util::CanAddWithoutOverflow<s64>(offset, size), fs::ResultOutOfRange());
R_SUCCEED();
static inline bool CheckOffsetAndSize(s64 offset, s64 size) {
return offset >= 0 &&
size >= 0 &&
offset <= (offset + size);
}
static ALWAYS_INLINE Result CheckOffsetAndSize(s64 offset, size_t size) {
R_RETURN(CheckOffsetAndSize(offset, static_cast<s64>(size)));
}
static inline Result CheckOffsetAndSizeWithResult(s64 offset, s64 size, Result fail_result) {
R_TRY_CATCH(CheckOffsetAndSize(offset, size)) {
R_CONVERT_ALL(fail_result);
} R_END_TRY_CATCH;
R_SUCCEED();
}
static ALWAYS_INLINE Result CheckOffsetAndSizeWithResult(s64 offset, size_t size, Result fail_result) {
R_RETURN(CheckOffsetAndSizeWithResult(offset, static_cast<s64>(size), fail_result));
static inline bool CheckOffsetAndSize(s64 offset, size_t size) {
return CheckOffsetAndSize(offset, static_cast<s64>(size));
}
};
@@ -73,23 +60,23 @@ namespace ams::fs {
ReadOnlyStorageAdapter(IStorage &s) : m_storage(s) { /* ... */ }
virtual Result Read(s64 offset, void *buffer, size_t size) override {
R_RETURN(m_storage.Read(offset, buffer, size));
return m_storage.Read(offset, buffer, size);
}
virtual Result Flush() override {
R_RETURN(m_storage.Flush());
return m_storage.Flush();
}
virtual Result GetSize(s64 *out) override {
R_RETURN(m_storage.GetSize(out));
return m_storage.GetSize(out);
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
};
@@ -106,9 +93,9 @@ namespace ams::fs {
R_SUCCEED_IF(size == 0);
/* Validate arguments and read. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_RETURN(m_storage.Read(m_offset + offset, buffer, size));
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
return m_storage.Read(m_offset + offset, buffer, size);
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override{
@@ -116,22 +103,22 @@ namespace ams::fs {
R_SUCCEED_IF(size == 0);
/* Validate arguments and write. */
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_TRY(IStorage::CheckAccessRange(offset, size, m_size));
R_RETURN(m_storage.Write(m_offset + offset, buffer, size));
R_UNLESS(buffer != nullptr, fs::ResultNullptrArgument());
R_UNLESS(IStorage::CheckAccessRange(offset, size, m_size), fs::ResultOutOfRange());
return m_storage.Write(m_offset + offset, buffer, size);
}
virtual Result Flush() override {
R_RETURN(m_storage.Flush());
return m_storage.Flush();
}
virtual Result GetSize(s64 *out) override {
*out = m_size;
R_SUCCEED();
return ResultSuccess();
}
virtual Result SetSize(s64 size) override {
R_THROW(fs::ResultUnsupportedSetSizeForNotResizableSubStorage());
return fs::ResultUnsupportedSetSizeForNotResizableSubStorage();
}
};

View File

@@ -33,11 +33,11 @@ namespace ams::nxboot {
ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size));
}
R_RETURN(ReadSdCard(buffer, size, offset / sdmmc::SectorSize, size / sdmmc::SectorSize));
return ReadSdCard(buffer, size, offset / sdmmc::SectorSize, size / sdmmc::SectorSize);
}
virtual Result Flush() override {
R_SUCCEED();
return ResultSuccess();
}
virtual Result GetSize(s64 *out) override {
@@ -45,15 +45,15 @@ namespace ams::nxboot {
R_TRY(GetSdCardMemoryCapacity(std::addressof(num_sectors)));
*out = static_cast<s64>(num_sectors) * static_cast<s64>(sdmmc::SectorSize);
R_SUCCEED();
return ResultSuccess();
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
};
@@ -67,11 +67,11 @@ namespace ams::nxboot {
ShowFatalError("SdCard: unaligned access to %" PRIx64 ", size=%" PRIx64"\n", static_cast<u64>(offset), static_cast<u64>(size));
}
R_RETURN(ReadMmc(buffer, size, Partition, offset / sdmmc::SectorSize, size / sdmmc::SectorSize));
return ReadMmc(buffer, size, Partition, offset / sdmmc::SectorSize, size / sdmmc::SectorSize);
}
virtual Result Flush() override {
R_SUCCEED();
return ResultSuccess();
}
virtual Result GetSize(s64 *out) override {
@@ -79,15 +79,15 @@ namespace ams::nxboot {
R_TRY(GetMmcMemoryCapacity(std::addressof(num_sectors), Partition));
*out = num_sectors * sdmmc::SectorSize;
R_SUCCEED();
return ResultSuccess();
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
};
@@ -153,23 +153,23 @@ namespace ams::nxboot {
subofs = 0;
}
R_SUCCEED();
return ResultSuccess();
}
virtual Result Flush() override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result GetSize(s64 *out) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result Write(s64 offset, const void *buffer, size_t size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
virtual Result SetSize(s64 size) override {
R_THROW(fs::ResultUnsupportedOperation());
return fs::ResultUnsupportedOperation();
}
};
@@ -349,11 +349,11 @@ namespace ams::nxboot {
}
Result ReadBoot0(s64 offset, void *dst, size_t size) {
R_RETURN(g_boot0_storage->Read(offset, dst, size));
return g_boot0_storage->Read(offset, dst, size);
}
Result ReadPackage2(s64 offset, void *dst, size_t size) {
R_RETURN(g_package2_storage->Read(offset, dst, size));
return g_package2_storage->Read(offset, dst, size);
}
}

View File

@@ -45,7 +45,7 @@ namespace ams::nxboot {
/* Write the context to the file. */
R_TRY(fs::WriteFile(file, 0, ctx, sizeof(*ctx), fs::WriteOption::Flush));
R_SUCCEED();
return ResultSuccess();
}
}

View File

@@ -23,17 +23,17 @@ namespace ams::nxboot {
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0xEC, 0x61, 0xBC, 0x82, 0x1E, 0x0F, 0x5A, 0xC3, 0x2B, 0x64, 0x3F, 0x9D, 0xD6, 0x19, 0x22, 0x2D
0xD2, 0x68, 0xC6, 0x53, 0x9D, 0x94, 0xF9, 0xA8, 0xA5, 0xA8, 0xA7, 0xC8, 0x8F, 0x53, 0x4B, 0x7A
};
alignas(se::AesBlockSize) constexpr inline const u8 MarikoMasterKekSourceDev[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0x18, 0xA5, 0x6F, 0xEF, 0x72, 0x11, 0x62, 0xC5, 0x1A, 0x14, 0xF1, 0x8C, 0x21, 0x83, 0x27, 0xB7
0xEC, 0x5E, 0xB5, 0x11, 0xD5, 0x43, 0x1E, 0x6A, 0x4E, 0x54, 0x6F, 0xD4, 0xD3, 0x22, 0xCE, 0x87
};
alignas(se::AesBlockSize) constexpr inline const u8 EristaMasterKekSource[se::AesBlockSize] = {
/* TODO: Update on next change of keys. */
0x6E, 0x77, 0x86, 0xAC, 0x83, 0x0A, 0x8D, 0x3E, 0x7D, 0xB7, 0x66, 0xA0, 0x22, 0xB7, 0x6E, 0x67
0xF0, 0x13, 0x37, 0x9A, 0xD5, 0x63, 0x51, 0xC3, 0xB4, 0x96, 0x35, 0xBC, 0x9C, 0xE8, 0x76, 0x81
};
alignas(se::AesBlockSize) constexpr inline const u8 KeyblobKeySource[se::AesBlockSize] = {
@@ -68,7 +68,6 @@ namespace ams::nxboot {
{ 0xAA, 0xFD, 0xBC, 0xBB, 0x25, 0xC3, 0xA4, 0xEF, 0xE3, 0xEE, 0x58, 0x53, 0xB7, 0xF8, 0xDD, 0xD6 }, /* 12.1.0 Device Master Key Source Source. */
{ 0xE4, 0xF3, 0x45, 0x6F, 0x18, 0xA1, 0x89, 0xF8, 0xDA, 0x4C, 0x64, 0x75, 0x68, 0xE6, 0xBD, 0x4F }, /* 13.0.0 Device Master Key Source Source. */
{ 0x5B, 0x94, 0x63, 0xF7, 0xAD, 0x96, 0x1B, 0xA6, 0x23, 0x30, 0x06, 0x4D, 0x01, 0xE4, 0xCE, 0x1D }, /* 14.0.0 Device Master Key Source Source. */
{ 0x5E, 0xC9, 0xC5, 0x0A, 0xD0, 0x5F, 0x8B, 0x7B, 0xA7, 0x39, 0xEA, 0xBC, 0x60, 0x0F, 0x74, 0xE6 }, /* 15.0.0 Device Master Key Source Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSources[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -83,7 +82,6 @@ namespace ams::nxboot {
{ 0xC2, 0x65, 0x34, 0x6E, 0xC7, 0xC6, 0x5D, 0x97, 0x3E, 0x34, 0x5C, 0x6B, 0xB3, 0x7E, 0xC6, 0xE3 }, /* 12.1.0 Device Master Kek Source. */
{ 0x77, 0x52, 0x92, 0xF0, 0xAA, 0xE3, 0xFB, 0xE0, 0x60, 0x16, 0xB3, 0x78, 0x68, 0x53, 0xF7, 0xA8 }, /* 13.0.0 Device Master Kek Source. */
{ 0x67, 0xD5, 0xD6, 0x0C, 0x08, 0xF5, 0xA3, 0x11, 0xBD, 0x6D, 0x5A, 0xEB, 0x96, 0x24, 0xB0, 0xD2 }, /* 14.0.0 Device Master Kek Source. */
{ 0x7C, 0x30, 0xED, 0x8B, 0x39, 0x25, 0x2C, 0x08, 0x8F, 0x48, 0xDC, 0x28, 0xE6, 0x1A, 0x6B, 0x49 }, /* 15.0.0 Device Master Kek Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 DeviceMasterKekSourcesDev[pkg1::OldDeviceMasterKeyCount][se::AesBlockSize] = {
@@ -98,7 +96,6 @@ namespace ams::nxboot {
{ 0xC4, 0xBB, 0xF3, 0x9F, 0xA3, 0xAA, 0x00, 0x99, 0x7C, 0x97, 0xAD, 0x91, 0x8F, 0xE8, 0x45, 0xCB }, /* 12.1.0 Device Master Kek Source. */
{ 0x20, 0x20, 0xAA, 0xFB, 0x89, 0xC2, 0xF0, 0x70, 0xB5, 0xE0, 0xA3, 0x11, 0x8A, 0x29, 0x8D, 0x0F }, /* 13.0.0 Device Master Kek Source. */
{ 0xCE, 0x14, 0x74, 0x66, 0x98, 0xA8, 0x6D, 0x7D, 0xBD, 0x54, 0x91, 0x68, 0x5F, 0x1D, 0x0E, 0xEA }, /* 14.0.0 Device Master Kek Source. */
{ 0xAE, 0x05, 0x48, 0x65, 0xAB, 0x17, 0x9D, 0x3D, 0x51, 0xB7, 0x56, 0xBD, 0x9B, 0x0B, 0x5B, 0x6E }, /* 15.0.0 Device Master Kek Source. */
};
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySources[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -116,7 +113,6 @@ namespace ams::nxboot {
{ 0xC1, 0x8D, 0x16, 0xBB, 0x2A, 0xE4, 0x1D, 0xD4, 0xC2, 0xC1, 0xB6, 0x40, 0x94, 0x35, 0x63, 0x98 }, /* Master key 0A encrypted with Master key 0B. */
{ 0xA3, 0x24, 0x65, 0x75, 0xEA, 0xCC, 0x6E, 0x8D, 0xFB, 0x5A, 0x16, 0x50, 0x74, 0xD2, 0x15, 0x06 }, /* Master key 0B encrypted with Master key 0C. */
{ 0x83, 0x67, 0xAF, 0x01, 0xCF, 0x93, 0xA1, 0xAB, 0x80, 0x45, 0xF7, 0x3F, 0x72, 0xFD, 0x3B, 0x38 }, /* Master key 0C encrypted with Master key 0D. */
{ 0xB1, 0x81, 0xA6, 0x0D, 0x72, 0xC7, 0xEE, 0x15, 0x21, 0xF3, 0xC0, 0xB5, 0x6B, 0x61, 0x6D, 0xE7 }, /* Master key 0D encrypted with Master key 0E. */
};
alignas(se::AesBlockSize) constexpr inline const u8 MasterKeySourcesDev[pkg1::KeyGeneration_Count][se::AesBlockSize] = {
@@ -134,7 +130,6 @@ namespace ams::nxboot {
{ 0x21, 0x88, 0x6B, 0x10, 0x9E, 0x83, 0xD6, 0x52, 0xAB, 0x08, 0xDB, 0x6D, 0x39, 0xFF, 0x1C, 0x9C }, /* Master key 0A encrypted with Master key 0B. */
{ 0x8A, 0xCE, 0xC4, 0x7F, 0xBE, 0x08, 0x61, 0x88, 0xD3, 0x73, 0x64, 0x51, 0xE2, 0xB6, 0x53, 0x15 }, /* Master key 0B encrypted with Master key 0C. */
{ 0x08, 0xE0, 0xF4, 0xBE, 0xAA, 0x6E, 0x5A, 0xC3, 0xA6, 0xBC, 0xFE, 0xB9, 0xE2, 0xA3, 0x24, 0x12 }, /* Master key 0C encrypted with Master key 0D. */
{ 0xD6, 0x80, 0x98, 0xC0, 0xFA, 0xC7, 0x13, 0xCB, 0x93, 0xD2, 0x0B, 0x82, 0x4C, 0xA1, 0x7B, 0x8D }, /* Master key 0D encrypted with Master key 0E. */
};
alignas(se::AesBlockSize) constinit u8 MasterKeys[pkg1::OldMasterKeyCount][se::AesBlockSize] = {};

View File

@@ -34,7 +34,7 @@ namespace ams::nxboot {
g_mmc_partition = partition;
}
R_SUCCEED();
return ResultSuccess();
}
}
@@ -47,29 +47,29 @@ namespace ams::nxboot {
sdmmc::SetMmcWorkBuffer(MmcPort, g_mmc_work_buffer, sizeof(g_mmc_work_buffer));
/* Activate the mmc. */
R_RETURN(sdmmc::Activate(MmcPort));
return sdmmc::Activate(MmcPort);
}
Result CheckMmcConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
R_RETURN(sdmmc::CheckMmcConnection(out_sm, out_bw, MmcPort));
return sdmmc::CheckMmcConnection(out_sm, out_bw, MmcPort);
}
Result GetMmcMemoryCapacity(u32 *out_num_sectors, sdmmc::MmcPartition partition) {
if (partition == sdmmc::MmcPartition_UserData) {
R_RETURN(sdmmc::GetDeviceMemoryCapacity(out_num_sectors, MmcPort));
return sdmmc::GetDeviceMemoryCapacity(out_num_sectors, MmcPort);
} else {
R_RETURN(sdmmc::GetMmcBootPartitionCapacity(out_num_sectors, MmcPort));
return sdmmc::GetMmcBootPartitionCapacity(out_num_sectors, MmcPort);
}
}
Result ReadMmc(void *dst, size_t size, sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count) {
R_TRY(SelectMmcPartition(partition));
R_RETURN(sdmmc::Read(dst, size, MmcPort, sector_index, sector_count));
return sdmmc::Read(dst, size, MmcPort, sector_index, sector_count);
}
Result WriteMmc(sdmmc::MmcPartition partition, size_t sector_index, size_t sector_count, const void *src, size_t size) {
R_TRY(SelectMmcPartition(partition));
R_RETURN(sdmmc::Write(MmcPort, sector_index, sector_count, src, size));
return sdmmc::Write(MmcPort, sector_index, sector_count, src, size);
}
}

View File

@@ -80,7 +80,7 @@ namespace ams::nxboot {
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 15);
static_assert(pkg1::KeyGeneration_Count == 14);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}

View File

@@ -78,7 +78,7 @@ namespace ams::nxboot {
sdmmc::SetSdCardWorkBuffer(SdCardPort, g_sd_work_buffer, sizeof(g_sd_work_buffer));
/* Activate the SD card. */
R_RETURN(sdmmc::Activate(SdCardPort));
return sdmmc::Activate(SdCardPort);
}
void FinalizeSdCard() {
@@ -90,19 +90,19 @@ namespace ams::nxboot {
}
Result CheckSdCardConnection(sdmmc::SpeedMode *out_sm, sdmmc::BusWidth *out_bw) {
R_RETURN(sdmmc::CheckSdCardConnection(out_sm, out_bw, SdCardPort));
return sdmmc::CheckSdCardConnection(out_sm, out_bw, SdCardPort);
}
Result GetSdCardMemoryCapacity(u32 *out_num_sectors) {
R_RETURN(sdmmc::GetDeviceMemoryCapacity(out_num_sectors, SdCardPort));
return sdmmc::GetDeviceMemoryCapacity(out_num_sectors, SdCardPort);
}
Result ReadSdCard(void *dst, size_t size, size_t sector_index, size_t sector_count) {
R_RETURN(sdmmc::Read(dst, size, SdCardPort, sector_index, sector_count));
return sdmmc::Read(dst, size, SdCardPort, sector_index, sector_count);
}
Result WriteSdCard(size_t sector_index, size_t sector_count, const void *src, size_t size) {
R_RETURN(sdmmc::Write(SdCardPort, sector_index, sector_count, src, size));
return sdmmc::Write(SdCardPort, sector_index, sector_count, src, size);
}
}

View File

@@ -253,8 +253,6 @@ namespace ams::nxboot {
return ams::TargetFirmware_13_2_1;
} else if (std::memcmp(package1 + 0x10, "20220209", 8) == 0) {
return ams::TargetFirmware_14_0_0;
} else if (std::memcmp(package1 + 0x10, "20220801", 8) == 0) {
return ams::TargetFirmware_15_0_0;
}
break;
default:

View File

@@ -156,9 +156,6 @@ namespace ams::nxboot {
FsVersion_14_0_0,
FsVersion_14_0_0_Exfat,
FsVersion_15_0_0,
FsVersion_15_0_0_Exfat,
FsVersion_Count,
};
@@ -230,10 +227,6 @@ namespace ams::nxboot {
{ 0x88, 0x7A, 0xC1, 0x50, 0x80, 0x6C, 0x75, 0xCC }, /* FsVersion_14_0_0 */
{ 0xD4, 0x88, 0xD1, 0xF2, 0x92, 0x17, 0x35, 0x5C }, /* FsVersion_14_0_0_Exfat */
{ 0xD0, 0xD4, 0x49, 0x18, 0x14, 0xB5, 0x62, 0xAF }, /* FsVersion_15_0_0 */
{ 0x34, 0xC0, 0xD9, 0xED, 0x6A, 0xD1, 0x87, 0x3D }, /* FsVersion_15_0_0_Exfat */
};
const InitialProcessBinaryHeader *FindInitialProcessBinary(const pkg2::Package2Header *header, const u8 *data, ams::TargetFirmware target_firmware) {
@@ -635,14 +628,6 @@ namespace ams::nxboot {
AddPatch(fs_meta, 0x195769, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x16F6B0, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_15_0_0:
AddPatch(fs_meta, 0x184259, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x15EDE4, NogcPatch1, sizeof(NogcPatch1));
break;
case FsVersion_15_0_0_Exfat:
AddPatch(fs_meta, 0x18F1E9, NogcPatch0, sizeof(NogcPatch0));
AddPatch(fs_meta, 0x169D74, NogcPatch1, sizeof(NogcPatch1));
break;
default:
break;
}

View File

@@ -85,6 +85,7 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE( 3, 12)
HANDLE_DRAM_CASE( 5, 12)
HANDLE_DRAM_CASE( 6, 12)
HANDLE_DRAM_CASE( 7, 0)
HANDLE_DRAM_CASE( 8, 1)
HANDLE_DRAM_CASE( 9, 2)
HANDLE_DRAM_CASE(10, 3)
@@ -93,6 +94,7 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE(13, 2)
HANDLE_DRAM_CASE(14, 3)
HANDLE_DRAM_CASE(15, 4)
HANDLE_DRAM_CASE(16, 5)
HANDLE_DRAM_CASE(17, 6)
HANDLE_DRAM_CASE(18, 7)
HANDLE_DRAM_CASE(19, 6)
@@ -105,12 +107,6 @@ namespace ams::nxboot {
HANDLE_DRAM_CASE(26, 11)
HANDLE_DRAM_CASE(27, 11)
HANDLE_DRAM_CASE(28, 7)
HANDLE_DRAM_CASE(29, 0)
HANDLE_DRAM_CASE(30, 0)
HANDLE_DRAM_CASE(31, 0)
HANDLE_DRAM_CASE(32, 5)
HANDLE_DRAM_CASE(33, 5)
HANDLE_DRAM_CASE(34, 5)
default:
AMS_ABORT("Invalid DRAM id");
}

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = b2232894f31953511d33bc665f68216badc3bb07
parent = 8ce4f1961580a09381e486cc51c160a00fa86b88
commit = 0d161b8588aa6482b84f3c44dd001055b01a047f
parent = 4efa5d7dd0bfbdf89a6261af0aef3878ca784b05
method = merge
cmdver = 0.4.1

View File

@@ -67,8 +67,6 @@ endif
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map)
else ifeq ($(ATMOSPHERE_OS_NAME),macos)
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-map,$(notdir $@.map)
else
export LDFLAGS = $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $@.map)
endif

View File

@@ -55,7 +55,7 @@ namespace ams::fuse {
DramId_IcosaSamsung6GB = 4,
DramId_HoagHynix1y4GB = 5,
DramId_AulaHynix1y4GB = 6,
DramId_Deprecated7 = 7,
DramId_IowaX1X2Samsung4GB = 7,
DramId_IowaSansung4GB = 8,
DramId_IowaSamsung8GB = 9,
DramId_IowaHynix4GB = 10,
@@ -64,7 +64,7 @@ namespace ams::fuse {
DramId_HoagSamsung8GB = 13,
DramId_HoagHynix4GB = 14,
DramId_HoagMicron4GB = 15,
DramId_Deprecated16 = 16,
DramId_IowaSamsung4GBY = 16,
DramId_IowaSamsung1y4GBX = 17,
DramId_IowaSamsung1y8GBX = 18,
DramId_HoagSamsung1y4GBX = 19,
@@ -77,12 +77,6 @@ namespace ams::fuse {
DramId_HoagMicron1y4GB = 26,
DramId_AulaMicron1y4GB = 27,
DramId_AulaSamsung1y8GBX = 28,
DramId_IowaX1X2Samsung4GB = 29,
DramId_HoagX1X2Samsung4GB = 30,
DramId_AulaX1X2Samsung4GB = 31,
DramId_IowaSamsung4GBY = 32,
DramId_HoagSamsung4GBY = 33,
DramId_AulaSamsung4GBY = 34,
DramId_Count,
};
@@ -125,4 +119,4 @@ namespace ams::fuse {
bool IsOdmProductionMode();
void ConfigureFuseBypass();
}
}

View File

@@ -34,7 +34,6 @@ namespace ams::pkg1 {
KeyGeneration_12_1_0 = 0x0B,
KeyGeneration_13_0_0 = 0x0C,
KeyGeneration_14_0_0 = 0x0D,
KeyGeneration_15_0_0 = 0x0E,
KeyGeneration_Count,

View File

@@ -23,8 +23,8 @@ namespace ams::pkg2 {
constexpr inline int PayloadCount = 3;
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x16 in Nintendo's code. */
constexpr inline int CurrentBootloaderVersion = 0x12;
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x15 in Nintendo's code. */
constexpr inline int CurrentBootloaderVersion = 0x11;
struct Package2Meta {
using Magic = util::FourCC<'P','K','2','1'>;

View File

@@ -39,13 +39,12 @@ namespace ams::fuse {
struct OdmWord4 {
using HardwareState1 = util::BitPack32::Field<0, 2, int>;
using HardwareType1 = util::BitPack32::Field<HardwareState1::Next, 1, int>;
using DramId1 = util::BitPack32::Field<HardwareType1::Next, 5, int>;
using HardwareType2 = util::BitPack32::Field<DramId1::Next, 1, int>;
using DramId = util::BitPack32::Field<HardwareType1::Next, 5, int>;
using HardwareType2 = util::BitPack32::Field<DramId::Next, 1, int>;
using HardwareState2 = util::BitPack32::Field<HardwareType2::Next, 1, int>;
using RetailInteractiveDisplayState = util::BitPack32::Field<HardwareState2::Next, 1, int>;
using FormatVersion = util::BitPack32::Field<RetailInteractiveDisplayState::Next, 1, int>;
using DramId2 = util::BitPack32::Field<FormatVersion::Next, 3, int>;
using Reserved = util::BitPack32::Field<DramId2::Next, 1, int>;
using Reserved = util::BitPack32::Field<FormatVersion::Next, 4, int>;
using HardwareType3 = util::BitPack32::Field<Reserved::Next, 4, int>;
};
@@ -72,15 +71,6 @@ namespace ams::fuse {
(odm_word4.Get<OdmWord4::HardwareType3>() << HardwareType3Shift);
}
constexpr ALWAYS_INLINE int GetDramIdValue(const util::BitPack32 odm_word4) {
constexpr auto DramId1Shift = 0;
constexpr auto DramId2Shift = OdmWord4::DramId1::Count + DramId1Shift;
return (odm_word4.Get<OdmWord4::DramId1>() << DramId1Shift) |
(odm_word4.Get<OdmWord4::DramId2>() << DramId2Shift);
}
constinit uintptr_t g_register_address = secmon::MemoryRegionPhysicalDeviceFuses.GetAddress();
constinit bool g_checked_for_rcm_bug_patch = false;
@@ -177,7 +167,6 @@ namespace ams::fuse {
}
constexpr const TargetFirmware FuseVersionIncrementFirmwares[] = {
TargetFirmware_15_0_0,
TargetFirmware_13_2_1,
TargetFirmware_12_0_2,
TargetFirmware_11_0_0,
@@ -316,8 +305,7 @@ namespace ams::fuse {
}
DramId GetDramId() {
/* Get the value. */
return static_cast<DramId>(GetDramIdValue(util::BitPack32{GetCommonOdmWord(4)}));
return static_cast<DramId>(util::BitPack32{GetCommonOdmWord(4)}.Get<OdmWord4::DramId>());
}
HardwareType GetHardwareType() {

View File

@@ -178,7 +178,7 @@ namespace ams::kern::arch::arm64 {
}
NOINLINE Result InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end);
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, KSystemResource *system_resource, KResourceLimit *resource_limit);
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, KResourceLimit *resource_limit);
Result Finalize();
private:
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);
@@ -208,7 +208,7 @@ namespace ams::kern::arch::arm64 {
}
}
Result MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, bool not_first, 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, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll);
bool MergePages(KProcessAddress virt_addr, PageLinkedList *page_list);

View File

@@ -28,8 +28,8 @@ namespace ams::kern::arch::arm64 {
m_page_table.Activate(id);
}
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, KSystemResource *system_resource, KResourceLimit *resource_limit) {
R_RETURN(m_page_table.InitializeForProcess(id, as_type, enable_aslr, enable_das_merge, from_back, pool, code_address, code_size, system_resource, resource_limit));
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, KResourceLimit *resource_limit) {
R_RETURN(m_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, resource_limit));
}
void Finalize() { m_page_table.Finalize(); }
@@ -110,14 +110,6 @@ namespace ams::kern::arch::arm64 {
R_RETURN(m_page_table.MapRegion(region_type, perm));
}
Result MapInsecureMemory(KProcessAddress address, size_t size) {
R_RETURN(m_page_table.MapInsecureMemory(address, size));
}
Result UnmapInsecureMemory(KProcessAddress address, size_t size) {
R_RETURN(m_page_table.UnmapInsecureMemory(address, size));
}
Result MapPageGroup(KProcessAddress addr, const KPageGroup &pg, KMemoryState state, KMemoryPermission perm) {
R_RETURN(m_page_table.MapPageGroup(addr, pg, state, perm));
}
@@ -166,12 +158,12 @@ namespace ams::kern::arch::arm64 {
R_RETURN(m_page_table.WriteDebugIoMemory(address, buffer, size));
}
Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap) {
R_RETURN(m_page_table.LockForMapDeviceAddressSpace(out_is_io, address, size, perm, is_aligned, check_heap));
Result LockForMapDeviceAddressSpace(KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
R_RETURN(m_page_table.LockForMapDeviceAddressSpace(address, size, perm, is_aligned));
}
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap) {
R_RETURN(m_page_table.LockForUnmapDeviceAddressSpace(address, size, check_heap));
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size) {
R_RETURN(m_page_table.LockForUnmapDeviceAddressSpace(address, size));
}
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) {

View File

@@ -44,8 +44,8 @@ namespace ams::kern::board::generic {
R_THROW(ams::kern::svc::ResultNotImplemented());
}
Result ALWAYS_INLINE Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io) {
MESOSPHERE_UNUSED(page_table, process_address, size, device_address, device_perm, is_aligned, is_io);
Result ALWAYS_INLINE Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
MESOSPHERE_UNUSED(page_table, process_address, size, device_address, device_perm, is_aligned);
R_THROW(ams::kern::svc::ResultNotImplemented());
}

View File

@@ -74,7 +74,7 @@ namespace ams::kern::board::nintendo::nx {
Result Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size);
Result Detach(ams::svc::DeviceName device_name);
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io);
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned);
Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address);
void Unmap(KDeviceVirtualAddress device_address, size_t size) {

View File

@@ -20,9 +20,6 @@
namespace ams::kern::board::nintendo::nx {
class KSystemControl : public KSystemControlBase {
public:
/* This can be overridden as needed. */
static constexpr size_t SecureAppletMemorySize = 4_MB;
public:
class Init : public KSystemControlBase::Init {
public:

View File

@@ -36,13 +36,13 @@ namespace ams::kern::init {
size_t num_KDebug;
size_t num_KIoPool;
size_t num_KIoRegion;
size_t num_KSessionRequestMappings;
};
NOINLINE void InitializeSlabResourceCounts();
const KSlabResourceCounts &GetSlabResourceCounts();
size_t CalculateTotalSlabHeapSize();
NOINLINE void InitializeKPageBufferSlabHeap();
NOINLINE void InitializeSlabHeaps();
}

View File

@@ -21,8 +21,6 @@ namespace ams::kern {
class KAutoObject;
class KSystemResource;
#define FOR_EACH_K_CLASS_TOKEN_OBJECT_TYPE(HANDLER) \
HANDLER(KAutoObject) \
\
@@ -50,8 +48,7 @@ namespace ams::kern {
HANDLER(KSessionRequest) \
HANDLER(KCodeMemory) \
HANDLER(KIoPool) \
HANDLER(KIoRegion) \
HANDLER(KSystemResource)
HANDLER(KIoRegion)
class KClassTokenGenerator {
public:
@@ -98,7 +95,7 @@ namespace ams::kern {
if constexpr (std::is_same<T, KAutoObject>::value) {
static_assert(T::ObjectType == ObjectType::KAutoObject);
return 0;
} else if constexpr (!std::is_final<T>::value && !std::same_as<T, KSystemResource>) {
} else if constexpr (!std::is_final<T>::value) {
static_assert(ObjectType::BaseClassesStart <= T::ObjectType && T::ObjectType < ObjectType::BaseClassesEnd);
constexpr auto ClassIndex = static_cast<TokenBaseType>(T::ObjectType) - static_cast<TokenBaseType>(ObjectType::BaseClassesStart);
return BaseClassToken<ClassIndex> | GetClassToken<typename T::BaseClass>();
@@ -145,12 +142,6 @@ namespace ams::kern {
KIoPool,
KIoRegion,
/* NOTE: What occupies these gaps? They can be inferred, but they don't make sense. */
KAlpha,
KBeta,
KSystemResource,
FinalClassesLast,
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
@@ -187,10 +178,8 @@ namespace ams::kern {
}
for (auto fin = util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesStart); fin < util::ToUnderlying(KClassTokenGenerator::ObjectType::FinalClassesLast); ++fin) {
if (const auto o = static_cast<KClassTokenGenerator::ObjectType>(fin); !IsObjectTypeIncludedByMacro(o)) {
if (o != KClassTokenGenerator::ObjectType::KAlpha && o != KClassTokenGenerator::ObjectType::KBeta) {
return false;
}
if (!IsObjectTypeIncludedByMacro(static_cast<KClassTokenGenerator::ObjectType>(fin))) {
return false;
}
}

View File

@@ -41,17 +41,17 @@ namespace ams::kern {
Result Attach(ams::svc::DeviceName device_name);
Result Detach(ams::svc::DeviceName device_name);
Result MapByForce(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, option, false));
Result MapByForce(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(this->Map(page_table, process_address, size, device_address, device_perm, false));
}
Result MapAligned(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option) {
R_RETURN(this->Map(page_table, process_address, size, device_address, option, true));
Result MapAligned(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(this->Map(page_table, process_address, size, device_address, device_perm, true));
}
Result Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address);
private:
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option, bool is_aligned);
Result Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned);
public:
static void Initialize();
};

View File

@@ -38,37 +38,30 @@ namespace ams::kern {
size_t m_peak;
size_t m_count;
KVirtualAddress m_address;
KVirtualAddress m_aligned_address;
size_t m_size;
public:
KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(Null<KVirtualAddress>), m_aligned_address(Null<KVirtualAddress>), m_size() { /* ... */ }
KDynamicPageManager() : m_lock(), m_page_bitmap(), m_used(), m_peak(), m_count(), m_address(Null<KVirtualAddress>), m_size() { /* ... */ }
Result Initialize(KVirtualAddress memory, size_t size, size_t align) {
Result Initialize(KVirtualAddress memory, size_t sz) {
/* We need to have positive size. */
R_UNLESS(size > 0, svc::ResultOutOfMemory());
R_UNLESS(sz > 0, svc::ResultOutOfMemory());
/* Set addresses. */
m_address = memory;
m_aligned_address = util::AlignDown(GetInteger(memory), align);
/* Calculate extents. */
const size_t managed_size = m_address + size - m_aligned_address;
const size_t overhead_size = util::AlignUp(KPageBitmap::CalculateManagementOverheadSize(managed_size / sizeof(PageBuffer)), sizeof(PageBuffer));
R_UNLESS(overhead_size < size, svc::ResultOutOfMemory());
/* Calculate management overhead. */
const size_t management_size = KPageBitmap::CalculateManagementOverheadSize(sz / sizeof(PageBuffer));
const size_t allocatable_size = sz - management_size;
/* Set tracking fields. */
m_size = util::AlignDown(size - overhead_size, sizeof(PageBuffer));
m_count = m_size / sizeof(PageBuffer);
m_address = memory;
m_size = util::AlignDown(allocatable_size, sizeof(PageBuffer));
m_count = allocatable_size / sizeof(PageBuffer);
R_UNLESS(m_count > 0, svc::ResultOutOfMemory());
/* Clear the management region. */
u64 *management_ptr = GetPointer<u64>(m_address + size - overhead_size);
std::memset(management_ptr, 0, overhead_size);
u64 *management_ptr = GetPointer<u64>(m_address + allocatable_size);
std::memset(management_ptr, 0, management_size);
/* Initialize the bitmap. */
const size_t allocatable_region_size = (GetInteger(m_address) + size - overhead_size) - GetInteger(m_aligned_address);
MESOSPHERE_ABORT_UNLESS(allocatable_region_size >= sizeof(PageBuffer));
m_page_bitmap.Initialize(management_ptr, allocatable_region_size / sizeof(PageBuffer));
m_page_bitmap.Initialize(management_ptr, m_count);
/* Free the pages to the bitmap. */
for (size_t i = 0; i < m_count; i++) {
@@ -76,7 +69,7 @@ namespace ams::kern {
cpu::ClearPageToZero(GetPointer<PageBuffer>(m_address) + i);
/* Set the bit for the free page. */
m_page_bitmap.SetBit((GetInteger(m_address) + (i * sizeof(PageBuffer)) - GetInteger(m_aligned_address)) / sizeof(PageBuffer));
m_page_bitmap.SetBit(i);
}
R_SUCCEED();
@@ -105,28 +98,7 @@ namespace ams::kern {
m_page_bitmap.ClearBit(offset);
m_peak = std::max(m_peak, (++m_used));
return GetPointer<PageBuffer>(m_aligned_address) + offset;
}
PageBuffer *Allocate(size_t count) {
/* Take the lock. */
KScopedInterruptDisable di;
KScopedSpinLock lk(m_lock);
/* Find a random free block. */
ssize_t soffset = m_page_bitmap.FindFreeRange(count);
if (AMS_UNLIKELY(soffset < 0)) {
return nullptr;
}
const size_t offset = static_cast<size_t>(soffset);
/* Update our tracking. */
m_page_bitmap.ClearRange(offset, count);
m_used += count;
m_peak = std::max(m_peak, m_used);
return GetPointer<PageBuffer>(m_aligned_address) + offset;
return GetPointer<PageBuffer>(m_address) + offset;
}
void Free(PageBuffer *pb) {
@@ -138,7 +110,7 @@ namespace ams::kern {
KScopedSpinLock lk(m_lock);
/* Set the bit for the free page. */
size_t offset = (reinterpret_cast<uintptr_t>(pb) - GetInteger(m_aligned_address)) / sizeof(PageBuffer);
size_t offset = (reinterpret_cast<uintptr_t>(pb) - GetInteger(m_address)) / sizeof(PageBuffer);
m_page_bitmap.SetBit(offset);
/* Decrement our used count. */

View File

@@ -70,20 +70,15 @@ namespace ams::kern {
u16 m_next_linear_id;
u16 m_count;
public:
constexpr explicit KHandleTable(util::ConstantInitializeTag) : m_entry_infos(), m_objects(), m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(), m_count() { /* ... */ }
constexpr explicit KHandleTable(util::ConstantInitializeTag) : m_entry_infos(), m_objects(), m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(MinLinearId), m_count() { /* ... */ }
explicit KHandleTable() : m_lock(), m_free_head_index(-1), m_table_size(), m_max_count(), m_next_linear_id(), m_count() { MESOSPHERE_ASSERT_THIS(); }
explicit KHandleTable() : m_lock(), m_free_head_index(-1), m_count() { MESOSPHERE_ASSERT_THIS(); }
MESOSPHERE_NOINLINE_IF_DEBUG Result Initialize(s32 size) {
constexpr MESOSPHERE_NOINLINE_IF_DEBUG Result Initialize(s32 size) {
MESOSPHERE_ASSERT_THIS();
/* Check that the table size is valid. */
R_UNLESS(size <= static_cast<s32>(MaxTableSize), svc::ResultOutOfMemory());
/* Lock. */
KScopedDisableDispatch dd;
KScopedSpinLock lk(m_lock);
/* Initialize all fields. */
m_max_count = 0;
m_table_size = (size <= 0) ? MaxTableSize : size;

View File

@@ -22,7 +22,9 @@
namespace ams::kern {
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent>, public KInterruptTask {
class KInterruptEventTask;
class KInterruptEvent final : public KAutoObjectWithSlabHeapAndContainer<KInterruptEvent, KReadableEvent> {
MESOSPHERE_AUTOOBJECT_TRAITS(KInterruptEvent, KReadableEvent);
private:
s32 m_interrupt_id;
@@ -52,9 +54,21 @@ namespace ams::kern {
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr s32 GetInterruptId() const { return m_interrupt_id; }
};
class KInterruptEventTask : public KSlabAllocated<KInterruptEventTask>, public KInterruptTask {
private:
KInterruptEvent *m_event;
public:
constexpr KInterruptEventTask() : m_event(nullptr) { /* ... */ }
~KInterruptEventTask() { /* ... */ }
virtual KInterruptTask *OnInterrupt(s32 interrupt_id) override;
virtual void DoTask() override;
void Unregister(s32 interrupt_id, s32 core_id);
public:
static Result Register(s32 interrupt_id, s32 core_id, bool level, KInterruptEvent *event);
};
}

View File

@@ -43,7 +43,6 @@ namespace ams::kern {
KMemoryState_FlagCanMapProcess = (1 << 23),
KMemoryState_FlagCanChangeAttribute = (1 << 24),
KMemoryState_FlagCanCodeMemory = (1 << 25),
KMemoryState_FlagLinearMapped = (1 << 26),
KMemoryState_FlagsData = KMemoryState_FlagCanReprotect | KMemoryState_FlagCanUseIpc |
KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc |
@@ -51,27 +50,25 @@ namespace ams::kern {
KMemoryState_FlagCanTransfer | KMemoryState_FlagCanQueryPhysical |
KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap |
KMemoryState_FlagCanIpcUserBuffer | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagCanChangeAttribute | KMemoryState_FlagLinearMapped,
KMemoryState_FlagCanChangeAttribute,
KMemoryState_FlagsCode = KMemoryState_FlagCanDebug | KMemoryState_FlagCanUseIpc |
KMemoryState_FlagCanUseNonDeviceIpc | KMemoryState_FlagCanUseNonSecureIpc |
KMemoryState_FlagMapped | KMemoryState_FlagCode |
KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap |
KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagLinearMapped,
KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagReferenceCounted,
KMemoryState_FlagsMisc = KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted |
KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap |
KMemoryState_FlagLinearMapped,
KMemoryState_FlagCanQueryPhysical | KMemoryState_FlagCanDeviceMap,
KMemoryState_Free = ams::svc::MemoryState_Free,
KMemoryState_Io = ams::svc::MemoryState_Io | KMemoryState_FlagMapped | KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap,
KMemoryState_Io = ams::svc::MemoryState_Io | KMemoryState_FlagMapped,
KMemoryState_Static = ams::svc::MemoryState_Static | KMemoryState_FlagMapped | KMemoryState_FlagCanQueryPhysical,
KMemoryState_Code = ams::svc::MemoryState_Code | KMemoryState_FlagsCode | KMemoryState_FlagCanMapProcess,
KMemoryState_CodeData = ams::svc::MemoryState_CodeData | KMemoryState_FlagsData | KMemoryState_FlagCanMapProcess | KMemoryState_FlagCanCodeMemory,
KMemoryState_Normal = ams::svc::MemoryState_Normal | KMemoryState_FlagsData | KMemoryState_FlagCanCodeMemory,
KMemoryState_Shared = ams::svc::MemoryState_Shared | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped,
KMemoryState_Shared = ams::svc::MemoryState_Shared | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted,
/* KMemoryState_Alias was removed after 1.0.0. */
@@ -85,7 +82,7 @@ namespace ams::kern {
KMemoryState_Stack = ams::svc::MemoryState_Stack | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagMapped | KMemoryState_FlagLinearMapped,
KMemoryState_ThreadLocal = ams::svc::MemoryState_ThreadLocal | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted,
KMemoryState_Transfered = ams::svc::MemoryState_Transfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap | KMemoryState_FlagCanChangeAttribute
| KMemoryState_FlagCanUseIpc | KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
@@ -93,7 +90,7 @@ namespace ams::kern {
KMemoryState_SharedTransfered = ams::svc::MemoryState_SharedTransfered | KMemoryState_FlagsMisc | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_SharedCode = ams::svc::MemoryState_SharedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped
KMemoryState_SharedCode = ams::svc::MemoryState_SharedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
KMemoryState_Inaccessible = ams::svc::MemoryState_Inaccessible,
@@ -106,41 +103,36 @@ namespace ams::kern {
KMemoryState_Kernel = ams::svc::MemoryState_Kernel | KMemoryState_FlagMapped,
KMemoryState_GeneratedCode = ams::svc::MemoryState_GeneratedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDebug | KMemoryState_FlagLinearMapped,
KMemoryState_CodeOut = ams::svc::MemoryState_CodeOut | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped,
KMemoryState_GeneratedCode = ams::svc::MemoryState_GeneratedCode | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDebug,
KMemoryState_CodeOut = ams::svc::MemoryState_CodeOut | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted,
KMemoryState_Coverage = ams::svc::MemoryState_Coverage | KMemoryState_FlagMapped,
KMemoryState_Insecure = ams::svc::MemoryState_Insecure | KMemoryState_FlagMapped | KMemoryState_FlagReferenceCounted | KMemoryState_FlagLinearMapped | KMemoryState_FlagCanChangeAttribute
| KMemoryState_FlagCanDeviceMap | KMemoryState_FlagCanAlignedDeviceMap
| KMemoryState_FlagCanUseNonSecureIpc | KMemoryState_FlagCanUseNonDeviceIpc,
};
#if 1
static_assert(KMemoryState_Free == 0x00000000);
static_assert(KMemoryState_Io == 0x00182001);
static_assert(KMemoryState_Io == 0x00002001);
static_assert(KMemoryState_Static == 0x00042002);
static_assert(KMemoryState_Code == 0x04DC7E03);
static_assert(KMemoryState_CodeData == 0x07FEBD04);
static_assert(KMemoryState_Normal == 0x077EBD05);
static_assert(KMemoryState_Shared == 0x04402006);
static_assert(KMemoryState_Code == 0x00DC7E03);
static_assert(KMemoryState_CodeData == 0x03FEBD04);
static_assert(KMemoryState_Normal == 0x037EBD05);
static_assert(KMemoryState_Shared == 0x00402006);
static_assert(KMemoryState_AliasCode == 0x04DD7E08);
static_assert(KMemoryState_AliasCodeData == 0x07FFBD09);
static_assert(KMemoryState_Ipc == 0x045C3C0A);
static_assert(KMemoryState_Stack == 0x045C3C0B);
static_assert(KMemoryState_ThreadLocal == 0x0400200C);
static_assert(KMemoryState_Transfered == 0x055C3C0D);
static_assert(KMemoryState_SharedTransfered == 0x045C380E);
static_assert(KMemoryState_SharedCode == 0x0440380F);
static_assert(KMemoryState_AliasCode == 0x00DD7E08);
static_assert(KMemoryState_AliasCodeData == 0x03FFBD09);
static_assert(KMemoryState_Ipc == 0x005C3C0A);
static_assert(KMemoryState_Stack == 0x005C3C0B);
static_assert(KMemoryState_ThreadLocal == 0x0040200C);
static_assert(KMemoryState_Transfered == 0x015C3C0D);
static_assert(KMemoryState_SharedTransfered == 0x005C380E);
static_assert(KMemoryState_SharedCode == 0x0040380F);
static_assert(KMemoryState_Inaccessible == 0x00000010);
static_assert(KMemoryState_NonSecureIpc == 0x045C3811);
static_assert(KMemoryState_NonDeviceIpc == 0x044C2812);
static_assert(KMemoryState_NonSecureIpc == 0x005C3811);
static_assert(KMemoryState_NonDeviceIpc == 0x004C2812);
static_assert(KMemoryState_Kernel == 0x00002013);
static_assert(KMemoryState_GeneratedCode == 0x04402214);
static_assert(KMemoryState_CodeOut == 0x04402015);
static_assert(KMemoryState_GeneratedCode == 0x00402214);
static_assert(KMemoryState_CodeOut == 0x00402015);
static_assert(KMemoryState_Coverage == 0x00002016);
static_assert(KMemoryState_Insecure == 0x05583817);
#endif
enum KMemoryPermission : u8 {

View File

@@ -50,11 +50,9 @@ namespace ams::kern {
constexpr size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSizeMax;
/* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x800. */
constexpr size_t KernelPageBufferHeapSize = 0x3E0000;
constexpr size_t KernelSlabHeapAdditionalSize = 0x148000;
constexpr size_t KernelPageBufferAdditionalSize = 0x33C000;
constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize + KernelPageBufferHeapSize;
constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;
class KMemoryLayout {
private:
@@ -152,8 +150,6 @@ namespace ams::kern {
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetSecureAppletMemoryRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelSecureAppletMemory)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) { return Dereference(FindLinear(address)); }
static MESOSPHERE_NOINLINE_IF_DEBUG const KMemoryRegion &GetPhysicalLinearRegion(KPhysicalAddress address) { return Dereference(FindLinear(address)); }
@@ -191,7 +187,7 @@ namespace ams::kern {
static void InitializeLinearMemoryRegionTrees();
static size_t GetResourceRegionSizeForInit(bool use_extra_resource);
static size_t GetResourceRegionSizeForInit();
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode); }
@@ -213,7 +209,6 @@ namespace ams::kern {
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelBase); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelCodeRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelSlabRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelSecureAppletMemoryRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSecureAppletMemory); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelPageTableHeapRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap); }
static MESOSPHERE_NOINLINE_IF_DEBUG auto GetKernelInitPageTableRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt); }

View File

@@ -200,7 +200,7 @@ namespace ams::kern {
NOINLINE KPhysicalAddress AllocateAndOpenContinuous(size_t num_pages, size_t align_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);
Pool GetPool(KPhysicalAddress address) const {
return this->GetManager(address).GetPool();
@@ -222,22 +222,6 @@ namespace ams::kern {
}
}
void OpenFirst(KPhysicalAddress address, size_t num_pages) {
/* Repeatedly open references until we've done so for all pages. */
while (num_pages) {
auto &manager = this->GetManager(address);
const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
{
KScopedLightLock lk(m_pool_locks[manager.GetPool()]);
manager.OpenFirst(address, cur_pages);
}
num_pages -= cur_pages;
address += cur_pages * PageSize;
}
}
void Close(KPhysicalAddress address, size_t num_pages) {
/* Repeatedly close references until we've done so for all pages. */
while (num_pages) {

View File

@@ -211,8 +211,6 @@ namespace ams::kern {
static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramKernelSecureAppletMemory = KMemoryRegionType_DramKernelBase.DeriveSparse(1, 3, 0).SetAttribute(KMemoryRegionAttr_LinearMapped);
static_assert(KMemoryRegionType_DramKernelSecureAppletMemory.GetValue() == (0x18E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramReservedEarly = KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == (0x16 | KMemoryRegionAttr_NoUserMap));
@@ -253,9 +251,6 @@ namespace ams::kern {
constexpr inline const auto KMemoryRegionType_VirtualDramUnknownDebug = KMemoryRegionType_Dram.DeriveSparse(2, 2, 1);
static_assert(KMemoryRegionType_VirtualDramUnknownDebug.GetValue() == (0x52));
constexpr inline const auto KMemoryRegionType_VirtualDramKernelSecureAppletMemory = KMemoryRegionType_Dram.DeriveSparse(3, 1, 0);
static_assert(KMemoryRegionType_VirtualDramKernelSecureAppletMemory.GetValue() == (0x62));
constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
@@ -332,8 +327,6 @@ namespace ams::kern {
return KMemoryRegionType_VirtualDramKernelTraceBuffer;
} else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelPtHeap;
} else if (KMemoryRegionType_DramKernelSecureAppletMemory.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelSecureAppletMemory;
} else if ((type_id | KMemoryRegionAttr_ShouldKernelMap) == type_id) {
return KMemoryRegionType_VirtualDramUnknownDebug;
} else {

View File

@@ -113,12 +113,11 @@ namespace ams::kern {
static constexpr size_t MaxDepth = 4;
private:
u64 *m_bit_storages[MaxDepth];
u64 *m_end_storages[MaxDepth];
RandomBitGenerator m_rng;
size_t m_num_bits;
size_t m_used_depths;
public:
KPageBitmap() : m_bit_storages(), m_end_storages(), m_rng(), m_num_bits(), m_used_depths() { /* ... */ }
KPageBitmap() : m_bit_storages(), m_rng(), m_num_bits(), m_used_depths() { /* ... */ }
constexpr size_t GetNumBits() const { return m_num_bits; }
constexpr s32 GetHighestDepthIndex() const { return static_cast<s32>(m_used_depths) - 1; }
@@ -136,7 +135,6 @@ namespace ams::kern {
m_bit_storages[depth] = storage;
size = util::AlignUp(size, BITSIZEOF(u64)) / BITSIZEOF(u64);
storage += size;
m_end_storages[depth] = storage;
}
return storage;
@@ -173,45 +171,6 @@ namespace ams::kern {
return static_cast<ssize_t>(offset);
}
ssize_t FindFreeRange(size_t count) {
/* Check that it is possible to find a range. */
const u64 * const storage_start = m_bit_storages[m_used_depths - 1];
const u64 * const storage_end = m_end_storages[m_used_depths - 1];
/* If we don't have a storage to iterate (or want more blocks than fit in a single storage), we can't find a free range. */
if (!(storage_start < storage_end && count <= BITSIZEOF(u64))) {
return -1;
}
/* Walk the storages to select a random free range. */
const size_t options_per_storage = std::max<size_t>(BITSIZEOF(u64) / count, 1);
const size_t num_entries = std::max<size_t>(storage_end - storage_start, 1);
const u64 free_mask = (static_cast<u64>(1) << count) - 1;
size_t num_valid_options = 0;
ssize_t chosen_offset = -1;
for (size_t storage_index = 0; storage_index < num_entries; ++storage_index) {
u64 storage = storage_start[storage_index];
for (size_t option = 0; option < options_per_storage; ++option) {
if ((storage & free_mask) == free_mask) {
/* We've found a new valid option. */
++num_valid_options;
/* Select the Kth valid option with probability 1/K. This leads to an overall uniform distribution. */
if (num_valid_options == 1 || m_rng.GenerateRandom(num_valid_options) == 0) {
/* This is our first option, so select it. */
chosen_offset = storage_index * BITSIZEOF(u64) + option * count;
}
}
storage >>= count;
}
}
/* Return the random offset we chose.*/
return chosen_offset;
}
void SetBit(size_t offset) {
this->SetBit(this->GetHighestDepthIndex(), offset);
m_num_bits++;

View File

@@ -16,33 +16,12 @@
#pragma once
#include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_k_memory_layout.hpp>
#include <mesosphere/kern_k_dynamic_page_manager.hpp>
namespace ams::kern {
class KDynamicPageManager;
class KPageBuffer;
class KPageBufferSlabHeap : protected impl::KSlabHeapImpl {
public:
static constexpr size_t BufferSize = PageSize;
static constinit inline size_t s_buffer_count = 0;
class KPageBuffer : public KSlabAllocated<KPageBuffer> {
private:
size_t m_obj_size{};
public:
constexpr KPageBufferSlabHeap() = default;
/* See kern_init_slab_setup.cpp for definition. */
void Initialize(KDynamicPageManager &allocator);
KPageBuffer *Allocate();
void Free(KPageBuffer *pb);
};
class KPageBuffer {
private:
u8 m_buffer[KPageBufferSlabHeap::BufferSize];
alignas(PageSize) u8 m_buffer[PageSize];
public:
KPageBuffer() {
std::memset(m_buffer, 0, sizeof(m_buffer));
@@ -60,49 +39,8 @@ namespace ams::kern {
return GetPointer<KPageBuffer>(virt_addr);
}
private:
static constinit inline KPageBufferSlabHeap s_slab_heap;
public:
static void InitializeSlabHeap(KDynamicPageManager &allocator) {
s_slab_heap.Initialize(allocator);
}
static KPageBuffer *Allocate() {
return s_slab_heap.Allocate();
}
static void Free(KPageBuffer *obj) {
s_slab_heap.Free(obj);
}
template<size_t ExpectedSize>
static ALWAYS_INLINE KPageBuffer *AllocateChecked() {
/* Check that the allocation is valid. */
MESOSPHERE_ABORT_UNLESS(sizeof(KPageBuffer) == ExpectedSize);
return Allocate();
}
template<size_t ExpectedSize>
static ALWAYS_INLINE void FreeChecked(KPageBuffer *obj) {
/* Check that the free is valid. */
MESOSPHERE_ABORT_UNLESS(sizeof(KPageBuffer) == ExpectedSize);
return Free(obj);
}
};
static_assert(sizeof(KPageBuffer) == KPageBufferSlabHeap::BufferSize);
ALWAYS_INLINE KPageBuffer *KPageBufferSlabHeap::Allocate() {
KPageBuffer *pb = static_cast<KPageBuffer *>(KSlabHeapImpl::Allocate());
if (AMS_LIKELY(pb != nullptr)) {
std::construct_at(pb);
}
return pb;
}
ALWAYS_INLINE void KPageBufferSlabHeap::Free(KPageBuffer *pb) {
KSlabHeapImpl::Free(pb);
}
static_assert(sizeof(KPageBuffer) == PageSize);
static_assert(alignof(KPageBuffer) == PageSize);
}

View File

@@ -138,7 +138,6 @@ namespace ams::kern {
Result AddBlock(KPhysicalAddress addr, size_t num_pages);
void Open() const;
void OpenFirst() const;
void Close() const;
size_t GetNumPages() const;

View File

@@ -48,7 +48,6 @@ namespace ams::kern {
static_assert(sizeof(KPageProperties) == sizeof(u32));
class KResourceLimit;
class KSystemResource;
class KPageTableBase {
NON_COPYABLE(KPageTableBase);
@@ -73,12 +72,10 @@ namespace ams::kern {
enum OperationType {
OperationType_Map = 0,
OperationType_MapFirst = 1,
OperationType_MapGroup = 2,
OperationType_Unmap = 3,
OperationType_ChangePermissions = 4,
OperationType_ChangePermissionsAndRefresh = 5,
OperationType_Separate = 6,
OperationType_MapGroup = 1,
OperationType_Unmap = 2,
OperationType_ChangePermissions = 3,
OperationType_ChangePermissionsAndRefresh = 4,
};
static constexpr size_t MaxPhysicalMapAlignment = 1_GB;
@@ -165,7 +162,6 @@ namespace ams::kern {
size_t m_max_heap_size;
size_t m_mapped_physical_memory_size;
size_t m_mapped_unsafe_physical_memory;
size_t m_mapped_insecure_memory;
size_t m_mapped_ipc_server_memory;
mutable KLightLock m_general_lock;
mutable KLightLock m_map_physical_memory_lock;
@@ -192,8 +188,8 @@ namespace ams::kern {
m_alias_region_end(Null<KProcessAddress>), m_stack_region_start(Null<KProcessAddress>), m_stack_region_end(Null<KProcessAddress>),
m_kernel_map_region_start(Null<KProcessAddress>), m_kernel_map_region_end(Null<KProcessAddress>), m_alias_code_region_start(Null<KProcessAddress>),
m_alias_code_region_end(Null<KProcessAddress>), m_code_region_start(Null<KProcessAddress>), m_code_region_end(Null<KProcessAddress>),
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_insecure_memory(), m_mapped_ipc_server_memory(),
m_general_lock(), m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
m_max_heap_size(), m_mapped_physical_memory_size(), m_mapped_unsafe_physical_memory(), m_mapped_ipc_server_memory(), m_general_lock(),
m_map_physical_memory_lock(), m_device_map_lock(), m_impl(util::ConstantInitialize), m_memory_block_manager(util::ConstantInitialize),
m_allocate_option(), m_address_space_width(), m_is_kernel(), m_enable_aslr(), m_enable_device_address_space_merge(),
m_memory_block_slab_manager(), m_block_info_manager(), m_resource_limit(), m_cached_physical_linear_region(), m_cached_physical_heap_region(),
m_heap_fill_value(), m_ipc_fill_value(), m_stack_fill_value()
@@ -204,7 +200,7 @@ namespace ams::kern {
explicit KPageTableBase() { /* ... */ }
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 enable_device_address_space_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit);
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, KResourceLimit *resource_limit);
void Finalize();
@@ -366,8 +362,6 @@ namespace ams::kern {
Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size);
Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm);
Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm);
Result MapInsecureMemory(KProcessAddress address, size_t size);
Result UnmapInsecureMemory(KProcessAddress address, size_t size);
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
R_RETURN(this->MapPages(out_addr, num_pages, alignment, phys_addr, true, region_start, region_num_pages, state, perm));
@@ -398,8 +392,8 @@ namespace ams::kern {
Result WriteDebugMemory(KProcessAddress address, const void *buffer, size_t size);
Result WriteDebugIoMemory(KProcessAddress address, const void *buffer, size_t size);
Result LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap);
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap);
Result LockForMapDeviceAddressSpace(KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned);
Result LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size);
Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size);
Result UnlockForDeviceAddressSpacePartialMap(KProcessAddress address, size_t size);

View File

@@ -31,7 +31,6 @@
#include <mesosphere/kern_k_wait_object.hpp>
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp>
#include <mesosphere/kern_k_system_resource.hpp>
namespace ams::kern {
@@ -65,7 +64,8 @@ namespace ams::kern {
s32 m_ideal_core_id;
void *m_attached_object;
KResourceLimit *m_resource_limit;
KSystemResource *m_system_resource;
KVirtualAddress m_system_resource_address;
size_t m_system_resource_num_pages;
size_t m_memory_release_hint;
State m_state;
KLightLock m_state_lock;
@@ -117,6 +117,13 @@ namespace ams::kern {
util::Atomic<s64> m_num_ipc_messages;
util::Atomic<s64> m_num_ipc_replies;
util::Atomic<s64> m_num_ipc_receives;
KDynamicPageManager m_dynamic_page_manager;
KMemoryBlockSlabManager m_memory_block_slab_manager;
KBlockInfoManager m_block_info_manager;
KPageTableManager m_page_table_manager;
KMemoryBlockSlabHeap m_memory_block_heap;
KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap;
private:
Result Initialize(const ams::svc::CreateProcessParameter &params);
@@ -277,12 +284,12 @@ namespace ams::kern {
void IncrementRunningThreadCount();
void DecrementRunningThreadCount();
size_t GetTotalSystemResourceSize() const {
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetSize() : 0;
}
size_t GetTotalSystemResourceSize() const { return m_system_resource_num_pages * PageSize; }
size_t GetUsedSystemResourceSize() const {
return m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->GetUsedSize() : 0;
if (m_system_resource_num_pages == 0) {
return 0;
}
return m_dynamic_page_manager.GetUsed() * PageSize;
}
void SetRunningThread(s32 core, KThread *thread, u64 idle_count) {
@@ -298,11 +305,10 @@ namespace ams::kern {
}
}
const KSystemResource &GetSystemResource() const { return *m_system_resource; }
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_system_resource->GetMemoryBlockSlabManager(); }
const KBlockInfoManager &GetBlockInfoManager() const { return m_system_resource->GetBlockInfoManager(); }
const KPageTableManager &GetPageTableManager() const { return m_system_resource->GetPageTableManager(); }
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; }
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return m_memory_block_slab_manager; }
const KBlockInfoManager &GetBlockInfoManager() const { return m_block_info_manager; }
const KPageTableManager &GetPageTableManager() const { return m_page_table_manager; }
constexpr KThread *GetRunningThread(s32 core) const { return m_running_threads[core]; }
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return m_running_thread_idle_counts[core]; }

View File

@@ -152,7 +152,7 @@ namespace ams::kern {
static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority);
static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core);
static NOINLINE void RotateScheduledQueue(s32 core_id, s32 priority);
static NOINLINE void RotateScheduledQueue(s32 priority, s32 core_id);
static NOINLINE void YieldWithoutCoreMigration();
static NOINLINE void YieldWithCoreMigration();

View File

@@ -29,10 +29,7 @@ namespace ams::kern {
public:
class SessionMappings {
private:
/* At most 15 buffers of each type (4-bit descriptor counts), for 45 total. */
static constexpr size_t NumMappings = ((1ul << 4) - 1) * 3;
static constexpr size_t NumStaticMappings = 8;
static constexpr size_t NumDynamicMappings = NumMappings - NumStaticMappings;
static constexpr size_t NumStaticMappings = 8;
class Mapping {
private:
@@ -53,27 +50,16 @@ namespace ams::kern {
constexpr ALWAYS_INLINE size_t GetSize() const { return m_size; }
constexpr ALWAYS_INLINE KMemoryState GetMemoryState() const { return m_state; }
};
public:
class DynamicMappings : public KSlabAllocated<DynamicMappings, true> {
private:
Mapping m_mappings[NumDynamicMappings];
public:
constexpr explicit DynamicMappings() : m_mappings() { /* ... */ }
constexpr ALWAYS_INLINE Mapping &Get(size_t idx) { return m_mappings[idx]; }
constexpr ALWAYS_INLINE const Mapping &Get(size_t idx) const { return m_mappings[idx]; }
};
static_assert(sizeof(DynamicMappings) == sizeof(Mapping) * NumDynamicMappings);
private:
Mapping m_static_mappings[NumStaticMappings];
DynamicMappings *m_dynamic_mappings;
Mapping *m_mappings;
u8 m_num_send;
u8 m_num_recv;
u8 m_num_exch;
public:
constexpr explicit SessionMappings(util::ConstantInitializeTag) : m_static_mappings(), m_dynamic_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
constexpr explicit SessionMappings(util::ConstantInitializeTag) : m_static_mappings(), m_mappings(), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
explicit SessionMappings() : m_dynamic_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
explicit SessionMappings() : m_mappings(nullptr), m_num_send(), m_num_recv(), m_num_exch() { /* ... */ }
void Initialize() { /* ... */ }
void Finalize();
@@ -110,7 +96,7 @@ namespace ams::kern {
if (index < NumStaticMappings) {
return m_static_mappings[index];
} else {
return m_dynamic_mappings->Get(index - NumStaticMappings);
return m_mappings[index - NumStaticMappings];
}
}
@@ -121,7 +107,7 @@ namespace ams::kern {
if (index < NumStaticMappings) {
return m_static_mappings[index];
} else {
return m_dynamic_mappings->Get(index - NumStaticMappings);
return m_mappings[index - NumStaticMappings];
}
}
@@ -132,7 +118,7 @@ namespace ams::kern {
if (index < NumStaticMappings) {
return m_static_mappings[index];
} else {
return m_dynamic_mappings->Get(index - NumStaticMappings);
return m_mappings[index - NumStaticMappings];
}
}
};

View File

@@ -35,7 +35,7 @@ namespace ams::kern {
bool m_is_initialized;
public:
explicit KSharedMemory()
: m_page_group(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer()), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()),
: m_page_group(std::addressof(Kernel::GetSystemBlockInfoManager())), m_resource_limit(nullptr), m_owner_process_id(std::numeric_limits<u64>::max()),
m_owner_perm(ams::svc::MemoryPermission_None), m_remote_perm(ams::svc::MemoryPermission_None), m_is_initialized(false)
{
/* ... */

View File

@@ -25,12 +25,7 @@ namespace ams::kern {
namespace ams::kern {
class KResourceLimit;
class KSystemControlBase {
public:
/* This can be overridden as needed. */
static constexpr size_t SecureAppletMemorySize = 0;
protected:
/* Nintendo uses std::mt19937_t for randomness. */
/* To save space (and because mt19337_t isn't secure anyway), */
@@ -88,10 +83,6 @@ namespace ams::kern {
static size_t CalculateRequiredSecureMemorySize(size_t size, u32 pool);
static Result AllocateSecureMemory(KVirtualAddress *out, size_t size, u32 pool);
static void FreeSecureMemory(KVirtualAddress address, size_t size, u32 pool);
/* Insecure Memory. */
static KResourceLimit *GetInsecureMemoryResourceLimit();
static u32 GetInsecureMemoryPool();
protected:
template<typename F>
static ALWAYS_INLINE u64 GenerateUniformRange(u64 min, u64 max, F f) {

View File

@@ -1,108 +0,0 @@
/*
* Copyright (c) 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>
#include <mesosphere/kern_k_memory_manager.hpp>
#include <mesosphere/kern_k_dynamic_resource_manager.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp>
#include <mesosphere/kern_k_resource_limit.hpp>
namespace ams::kern {
/* NOTE: Nintendo's implementation does not have the "is_secure_resource" field, and instead uses virtual IsSecureResource(). */
class KSystemResource : public KAutoObject {
MESOSPHERE_AUTOOBJECT_TRAITS(KSystemResource, KAutoObject);
private:
KMemoryBlockSlabManager *m_p_memory_block_slab_manager{};
KBlockInfoManager *m_p_block_info_manager{};
KPageTableManager *m_p_page_table_manager{};
bool m_is_secure_resource{false};
public:
explicit KSystemResource() : KAutoObject() { /* ... */ }
constexpr explicit KSystemResource(util::ConstantInitializeTag) : KAutoObject(util::ConstantInitialize) { /* ... */ }
protected:
ALWAYS_INLINE void SetSecureResource() { m_is_secure_resource = true; }
public:
virtual void Destroy() override { MESOSPHERE_PANIC("KSystemResource::Destroy() was called"); }
ALWAYS_INLINE bool IsSecureResource() const { return m_is_secure_resource; }
void SetManagers(KMemoryBlockSlabManager &mb, KBlockInfoManager &bi, KPageTableManager &pt) {
MESOSPHERE_ASSERT(m_p_memory_block_slab_manager == nullptr);
MESOSPHERE_ASSERT(m_p_block_info_manager == nullptr);
MESOSPHERE_ASSERT(m_p_page_table_manager == nullptr);
m_p_memory_block_slab_manager = std::addressof(mb);
m_p_block_info_manager = std::addressof(bi);
m_p_page_table_manager = std::addressof(pt);
}
const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return *m_p_memory_block_slab_manager; }
const KBlockInfoManager &GetBlockInfoManager() const { return *m_p_block_info_manager; }
const KPageTableManager &GetPageTableManager() const { return *m_p_page_table_manager; }
KMemoryBlockSlabManager &GetMemoryBlockSlabManager() { return *m_p_memory_block_slab_manager; }
KBlockInfoManager &GetBlockInfoManager() { return *m_p_block_info_manager; }
KPageTableManager &GetPageTableManager() { return *m_p_page_table_manager; }
KMemoryBlockSlabManager *GetMemoryBlockSlabManagerPointer() { return m_p_memory_block_slab_manager; }
KBlockInfoManager *GetBlockInfoManagerPointer() { return m_p_block_info_manager; }
KPageTableManager *GetPageTableManagerPointer() { return m_p_page_table_manager; }
};
class KSecureSystemResource final : public KAutoObjectWithSlabHeap<KSecureSystemResource, KSystemResource> {
private:
bool m_is_initialized;
KMemoryManager::Pool m_resource_pool;
KDynamicPageManager m_dynamic_page_manager;
KMemoryBlockSlabManager m_memory_block_slab_manager;
KBlockInfoManager m_block_info_manager;
KPageTableManager m_page_table_manager;
KMemoryBlockSlabHeap m_memory_block_heap;
KBlockInfoSlabHeap m_block_info_heap;
KPageTableSlabHeap m_page_table_heap;
KResourceLimit *m_resource_limit;
KVirtualAddress m_resource_address;
size_t m_resource_size;
public:
explicit KSecureSystemResource() : m_is_initialized(false), m_resource_limit(nullptr) {
/* Mark ourselves as being a secure resource. */
this->SetSecureResource();
}
Result Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool);
void Finalize();
bool IsInitialized() const { return m_is_initialized; }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
ALWAYS_INLINE size_t CalculateRequiredSecureMemorySize() const {
return CalculateRequiredSecureMemorySize(m_resource_size, m_resource_pool);
}
ALWAYS_INLINE size_t GetSize() const { return m_resource_size; }
ALWAYS_INLINE size_t GetUsedSize() const { return m_dynamic_page_manager.GetUsed() * PageSize; }
const KDynamicPageManager &GetDynamicPageManager() const { return m_dynamic_page_manager; }
public:
static size_t CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool);
};
}

View File

@@ -63,7 +63,7 @@ namespace ams::kern {
static constexpr size_t ApplicationMemoryBlockSlabHeapSize = 20000;
static constexpr size_t SystemMemoryBlockSlabHeapSize = 10000;
static constexpr size_t BlockInfoSlabHeapSize = 4000;
static constexpr size_t ReservedDynamicPageCount = 64;
static constexpr size_t ReservedDynamicPageCount = 70;
private:
static State s_state;
static KResourceLimit s_system_resource_limit;
@@ -78,8 +78,6 @@ namespace ams::kern {
static KMemoryBlockSlabManager s_sys_memory_block_manager;
static KBlockInfoManager s_app_block_info_manager;
static KBlockInfoManager s_sys_block_info_manager;
static KSystemResource s_app_system_resource;
static KSystemResource s_sys_system_resource;
static KSupervisorPageTable s_supervisor_page_table;
static KUnsafeMemory s_unsafe_memory;
static KWorkerTaskManager s_worker_task_managers[KWorkerTaskManager::WorkerType_Count];
@@ -131,12 +129,28 @@ namespace ams::kern {
return s_memory_manager;
}
static ALWAYS_INLINE KSystemResource &GetApplicationSystemResource() {
return s_app_system_resource;
static ALWAYS_INLINE KMemoryBlockSlabManager &GetApplicationMemoryBlockManager() {
return s_app_memory_block_manager;
}
static ALWAYS_INLINE KSystemResource &GetSystemSystemResource() {
return s_sys_system_resource;
static ALWAYS_INLINE KMemoryBlockSlabManager &GetSystemMemoryBlockManager() {
return s_sys_memory_block_manager;
}
static ALWAYS_INLINE KBlockInfoManager &GetApplicationBlockInfoManager() {
return s_app_block_info_manager;
}
static ALWAYS_INLINE KBlockInfoManager &GetSystemBlockInfoManager() {
return s_sys_block_info_manager;
}
static ALWAYS_INLINE KPageTableManager &GetApplicationPageTableManager() {
return s_app_page_table_manager;
}
static ALWAYS_INLINE KPageTableManager &GetSystemPageTableManager() {
return s_sys_page_table_manager;
}
static ALWAYS_INLINE KSupervisorPageTable &GetKernelPageTable() {

View File

@@ -64,13 +64,11 @@ namespace ams::kern {
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
};
template<typename Derived, typename Base, bool SupportDynamicExpansion> requires std::derived_from<Base, KAutoObject>
class KAutoObjectWithSlabHeapBase : public Base {
private:
template<typename, typename, bool> friend class KAutoObjectWithSlabHeap;
template<typename, typename, bool> friend class KAutoObjectWithSlabHeapAndContainer;
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList>
class KAutoObjectWithSlabHeapAndContainer : public Base {
private:
static constinit inline KSlabHeap<Derived, SupportDynamicExpansion> s_slab_heap;
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
private:
static ALWAYS_INLINE Derived *Allocate() {
return s_slab_heap.Allocate();
@@ -79,6 +77,12 @@ namespace ams::kern {
static ALWAYS_INLINE void Free(Derived *obj) {
s_slab_heap.Free(obj);
}
public:
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
public:
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
private:
static ALWAYS_INLINE bool IsInitialized(const Derived *obj) {
if constexpr (requires { { obj->IsInitialized() } -> std::same_as<bool>; }) {
@@ -96,9 +100,9 @@ namespace ams::kern {
}
}
public:
constexpr explicit KAutoObjectWithSlabHeapBase(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : Base(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapBase() { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
/* NOTE: IsInitialized() and GetPostDestroyArgument() are virtual functions declared in this class, */
/* in Nintendo's kernel. We fully devirtualize them, as Destroy() is the only user of them. */
@@ -106,14 +110,14 @@ namespace ams::kern {
virtual void Destroy() override final {
Derived * const derived = static_cast<Derived *>(this);
if (KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::IsInitialized(derived)) {
Derived::PreFinalize(derived);
const uintptr_t arg = KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::GetPostDestroyArgument(derived);
if (IsInitialized(derived)) {
s_container.Unregister(derived);
const uintptr_t arg = GetPostDestroyArgument(derived);
derived->Finalize();
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
Free(derived);
Derived::PostDestroy(arg);
} else {
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::Free(derived);
Free(derived);
}
}
@@ -123,6 +127,7 @@ namespace ams::kern {
public:
static void InitializeSlabHeap(void *memory, size_t memory_size) {
s_slab_heap.Initialize(memory, memory_size);
s_container.Initialize();
}
static Derived *Create() {
@@ -145,6 +150,10 @@ namespace ams::kern {
return obj;
}
static void Register(Derived *obj) {
return s_container.Register(obj);
}
static size_t GetObjectSize() { return s_slab_heap.GetObjectSize(); }
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
@@ -153,42 +162,4 @@ namespace ams::kern {
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
};
template<typename Derived, typename Base, bool SupportDynamicExpansion = false>
class KAutoObjectWithSlabHeap : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
public:
constexpr explicit KAutoObjectWithSlabHeap(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeap() { /* ... */ }
static ALWAYS_INLINE void PreFinalize(Derived *) { /* ... */ }
};
template<typename Derived, typename Base, bool SupportDynamicExpansion = false> requires std::derived_from<Base, KAutoObjectWithList>
class KAutoObjectWithSlabHeapAndContainer : public KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion> {
private:
static constinit inline KAutoObjectWithListContainer<Derived> s_container;
public:
class ListAccessor : public KAutoObjectWithListContainer<Derived>::ListAccessor {
public:
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer<Derived>::ListAccessor(s_container) { /* ... */ }
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
};
public:
constexpr explicit KAutoObjectWithSlabHeapAndContainer(util::ConstantInitializeTag) : KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>(util::ConstantInitialize) { /* ... */ }
explicit KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
public:
static void InitializeSlabHeap(void *memory, size_t memory_size) {
KAutoObjectWithSlabHeapBase<Derived, Base, SupportDynamicExpansion>::InitializeSlabHeap(memory, memory_size);
s_container.Initialize();
}
static void Register(Derived *obj) {
return s_container.Register(obj);
}
static ALWAYS_INLINE void PreFinalize(Derived *obj) { s_container.Unregister(obj); }
};
}

View File

@@ -38,25 +38,6 @@ namespace ams::kern::arch::arm64::cpu {
ALWAYS_INLINE ~KScopedCoreMigrationDisable() { GetCurrentThread().EnableCoreMigration(); }
};
class KScopedCacheMaintenance {
private:
bool m_active;
public:
ALWAYS_INLINE KScopedCacheMaintenance() {
__asm__ __volatile__("" ::: "memory");
if (m_active = !GetCurrentThread().IsInCacheMaintenanceOperation(); m_active) {
GetCurrentThread().SetInCacheMaintenanceOperation();
}
}
ALWAYS_INLINE ~KScopedCacheMaintenance() {
if (m_active) {
GetCurrentThread().ClearInCacheMaintenanceOperation();
}
__asm__ __volatile__("" ::: "memory");
}
};
/* Nintendo registers a handler for a SGI on thread termination, but does not handle anything. */
/* This is sufficient, because post-interrupt scheduling is all they really intend to occur. */
class KThreadTerminationInterruptHandler : public KInterruptHandler {
@@ -451,7 +432,9 @@ namespace ams::kern::arch::arm64::cpu {
Result InvalidateDataCache(void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
KScopedCacheMaintenance cm;
__asm__ __volatile__("" ::: "memory");
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = reinterpret_cast<uintptr_t>(addr);
const uintptr_t end = start + size;
@@ -477,7 +460,9 @@ namespace ams::kern::arch::arm64::cpu {
Result StoreDataCache(const void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
KScopedCacheMaintenance cm;
__asm__ __volatile__("" ::: "memory");
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize);
const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize);
@@ -487,7 +472,9 @@ namespace ams::kern::arch::arm64::cpu {
Result FlushDataCache(const void *addr, size_t size) {
/* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */
KScopedCacheMaintenance cm;
__asm__ __volatile__("" ::: "memory");
GetCurrentThread().SetInCacheMaintenanceOperation();
ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); };
const uintptr_t start = util::AlignDown(reinterpret_cast<uintptr_t>(addr), DataCacheLineSize);
const uintptr_t end = util::AlignUp( reinterpret_cast<uintptr_t>(addr) + size, DataCacheLineSize);

View File

@@ -192,7 +192,7 @@ namespace ams::kern::arch::arm64 {
Result KPageTable::InitializeForKernel(void *table, KVirtualAddress start, KVirtualAddress end) {
/* Initialize basic fields. */
m_asid = 0;
m_manager = Kernel::GetSystemSystemResource().GetPageTableManagerPointer();
m_manager = std::addressof(Kernel::GetSystemPageTableManager());
/* Allocate a page for ttbr. */
/* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */
@@ -207,7 +207,7 @@ namespace ams::kern::arch::arm64 {
R_SUCCEED();
}
Result KPageTable::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, KSystemResource *system_resource, KResourceLimit *resource_limit) {
Result KPageTable::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, KResourceLimit *resource_limit) {
/* The input ID isn't actually used. */
MESOSPHERE_UNUSED(id);
@@ -216,7 +216,7 @@ namespace ams::kern::arch::arm64 {
ON_RESULT_FAILURE { g_asid_manager.Release(m_asid); };
/* Set our manager. */
m_manager = system_resource->GetPageTableManagerPointer();
m_manager = pt_manager;
/* Allocate a new table, and set our ttbr value. */
const KVirtualAddress new_table = m_manager->Allocate();
@@ -228,7 +228,7 @@ namespace ams::kern::arch::arm64 {
const size_t as_width = GetAddressSpaceWidth(as_type);
const KProcessAddress as_start = 0;
const KProcessAddress as_end = (1ul << as_width);
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, system_resource, resource_limit));
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, enable_das_merge, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, mem_block_slab_manager, block_info_manager, resource_limit));
/* Note that we've updated the table (since we created it). */
this->NoteUpdated();
@@ -348,7 +348,7 @@ namespace ams::kern::arch::arm64 {
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(virt_addr), PageSize));
MESOSPHERE_ASSERT(this->ContainsPages(virt_addr, num_pages));
if (operation == OperationType_Map || operation == OperationType_MapFirst) {
if (operation == OperationType_Map) {
MESOSPHERE_ABORT_UNLESS(is_pa_valid);
MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize));
} else {
@@ -357,26 +357,12 @@ namespace ams::kern::arch::arm64 {
if (operation == OperationType_Unmap) {
R_RETURN(this->Unmap(virt_addr, num_pages, page_list, false, reuse_ll));
} else if (operation == OperationType_Separate) {
const size_t size = num_pages * PageSize;
R_TRY(this->SeparatePages(virt_addr, std::min(util::GetAlignment(GetInteger(virt_addr)), size), page_list, reuse_ll));
ON_RESULT_FAILURE { this->MergePages(virt_addr, page_list); };
if (num_pages > 1) {
const auto end_page = virt_addr + size;
const auto last_page = end_page - PageSize;
R_TRY(this->SeparatePages(last_page, std::min(util::GetAlignment(GetInteger(end_page)), size), page_list, reuse_ll));
}
R_SUCCEED();
} else {
auto entry_template = this->GetEntryTemplate(properties);
switch (operation) {
case OperationType_Map:
case OperationType_MapFirst:
R_RETURN(this->MapContiguous(virt_addr, phys_addr, num_pages, entry_template, properties.disable_merge_attributes == DisableMergeAttribute_DisableHead, operation != OperationType_MapFirst, page_list, reuse_ll));
R_RETURN(this->MapContiguous(virt_addr, phys_addr, num_pages, entry_template, properties.disable_merge_attributes == DisableMergeAttribute_DisableHead, page_list, reuse_ll));
case OperationType_ChangePermissions:
R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, false, page_list, reuse_ll));
case OperationType_ChangePermissionsAndRefresh:
@@ -754,7 +740,7 @@ namespace ams::kern::arch::arm64 {
R_SUCCEED();
}
Result KPageTable::MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, bool not_first, PageLinkedList *page_list, bool reuse_ll) {
Result KPageTable::MapContiguous(KProcessAddress virt_addr, KPhysicalAddress phys_addr, size_t num_pages, PageTableEntry entry_template, bool disable_head_merge, PageLinkedList *page_list, bool reuse_ll) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
/* Cache initial addresses for use on cleanup. */
@@ -825,11 +811,7 @@ namespace ams::kern::arch::arm64 {
/* Open references to the pages, if we should. */
if (IsHeapPhysicalAddress(orig_phys_addr)) {
if (not_first) {
Kernel::GetMemoryManager().Open(orig_phys_addr, num_pages);
} else {
Kernel::GetMemoryManager().OpenFirst(orig_phys_addr, num_pages);
}
Kernel::GetMemoryManager().Open(orig_phys_addr, num_pages);
}
R_SUCCEED();

View File

@@ -86,10 +86,9 @@ _ZN3ams4kern3svc14RestoreContextEm:
/* Get our exception flags. */
ldrb w9, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)]
/* Clear in-svc, in-user-exception, and needs-fpu-restore flags. */
/* Clear in-svc and needs-fpu-restore flags. */
and w10, w9, #(~(THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED))
and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_CALLING_SVC))
and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_IN_USERMODE_EXCEPTION_HANDLER))
strb w10, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)]
/* If we don't need to restore the fpu, skip restoring it. */

View File

@@ -651,13 +651,11 @@ namespace ams::kern::board::nintendo::nx {
g_memory_controller_address = KMemoryLayout::GetDevicePhysicalAddress(KMemoryRegionType_MemoryController);
/* Allocate a page to use as a reserved/no device table. */
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
const KVirtualAddress table_virt_addr = ptm.Allocate();
const KVirtualAddress table_virt_addr = Kernel::GetSystemPageTableManager().Allocate();
MESOSPHERE_ABORT_UNLESS(table_virt_addr != Null<KVirtualAddress>);
const KPhysicalAddress table_phys_addr = GetPageTablePhysicalAddress(table_virt_addr);
MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr));
ptm.Open(table_virt_addr, 1);
Kernel::GetSystemPageTableManager().Open(table_virt_addr, 1);
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
/* NOTE: Nintendo does not check the result of StoreDataCache. */
@@ -781,7 +779,7 @@ namespace ams::kern::board::nintendo::nx {
const size_t end_index = (space_address + space_size - 1) / DeviceRegionSize;
/* Get the page table manager. */
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
auto &ptm = Kernel::GetSystemPageTableManager();
/* Clear the tables. */
static_assert(TableCount == (1ul << DeviceVirtualAddressBits) / DeviceRegionSize);
@@ -841,7 +839,7 @@ namespace ams::kern::board::nintendo::nx {
void KDevicePageTable::Finalize() {
/* Get the page table manager. */
auto &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
auto &ptm = Kernel::GetSystemPageTableManager();
/* Detach from all devices. */
{
@@ -1016,7 +1014,7 @@ namespace ams::kern::board::nintendo::nx {
/* Get the memory manager and page table manager. */
KMemoryManager &mm = Kernel::GetMemoryManager();
KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
KPageTableManager &ptm = Kernel::GetSystemPageTableManager();
/* Cache permissions. */
const bool read = (device_perm & ams::svc::MemoryPermission_Read) != 0;
@@ -1118,7 +1116,6 @@ namespace ams::kern::board::nintendo::nx {
}
Result KDevicePageTable::MapImpl(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
/* Ensure that the region we're mapping to is free. */
R_UNLESS(this->IsFree(device_address, size), svc::ResultInvalidCurrentMemory());
@@ -1161,10 +1158,10 @@ namespace ams::kern::board::nintendo::nx {
/* Get the memory manager and page table manager. */
KMemoryManager &mm = Kernel::GetMemoryManager();
KPageTableManager &ptm = Kernel::GetSystemSystemResource().GetPageTableManager();
KPageTableManager &ptm = Kernel::GetSystemPageTableManager();
/* Make a page group for the pages we're closing. */
KPageGroup pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
KPageGroup pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
/* Walk the directory. */
u64 remaining = size;
@@ -1417,15 +1414,11 @@ namespace ams::kern::board::nintendo::nx {
return true;
}
Result KDevicePageTable::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool is_io) {
Result KDevicePageTable::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
/* Validate address/size. */
MESOSPHERE_ASSERT((device_address & ~DeviceVirtualAddressMask) == 0);
MESOSPHERE_ASSERT(((device_address + size - 1) & ~DeviceVirtualAddressMask) == 0);
/* IO is not supported on NX board. */
MESOSPHERE_ASSERT(!is_io);
MESOSPHERE_UNUSED(is_io);
/* Map the pages. */
R_RETURN(this->MapImpl(page_table, process_address, size, device_address, device_perm, is_aligned));
}

View File

@@ -29,6 +29,7 @@ namespace ams::kern::board::nintendo::nx {
constinit bool g_call_smc_on_panic;
/* Global variables for secure memory. */
constexpr size_t SecureAppletMemorySize = 4_MB;
constinit KSpinLock g_secure_applet_lock;
constinit bool g_secure_applet_memory_used = false;
constinit KVirtualAddress g_secure_applet_memory_address = Null<KVirtualAddress>;
@@ -245,8 +246,8 @@ namespace ams::kern::board::nintendo::nx {
Result AllocateSecureMemoryForApplet(KVirtualAddress *out, size_t size) {
/* Verify that the size is valid. */
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
R_UNLESS(size <= KSystemControl::SecureAppletMemorySize, svc::ResultOutOfMemory());
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
R_UNLESS(size <= SecureAppletMemorySize, svc::ResultOutOfMemory());
/* Disable interrupts and acquire the secure applet lock. */
KScopedInterruptDisable di;
@@ -272,7 +273,7 @@ namespace ams::kern::board::nintendo::nx {
/* Verify that the memory being freed is correct. */
MESOSPHERE_ABORT_UNLESS(address == g_secure_applet_memory_address);
MESOSPHERE_ABORT_UNLESS(size <= KSystemControl::SecureAppletMemorySize);
MESOSPHERE_ABORT_UNLESS(size <= SecureAppletMemorySize);
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, PageSize));
MESOSPHERE_ABORT_UNLESS(g_secure_applet_memory_used);
@@ -450,11 +451,17 @@ namespace ams::kern::board::nintendo::nx {
/* Initialize the sleep manager. */
KSleepManager::Initialize();
/* Get the secure applet memory. */
const auto &secure_applet_memory = KMemoryLayout::GetSecureAppletMemoryRegion();
MESOSPHERE_INIT_ABORT_UNLESS(secure_applet_memory.GetSize() == SecureAppletMemorySize);
/* Reserve secure applet memory. */
if (GetTargetFirmware() >= TargetFirmware_5_0_0) {
MESOSPHERE_ABORT_UNLESS(g_secure_applet_memory_address == Null<KVirtualAddress>);
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, SecureAppletMemorySize));
g_secure_applet_memory_address = secure_applet_memory.GetAddress();
constexpr auto SecureAppletAllocateOption = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
const KPhysicalAddress secure_applet_memory_phys_addr = Kernel::GetMemoryManager().AllocateAndOpenContinuous(SecureAppletMemorySize / PageSize, 1, SecureAppletAllocateOption);
MESOSPHERE_ABORT_UNLESS(secure_applet_memory_phys_addr != Null<KPhysicalAddress>);
g_secure_applet_memory_address = KMemoryLayout::GetLinearVirtualAddress(secure_applet_memory_phys_addr);
}
/* Initialize KTrace (and potentially other init). */
KSystemControlBase::InitializePhase2();

View File

@@ -17,34 +17,30 @@
namespace ams::kern::init {
/* For macro convenience. */
using KSessionRequestMappings = KSessionRequest::SessionMappings::DynamicMappings;
#define SLAB_COUNT(CLASS) g_slab_resource_counts.num_##CLASS
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
HANDLER(KPort, (SLAB_COUNT(KPort)), ## __VA_ARGS__) \
HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ## __VA_ARGS__) \
HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ## __VA_ARGS__) \
HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ## __VA_ARGS__) \
HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ## __VA_ARGS__) \
HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ## __VA_ARGS__) \
HANDLER(KSession, (SLAB_COUNT(KSession)), ## __VA_ARGS__) \
HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ## __VA_ARGS__) \
HANDLER(KLightSession, (SLAB_COUNT(KLightSession)), ## __VA_ARGS__) \
HANDLER(KThreadLocalPage, (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), ## __VA_ARGS__) \
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
HANDLER(KIoPool, (SLAB_COUNT(KIoPool)), ## __VA_ARGS__) \
HANDLER(KIoRegion, (SLAB_COUNT(KIoRegion)), ## __VA_ARGS__) \
HANDLER(KSecureSystemResource, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
HANDLER(KSessionRequestMappings, (SLAB_COUNT(KSessionRequestMappings)), ## __VA_ARGS__)
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
HANDLER(KPort, (SLAB_COUNT(KPort)), ## __VA_ARGS__) \
HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ## __VA_ARGS__) \
HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ## __VA_ARGS__) \
HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ## __VA_ARGS__) \
HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ## __VA_ARGS__) \
HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ## __VA_ARGS__) \
HANDLER(KSession, (SLAB_COUNT(KSession)), ## __VA_ARGS__) \
HANDLER(KSessionRequest, (SLAB_COUNT(KSession) * 2), ## __VA_ARGS__) \
HANDLER(KLightSession, (SLAB_COUNT(KLightSession)), ## __VA_ARGS__) \
HANDLER(KThreadLocalPage, (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), ## __VA_ARGS__) \
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
HANDLER(KIoPool, (SLAB_COUNT(KIoPool)), ## __VA_ARGS__) \
HANDLER(KIoRegion, (SLAB_COUNT(KIoRegion)), ## __VA_ARGS__)
namespace {
@@ -59,55 +55,50 @@ namespace ams::kern::init {
#undef DEFINE_SLAB_TYPE_ENUM_MEMBER
/* Constexpr counts. */
constexpr size_t SlabCountKProcess = 80;
constexpr size_t SlabCountKThread = 800;
constexpr size_t SlabCountKEvent = 900;
constexpr size_t SlabCountKInterruptEvent = 100;
constexpr size_t SlabCountKPort = 384;
constexpr size_t SlabCountKSharedMemory = 80;
constexpr size_t SlabCountKTransferMemory = 200;
constexpr size_t SlabCountKCodeMemory = 10;
constexpr size_t SlabCountKDeviceAddressSpace = 300;
constexpr size_t SlabCountKSession = 1133;
constexpr size_t SlabCountKLightSession = 100;
constexpr size_t SlabCountKObjectName = 7;
constexpr size_t SlabCountKResourceLimit = 5;
constexpr size_t SlabCountKDebug = cpu::NumCores;
constexpr size_t SlabCountKIoPool = 1;
constexpr size_t SlabCountKIoRegion = 6;
constexpr size_t SlabcountKSessionRequestMappings = 40;
constexpr size_t SlabCountKProcess = 80;
constexpr size_t SlabCountKThread = 800;
constexpr size_t SlabCountKEvent = 900;
constexpr size_t SlabCountKInterruptEvent = 100;
constexpr size_t SlabCountKPort = 384;
constexpr size_t SlabCountKSharedMemory = 80;
constexpr size_t SlabCountKTransferMemory = 200;
constexpr size_t SlabCountKCodeMemory = 10;
constexpr size_t SlabCountKDeviceAddressSpace = 300;
constexpr size_t SlabCountKSession = 1133;
constexpr size_t SlabCountKLightSession = 100;
constexpr size_t SlabCountKObjectName = 7;
constexpr size_t SlabCountKResourceLimit = 5;
constexpr size_t SlabCountKDebug = cpu::NumCores;
constexpr size_t SlabCountKIoPool = 1;
constexpr size_t SlabCountKIoRegion = 6;
constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread;
constexpr size_t SlabCountExtraKThread = (1024 + 256 + 256) - SlabCountKThread;
namespace test {
constexpr size_t RequiredSizeForExtraThreadCount = SlabCountExtraKThread * (sizeof(KThread) + (sizeof(KThreadLocalPage) / 8) + sizeof(KEventInfo));
static_assert(RequiredSizeForExtraThreadCount <= KernelSlabHeapAdditionalSize);
static_assert(KernelPageBufferHeapSize == 2 * PageSize + (SlabCountKProcess + SlabCountKThread + (SlabCountKProcess + SlabCountKThread) / 8) * PageSize);
static_assert(KernelPageBufferAdditionalSize == (SlabCountExtraKThread + (SlabCountExtraKThread / 8)) * PageSize);
}
/* Global to hold our resource counts. */
constinit KSlabResourceCounts g_slab_resource_counts = {
.num_KProcess = SlabCountKProcess,
.num_KThread = SlabCountKThread,
.num_KEvent = SlabCountKEvent,
.num_KInterruptEvent = SlabCountKInterruptEvent,
.num_KPort = SlabCountKPort,
.num_KSharedMemory = SlabCountKSharedMemory,
.num_KTransferMemory = SlabCountKTransferMemory,
.num_KCodeMemory = SlabCountKCodeMemory,
.num_KDeviceAddressSpace = SlabCountKDeviceAddressSpace,
.num_KSession = SlabCountKSession,
.num_KLightSession = SlabCountKLightSession,
.num_KObjectName = SlabCountKObjectName,
.num_KResourceLimit = SlabCountKResourceLimit,
.num_KDebug = SlabCountKDebug,
.num_KIoPool = SlabCountKIoPool,
.num_KIoRegion = SlabCountKIoRegion,
.num_KSessionRequestMappings = SlabcountKSessionRequestMappings,
.num_KProcess = SlabCountKProcess,
.num_KThread = SlabCountKThread,
.num_KEvent = SlabCountKEvent,
.num_KInterruptEvent = SlabCountKInterruptEvent,
.num_KPort = SlabCountKPort,
.num_KSharedMemory = SlabCountKSharedMemory,
.num_KTransferMemory = SlabCountKTransferMemory,
.num_KCodeMemory = SlabCountKCodeMemory,
.num_KDeviceAddressSpace = SlabCountKDeviceAddressSpace,
.num_KSession = SlabCountKSession,
.num_KLightSession = SlabCountKLightSession,
.num_KObjectName = SlabCountKObjectName,
.num_KResourceLimit = SlabCountKResourceLimit,
.num_KDebug = SlabCountKDebug,
.num_KIoPool = SlabCountKIoPool,
.num_KIoRegion = SlabCountKIoRegion,
};
template<typename T>
@@ -140,7 +131,7 @@ namespace ams::kern::init {
}
size_t CalculateSlabHeapGapSize() {
constexpr size_t KernelSlabHeapGapSize = 2_MB - 320_KB;
constexpr size_t KernelSlabHeapGapSize = 2_MB - 296_KB;
static_assert(KernelSlabHeapGapSize <= KernelSlabHeapGapsSizeMax);
return KernelSlabHeapGapSize;
}
@@ -164,6 +155,23 @@ namespace ams::kern::init {
return size;
}
void InitializeKPageBufferSlabHeap() {
const auto &counts = GetSlabResourceCounts();
const size_t num_pages = counts.num_KProcess + counts.num_KThread + (counts.num_KProcess + counts.num_KThread) / 8;
const size_t slab_size = num_pages * PageSize;
/* Reserve memory from the system resource limit. */
MESOSPHERE_ABORT_UNLESS(Kernel::GetSystemResourceLimit().Reserve(ams::svc::LimitableResource_PhysicalMemoryMax, slab_size));
/* Allocate memory for the slab. */
constexpr auto AllocateOption = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
const KPhysicalAddress slab_address = Kernel::GetMemoryManager().AllocateAndOpenContinuous(num_pages, 1, AllocateOption);
MESOSPHERE_ABORT_UNLESS(slab_address != Null<KPhysicalAddress>);
/* Initialize the slabheap. */
KPageBuffer::InitializeSlabHeap(GetVoidPointer(KMemoryLayout::GetLinearVirtualAddress(slab_address)), slab_size);
}
void InitializeSlabHeaps() {
/* Get the slab region, since that's where we'll be working. */
const KMemoryRegion &slab_region = KMemoryLayout::GetSlabRegion();
@@ -232,34 +240,4 @@ namespace ams::kern::init {
FreeUnusedSlabMemory(gap_start, gap_size + (slab_region.GetEndAddress() - GetInteger(address)));
}
}
namespace ams::kern {
void KPageBufferSlabHeap::Initialize(KDynamicPageManager &allocator) {
/* Get slab resource counts. */
const auto &counts = init::GetSlabResourceCounts();
/* If size is correct, account for thread local pages. */
if (BufferSize == PageSize) {
s_buffer_count += counts.num_KProcess + counts.num_KThread + (counts.num_KProcess + counts.num_KThread) / 8;
}
/* Set our object size. */
m_obj_size = BufferSize;
/* Initialize the base allocator. */
KSlabHeapImpl::Initialize();
/* Allocate the desired page count. */
for (size_t i = 0; i < s_buffer_count; ++i) {
/* Allocate an appropriate buffer. */
auto * const pb = (BufferSize <= PageSize) ? allocator.Allocate() : allocator.Allocate(BufferSize / PageSize);
MESOSPHERE_ABORT_UNLESS(pb != nullptr);
/* Free to our slab. */
KSlabHeapImpl::Free(pb);
}
}
}
}

View File

@@ -128,13 +128,13 @@ namespace ams::kern {
KProcess *new_process = nullptr;
{
/* Make page groups to represent the data. */
KPageGroup pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
KPageGroup workaround_pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
KPageGroup pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
KPageGroup workaround_pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
/* Populate the page group to represent the data. */
{
/* Allocate the previously unreserved pages. */
KPageGroup unreserve_pg(Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer());
KPageGroup unreserve_pg(std::addressof(Kernel::GetSystemBlockInfoManager()));
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(unreserve_pg), unreserved_size / PageSize, KMemoryManager::EncodeOption(dst_pool, KMemoryManager::Direction_FromFront)));
/* Add the previously reserved pages. */

View File

@@ -123,7 +123,7 @@ namespace ams::kern {
s32 new_value;
if (count <= 0) {
if ((it != m_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
new_value = value - 1;
new_value = value - 2;
} else {
new_value = value + 1;
}
@@ -132,7 +132,7 @@ namespace ams::kern {
auto tmp_it = it;
s32 tmp_num_waiters = 0;
while ((++tmp_it != m_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr)) {
if ((++tmp_num_waiters) >= count) {
if ((tmp_num_waiters++) >= count) {
break;
}
}

View File

@@ -43,12 +43,6 @@ namespace ams::kern {
static_assert(ClassToken<KDeviceAddressSpace> == 0b10010001'00000000);
static_assert(ClassToken<KSessionRequest> == 0b01100001'00000000);
static_assert(ClassToken<KCodeMemory> == 0b10100001'00000000);
static_assert(ClassToken<KIoPool> == 0b11000001'00000000);
static_assert(ClassToken<KIoRegion> == 0b00001110'00000000);
/* 0b00010110'00000000 */
/* 0b00100110'00000000 */
static_assert(ClassToken<KSystemResource> == 0b01000110'00000000);
/* Ensure that the token hierarchy is correct. */
@@ -78,10 +72,6 @@ namespace ams::kern {
static_assert(ClassToken<KDeviceAddressSpace> == ((0b10010001 << 8) | ClassToken<KAutoObject>));
static_assert(ClassToken<KSessionRequest> == ((0b01100001 << 8) | ClassToken<KAutoObject>));
static_assert(ClassToken<KCodeMemory> == ((0b10100001 << 8) | ClassToken<KAutoObject>));
static_assert(ClassToken<KIoPool> == ((0b11000001 << 8) | ClassToken<KAutoObject>));
static_assert(ClassToken<KIoRegion> == ((0b00001110 << 8) | ClassToken<KAutoObject>));
static_assert(ClassToken<KSystemResource> == ((0b01000110 << 8) | ClassToken<KAutoObject>));
/* Ensure that the token hierarchy reflects the class hierarchy. */
@@ -110,10 +100,6 @@ namespace ams::kern {
static_assert(std::is_final<KDeviceAddressSpace>::value && std::is_base_of<KAutoObject, KDeviceAddressSpace>::value);
static_assert(std::is_final<KSessionRequest>::value && std::is_base_of<KAutoObject, KSessionRequest>::value);
static_assert(std::is_final<KCodeMemory>::value && std::is_base_of<KAutoObject, KCodeMemory>::value);
static_assert(std::is_final<KIoPool>::value && std::is_base_of<KAutoObject, KIoPool>::value);
static_assert(std::is_final<KIoRegion>::value && std::is_base_of<KAutoObject, KIoRegion>::value);
static_assert(std::is_base_of<KAutoObject, KSystemResource>::value);
}

View File

@@ -61,21 +61,10 @@ namespace ams::kern {
R_RETURN(m_table.Detach(device_name));
}
Result KDeviceAddressSpace::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, u32 option, bool is_aligned) {
Result KDeviceAddressSpace::Map(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned) {
/* Check that the address falls within the space. */
R_UNLESS((m_space_address <= device_address && device_address + size - 1 <= m_space_address + m_space_size - 1), svc::ResultInvalidCurrentMemory());
/* Decode the option. */
const util::BitPack32 option_pack = { option };
const auto device_perm = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Permission>();
const auto flags = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Flags>();
const auto reserved = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Reserved>();
/* Validate the option. */
/* TODO: It is likely that this check for flags == none is only on NX board. */
R_UNLESS(flags == ams::svc::MapDeviceAddressSpaceFlag_None, svc::ResultInvalidEnumValue());
R_UNLESS(reserved == 0, svc::ResultInvalidEnumValue());
/* Lock the address space. */
KScopedLightLock lk(m_lock);
@@ -83,21 +72,15 @@ namespace ams::kern {
KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
/* Lock the pages. */
bool is_io{};
R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size, ConvertToKMemoryPermission(device_perm), is_aligned, true));
R_TRY(page_table->LockForMapDeviceAddressSpace(process_address, size, ConvertToKMemoryPermission(device_perm), is_aligned));
/* Ensure that if we fail, we don't keep unmapped pages locked. */
ON_RESULT_FAILURE { MESOSPHERE_R_ABORT_UNLESS(page_table->UnlockForDeviceAddressSpace(process_address, size)); };
/* Check that the io status is allowable. */
if (is_io) {
R_UNLESS((flags & ams::svc::MapDeviceAddressSpaceFlag_NotIoRegister) == 0, svc::ResultInvalidCombination());
}
/* Map the pages. */
{
/* Perform the mapping. */
R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, is_aligned, is_io));
R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, is_aligned));
/* Ensure that we unmap the pages if we fail to update the protections. */
/* NOTE: Nintendo does not check the result of this unmap call. */
@@ -122,7 +105,7 @@ namespace ams::kern {
KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
/* Lock the pages. */
R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true));
R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size));
/* Unmap the pages. */
{

View File

@@ -332,6 +332,7 @@ namespace ams::kern::KDumpObject {
MESOSPHERE_RELEASE_LOG(#__OBJECT__ "\n"); \
MESOSPHERE_RELEASE_LOG(" Cur=%3zu Peak=%3zu Max=%3zu\n", __OBJECT__::GetSlabHeapSize() - __OBJECT__::GetNumRemaining(), __OBJECT__::GetPeakIndex(), __OBJECT__::GetSlabHeapSize())
DUMP_KSLABOBJ(KPageBuffer);
DUMP_KSLABOBJ(KEvent);
DUMP_KSLABOBJ(KInterruptEvent);
DUMP_KSLABOBJ(KProcess);
@@ -361,24 +362,24 @@ namespace ams::kern::KDumpObject {
/* Memory block slabs. */
{
MESOSPHERE_RELEASE_LOG("App Memory Block\n");
auto &app = Kernel::GetApplicationSystemResource().GetMemoryBlockSlabManager();
auto &app = Kernel::GetApplicationMemoryBlockManager();
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", app.GetUsed(), app.GetPeak(), app.GetCount());
MESOSPHERE_RELEASE_LOG("Sys Memory Block\n");
auto &sys = Kernel::GetSystemSystemResource().GetMemoryBlockSlabManager();
auto &sys = Kernel::GetSystemMemoryBlockManager();
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", sys.GetUsed(), sys.GetPeak(), sys.GetCount());
}
/* KBlockInfo slab. */
{
MESOSPHERE_RELEASE_LOG("KBlockInfo\n");
auto &manager = Kernel::GetSystemSystemResource().GetBlockInfoManager();
auto &manager = Kernel::GetSystemBlockInfoManager();
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
}
/* Page Table slab. */
{
MESOSPHERE_RELEASE_LOG("Page Table\n");
auto &manager = Kernel::GetSystemSystemResource().GetPageTableManager();
auto &manager = Kernel::GetSystemPageTableManager();
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount());
}
}
@@ -424,17 +425,15 @@ namespace ams::kern::KDumpObject {
process_pts += pts;
MESOSPHERE_RELEASE_LOG("%-12s: PID=%3lu Thread %4d / Event %4d / PageTable %5zu\n", process->GetName(), process->GetId(), threads, events, pts);
if (const auto &system_resource = process->GetSystemResource(); system_resource.IsSecureResource()) {
const auto &secure_resource = static_cast<const KSecureSystemResource &>(system_resource);
if (process->GetTotalSystemResourceSize() != 0) {
MESOSPHERE_RELEASE_LOG(" System Resource\n");
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetDynamicPageManager().GetUsed(), secure_resource.GetDynamicPageManager().GetPeak(), secure_resource.GetDynamicPageManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetDynamicPageManager().GetUsed(), process->GetDynamicPageManager().GetPeak(), process->GetDynamicPageManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Memory Block\n");
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetMemoryBlockSlabManager().GetUsed(), secure_resource.GetMemoryBlockSlabManager().GetPeak(), secure_resource.GetMemoryBlockSlabManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetMemoryBlockSlabManager().GetUsed(), process->GetMemoryBlockSlabManager().GetPeak(), process->GetMemoryBlockSlabManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Page Table\n");
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetPageTableManager().GetUsed(), secure_resource.GetPageTableManager().GetPeak(), secure_resource.GetPageTableManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetPageTableManager().GetUsed(), process->GetPageTableManager().GetPeak(), process->GetPageTableManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Block Info\n");
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", secure_resource.GetBlockInfoManager().GetUsed(), secure_resource.GetBlockInfoManager().GetPeak(), secure_resource.GetBlockInfoManager().GetCount());
MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetBlockInfoManager().GetUsed(), process->GetBlockInfoManager().GetPeak(), process->GetBlockInfoManager().GetCount());
}
}

View File

@@ -17,6 +17,13 @@
namespace ams::kern {
namespace {
constinit KLightLock g_interrupt_event_lock;
constinit KInterruptEventTask *g_interrupt_event_task_table[KInterruptController::NumInterrupts] = {};
}
Result KInterruptEvent::Initialize(int32_t interrupt_name, ams::svc::InterruptType type) {
MESOSPHERE_ASSERT_THIS();
@@ -33,8 +40,8 @@ namespace ams::kern {
/* Initialize readable event base. */
KReadableEvent::Initialize(nullptr);
/* Bind ourselves as the handler for our interrupt id. */
R_TRY(Kernel::GetInterruptManager().BindHandler(this, m_interrupt_id, m_core_id, KInterruptController::PriorityLevel_High, true, type == ams::svc::InterruptType_Level));
/* Try to register the task. */
R_TRY(KInterruptEventTask::Register(m_interrupt_id, m_core_id, type == ams::svc::InterruptType_Level, this));
/* Mark initialized. */
m_is_initialized = true;
@@ -44,11 +51,7 @@ namespace ams::kern {
void KInterruptEvent::Finalize() {
MESOSPHERE_ASSERT_THIS();
/* Unbind ourselves as the handler for our interrupt id. */
Kernel::GetInterruptManager().UnbindHandler(m_interrupt_id, m_core_id);
/* Synchronize the unbind on all cores, before proceeding. */
KDpcManager::Sync();
g_interrupt_event_task_table[m_interrupt_id]->Unregister(m_interrupt_id, m_core_id);
/* Perform inherited finalization. */
KReadableEvent::Finalize();
@@ -69,19 +72,79 @@ namespace ams::kern {
R_SUCCEED();
}
KInterruptTask *KInterruptEvent::OnInterrupt(s32 interrupt_id) {
Result KInterruptEventTask::Register(s32 interrupt_id, s32 core_id, bool level, KInterruptEvent *event) {
/* Lock the task table. */
KScopedLightLock lk(g_interrupt_event_lock);
/* Get a task for the id. */
bool allocated = false;
KInterruptEventTask *task = g_interrupt_event_task_table[interrupt_id];
if (task != nullptr) {
/* Check that there's not already an event for this task. */
R_UNLESS(task->m_event == nullptr, svc::ResultBusy());
} else {
/* Allocate a new task. */
task = KInterruptEventTask::Allocate();
R_UNLESS(task != nullptr, svc::ResultOutOfResource());
allocated = true;
}
/* Ensure that the task is cleaned up if anything goes wrong. */
ON_RESULT_FAILURE { if (allocated) { KInterruptEventTask::Free(task); } };
/* Register/bind the interrupt task. */
{
/* Lock the scheduler. */
KScopedSchedulerLock sl;
/* Bind the interrupt handler. */
R_TRY(Kernel::GetInterruptManager().BindHandler(task, interrupt_id, core_id, KInterruptController::PriorityLevel_High, true, level));
/* Set the event. */
task->m_event = event;
}
/* If we allocated, set the event in the table. */
if (allocated) {
g_interrupt_event_task_table[interrupt_id] = task;
}
R_SUCCEED();
}
void KInterruptEventTask::Unregister(s32 interrupt_id, s32 core_id) {
MESOSPHERE_ASSERT_THIS();
/* Lock the task table. */
KScopedLightLock lk(g_interrupt_event_lock);
/* Lock the scheduler. */
KScopedSchedulerLock sl;
/* Ensure we can unregister. */
MESOSPHERE_ABORT_UNLESS(g_interrupt_event_task_table[interrupt_id] == this);
MESOSPHERE_ABORT_UNLESS(m_event != nullptr);
/* Unbind the interrupt. */
m_event = nullptr;
Kernel::GetInterruptManager().UnbindHandler(interrupt_id, core_id);
}
KInterruptTask *KInterruptEventTask::OnInterrupt(s32 interrupt_id) {
MESOSPHERE_ASSERT_THIS();
MESOSPHERE_UNUSED(interrupt_id);
return this;
}
void KInterruptEvent::DoTask() {
void KInterruptEventTask::DoTask() {
MESOSPHERE_ASSERT_THIS();
/* Lock the scheduler. */
KScopedSchedulerLock sl;
/* Signal. */
this->Signal();
if (m_event != nullptr) {
m_event->Signal();
}
}
}

View File

@@ -126,8 +126,11 @@ namespace ams::kern {
}
}
size_t KMemoryLayout::GetResourceRegionSizeForInit(bool use_extra_resource) {
return KernelResourceSize + KSystemControl::SecureAppletMemorySize + (use_extra_resource ? KernelSlabHeapAdditionalSize + KernelPageBufferAdditionalSize : 0);
size_t KMemoryLayout::GetResourceRegionSizeForInit() {
/* Calculate resource region size based on whether we allow extra threads. */
const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
return KernelResourceSize + (use_extra_resources ? KernelSlabHeapAdditionalSize : 0);
}
}

View File

@@ -308,7 +308,7 @@ namespace ams::kern {
R_SUCCEED();
}
Result KMemoryManager::AllocateForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern) {
Result KMemoryManager::AllocateAndOpenForProcess(KPageGroup *out, size_t num_pages, u32 option, u64 process_id, u8 fill_pattern) {
MESOSPHERE_ASSERT(out != nullptr);
MESOSPHERE_ASSERT(out->GetNumPages() == 0);
@@ -330,6 +330,24 @@ namespace ams::kern {
/* Set whether we should optimize. */
optimized = has_optimized && is_optimized;
/* Open the first reference to the pages. */
for (const auto &block : *out) {
KPhysicalAddress cur_address = block.GetAddress();
size_t remaining_pages = block.GetNumPages();
while (remaining_pages > 0) {
/* Get the manager for the current address. */
auto &manager = this->GetManager(cur_address);
/* Process part or all of the block. */
const size_t cur_pages = std::min(remaining_pages, manager.GetPageOffsetToEnd(cur_address));
manager.OpenFirst(cur_address, cur_pages);
/* Advance. */
cur_address += cur_pages * PageSize;
remaining_pages -= cur_pages;
}
}
}
/* Perform optimized memory tracking, if we should. */

View File

@@ -92,14 +92,6 @@ namespace ams::kern {
}
}
void KPageGroup::OpenFirst() const {
auto &mm = Kernel::GetMemoryManager();
for (const auto &it : *this) {
mm.OpenFirst(it.GetAddress(), it.GetNumPages());
}
}
void KPageGroup::Close() const {
auto &mm = Kernel::GetMemoryManager();

View File

@@ -103,11 +103,10 @@ namespace ams::kern {
m_max_heap_size = 0;
m_mapped_physical_memory_size = 0;
m_mapped_unsafe_physical_memory = 0;
m_mapped_insecure_memory = 0;
m_mapped_ipc_server_memory = 0;
m_memory_block_slab_manager = Kernel::GetSystemSystemResource().GetMemoryBlockSlabManagerPointer();
m_block_info_manager = Kernel::GetSystemSystemResource().GetBlockInfoManagerPointer();
m_memory_block_slab_manager = std::addressof(Kernel::GetSystemMemoryBlockManager());
m_block_info_manager = std::addressof(Kernel::GetSystemBlockInfoManager());
m_resource_limit = std::addressof(Kernel::GetSystemResourceLimit());
m_allocate_option = KMemoryManager::EncodeOption(KMemoryManager::Pool_System, KMemoryManager::Direction_FromFront);
@@ -125,7 +124,7 @@ namespace ams::kern {
R_RETURN(m_memory_block_manager.Initialize(m_address_space_start, m_address_space_end, m_memory_block_slab_manager));
}
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_merge, bool from_back, KMemoryManager::Pool pool, void *table, KProcessAddress start, KProcessAddress end, KProcessAddress code_address, size_t code_size, KSystemResource *system_resource, KResourceLimit *resource_limit) {
Result KPageTableBase::InitializeForProcess(ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool enable_das_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, KResourceLimit *resource_limit) {
/* Validate the region. */
MESOSPHERE_ABORT_UNLESS(start <= code_address);
MESOSPHERE_ABORT_UNLESS(code_address < code_address + code_size);
@@ -187,8 +186,8 @@ namespace ams::kern {
m_address_space_start = start;
m_address_space_end = end;
m_is_kernel = false;
m_memory_block_slab_manager = system_resource->GetMemoryBlockSlabManagerPointer();
m_block_info_manager = system_resource->GetBlockInfoManagerPointer();
m_memory_block_slab_manager = mem_block_slab_manager;
m_block_info_manager = block_info_manager;
m_resource_limit = resource_limit;
/* Determine the region we can place our undetermineds in. */
@@ -288,7 +287,6 @@ namespace ams::kern {
m_max_heap_size = 0;
m_mapped_physical_memory_size = 0;
m_mapped_unsafe_physical_memory = 0;
m_mapped_insecure_memory = 0;
m_mapped_ipc_server_memory = 0;
const bool fill_memory = KTargetSystem::IsDebugMemoryFillEnabled();
@@ -342,13 +340,6 @@ namespace ams::kern {
Kernel::GetUnsafeMemory().Release(m_mapped_unsafe_physical_memory);
}
/* Release any insecure mapped memory. */
if (m_mapped_insecure_memory) {
if (auto * const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(); insecure_resource_limit != nullptr) {
insecure_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, m_mapped_insecure_memory);
}
}
/* Release any ipc server memory. */
if (m_mapped_ipc_server_memory) {
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, m_mapped_ipc_server_memory);
@@ -384,7 +375,6 @@ namespace ams::kern {
case KMemoryState_GeneratedCode:
case KMemoryState_CodeOut:
case KMemoryState_Coverage:
case KMemoryState_Insecure:
return m_alias_code_region_start;
case KMemoryState_Code:
case KMemoryState_CodeData:
@@ -419,7 +409,6 @@ namespace ams::kern {
case KMemoryState_GeneratedCode:
case KMemoryState_CodeOut:
case KMemoryState_Coverage:
case KMemoryState_Insecure:
return m_alias_code_region_end - m_alias_code_region_start;
case KMemoryState_Code:
case KMemoryState_CodeData:
@@ -457,7 +446,6 @@ namespace ams::kern {
case KMemoryState_GeneratedCode:
case KMemoryState_CodeOut:
case KMemoryState_Coverage:
case KMemoryState_Insecure:
return is_in_region && !is_in_heap && !is_in_alias;
case KMemoryState_Normal:
MESOSPHERE_ASSERT(is_in_heap);
@@ -1050,97 +1038,6 @@ namespace ams::kern {
R_SUCCEED();
}
Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
/* Get the insecure memory resource limit and pool. */
auto * const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit();
const auto insecure_pool = static_cast<KMemoryManager::Pool>(KSystemControl::GetInsecureMemoryPool());
/* Reserve the insecure memory. */
/* NOTE: ResultOutOfMemory is returned here instead of the usual LimitReached. */
KScopedResourceReservation memory_reservation(insecure_resource_limit, ams::svc::LimitableResource_PhysicalMemoryMax, size);
R_UNLESS(memory_reservation.Succeeded(), svc::ResultOutOfMemory());
/* Allocate pages for the insecure memory. */
KPageGroup pg(m_block_info_manager);
R_TRY(Kernel::GetMemoryManager().AllocateAndOpen(std::addressof(pg), size / PageSize, KMemoryManager::EncodeOption(insecure_pool, KMemoryManager::Direction_FromFront)));
/* Close the opened pages when we're done with them. */
/* If the mapping succeeds, each page will gain an extra reference, otherwise they will be freed automatically. */
ON_SCOPE_EXIT { pg.Close(); };
/* Clear all the newly allocated pages. */
for (const auto &it : pg) {
std::memset(GetVoidPointer(GetHeapVirtualAddress(it.GetAddress())), m_heap_fill_value, it.GetSize());
}
/* Lock the table. */
KScopedLightLock lk(m_general_lock);
/* Validate that the address's state is valid. */
size_t num_allocator_blocks;
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), address, size, KMemoryState_All, KMemoryState_Free, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_None, KMemoryAttribute_None));
/* Create an update allocator. */
Result allocator_result;
KMemoryBlockManagerUpdateAllocator allocator(std::addressof(allocator_result), m_memory_block_slab_manager, num_allocator_blocks);
R_TRY(allocator_result);
/* We're going to perform an update, so create a helper. */
KScopedPageTableUpdater updater(this);
/* Map the pages. */
const size_t num_pages = size / PageSize;
const KPageProperties map_properties = { KMemoryPermission_UserReadWrite, false, false, DisableMergeAttribute_DisableHead };
R_TRY(this->Operate(updater.GetPageList(), address, num_pages, pg, map_properties, OperationType_MapGroup, false));
/* Apply the memory block update. */
m_memory_block_manager.Update(std::addressof(allocator), address, num_pages, KMemoryState_Insecure, KMemoryPermission_UserReadWrite, KMemoryAttribute_None, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None);
/* Update our mapped insecure size. */
m_mapped_insecure_memory += size;
/* Commit the memory reservation. */
memory_reservation.Commit();
/* We succeeded. */
R_SUCCEED();
}
Result KPageTableBase::UnmapInsecureMemory(KProcessAddress address, size_t size) {
/* Lock the table. */
KScopedLightLock lk(m_general_lock);
/* Check the memory state. */
size_t num_allocator_blocks;
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), address, size, KMemoryState_All, KMemoryState_Insecure, KMemoryPermission_All, KMemoryPermission_UserReadWrite, KMemoryAttribute_All, KMemoryAttribute_None));
/* Create an update allocator. */
Result allocator_result;
KMemoryBlockManagerUpdateAllocator allocator(std::addressof(allocator_result), m_memory_block_slab_manager, num_allocator_blocks);
R_TRY(allocator_result);
/* We're going to perform an update, so create a helper. */
KScopedPageTableUpdater updater(this);
/* Unmap the memory. */
const size_t num_pages = size / PageSize;
const KPageProperties unmap_properties = { KMemoryPermission_None, false, false, DisableMergeAttribute_None };
R_TRY(this->Operate(updater.GetPageList(), address, num_pages, Null<KPhysicalAddress>, false, unmap_properties, OperationType_Unmap, false));
/* Apply the memory block update. */
m_memory_block_manager.Update(std::addressof(allocator), address, num_pages, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None, KMemoryBlockDisableMergeAttribute_None, KMemoryBlockDisableMergeAttribute_Normal);
/* Update our mapped insecure size. */
m_mapped_insecure_memory -= size;
/* Release the insecure memory from the insecure limit. */
if (auto * const insecure_resource_limit = KSystemControl::GetInsecureMemoryResourceLimit(); insecure_resource_limit != nullptr) {
insecure_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, size);
}
R_SUCCEED();
}
KProcessAddress KPageTableBase::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 address = Null<KProcessAddress>;
@@ -1487,8 +1384,11 @@ namespace ams::kern {
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
R_UNLESS(impl.BeginTraversal(std::addressof(cur_entry), std::addressof(context), address), svc::ResultInvalidCurrentMemory());
/* Traverse until we have enough size or we aren't contiguous any more. */
/* The region we're traversing has to be heap. */
const KPhysicalAddress phys_address = cur_entry.phys_addr;
R_UNLESS(this->IsHeapPhysicalAddress(phys_address), svc::ResultInvalidCurrentMemory());
/* Traverse until we have enough size or we aren't contiguous any more. */
size_t contig_size;
for (contig_size = cur_entry.block_size - (GetInteger(phys_address) & (cur_entry.block_size - 1)); contig_size < size; contig_size += cur_entry.block_size) {
if (!impl.ContinueTraversal(std::addressof(cur_entry), std::addressof(context))) {
@@ -1502,11 +1402,11 @@ namespace ams::kern {
/* Take the minimum size for our region. */
size = std::min(size, contig_size);
/* Check that the memory is contiguous (modulo the reference count bit). */
const u32 test_state_mask = state_mask | KMemoryState_FlagReferenceCounted;
if (R_FAILED(this->CheckMemoryStateContiguous(address, size, test_state_mask, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr))) {
R_TRY(this->CheckMemoryStateContiguous(address, size, test_state_mask, state, perm_mask, perm, attr_mask, attr));
}
/* Check that the memory is contiguous. */
R_TRY(this->CheckMemoryStateContiguous(address, size,
state_mask | KMemoryState_FlagReferenceCounted, state | KMemoryState_FlagReferenceCounted,
perm_mask, perm,
attr_mask, attr));
/* The memory is contiguous, so set the output range. */
*out = {
@@ -2013,7 +1913,7 @@ namespace ams::kern {
R_TRY(this->Operate(updater.GetPageList(), dst_address, num_pages, phys_addr, true, properties, OperationType_Map, false));
/* Update the blocks. */
m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, KMemoryState_Io, perm, KMemoryAttribute_Locked, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None);
m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, KMemoryState_Io, perm, KMemoryAttribute_None, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None);
/* We successfully mapped the pages. */
R_SUCCEED();
@@ -2027,7 +1927,7 @@ namespace ams::kern {
/* Validate the memory state. */
size_t num_allocator_blocks;
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), dst_address, size, KMemoryState_All, KMemoryState_Io, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_Locked));
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), dst_address, size, KMemoryState_All, KMemoryState_Io, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_None));
/* Validate that the region being unmapped corresponds to the physical range described. */
{
@@ -2787,7 +2687,7 @@ namespace ams::kern {
R_SUCCEED();
}
Result KPageTableBase::LockForMapDeviceAddressSpace(bool *out_is_io, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned, bool check_heap) {
Result KPageTableBase::LockForMapDeviceAddressSpace(KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) {
/* Lightly validate the range before doing anything else. */
const size_t num_pages = size / PageSize;
R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory());
@@ -2796,10 +2696,9 @@ namespace ams::kern {
KScopedLightLock lk(m_general_lock);
/* Check the memory state. */
const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap) | (check_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_None);
const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap);
size_t num_allocator_blocks;
KMemoryState old_state;
R_TRY(this->CheckMemoryState(std::addressof(old_state), nullptr, nullptr, std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), address, size, test_state, test_state, perm, perm, KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, KMemoryAttribute_None, KMemoryAttribute_DeviceShared));
/* Create an update allocator. */
Result allocator_result;
@@ -2809,13 +2708,10 @@ namespace ams::kern {
/* Update the memory blocks. */
m_memory_block_manager.UpdateLock(std::addressof(allocator), address, num_pages, &KMemoryBlock::ShareToDevice, KMemoryPermission_None);
/* Set whether the locked memory was io. */
*out_is_io = old_state == KMemoryState_Io;
R_SUCCEED();
}
Result KPageTableBase::LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size, bool check_heap) {
Result KPageTableBase::LockForUnmapDeviceAddressSpace(KProcessAddress address, size_t size) {
/* Lightly validate the range before doing anything else. */
const size_t num_pages = size / PageSize;
R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory());
@@ -2824,11 +2720,10 @@ namespace ams::kern {
KScopedLightLock lk(m_general_lock);
/* Check the memory state. */
const u32 test_state = KMemoryState_FlagCanDeviceMap | (check_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_None);
size_t num_allocator_blocks;
R_TRY(this->CheckMemoryStateContiguous(std::addressof(num_allocator_blocks),
address, size,
test_state, test_state,
KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDeviceMap, KMemoryState_FlagReferenceCounted | KMemoryState_FlagCanDeviceMap,
KMemoryPermission_None, KMemoryPermission_None,
KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared));
@@ -2903,7 +2798,7 @@ namespace ams::kern {
KScopedLightLock lk(m_general_lock);
/* Get the range. */
const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap);
const u32 test_state = KMemoryState_FlagReferenceCounted | (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap);
R_TRY(this->GetContiguousMemoryRangeWithState(out,
address, size,
test_state, test_state,
@@ -4241,13 +4136,10 @@ namespace ams::kern {
/* Allocate pages for the new memory. */
KPageGroup pg(m_block_info_manager);
R_TRY(Kernel::GetMemoryManager().AllocateForProcess(std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, GetCurrentProcess().GetId(), m_heap_fill_value));
R_TRY(Kernel::GetMemoryManager().AllocateAndOpenForProcess(std::addressof(pg), (size - mapped_size) / PageSize, m_allocate_option, GetCurrentProcess().GetId(), m_heap_fill_value));
/* If we fail in the next bit (or retry), we need to cleanup the pages. */
auto pg_guard = SCOPE_GUARD {
pg.OpenFirst();
pg.Close();
};
/* Close our reference when we're done. */
ON_SCOPE_EXIT { pg.Close(); };
/* Map the memory. */
{
@@ -4314,13 +4206,7 @@ namespace ams::kern {
/* We're going to perform an update, so create a helper. */
KScopedPageTableUpdater updater(this);
/* Prepare to iterate over the memory. */
auto pg_it = pg.begin();
KPhysicalAddress pg_phys_addr = pg_it->GetAddress();
size_t pg_pages = pg_it->GetNumPages();
/* Reset the current tracking address, and make sure we clean up on failure. */
pg_guard.Cancel();
cur_address = address;
ON_RESULT_FAILURE {
if (cur_address > address) {
@@ -4357,16 +4243,13 @@ namespace ams::kern {
++it;
}
}
/* Release any remaining unmapped memory. */
Kernel::GetMemoryManager().OpenFirst(pg_phys_addr, pg_pages);
Kernel::GetMemoryManager().Close(pg_phys_addr, pg_pages);
for (++pg_it; pg_it != pg.end(); ++pg_it) {
Kernel::GetMemoryManager().OpenFirst(pg_it->GetAddress(), pg_it->GetNumPages());
Kernel::GetMemoryManager().Close(pg_it->GetAddress(), pg_it->GetNumPages());
}
};
/* Iterate over the memory. */
auto pg_it = pg.begin();
KPhysicalAddress pg_phys_addr = pg_it->GetAddress();
size_t pg_pages = pg_it->GetNumPages();
auto it = m_memory_block_manager.FindIterator(cur_address);
while (true) {
/* Check that the iterator is valid. */
@@ -4396,7 +4279,7 @@ namespace ams::kern {
/* Map whatever we can. */
const size_t cur_pages = std::min(pg_pages, map_pages);
R_TRY(this->Operate(updater.GetPageList(), cur_address, cur_pages, pg_phys_addr, true, map_properties, OperationType_MapFirst, false));
R_TRY(this->Operate(updater.GetPageList(), cur_address, cur_pages, pg_phys_addr, true, map_properties, OperationType_Map, false));
/* Advance. */
cur_address += cur_pages * PageSize;
@@ -4445,9 +4328,6 @@ namespace ams::kern {
const KProcessAddress last_address = address + size - 1;
/* Define iteration variables. */
KProcessAddress map_start_address = Null<KProcessAddress>;
KProcessAddress map_last_address = Null<KProcessAddress>;
KProcessAddress cur_address;
size_t mapped_size;
size_t num_allocator_blocks = 0;
@@ -4474,26 +4354,27 @@ namespace ams::kern {
if (is_normal) {
R_UNLESS(info.GetAttribute() == KMemoryAttribute_None, svc::ResultInvalidCurrentMemory());
if (map_start_address == Null<KProcessAddress>) {
map_start_address = cur_address;
}
map_last_address = (last_address >= info.GetLastAddress()) ? info.GetLastAddress() : last_address;
if (info.GetAddress() < GetInteger(address)) {
++num_allocator_blocks;
}
if (last_address < info.GetLastAddress()) {
++num_allocator_blocks;
}
mapped_size += (map_last_address + 1 - cur_address);
}
/* Check if we're done. */
if (last_address <= info.GetLastAddress()) {
if (is_normal) {
mapped_size += (last_address + 1 - cur_address);
}
break;
}
/* Track the memory if it's mapped. */
if (is_normal) {
mapped_size += KProcessAddress(info.GetEndAddress()) - cur_address;
}
/* Advance. */
cur_address = info.GetEndAddress();
++it;
@@ -4503,6 +4384,54 @@ namespace ams::kern {
R_SUCCEED_IF(mapped_size == 0);
}
/* Make a page group for the unmap region. */
KPageGroup pg(m_block_info_manager);
{
auto &impl = this->GetImpl();
/* Begin traversal. */
TraversalContext context;
TraversalEntry cur_entry = { .phys_addr = Null<KPhysicalAddress>, .block_size = 0, .sw_reserved_bits = 0 };
bool cur_valid = false;
TraversalEntry next_entry;
bool next_valid;
size_t tot_size = 0;
cur_address = address;
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), cur_address);
next_entry.block_size = (next_entry.block_size - (GetInteger(next_entry.phys_addr) & (next_entry.block_size - 1)));
/* Iterate, building the group. */
while (true) {
if ((!next_valid && !cur_valid) || (next_valid && cur_valid && next_entry.phys_addr == cur_entry.phys_addr + cur_entry.block_size)) {
cur_entry.block_size += next_entry.block_size;
} else {
if (cur_valid) {
MESOSPHERE_ABORT_UNLESS(IsHeapPhysicalAddress(cur_entry.phys_addr));
R_TRY(pg.AddBlock(cur_entry.phys_addr, cur_entry.block_size / PageSize));
}
/* Update tracking variables. */
tot_size += cur_entry.block_size;
cur_entry = next_entry;
cur_valid = next_valid;
}
if (cur_entry.block_size + tot_size >= size) {
break;
}
next_valid = impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context));
}
/* Add the last block. */
if (cur_valid) {
MESOSPHERE_ABORT_UNLESS(IsHeapPhysicalAddress(cur_entry.phys_addr));
R_TRY(pg.AddBlock(cur_entry.phys_addr, (size - tot_size) / PageSize));
}
}
MESOSPHERE_ASSERT(pg.GetNumPages() == mapped_size / PageSize);
/* Create an update allocator. */
MESOSPHERE_ASSERT(num_allocator_blocks <= KMemoryBlockManagerUpdateAllocator::MaxBlocks);
Result allocator_result;
@@ -4512,12 +4441,69 @@ namespace ams::kern {
/* We're going to perform an update, so create a helper. */
KScopedPageTableUpdater updater(this);
/* Separate the mapping. */
const KPageProperties sep_properties = { KMemoryPermission_None, false, false, DisableMergeAttribute_None };
R_TRY(this->Operate(updater.GetPageList(), map_start_address, (map_last_address + 1 - map_start_address) / PageSize, Null<KPhysicalAddress>, false, sep_properties, OperationType_Separate, false));
/* Open a reference to the pages, we're unmapping, and close the reference when we're done. */
pg.Open();
ON_SCOPE_EXIT { pg.Close(); };
/* Reset the current tracking address, and make sure we clean up on failure. */
cur_address = address;
ON_RESULT_FAILURE {
if (cur_address > address) {
const KProcessAddress last_map_address = cur_address - 1;
cur_address = address;
/* Iterate over the memory we unmapped. */
auto it = m_memory_block_manager.FindIterator(cur_address);
auto pg_it = pg.begin();
KPhysicalAddress pg_phys_addr = pg_it->GetAddress();
size_t pg_pages = pg_it->GetNumPages();
while (true) {
/* Get the memory info for the pages we unmapped, convert to property. */
const KMemoryInfo info = it->GetMemoryInfo();
const KPageProperties prev_properties = { info.GetPermission(), false, false, DisableMergeAttribute_None };
/* If the memory is normal, we unmapped it and need to re-map it. */
if (info.GetState() == KMemoryState_Normal) {
/* Determine the range to map. */
size_t map_pages = std::min(KProcessAddress(info.GetEndAddress()) - cur_address, last_map_address + 1 - cur_address) / PageSize;
/* While we have pages to map, map them. */
while (map_pages > 0) {
/* Check if we're at the end of the physical block. */
if (pg_pages == 0) {
/* Ensure there are more pages to map. */
MESOSPHERE_ABORT_UNLESS(pg_it != pg.end());
/* Advance our physical block. */
++pg_it;
pg_phys_addr = pg_it->GetAddress();
pg_pages = pg_it->GetNumPages();
}
/* Map whatever we can. */
const size_t cur_pages = std::min(pg_pages, map_pages);
MESOSPHERE_R_ABORT_UNLESS(this->Operate(updater.GetPageList(), cur_address, cur_pages, pg_phys_addr, true, prev_properties, OperationType_Map, true));
/* Advance. */
cur_address += cur_pages * PageSize;
map_pages -= cur_pages;
pg_phys_addr += cur_pages * PageSize;
pg_pages -= cur_pages;
}
}
/* Check if we're done. */
if (last_map_address <= info.GetLastAddress()) {
break;
}
/* Advance. */
++it;
}
}
};
/* Iterate over the memory, unmapping as we go. */
auto it = m_memory_block_manager.FindIterator(cur_address);
@@ -4535,7 +4521,7 @@ namespace ams::kern {
const size_t cur_pages = std::min(KProcessAddress(info.GetEndAddress()) - cur_address, last_address + 1 - cur_address) / PageSize;
/* Unmap. */
MESOSPHERE_R_ABORT_UNLESS(this->Operate(updater.GetPageList(), cur_address, cur_pages, Null<KPhysicalAddress>, false, unmap_properties, OperationType_Unmap, false));
R_TRY(this->Operate(updater.GetPageList(), cur_address, cur_pages, Null<KPhysicalAddress>, false, unmap_properties, OperationType_Unmap, false));
}
/* Check if we're done. */

View File

@@ -117,19 +117,34 @@ namespace ams::kern {
this->DeleteThreadLocalRegion(m_plr_address);
/* Get the used memory size. */
const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize();
const size_t used_memory_size = this->GetUsedUserPhysicalMemorySize();
/* Finalize the page table. */
m_page_table.Finalize();
/* Finish using our system resource. */
{
if (m_system_resource->IsSecureResource()) {
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
}
/* Free the system resource. */
if (m_system_resource_address != Null<KVirtualAddress>) {
/* Check that we have no outstanding allocations. */
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
m_system_resource->Close();
/* Free the memory. */
KSystemControl::FreeSecureMemory(m_system_resource_address, m_system_resource_num_pages * PageSize, m_memory_pool);
/* Clear our tracking variables. */
m_system_resource_address = Null<KVirtualAddress>;
m_system_resource_num_pages = 0;
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
}
/* Release memory to the resource limit. */
if (m_resource_limit != nullptr) {
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
m_resource_limit->Close();
}
/* Free all shared memory infos. */
@@ -164,13 +179,6 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(m_partially_used_tlp_tree.empty());
MESOSPHERE_ABORT_UNLESS(m_fully_used_tlp_tree.empty());
/* Release memory to the resource limit. */
if (m_resource_limit != nullptr) {
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
m_resource_limit->Close();
}
/* Log that we finalized for debug. */
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", m_process_id, m_name);
@@ -259,18 +267,13 @@ namespace ams::kern {
MESOSPHERE_ASSERT(res_limit != nullptr);
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
/* Determine is application. */
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
/* Set members. */
m_memory_pool = pool;
m_resource_limit = res_limit;
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
m_system_resource_address = Null<KVirtualAddress>;
m_system_resource_num_pages = 0;
m_is_immortal = immortal;
/* Open reference to our system resource. */
m_system_resource->Open();
/* Setup page table. */
/* NOTE: Nintendo passes process ID despite not having set it yet. */
/* This goes completely unused, but even so... */
@@ -278,7 +281,11 @@ namespace ams::kern {
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit));
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
auto *mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
auto *block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
auto *pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, mem_block_manager, block_info_manager, pt_manager, res_limit));
}
ON_RESULT_FAILURE { m_page_table.Finalize(); };
@@ -321,35 +328,64 @@ namespace ams::kern {
const size_t code_size = code_num_pages * PageSize;
const size_t system_resource_size = system_resource_num_pages * PageSize;
/* Reserve memory for our code resource. */
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size);
/* Reserve memory for the system resource. */
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size + KSystemControl::CalculateRequiredSecureMemorySize(system_resource_size, pool));
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
/* Setup our system resource. */
/* Setup page table resource objects. */
KMemoryBlockSlabManager *mem_block_manager;
KBlockInfoManager *block_info_manager;
KPageTableManager *pt_manager;
m_system_resource_address = Null<KVirtualAddress>;
m_system_resource_num_pages = 0;
if (system_resource_num_pages != 0) {
/* Create a secure system resource. */
KSecureSystemResource *secure_resource = KSecureSystemResource::Create();
R_UNLESS(secure_resource != nullptr, svc::ResultOutOfResource());
/* Allocate secure memory. */
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_system_resource_address), system_resource_size, pool));
ON_RESULT_FAILURE { secure_resource->Close(); };
/* Set the number of system resource pages. */
MESOSPHERE_ASSERT(m_system_resource_address != Null<KVirtualAddress>);
m_system_resource_num_pages = system_resource_num_pages;
/* Initialize the secure resource. */
R_TRY(secure_resource->Initialize(system_resource_size, m_resource_limit, m_memory_pool));
/* Initialize slab heaps. */
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(system_resource_size), PageSize);
m_dynamic_page_manager.Initialize(m_system_resource_address + rc_size, system_resource_size - rc_size);
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_system_resource_address));
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
/* Set our system resource. */
m_system_resource = secure_resource;
/* Initialize managers. */
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
mem_block_manager = std::addressof(m_memory_block_slab_manager);
block_info_manager = std::addressof(m_block_info_manager);
pt_manager = std::addressof(m_page_table_manager);
} else {
/* Use the system-wide system resource. */
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
/* Open reference to the system resource. */
m_system_resource->Open();
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
}
/* Ensure we clean up our secure resource, if we fail. */
ON_RESULT_FAILURE { m_system_resource->Close(); };
/* Ensure we don't leak any secure memory we allocated. */
ON_RESULT_FAILURE {
if (m_system_resource_address != Null<KVirtualAddress>) {
/* Check that we have no outstanding allocations. */
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
/* Free the memory. */
KSystemControl::FreeSecureMemory(m_system_resource_address, system_resource_size, pool);
/* Clear our tracking variables. */
m_system_resource_address = Null<KVirtualAddress>;
m_system_resource_num_pages = 0;
}
};
/* Setup page table. */
/* NOTE: Nintendo passes process ID despite not having set it yet. */
@@ -358,7 +394,7 @@ namespace ams::kern {
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, m_system_resource, res_limit));
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, mem_block_manager, block_info_manager, pt_manager, res_limit));
}
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
@@ -377,7 +413,7 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
/* If we should optimize memory allocations, do so. */
if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
if (m_system_resource_address != Null<KVirtualAddress> && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
}
@@ -425,7 +461,7 @@ namespace ams::kern {
if (!m_is_immortal) {
/* Release resource limit hint. */
if (m_resource_limit != nullptr) {
m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize();
m_memory_release_hint = this->GetUsedUserPhysicalMemorySize();
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
}
@@ -844,7 +880,7 @@ namespace ams::kern {
size_t KProcess::GetUsedUserPhysicalMemorySize() const {
const size_t norm_size = m_page_table.GetNormalMemorySize();
const size_t other_size = m_code_size + m_main_thread_stack_size;
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
return norm_size + other_size + sec_size;
}
@@ -873,7 +909,7 @@ namespace ams::kern {
/* Get the amount of free and used size. */
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
const size_t used_size = this->GetUsedUserPhysicalMemorySize();
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
const size_t max_size = m_max_process_memory;
if (used_size + free_size > max_size) {

View File

@@ -88,10 +88,6 @@ namespace ams::kern {
return m_recv_list_count > ipc::MessageBuffer::MessageHeader::ReceiveListCountType_CountOffset;
}
constexpr ALWAYS_INLINE bool IsToMessageBuffer() const {
return m_recv_list_count == ipc::MessageBuffer::MessageHeader::ReceiveListCountType_ToMessageBuffer;
}
void GetBuffer(uintptr_t &out, size_t size, int &key) const {
switch (m_recv_list_count) {
case ipc::MessageBuffer::MessageHeader::ReceiveListCountType_None:
@@ -268,12 +264,12 @@ namespace ams::kern {
static_cast<KMemoryPermission>(KMemoryPermission_NotMapped | KMemoryPermission_KernelReadWrite),
KMemoryAttribute_Uncached | KMemoryAttribute_Locked, KMemoryAttribute_Locked,
src_pointer,
KMemoryState_FlagLinearMapped, KMemoryState_FlagLinearMapped,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
KMemoryPermission_UserRead,
KMemoryAttribute_Uncached, KMemoryAttribute_None));
} else {
R_TRY(src_page_table.CopyMemoryFromLinearToUser(recv_pointer, recv_size, src_pointer,
KMemoryState_FlagLinearMapped, KMemoryState_FlagLinearMapped,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
KMemoryPermission_UserRead,
KMemoryAttribute_Uncached, KMemoryAttribute_None));
}
@@ -646,15 +642,12 @@ namespace ams::kern {
const size_t max_fast_size = std::min<size_t>(offset_words + raw_size, PageSize);
const size_t fast_size = max_fast_size - offset_words;
/* Determine source state; if user buffer, we require heap, and otherwise only linear mapped (to enable tls use). */
const auto src_state = src_user ? KMemoryState_FlagReferenceCounted : KMemoryState_FlagLinearMapped;
/* Determine the source permission. User buffer should be unmapped + read, TLS should be user readable. */
const KMemoryPermission src_perm = static_cast<KMemoryPermission>(src_user ? KMemoryPermission_NotMapped | KMemoryPermission_KernelRead : KMemoryPermission_UserRead);
/* Perform the fast part of the copy. */
R_TRY(src_page_table.CopyMemoryFromLinearToKernel(reinterpret_cast<uintptr_t>(dst_msg_ptr) + offset_words, fast_size, src_message_buffer + offset_words,
src_state, src_state,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
src_perm,
KMemoryAttribute_Uncached, KMemoryAttribute_None));
@@ -665,7 +658,7 @@ namespace ams::kern {
static_cast<KMemoryPermission>(KMemoryPermission_NotMapped | KMemoryPermission_KernelReadWrite),
KMemoryAttribute_Uncached | KMemoryAttribute_Locked, KMemoryAttribute_Locked,
src_message_buffer + max_fast_size,
src_state, src_state,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
src_perm,
KMemoryAttribute_Uncached, KMemoryAttribute_None));
}
@@ -751,11 +744,9 @@ namespace ams::kern {
R_UNLESS(recv_pointer != 0, svc::ResultOutOfResource());
/* Perform the pointer data copy. */
const bool dst_heap = dst_user && dst_recv_list.IsToMessageBuffer();
const auto dst_state = dst_heap ? KMemoryState_FlagReferenceCounted : KMemoryState_FlagLinearMapped;
const KMemoryPermission dst_perm = static_cast<KMemoryPermission>(dst_heap ? KMemoryPermission_NotMapped | KMemoryPermission_KernelReadWrite : KMemoryPermission_UserReadWrite);
const KMemoryPermission dst_perm = static_cast<KMemoryPermission>(dst_user ? KMemoryPermission_NotMapped | KMemoryPermission_KernelReadWrite : KMemoryPermission_UserReadWrite);
R_TRY(dst_page_table.CopyMemoryFromUserToLinear(recv_pointer, recv_size,
dst_state, dst_state,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
dst_perm,
KMemoryAttribute_Uncached, KMemoryAttribute_None,
src_pointer));
@@ -907,15 +898,12 @@ namespace ams::kern {
const size_t max_fast_size = std::min<size_t>(offset_words + raw_size, PageSize);
const size_t fast_size = max_fast_size - offset_words;
/* Determine dst state; if user buffer, we require heap, and otherwise only linear mapped (to enable tls use). */
const auto dst_state = dst_user ? KMemoryState_FlagReferenceCounted : KMemoryState_FlagLinearMapped;
/* Determine the dst permission. User buffer should be unmapped + read, TLS should be user readable. */
const KMemoryPermission dst_perm = static_cast<KMemoryPermission>(dst_user ? KMemoryPermission_NotMapped | KMemoryPermission_KernelReadWrite : KMemoryPermission_UserReadWrite);
/* Perform the fast part of the copy. */
R_TRY(dst_page_table.CopyMemoryFromKernelToLinear(dst_message_buffer + offset_words, fast_size,
dst_state, dst_state,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
dst_perm,
KMemoryAttribute_Uncached, KMemoryAttribute_None,
reinterpret_cast<uintptr_t>(src_msg_ptr) + offset_words));
@@ -923,7 +911,7 @@ namespace ams::kern {
/* If the fast part of the copy didn't get everything, perform the slow part of the copy. */
if (fast_size < raw_size) {
R_TRY(dst_page_table.CopyMemoryFromHeapToHeap(dst_page_table, dst_message_buffer + max_fast_size, raw_size - fast_size,
dst_state, dst_state,
KMemoryState_FlagReferenceCounted, KMemoryState_FlagReferenceCounted,
dst_perm,
KMemoryAttribute_Uncached, KMemoryAttribute_None,
src_message_buffer + max_fast_size,

View File

@@ -19,20 +19,22 @@ namespace ams::kern {
Result KSessionRequest::SessionMappings::PushMap(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state, size_t index) {
/* At most 15 buffers of each type (4-bit descriptor counts). */
MESOSPHERE_ASSERT(index < NumMappings);
MESOSPHERE_ASSERT(index < ((1ul << 4) - 1) * 3);
/* Get the mapping. */
Mapping *mapping;
if (index < NumStaticMappings) {
mapping = std::addressof(m_static_mappings[index]);
} else {
/* Allocate dynamic mappings as necessary. */
if (m_dynamic_mappings == nullptr) {
m_dynamic_mappings = DynamicMappings::Allocate();
R_UNLESS(m_dynamic_mappings != nullptr, svc::ResultOutOfMemory());
/* Allocate a page for the extra mappings. */
if (m_mappings == nullptr) {
KPageBuffer *page_buffer = KPageBuffer::Allocate();
R_UNLESS(page_buffer != nullptr, svc::ResultOutOfMemory());
m_mappings = reinterpret_cast<Mapping *>(page_buffer);
}
mapping = std::addressof(m_dynamic_mappings->Get(index - NumStaticMappings));
mapping = std::addressof(m_mappings[index - NumStaticMappings]);
}
/* Set the mapping. */
@@ -57,9 +59,9 @@ namespace ams::kern {
}
void KSessionRequest::SessionMappings::Finalize() {
if (m_dynamic_mappings) {
DynamicMappings::Free(m_dynamic_mappings);
m_dynamic_mappings = nullptr;
if (m_mappings) {
KPageBuffer::Free(reinterpret_cast<KPageBuffer *>(m_mappings));
m_mappings = nullptr;
}
}

View File

@@ -292,13 +292,4 @@ namespace ams::kern {
Kernel::GetMemoryManager().Close(KPageTable::GetHeapPhysicalAddress(address), size / PageSize);
}
/* Insecure Memory. */
KResourceLimit *KSystemControlBase::GetInsecureMemoryResourceLimit() {
return std::addressof(Kernel::GetSystemResourceLimit());
}
u32 KSystemControlBase::GetInsecureMemoryPool() {
return KMemoryManager::Pool_SystemNonSecure;
}
}

View File

@@ -1,90 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
Result KSecureSystemResource::Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool) {
/* Set members. */
m_resource_limit = resource_limit;
m_resource_size = size;
m_resource_pool = pool;
/* Determine required size for our secure resource. */
const size_t secure_size = this->CalculateRequiredSecureMemorySize();
/* Reserve memory for our secure resource. */
KScopedResourceReservation memory_reservation(m_resource_limit, ams::svc::LimitableResource_PhysicalMemoryMax, secure_size);
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
/* Allocate secure memory. */
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_resource_address), m_resource_size, m_resource_pool));
MESOSPHERE_ASSERT(m_resource_address != Null<KVirtualAddress>);
/* Ensure we clean up the secure memory, if we fail past this point. */
ON_RESULT_FAILURE { KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool); };
/* Check that our allocation is bigger than the reference counts needed for it. */
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
R_UNLESS(m_resource_size > rc_size, svc::ResultOutOfMemory());
/* Initialize slab heaps. */
m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, PageSize);
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_resource_address));
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
/* Initialize managers. */
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
/* Set our managers. */
this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
/* Commit the memory reservation. */
memory_reservation.Commit();
/* Open reference to our resource limit. */
m_resource_limit->Open();
/* Set ourselves as initialized. */
m_is_initialized = true;
R_SUCCEED();
}
void KSecureSystemResource::Finalize() {
/* Check that we have no outstanding allocations. */
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
/* Free our secure memory. */
KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool);
/* Release the memory reservation. */
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize());
/* Close reference to our resource limit. */
m_resource_limit->Close();
}
size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) {
return KSystemControl::CalculateRequiredSecureMemorySize(size, pool);
}
}

View File

@@ -46,7 +46,7 @@ namespace ams::kern {
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().UnmapPages(stack_bottom, 1, KMemoryState_Kernel));
/* Free the stack page. */
KPageBuffer::FreeChecked<PageSize>(KPageBuffer::FromPhysicalAddress(stack_paddr));
KPageBuffer::Free(KPageBuffer::FromPhysicalAddress(stack_paddr));
}
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait { /* ... */ };
@@ -334,7 +334,7 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(stack_region.GetEndAddress() != 0);
/* Allocate a page to use as the thread. */
KPageBuffer *page = KPageBuffer::AllocateChecked<PageSize>();
KPageBuffer *page = KPageBuffer::Allocate();
R_UNLESS(page != nullptr, svc::ResultOutOfResource());
/* Map the stack page. */
@@ -509,8 +509,7 @@ namespace ams::kern {
void KThread::OnLeaveUsermodeException() {
this->ClearUsermodeExceptionSvcPermissions();
/* NOTE: InUsermodeExceptionHandler will be cleared by RestoreContext. */
this->ClearInUsermodeExceptionHandler();
}
void KThread::Pin() {

View File

@@ -24,7 +24,7 @@ namespace ams::kern {
m_owner = process;
/* Allocate a new page. */
KPageBuffer *page_buf = KPageBuffer::AllocateChecked<PageSize>();
KPageBuffer *page_buf = KPageBuffer::Allocate();
R_UNLESS(page_buf != nullptr, svc::ResultOutOfMemory());
ON_RESULT_FAILURE { KPageBuffer::Free(page_buf); };
@@ -43,7 +43,7 @@ namespace ams::kern {
R_TRY(m_owner->GetPageTable().UnmapPages(this->GetAddress(), 1, KMemoryState_ThreadLocal));
/* Free the page. */
KPageBuffer::FreeChecked<PageSize>(KPageBuffer::FromPhysicalAddress(phys_addr));
KPageBuffer::Free(KPageBuffer::FromPhysicalAddress(phys_addr));
R_SUCCEED();
}

View File

@@ -75,10 +75,7 @@ namespace ams::kern {
size -= rc_size;
/* Initialize the resource managers' shared page manager. */
g_resource_manager_page_manager.Initialize(address, size, std::max<size_t>(PageSize, KPageBufferSlabHeap::BufferSize));
/* Initialize the KPageBuffer slab heap. */
KPageBuffer::InitializeSlabHeap(g_resource_manager_page_manager);
g_resource_manager_page_manager.Initialize(address, size);
/* Initialize the fixed-size slabheaps. */
s_app_memory_block_heap.Initialize(std::addressof(g_resource_manager_page_manager), ApplicationMemoryBlockSlabHeapSize);
@@ -103,14 +100,6 @@ namespace ams::kern {
/* Check that we have the correct number of dynamic pages available. */
MESOSPHERE_ABORT_UNLESS(g_resource_manager_page_manager.GetCount() - g_resource_manager_page_manager.GetUsed() == ReservedDynamicPageCount);
/* Create the system page table managers. */
KAutoObject::Create<KSystemResource>(std::addressof(s_app_system_resource));
KAutoObject::Create<KSystemResource>(std::addressof(s_sys_system_resource));
/* Set the managers for the system resources. */
s_app_system_resource.SetManagers(s_app_memory_block_manager, s_app_block_info_manager, s_app_page_table_manager);
s_sys_system_resource.SetManagers(s_sys_memory_block_manager, s_sys_block_info_manager, s_sys_page_table_manager);
}
void Kernel::PrintLayout() {
@@ -146,9 +135,6 @@ namespace ams::kern {
PrintMemoryRegion(" KernelRegion", KMemoryLayout::GetKernelRegionPhysicalExtents());
PrintMemoryRegion(" Code", KMemoryLayout::GetKernelCodeRegionPhysicalExtents());
PrintMemoryRegion(" Slab", KMemoryLayout::GetKernelSlabRegionPhysicalExtents());
if constexpr (KSystemControl::SecureAppletMemorySize > 0) {
PrintMemoryRegion(" SecureApplet", KMemoryLayout::GetKernelSecureAppletMemoryRegionPhysicalExtents());
}
PrintMemoryRegion(" PageTableHeap", KMemoryLayout::GetKernelPageTableHeapRegionPhysicalExtents());
PrintMemoryRegion(" InitPageTable", KMemoryLayout::GetKernelInitPageTableRegionPhysicalExtents());
if constexpr (IsKTraceEnabled) {

View File

@@ -58,6 +58,7 @@ namespace ams::kern {
MESOSPHERE_ABORT_UNLESS(management_region.GetEndAddress() != 0);
Kernel::GetMemoryManager().Initialize(management_region.GetAddress(), management_region.GetSize());
init::InitializeKPageBufferSlabHeap();
}
/* Copy the Initial Process Binary to safe memory. */

View File

@@ -80,12 +80,7 @@ namespace ams::kern::svc {
}
}
Result MapDeviceAddressSpaceByForce(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, u32 option) {
/* Decode the option. */
const util::BitPack32 option_pack = { option };
const auto device_perm = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Permission>();
const auto reserved = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Reserved>();
Result MapDeviceAddressSpaceByForce(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
/* Validate input. */
R_UNLESS(util::IsAligned(process_address, PageSize), svc::ResultInvalidAddress());
R_UNLESS(util::IsAligned(device_address, PageSize), svc::ResultInvalidAddress());
@@ -95,7 +90,6 @@ namespace ams::kern::svc {
R_UNLESS((device_address < device_address + size), svc::ResultInvalidMemoryRegion());
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), svc::ResultInvalidNewMemoryPermission());
R_UNLESS(reserved == 0, svc::ResultInvalidEnumValue());
/* Get the device address space. */
KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
@@ -110,15 +104,10 @@ namespace ams::kern::svc {
R_UNLESS(page_table.Contains(process_address, size), svc::ResultInvalidCurrentMemory());
/* Map. */
R_RETURN(das->MapByForce(std::addressof(page_table), KProcessAddress(process_address), size, device_address, option));
R_RETURN(das->MapByForce(std::addressof(page_table), KProcessAddress(process_address), size, device_address, device_perm));
}
Result MapDeviceAddressSpaceAligned(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, u32 option) {
/* Decode the option. */
const util::BitPack32 option_pack = { option };
const auto device_perm = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Permission>();
const auto reserved = option_pack.Get<ams::svc::MapDeviceAddressSpaceOption::Reserved>();
Result MapDeviceAddressSpaceAligned(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
/* Validate input. */
R_UNLESS(util::IsAligned(process_address, PageSize), svc::ResultInvalidAddress());
R_UNLESS(util::IsAligned(device_address, PageSize), svc::ResultInvalidAddress());
@@ -129,7 +118,6 @@ namespace ams::kern::svc {
R_UNLESS((device_address < device_address + size), svc::ResultInvalidMemoryRegion());
R_UNLESS((process_address == static_cast<uintptr_t>(process_address)), svc::ResultInvalidCurrentMemory());
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), svc::ResultInvalidNewMemoryPermission());
R_UNLESS(reserved == 0, svc::ResultInvalidEnumValue());
/* Get the device address space. */
KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject<KDeviceAddressSpace>(das_handle);
@@ -144,7 +132,7 @@ namespace ams::kern::svc {
R_UNLESS(page_table.Contains(process_address, size), svc::ResultInvalidCurrentMemory());
/* Map. */
R_RETURN(das->MapAligned(std::addressof(page_table), KProcessAddress(process_address), size, device_address, option));
R_RETURN(das->MapAligned(std::addressof(page_table), KProcessAddress(process_address), size, device_address, device_perm));
}
Result UnmapDeviceAddressSpace(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address) {
@@ -188,12 +176,12 @@ namespace ams::kern::svc {
R_RETURN(DetachDeviceAddressSpace(device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(das_handle, process_handle, process_address, size, device_address, option));
Result MapDeviceAddressSpaceByForce64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(MapDeviceAddressSpaceByForce(das_handle, process_handle, process_address, size, device_address, device_perm));
}
Result MapDeviceAddressSpaceAligned64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, option));
Result MapDeviceAddressSpaceAligned64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, device_perm));
}
Result UnmapDeviceAddressSpace64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address) {
@@ -214,12 +202,12 @@ namespace ams::kern::svc {
R_RETURN(DetachDeviceAddressSpace(device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(das_handle, process_handle, process_address, size, device_address, option));
Result MapDeviceAddressSpaceByForce64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(MapDeviceAddressSpaceByForce(das_handle, process_handle, process_address, size, device_address, device_perm));
}
Result MapDeviceAddressSpaceAligned64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, option));
Result MapDeviceAddressSpaceAligned64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) {
R_RETURN(MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, device_perm));
}
Result UnmapDeviceAddressSpace64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address) {

View File

@@ -1,76 +0,0 @@
/*
* Copyright (c) Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern::svc {
/* ============================= Common ============================= */
namespace {
Result MapInsecureMemory(uintptr_t address, size_t size) {
/* Validate the address/size. */
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
R_UNLESS(size > 0, svc::ResultInvalidSize());
R_UNLESS(util::IsAligned(address, PageSize), svc::ResultInvalidAddress());
R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory());
/* Verify that the mapping is in range. */
auto &pt = GetCurrentProcess().GetPageTable();
R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Insecure), svc::ResultInvalidMemoryRegion());
/* Map the insecure memory. */
R_RETURN(pt.MapInsecureMemory(address, size));
}
Result UnmapInsecureMemory(uintptr_t address, size_t size) {
/* Validate the address/size. */
R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize());
R_UNLESS(size > 0, svc::ResultInvalidSize());
R_UNLESS(util::IsAligned(address, PageSize), svc::ResultInvalidAddress());
R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory());
/* Verify that the mapping is in range. */
auto &pt = GetCurrentProcess().GetPageTable();
R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Insecure), svc::ResultInvalidMemoryRegion());
/* Map the insecure memory. */
R_RETURN(pt.UnmapInsecureMemory(address, size));
}
}
/* ============================= 64 ABI ============================= */
Result MapInsecureMemory64(ams::svc::Address address, ams::svc::Size size) {
R_RETURN(MapInsecureMemory(address, size));
}
Result UnmapInsecureMemory64(ams::svc::Address address, ams::svc::Size size) {
R_RETURN(UnmapInsecureMemory(address, size));
}
/* ============================= 64From32 ABI ============================= */
Result MapInsecureMemory64From32(ams::svc::Address address, ams::svc::Size size) {
R_RETURN(MapInsecureMemory(address, size));
}
Result UnmapInsecureMemory64From32(ams::svc::Address address, ams::svc::Size size) {
R_RETURN(UnmapInsecureMemory(address, size));
}
}

View File

@@ -55,7 +55,7 @@ namespace ams::ddsf {
/* Attach the session. */
m_session_list.push_back(*session);
R_SUCCEED();
return ResultSuccess();
}
void DetachSession(ISession *session) {
@@ -113,12 +113,12 @@ namespace ams::ddsf {
template<typename F>
Result ForEachSession(F f, bool return_on_fail) {
R_RETURN(impl::ForEach(m_session_list_lock, m_session_list, f, return_on_fail));
return impl::ForEach(m_session_list_lock, m_session_list, f, return_on_fail);
}
template<typename F>
Result ForEachSession(F f, bool return_on_fail) const {
R_RETURN(impl::ForEach(m_session_list_lock, m_session_list, f, return_on_fail));
return impl::ForEach(m_session_list_lock, m_session_list, f, return_on_fail);
}
template<typename F>

View File

@@ -76,12 +76,12 @@ namespace ams::ddsf {
template<typename F>
Result ForEachDevice(F f, bool return_on_fail) {
R_RETURN(impl::ForEach(m_device_list_lock, m_device_list, f, return_on_fail));
return impl::ForEach(m_device_list_lock, m_device_list, f, return_on_fail);
}
template<typename F>
Result ForEachDevice(F f, bool return_on_fail) const {
R_RETURN(impl::ForEach(m_device_list_lock, m_device_list, f, return_on_fail));
return impl::ForEach(m_device_list_lock, m_device_list, f, return_on_fail);
}
template<typename F>

View File

@@ -26,13 +26,13 @@ namespace ams::ddsf::impl {
for (auto && it : list) {
if (const auto cur_result = f(std::addressof(it)); R_FAILED(cur_result)) {
if (return_on_fail) {
R_RETURN(cur_result);
return cur_result;
} else if (R_SUCCEEDED(result)) {
result = cur_result;
}
}
}
R_RETURN(result);
return result;
}
template<typename List, typename F, typename Lock>

View File

@@ -832,12 +832,4 @@
HANDLER(FatFsBisUserDirectoryPeakOpenCount, 653, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsSdCardFilePeakOpenCount, 654, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsSdCardDirectoryPeakOpenCount, 655, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(SslAlertInfo, 656, NetworkSecurityCertificateInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(SslVersionInfo, 657, NetworkSecurityCertificateInfo, FieldType_U8Array, FieldFlag_None ) \
HANDLER(FatFsBisSystemUniqueFileEntryPeakOpenCount, 658, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsBisSystemUniqueDirectoryEntryPeakOpenCount, 659, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsBisUserUniqueFileEntryPeakOpenCount, 660, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsBisUserUniqueDirectoryEntryPeakOpenCount, 661, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsSdCardUniqueFileEntryPeakOpenCount, 662, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \
HANDLER(FatFsSdCardUniqueDirectoryEntryPeakOpenCount, 663, FsProxyErrorInfo, FieldType_NumericU16, FieldFlag_None ) \

View File

@@ -30,6 +30,7 @@
#include <stratosphere/fs/fsa/fs_registrar.hpp>
#include <stratosphere/fs/fs_remote_filesystem.hpp>
#include <stratosphere/fs/fs_read_only_filesystem.hpp>
#include <stratosphere/fs/fs_shared_filesystem_holder.hpp>
#include <stratosphere/fs/fs_istorage.hpp>
#include <stratosphere/fs/fs_i_event_notifier.hpp>
#include <stratosphere/fs/fs_substorage.hpp>
@@ -65,5 +66,4 @@
#include <stratosphere/fs/fs_program_index_map_info.hpp>
#include <stratosphere/fs/impl/fs_access_log_impl.hpp>
#include <stratosphere/fs/impl/fs_hash_generator_factory_selector.hpp>
#include <stratosphere/fs/impl/fs_storage_service_object_adapter.hpp>
#include <stratosphere/fs/fs_api.hpp>

View File

@@ -20,11 +20,9 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
class HierarchicalRomFileTable {
public:
using Position = u32;
using StorageSizeType = u32;
using Position = u32;
struct FindPosition {
Position next_dir;
@@ -32,7 +30,8 @@ namespace ams::fs {
};
static_assert(util::is_pod<FindPosition>::value);
using FileInfo = RomFileInfo;
using DirectoryInfo = RomDirectoryInfo;
using FileInfo = RomFileInfo;
static constexpr RomFileId PositionToFileId(Position pos) {
return static_cast<RomFileId>(pos);
@@ -81,23 +80,23 @@ namespace ams::fs {
using Base = KeyValueRomStorageTemplate<ImplKeyType, ValueType, MaxKeyLength>;
public:
Result Add(Position *out, const ClientKeyType &key, const Value &value) {
R_RETURN(Base::AddInternal(out, key.key, key.Hash(), key.name.begin(), key.name.length(), value));
return Base::AddInternal(out, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar), value);
}
Result Get(Position *out_pos, Value *out_val, const ClientKeyType &key) {
R_RETURN(Base::GetInternal(out_pos, out_val, key.key, key.Hash(), key.name.begin(), key.name.length()));
return Base::GetInternal(out_pos, out_val, key.key, key.Hash(), key.name.path, key.name.length * sizeof(RomPathChar));
}
Result GetByPosition(ImplKey *out_key, Value *out_val, Position pos) {
R_RETURN(Base::GetByPosition(out_key, out_val, pos));
return Base::GetByPosition(out_key, out_val, pos);
}
Result GetByPosition(ImplKey *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
R_RETURN(Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos));
return Base::GetByPosition(out_key, out_val, out_aux, out_aux_size, pos);
}
Result SetByPosition(Position pos, const Value &value) {
R_RETURN(Base::SetByPosition(pos, value));
return Base::SetByPosition(pos, value);
}
};
@@ -122,15 +121,16 @@ namespace ams::fs {
constexpr u32 Hash() const {
u32 hash = this->key.parent ^ 123456789;
const RomPathChar * cur = this->name.begin();
const RomPathChar * const end = this->name.end();
while (cur < end) {
const u32 c = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(cur++)));
hash = ((hash >> 5) | (hash << 27)) ^ c;
const RomPathChar * name = this->name.path;
const RomPathChar * const end = name + this->name.length;
while (name < end) {
const u32 cur = static_cast<u32>(static_cast<std::make_unsigned<RomPathChar>::type>(*(name++)));
hash = ((hash >> 5) | (hash << 27)) ^ cur;
}
return hash;
}
};
static_assert(util::is_pod<EntryKey>::value);
using DirectoryEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomDirectoryEntry>;
using FileEntryMapTable = EntryMapTable<RomEntryKey, EntryKey, RomFileEntry>;
@@ -138,24 +138,35 @@ namespace ams::fs {
DirectoryEntryMapTable m_dir_table;
FileEntryMapTable m_file_table;
public:
static s64 QueryDirectoryEntryBucketStorageSize(StorageSizeType count);
static s64 QueryDirectoryEntrySize(StorageSizeType aux_size);
static s64 QueryFileEntryBucketStorageSize(StorageSizeType count);
static s64 QueryFileEntrySize(StorageSizeType aux_size);
static s64 QueryDirectoryEntryBucketStorageSize(s64 count);
static size_t QueryDirectoryEntrySize(size_t aux_size);
static s64 QueryFileEntryBucketStorageSize(s64 count);
static size_t QueryFileEntrySize(size_t aux_size);
static Result Format(SubStorage dir_bucket, SubStorage file_bucket);
public:
HierarchicalRomFileTable();
constexpr u32 GetDirectoryEntryCount() const {
return m_dir_table.GetEntryCount();
}
constexpr u32 GetFileEntryCount() const {
return m_file_table.GetEntryCount();
}
Result Initialize(SubStorage dir_bucket, SubStorage dir_entry, SubStorage file_bucket, SubStorage file_entry);
void Finalize();
Result CreateRootDirectory();
Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path);
Result CreateDirectory(RomDirectoryId *out, const RomPathChar *path, const DirectoryInfo &info);
Result CreateFile(RomFileId *out, const RomPathChar *path, const FileInfo &info);
Result ConvertPathToDirectoryId(RomDirectoryId *out, const RomPathChar *path);
Result ConvertPathToFileId(RomFileId *out, const RomPathChar *path);
Result GetDirectoryInformation(DirectoryInfo *out, const RomPathChar *path);
Result GetDirectoryInformation(DirectoryInfo *out, RomDirectoryId id);
Result OpenFile(FileInfo *out, const RomPathChar *path);
Result OpenFile(FileInfo *out, RomFileId id);
@@ -167,7 +178,7 @@ namespace ams::fs {
Result QueryRomFileSystemSize(s64 *out_dir_entry_size, s64 *out_file_entry_size);
private:
Result GetParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path);
Result GetGrandParent(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, Position pos, RomPathTool::RomEntryName name, const RomPathChar *path);
Result FindParentDirectoryRecursive(Position *out_pos, EntryKey *out_dir_key, RomDirectoryEntry *out_dir_entry, RomPathTool::PathParser *parser, const RomPathChar *path);
@@ -183,6 +194,8 @@ namespace ams::fs {
Result GetFileEntry(Position *out_pos, RomFileEntry *out_entry, const EntryKey &key);
Result GetFileEntry(RomFileEntry *out_entry, RomFileId id);
Result GetDirectoryInformation(DirectoryInfo *out, const EntryKey &key);
Result OpenFile(FileInfo *out, const EntryKey &key);
Result FindOpen(FindPosition *out, const EntryKey &key);

View File

@@ -19,7 +19,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
template<typename KeyType, typename ValueType, size_t MaxAuxiliarySize>
class KeyValueRomStorageTemplate {
public:
@@ -28,8 +27,6 @@ namespace ams::fs {
using Position = u32;
using BucketIndex = s64;
using StorageSizeType = u32;
struct FindIndex {
BucketIndex ind;
Position pos;
@@ -42,7 +39,7 @@ namespace ams::fs {
Key key;
Value value;
Position next;
StorageSizeType size;
u32 size;
};
static_assert(util::is_pod<Element>::value);
private:
@@ -56,41 +53,53 @@ namespace ams::fs {
return num * sizeof(Position);
}
static constexpr s64 QueryBucketCount(StorageSizeType size) {
static constexpr s64 QueryBucketCount(s64 size) {
return size / sizeof(Position);
}
static constexpr size_t QueryEntrySize(StorageSizeType aux_size) {
return util::AlignUp<size_t>(sizeof(Element) + aux_size, alignof(Element));
static constexpr size_t QueryEntrySize(size_t aux_size) {
return util::AlignUp(sizeof(Element) + aux_size, alignof(Element));
}
static Result Format(SubStorage bucket, StorageSizeType count) {
static Result Format(SubStorage bucket, s64 count) {
const Position pos = InvalidPosition;
for (auto i = 0u; i < count; i++) {
for (s64 i = 0; i < count; i++) {
R_TRY(bucket.Write(i * sizeof(pos), std::addressof(pos), sizeof(pos)));
}
R_SUCCEED();
return ResultSuccess();
}
public:
constexpr KeyValueRomStorageTemplate() : m_bucket_count(), m_bucket_storage(), m_kv_storage(), m_total_entry_size(), m_entry_count() { /* ... */ }
KeyValueRomStorageTemplate() : m_bucket_count(), m_bucket_storage(), m_kv_storage(), m_total_entry_size(), m_entry_count() { /* ... */ }
Result Initialize(const SubStorage &bucket, s64 count, const SubStorage &kv) {
AMS_ASSERT(count > 0);
m_bucket_storage = bucket;
m_bucket_count = count;
m_kv_storage = kv;
R_SUCCEED();
return ResultSuccess();
}
void Finalize() {
m_bucket_storage = SubStorage();
m_bucket_count = 0;
m_kv_storage = SubStorage();
m_bucket_count = 0;
}
s64 GetTotalEntrySize() const {
return m_total_entry_size;
}
Result GetFreeSize(s64 *out) {
AMS_ASSERT(out != nullptr);
s64 kv_size = 0;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
*out = kv_size - m_total_entry_size;
return ResultSuccess();
}
constexpr u32 GetEntryCount() const {
return m_entry_count;
}
protected:
Result AddInternal(Position *out, const Key &key, u32 hash_key, const void *aux, size_t aux_size, const Value &value) {
AMS_ASSERT(out != nullptr);
@@ -107,18 +116,18 @@ namespace ams::fs {
}
Position pos;
R_TRY(this->AllocateEntry(std::addressof(pos), static_cast<StorageSizeType>(aux_size)));
R_TRY(this->AllocateEntry(std::addressof(pos), aux_size));
Position next_pos;
R_TRY(this->LinkEntry(std::addressof(next_pos), pos, hash_key));
const Element elem = { key, value, next_pos, static_cast<StorageSizeType>(aux_size) };
const Element elem = { key, value, next_pos, static_cast<u32>(aux_size) };
R_TRY(this->WriteKeyValue(std::addressof(elem), pos, aux, aux_size));
*out = pos;
m_entry_count++;
R_SUCCEED();
return ResultSuccess();
}
Result GetInternal(Position *out_pos, Value *out_val, const Key &key, u32 hash_key, const void *aux, size_t aux_size) {
@@ -132,7 +141,7 @@ namespace ams::fs {
*out_pos = pos;
*out_val = elem.value;
R_SUCCEED();
return ResultSuccess();
}
Result GetByPosition(Key *out_key, Value *out_val, Position pos) {
@@ -144,7 +153,7 @@ namespace ams::fs {
*out_key = elem.key;
*out_val = elem.value;
R_SUCCEED();
return ResultSuccess();
}
Result GetByPosition(Key *out_key, Value *out_val, void *out_aux, size_t *out_aux_size, Position pos) {
@@ -158,14 +167,14 @@ namespace ams::fs {
*out_key = elem.key;
*out_val = elem.value;
R_SUCCEED();
return ResultSuccess();
}
Result SetByPosition(Position pos, const Value &value) {
Element elem;
R_TRY(this->ReadKeyValue(std::addressof(elem), pos));
elem.value = value;
R_RETURN(this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0));
return this->WriteKeyValue(std::addressof(elem), pos, nullptr, 0);
}
private:
BucketIndex HashToBucket(u32 hash_key) const {
@@ -193,16 +202,17 @@ namespace ams::fs {
R_UNLESS(cur != InvalidPosition, fs::ResultDbmKeyNotFound());
auto buf = ::ams::fs::impl::MakeUnique<u8[]>(MaxAuxiliarySize);
R_UNLESS(buf != nullptr, fs::ResultAllocationMemoryFailedMakeUnique());
u8 *buf = static_cast<u8 *>(::ams::fs::impl::Allocate(MaxAuxiliarySize));
R_UNLESS(buf != nullptr, fs::ResultAllocationMemoryFailedInDbmRomKeyValueStorage());
ON_SCOPE_EXIT { ::ams::fs::impl::Deallocate(buf, MaxAuxiliarySize); };
while (true) {
size_t cur_aux_size;
R_TRY(this->ReadKeyValue(out_elem, buf.get(), std::addressof(cur_aux_size), cur));
R_TRY(this->ReadKeyValue(out_elem, buf, std::addressof(cur_aux_size), cur));
if (key.IsEqual(out_elem->key, aux, aux_size, buf.get(), cur_aux_size)) {
if (key.IsEqual(out_elem->key, aux, aux_size, buf, cur_aux_size)) {
*out_pos = cur;
R_SUCCEED();
return ResultSuccess();
}
*out_prev = cur;
@@ -211,18 +221,18 @@ namespace ams::fs {
}
}
Result AllocateEntry(Position *out, StorageSizeType aux_size) {
Result AllocateEntry(Position *out, size_t aux_size) {
AMS_ASSERT(out != nullptr);
s64 kv_size;
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
const size_t end_pos = m_total_entry_size + sizeof(Element) + static_cast<size_t>(aux_size);
const size_t end_pos = m_total_entry_size + sizeof(Element) + aux_size;
R_UNLESS(end_pos <= static_cast<size_t>(kv_size), fs::ResultDbmKeyFull());
*out = static_cast<Position>(m_total_entry_size);
m_total_entry_size = util::AlignUp<s64>(static_cast<s64>(end_pos), alignof(Position));
R_SUCCEED();
m_total_entry_size = util::AlignUp(static_cast<s64>(end_pos), alignof(Position));
return ResultSuccess();
}
Result LinkEntry(Position *out, Position pos, u32 hash_key) {
@@ -240,7 +250,7 @@ namespace ams::fs {
R_TRY(this->WriteBucket(pos, ind));
*out = next;
R_SUCCEED();
return ResultSuccess();
}
Result ReadBucket(Position *out, BucketIndex ind) {
@@ -248,14 +258,14 @@ namespace ams::fs {
AMS_ASSERT(ind < m_bucket_count);
const s64 offset = ind * sizeof(Position);
R_RETURN(m_bucket_storage.Read(offset, out, sizeof(*out)));
return m_bucket_storage.Read(offset, out, sizeof(*out));
}
Result WriteBucket(Position pos, BucketIndex ind) {
AMS_ASSERT(ind < m_bucket_count);
const s64 offset = ind * sizeof(Position);
R_RETURN(m_bucket_storage.Write(offset, std::addressof(pos), sizeof(pos)));
return m_bucket_storage.Write(offset, std::addressof(pos), sizeof(pos));
}
Result ReadKeyValue(Element *out, Position pos) {
@@ -265,7 +275,7 @@ namespace ams::fs {
R_TRY(m_kv_storage.GetSize(std::addressof(kv_size)));
AMS_ASSERT(pos < kv_size);
R_RETURN(m_kv_storage.Read(pos, out, sizeof(*out)));
return m_kv_storage.Read(pos, out, sizeof(*out));
}
Result ReadKeyValue(Element *out, void *out_aux, size_t *out_aux_size, Position pos) {
@@ -280,7 +290,7 @@ namespace ams::fs {
R_TRY(m_kv_storage.Read(pos + sizeof(*out), out_aux, out->size));
}
R_SUCCEED();
return ResultSuccess();
}
Result WriteKeyValue(const Element *elem, Position pos, const void *aux, size_t aux_size) {
@@ -297,7 +307,7 @@ namespace ams::fs {
R_TRY(m_kv_storage.Write(pos + sizeof(*elem), aux, aux_size));
}
R_SUCCEED();
return ResultSuccess();
}
};

View File

@@ -18,60 +18,34 @@
namespace ams::fs::RomPathTool {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
constexpr inline u32 MaxPathLength = 0x300;
constexpr ALWAYS_INLINE bool IsSeparator(RomPathChar c) {
struct RomEntryName {
size_t length;
const RomPathChar *path;
};
static_assert(util::is_pod<RomEntryName>::value);
constexpr void InitEntryName(RomEntryName *entry) {
AMS_ASSERT(entry != nullptr);
entry->length = 0;
}
constexpr inline bool IsSeparator(RomPathChar c) {
return c == RomStringTraits::DirectorySeparator;
}
constexpr ALWAYS_INLINE bool IsNullTerminator(RomPathChar c) {
constexpr inline bool IsNullTerminator(RomPathChar c) {
return c == RomStringTraits::NullTerminator;
}
constexpr ALWAYS_INLINE bool IsDot(RomPathChar c) {
constexpr inline bool IsDot(RomPathChar c) {
return c == RomStringTraits::Dot;
}
class RomEntryName {
private:
const RomPathChar *m_path;
size_t m_length;
public:
constexpr RomEntryName() : m_path(nullptr), m_length(0) {
/* ... */
}
constexpr void Initialize(const RomPathChar *p, size_t len) {
m_path = p;
m_length = len;
}
constexpr bool IsCurrentDirectory() const {
return m_length == 1 && IsDot(m_path[0]);
}
constexpr bool IsParentDirectory() const {
return m_length == 2 && IsDot(m_path[0]) && IsDot(m_path[1]);
}
constexpr bool IsRootDirectory() const {
return m_length == 0;
}
constexpr const RomPathChar *begin() const {
return m_path;
}
constexpr const RomPathChar *end() const {
return m_path + m_length;
}
constexpr size_t length() const {
return m_length;
}
};
constexpr inline bool IsCurrentDirectory(const RomEntryName &name) {
return name.length == 1 && IsDot(name.path[0]);
}
constexpr inline bool IsCurrentDirectory(const RomPathChar *p, size_t length) {
AMS_ASSERT(p != nullptr);
@@ -83,6 +57,10 @@ namespace ams::fs::RomPathTool {
return IsDot(p[0]) && IsNullTerminator(p[1]);
}
constexpr inline bool IsParentDirectory(const RomEntryName &name) {
return name.length == 2 && IsDot(name.path[0]) && IsDot(name.path[1]);
}
constexpr inline bool IsParentDirectory(const RomPathChar *p) {
AMS_ASSERT(p != nullptr);
return IsDot(p[0]) && IsDot(p[1]) && IsNullTerminator(p[2]);

View File

@@ -18,10 +18,9 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: 14.3.0.0 */
using RomPathChar = char;
using RomFileId = u32;
using RomDirectoryId = u32;
using RomFileId = s32;
using RomDirectoryId = s32;
struct RomFileSystemInformation {
s64 size;
@@ -38,6 +37,11 @@ namespace ams::fs {
static_assert(util::is_pod<RomFileSystemInformation>::value);
static_assert(sizeof(RomFileSystemInformation) == 0x50);
struct RomDirectoryInfo {
/* ... */
};
static_assert(util::is_pod<RomDirectoryInfo>::value);
struct RomFileInfo {
Int64 offset;
Int64 size;

View File

@@ -19,7 +19,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: 13.4.0.0 */
class DirectoryPathParser {
NON_COPYABLE(DirectoryPathParser);
NON_MOVEABLE(DirectoryPathParser);
@@ -102,9 +101,10 @@ namespace ams::fs {
s32 i;
for (i = m_position; m_buffer[i] != StringTraits::DirectorySeparator; ++i) {
if (m_buffer[i] == StringTraits::NullTerminator) {
char * const ret = (i != m_position) ? m_buffer + m_position : nullptr;
m_position = -1;
return ret;
if (i == m_position) {
m_position = -1;
return nullptr;
}
}
}

View File

@@ -22,7 +22,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
class FileStorage : public IStorage, public impl::Newable {
NON_COPYABLE(FileStorage);
NON_MOVEABLE(FileStorage);
@@ -75,7 +74,6 @@ namespace ams::fs {
virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override;
};
/* ACCURATE_TO_VERSION: Unknown */
class FileStorageBasedFileSystem : public FileStorage {
NON_COPYABLE(FileStorageBasedFileSystem);
NON_MOVEABLE(FileStorageBasedFileSystem);

View File

@@ -18,8 +18,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
enum AccessLogMode : u32 {
AccessLogMode_None = 0,
AccessLogMode_Log = 1,

View File

@@ -18,8 +18,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
void InitializeForSystem();
void InitializeWithMultiSessionForSystem();

View File

@@ -18,8 +18,6 @@
namespace ams::fs {
/* ACCURATE_TO_VERSION: Unknown */
Result MountApplicationPackage(const char *name, const char *common_path);
}

Some files were not shown because too many files have changed in this diff Show More