Compare commits
42 Commits
0.16.0
...
hid_refact
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b18db914c | ||
|
|
b69bf07d9c | ||
|
|
09978eafb9 | ||
|
|
8070de693d | ||
|
|
72671d39ab | ||
|
|
a4c4cf22c9 | ||
|
|
6ea1955e94 | ||
|
|
e81025af2e | ||
|
|
791638e6ba | ||
|
|
2e0378c724 | ||
|
|
59ada14680 | ||
|
|
25e944f519 | ||
|
|
3e87b8ff17 | ||
|
|
55502fcd0c | ||
|
|
d3e3292bb8 | ||
|
|
33c568963d | ||
|
|
c374f1c5ce | ||
|
|
825e2df2e0 | ||
|
|
b3efdebeaf | ||
|
|
b393f8f348 | ||
|
|
74e0ea1033 | ||
|
|
1738a308c4 | ||
|
|
8fe7373ad2 | ||
|
|
83dd25b894 | ||
|
|
5217a78637 | ||
|
|
2f0470ff1c | ||
|
|
e6733fb2d4 | ||
|
|
5be5be9e5c | ||
|
|
f86d23cb2c | ||
|
|
a7bc540fed | ||
|
|
0f7853417a | ||
|
|
11f90f03d9 | ||
|
|
7e2449b347 | ||
|
|
abe57ac5b2 | ||
|
|
8d458b44d7 | ||
|
|
1352690ece | ||
|
|
ac6fc7b965 | ||
|
|
d0e6fdb3da | ||
|
|
4c581d21f6 | ||
|
|
1365814b8d | ||
|
|
f63d79d8f9 | ||
|
|
14d50c0e39 |
7
Makefile
7
Makefile
@@ -141,16 +141,15 @@ dist: dist-no-debug
|
||||
cp stratosphere/creport/creport.elf atmosphere-$(AMSVER)-debug/creport.elf
|
||||
cp stratosphere/dmnt/dmnt.elf atmosphere-$(AMSVER)-debug/dmnt.elf
|
||||
cp stratosphere/eclct.stub/eclct.stub.elf atmosphere-$(AMSVER)-debug/eclct.stub.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/fatal/fatal.elf atmosphere-$(AMSVER)-debug/fatal.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/loader/loader.elf atmosphere-$(AMSVER)-debug/loader.elf
|
||||
cp stratosphere/ncm/ncm.elf atmosphere-$(AMSVER)-debug/ncm.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp stratosphere/pm/pm.elf atmosphere-$(AMSVER)-debug/pm.elf
|
||||
cp stratosphere/ro/ro.elf atmosphere-$(AMSVER)-debug/ro.elf
|
||||
cp stratosphere/sm/sm.elf atmosphere-$(AMSVER)-debug/sm.elf
|
||||
cp stratosphere/spl/spl.elf atmosphere-$(AMSVER)-debug/spl.elf
|
||||
cp stratosphere/erpt/erpt.elf atmosphere-$(AMSVER)-debug/erpt.elf
|
||||
cp stratosphere/jpegdec/jpegdec.elf atmosphere-$(AMSVER)-debug/jpegdec.elf
|
||||
cp stratosphere/pgl/pgl.elf atmosphere-$(AMSVER)-debug/pgl.elf
|
||||
cp troposphere/daybreak/daybreak.elf atmosphere-$(AMSVER)-debug/daybreak.elf
|
||||
cd atmosphere-$(AMSVER)-debug; zip -r ../atmosphere-$(AMSVER)-debug.zip ./*; cd ../;
|
||||
rm -r atmosphere-$(AMSVER)-debug
|
||||
|
||||
@@ -1,38 +1,4 @@
|
||||
# Changelog
|
||||
## 0.16.0
|
||||
+ Support was added for 11.0.0.
|
||||
+ `exosphère` was updated to reflect the latest official secure monitor behavior.
|
||||
+ `mesosphère` was updated to reflect the latest official kernel behavior.
|
||||
+ `loader`, `sm`, `boot`, `pgl` were updated to reflect the latest official behaviors.
|
||||
+ **Please Note**: 11.0.0 implements an opt-in version of the atmosphère `sm` extension that allows for closing session without unregistering services.
|
||||
+ Correspondingly, the extension will be deprecated in favor of the new official opt-in command. In 0.17.0, it will be removed entirely.
|
||||
+ If your custom system module relies on this extension (however unlikely that seems to me), please update it accordingly.
|
||||
+ `erpt` was partially updated to provide compatibility with 11.0.0.
|
||||
+ The latest firmware attaches additional fields and context information to logs.
|
||||
+ A future atmosphère update will implement this logic, so that users who are interested can also get the new information when examining their logs.
|
||||
+ **Please Note**: 11.0.0 introduced breaking changes to the `usb` system module's `usb:ds` API.
|
||||
+ Homebrew which uses the `usb:ds` service should rebuild with the latest libnx version to support running on 11.0.0.
|
||||
+ The `boot` system module was rewritten to reflect the huge driver changes introduced in 8.0.0.
|
||||
+ This includes a number of improvements to both logo display and battery management logic.
|
||||
+ Support was added for configuring the address space width for `hbl`.
|
||||
+ The `hbl_config!override_address_space_(#)` and `hbl_config!override_any_app_address_space` can now be set to `39_bit`, `36_bit`, or `32_bit` to control the address space for hbl on a per-override basis.
|
||||
+ If a configuration has not been set, hbl will now default to 39-bit address space.
|
||||
+ Previously, a legacy 36-bit address space was always used to maintain compatibility with 1.0.0.
|
||||
+ A new loader extension was added to support 39-bit whenever possible (including mesosphere-on-1.0.0), with fallback to 36-bit when unavailable.
|
||||
+ Support was added to a number of components for running on Mariko hardware.
|
||||
+ The `boot` system module can now safely be run on mariko hardware, performing correct hardware initialization.
|
||||
+ Daybreak (and generally, system update logic) were updated to be usable on Mariko.
|
||||
+ Boot0 protection/management logic was updated to perform correct actions on Mariko.
|
||||
+ Reboot to payload does not and cannot work on Mariko. Correspondingly, A "fatal error" handler was written, to display and save fatal errors from within TrustZone.
|
||||
+ **Please Note:** Atmosphere is still not properly usable on Mariko hardware.
|
||||
+ In particular, wake-from-sleep will not properly function (the magic numbers aren't set correctly), among a few other minor issues.
|
||||
+ `exosphère` received support for building under debug configuration.
|
||||
+ A small (otherwise unused) portion of IRAM is now reserved for debug-only exosphere code (this region is unused/untouched under release config).
|
||||
+ This enables logging (including printf) to uart from the secure monitor, for those interested.
|
||||
+ A number of bugs were fixed, including:
|
||||
+ Minor issues in a number of filesystem related code were fixed.
|
||||
+ An issue was fixed that could cause NCM to abort on consoles which came with 3.0.x and were never updated.
|
||||
+ Several issues were fixed, and usability and stability were improved.
|
||||
## 0.15.0
|
||||
+ fusee-primary's panic display was updated to automatically identify and give suggestions to resolve many of the most common errors users encounter.
|
||||
+ Having been tested as well as I can alone, `mesosphere` (atmosphère's reimplementation of the Nintendo Switch kernel) is now available for users interested in trying it.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/m4xw/emuMMC
|
||||
branch = develop
|
||||
commit = 6fd752dad13c02d482a5d89c24f4e8ce8b9d8f56
|
||||
parent = 4f1a4e74992aa84b8ab84bccacc720e2d5823791
|
||||
commit = 25075973d31a5be6f2e769f1ea0fff44daf0cdfa
|
||||
parent = 8ba513fefbcfd8278a433090e59017963ba9887f
|
||||
method = rebase
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -72,9 +72,6 @@ namespace ams::secmon::boot {
|
||||
/* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */
|
||||
/* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */
|
||||
reg::Write(pmc + APBDEV_PMC_SECURE_SCRATCH32, 0x129);
|
||||
|
||||
/* TODO: Fix to ensure correct scratch contents on mariko, as otherwise wb is broken. */
|
||||
AMS_ABORT_UNLESS(fuse::GetSocType() != fuse::SocType_Mariko);
|
||||
}
|
||||
|
||||
/* This function derives the master kek and device keys using the tsec root key. */
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_IcosaSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaMicron4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveHynix1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperSamsung4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IcosaSamsung6GB] = pkg1::MemorySize_6GB,
|
||||
[fuse::DramId_CopperHynix4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_CopperMicron4GB] = pkg1::MemorySize_4GB,
|
||||
@@ -66,13 +66,9 @@ namespace ams::secmon::smc {
|
||||
[fuse::DramId_HoagSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBY] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y8GBY] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_HoagMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveMicron1y4GB] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_IowaSamsung1y4GBA] = pkg1::MemorySize_4GB,
|
||||
[fuse::DramId_FiveSamsung1y8GBX] = pkg1::MemorySize_8GB,
|
||||
[fuse::DramId_FiveSamsung1y4GBX] = pkg1::MemorySize_4GB,
|
||||
};
|
||||
|
||||
constexpr const pkg1::MemoryMode MemoryModes[] = {
|
||||
|
||||
@@ -543,8 +543,8 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9B
|
||||
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0x80]
|
||||
mov w10, #3
|
||||
ldr x11, [sp, #0x90]
|
||||
mov w10, w28
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
@@ -567,11 +567,11 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1000, proc_id_recv)[] = {0xA9B
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_send)[] = {0xE0, 0x03, 0x15, 0xAA, 0xA8, 0x02, 0x40, 0xF9, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0x88, 0x4A, 0x3C, 0x8B, 0x09, 0xFC, 0x60, 0xD3, 0x00, 0x25, 0x00, 0x29};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9BF2FEA, 0xF94043EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9BF2FEA, 0xF9404BEB, 0x2A1C03EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54FFFFA0, 0xA9BF27E8, 0xF94002A8, 0xF9401D08, 0xAA1503E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
/*
|
||||
stp x10, x11, [sp, #-0x10]!
|
||||
ldr x11, [sp, #0xE0]
|
||||
mov w10, #3
|
||||
ldr w10, [sp, #0xC0]
|
||||
lsl x10, x10, #2
|
||||
ldr x10, [x11, x10]
|
||||
mov x9, #0x0000ffffffffffff
|
||||
@@ -594,7 +594,7 @@ static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_send)[] = {0xA9B
|
||||
mov x0, x8
|
||||
*/
|
||||
static const uint8_t MAKE_KERNEL_PATTERN_NAME(1100, proc_id_recv)[] = {0x08, 0x03, 0x40, 0xF9, 0xE0, 0x03, 0x18, 0xAA, 0x08, 0x1D, 0x40, 0xF9, 0x00, 0x01, 0x3F, 0xD6, 0xE8, 0x7F, 0x40, 0xF9, 0x09, 0xFC, 0x60, 0xD3, 0xEA, 0x5B, 0x40, 0xF9};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)[] = {0xA9BF2FEA, 0xF94073EB, 0x5280006A, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
static const instruction_t MAKE_KERNEL_PATCH_NAME(1100, proc_id_recv)[] = {0xA9BF2FEA, 0xF94073EB, 0xB940C3EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54FFFFA0, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0};
|
||||
|
||||
/* svcControlCodeMemory Patches */
|
||||
/* b.eq -> nop */
|
||||
@@ -1090,7 +1090,7 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
|
||||
|
||||
uint8_t *pattern_loc = search_pattern(kernel, *kernel_size, kernel_info->patches[i].pattern, kernel_info->patches[i].pattern_size);
|
||||
if (pattern_loc == NULL) {
|
||||
fatal_error("kernel_patcher: failed to identify patch location!\n");
|
||||
/* TODO: Should we print an error/abort here? */
|
||||
continue;
|
||||
}
|
||||
/* Patch kernel to branch to our hook at the desired place. */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
|
||||
branch = master
|
||||
commit = 78510a74f010eb532ba77f905171f41094df94cb
|
||||
parent = f72475872a5a6519e5ca9322e7f1960432230f40
|
||||
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
|
||||
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
|
||||
method = merge
|
||||
cmdver = 0.4.1
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace ams::fuse {
|
||||
DramId_IcosaSamsung4GB = 0,
|
||||
DramId_IcosaHynix4GB = 1,
|
||||
DramId_IcosaMicron4GB = 2,
|
||||
DramId_FiveHynix1y4GB = 3,
|
||||
DramId_CopperSamsung4GB = 3,
|
||||
DramId_IcosaSamsung6GB = 4,
|
||||
DramId_CopperHynix4GB = 5,
|
||||
DramId_CopperMicron4GB = 6,
|
||||
@@ -70,13 +70,9 @@ namespace ams::fuse {
|
||||
DramId_HoagSamsung1y4GBX = 19,
|
||||
DramId_IowaSamsung1y4GBY = 20,
|
||||
DramId_IowaSamsung1y8GBY = 21,
|
||||
DramId_FiveSamsung1y4GB = 22,
|
||||
DramId_HoagSamsung1y8GBX = 23,
|
||||
DramId_IowaSamsung1y4GBA = 22,
|
||||
DramId_FiveSamsung1y8GBX = 23,
|
||||
DramId_FiveSamsung1y4GBX = 24,
|
||||
DramId_IowaMicron1y4GB = 25,
|
||||
DramId_HoagMicron1y4GB = 26,
|
||||
DramId_FiveMicron1y4GB = 27,
|
||||
DramId_FiveSamsung1y8GBX = 28,
|
||||
|
||||
DramId_Count,
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ include $(CURRENT_DIRECTORY)/../config/common.mk
|
||||
PRECOMPILED_HEADERS := include/mesosphere.hpp
|
||||
|
||||
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -Wextra -Werror -fno-non-call-exceptions
|
||||
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit -flto
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
@@ -77,8 +77,6 @@
|
||||
#include <mesosphere/kern_select_debug.hpp>
|
||||
#include <mesosphere/kern_k_process.hpp>
|
||||
#include <mesosphere/kern_k_resource_limit.hpp>
|
||||
#include <mesosphere/kern_k_alpha.hpp>
|
||||
#include <mesosphere/kern_k_beta.hpp>
|
||||
|
||||
/* More Miscellaneous objects. */
|
||||
#include <mesosphere/kern_k_object_name.hpp>
|
||||
|
||||
@@ -668,7 +668,6 @@ namespace ams::kern::arch::arm64::init {
|
||||
this->PhysicallyRandomize(virt_addr, size, L2BlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3ContiguousBlockSize, do_copy);
|
||||
this->PhysicallyRandomize(virt_addr, size, L3BlockSize, do_copy);
|
||||
cpu::StoreEntireCacheForInit();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ams::kern::arch::arm64 {
|
||||
public:
|
||||
constexpr KNotAlignedSpinLock() : packed_tickets(0) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE void Lock() {
|
||||
void Lock() {
|
||||
u32 tmp0, tmp1, tmp2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
@@ -52,7 +52,7 @@ namespace ams::kern::arch::arm64 {
|
||||
);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
void Unlock() {
|
||||
const u32 value = this->packed_tickets + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[packed_tickets]\n"
|
||||
@@ -71,7 +71,7 @@ namespace ams::kern::arch::arm64 {
|
||||
public:
|
||||
constexpr KAlignedSpinLock() : current_ticket(0), next_ticket(0) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE void Lock() {
|
||||
void Lock() {
|
||||
u32 tmp0, tmp1, got_lock;
|
||||
|
||||
__asm__ __volatile__(
|
||||
@@ -94,7 +94,7 @@ namespace ams::kern::arch::arm64 {
|
||||
);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
void Unlock() {
|
||||
const u32 value = this->current_ticket + 1;
|
||||
__asm__ __volatile__(
|
||||
" stlrh %w[value], %[current_ticket]\n"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern::board::nintendo::nx::impl::cpu {
|
||||
|
||||
/* Virtual to Physical core map. */
|
||||
constexpr inline const s32 VirtualToPhysicalCoreMap[BITSIZEOF(u64)] = {
|
||||
0, 1, 2, 3, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 3,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -34,8 +34,6 @@ namespace ams::kern::init {
|
||||
size_t num_KObjectName;
|
||||
size_t num_KResourceLimit;
|
||||
size_t num_KDebug;
|
||||
size_t num_KAlpha;
|
||||
size_t num_KBeta;
|
||||
};
|
||||
|
||||
NOINLINE void InitializeSlabResourceCounts();
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KAlpha final : public KAutoObjectWithSlabHeapAndContainer<KAlpha, KAutoObjectWithList> {
|
||||
MESOSPHERE_AUTOOBJECT_TRAITS(KAlpha, KAutoObject);
|
||||
private:
|
||||
/* NOTE: Official KAlpha has size 0x50, corresponding to 0x20 bytes of fields. */
|
||||
/* TODO: Add these fields, if KAlpha is ever instantiable in the NX kernel. */
|
||||
public:
|
||||
explicit KAlpha() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~KAlpha() { /* ... */ }
|
||||
|
||||
/* virtual void Finalize() override; */
|
||||
|
||||
virtual bool IsInitialized() const override { return false /* TODO */; }
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -198,7 +198,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
~KScopedAutoObject() {
|
||||
ALWAYS_INLINE ~KScopedAutoObject() {
|
||||
if (this->obj != nullptr) {
|
||||
this->obj->Close();
|
||||
}
|
||||
@@ -206,7 +206,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
template<typename U> requires (std::derived_from<T, U> || std::derived_from<U, T>)
|
||||
constexpr KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
||||
constexpr ALWAYS_INLINE KScopedAutoObject(KScopedAutoObject<U> &&rhs) {
|
||||
if constexpr (std::derived_from<U, T>) {
|
||||
/* Upcast. */
|
||||
this->obj = rhs.obj;
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KProcess;
|
||||
|
||||
class KBeta final : public KAutoObjectWithSlabHeapAndContainer<KBeta, KAutoObjectWithList> {
|
||||
MESOSPHERE_AUTOOBJECT_TRAITS(KBeta, KAutoObject);
|
||||
private:
|
||||
friend class KProcess;
|
||||
private:
|
||||
/* NOTE: Official KBeta has size 0x88, corresponding to 0x58 bytes of fields. */
|
||||
/* TODO: Add these fields, if KBeta is ever instantiable in the NX kernel. */
|
||||
util::IntrusiveListNode process_list_node;
|
||||
public:
|
||||
explicit KBeta()
|
||||
: process_list_node()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
virtual ~KBeta() { /* ... */ }
|
||||
|
||||
/* virtual void Finalize() override; */
|
||||
|
||||
virtual bool IsInitialized() const override { return false /* TODO */; }
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -112,10 +112,6 @@ namespace ams::kern {
|
||||
KSessionRequest,
|
||||
KCodeMemory,
|
||||
|
||||
/* NOTE: True order for these has not been determined yet. */
|
||||
KAlpha,
|
||||
KBeta,
|
||||
|
||||
FinalClassesEnd = FinalClassesStart + NumFinalClasses,
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
extern KThread g_cv_arbiter_compare_thread;
|
||||
|
||||
class KConditionVariable {
|
||||
public:
|
||||
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;
|
||||
|
||||
@@ -160,16 +160,14 @@ namespace ams::kern {
|
||||
return this->template GetObjectWithoutPseudoHandle<T>(handle);
|
||||
}
|
||||
|
||||
KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
||||
ALWAYS_INLINE KScopedAutoObject<KAutoObject> GetObjectForIpcWithoutPseudoHandle(ams::svc::Handle handle) const {
|
||||
/* Lock and look up in table. */
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
|
||||
KAutoObject *obj = this->GetObjectImpl(handle);
|
||||
if (AMS_LIKELY(obj != nullptr)) {
|
||||
if (AMS_UNLIKELY(obj->DynamicCast<KInterruptEvent *>() != nullptr)) {
|
||||
return nullptr;
|
||||
}
|
||||
if (obj->DynamicCast<KInterruptEvent *>() != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return obj;
|
||||
|
||||
@@ -112,9 +112,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) {
|
||||
const auto ®ion = Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id)));
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
return region.GetEndAddress();
|
||||
return Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))).GetEndAddress();
|
||||
}
|
||||
public:
|
||||
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
|
||||
|
||||
@@ -70,13 +70,11 @@ namespace ams::kern {
|
||||
public:
|
||||
Impl() : heap(), page_reference_counts(), management_region(), pool(), next(), prev() { /* ... */ }
|
||||
|
||||
size_t Initialize(uintptr_t address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p);
|
||||
size_t Initialize(const KMemoryRegion *region, Pool pool, KVirtualAddress management_region, KVirtualAddress management_region_end);
|
||||
|
||||
KVirtualAddress AllocateBlock(s32 index, bool random) { return this->heap.AllocateBlock(index, random); }
|
||||
void Free(KVirtualAddress addr, size_t num_pages) { this->heap.Free(addr, num_pages); }
|
||||
|
||||
void UpdateUsedHeapSize() { this->heap.UpdateUsedSize(); }
|
||||
|
||||
void InitializeOptimizedMemory() { std::memset(GetVoidPointer(this->management_region), 0, CalculateOptimizedProcessOverheadSize(this->heap.GetSize())); }
|
||||
|
||||
void TrackUnoptimizedAllocation(KVirtualAddress block, size_t num_pages);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace ams::kern {
|
||||
private:
|
||||
uintptr_t address;
|
||||
uintptr_t pair_address;
|
||||
uintptr_t last_address;
|
||||
size_t region_size;
|
||||
u32 attributes;
|
||||
u32 type_id;
|
||||
public:
|
||||
@@ -43,18 +43,18 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), last_address(0), attributes(0), type_id(0) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, uintptr_t p, u32 r, u32 t) :
|
||||
address(a), pair_address(p), last_address(la), attributes(r), type_id(t)
|
||||
constexpr ALWAYS_INLINE KMemoryRegion() : address(0), pair_address(0), region_size(0), attributes(0), type_id(0) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, uintptr_t p, u32 r, u32 t) :
|
||||
address(a), pair_address(p), region_size(rs), attributes(r), type_id(t)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t la, u32 r, u32 t) : KMemoryRegion(a, la, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
|
||||
constexpr ALWAYS_INLINE KMemoryRegion(uintptr_t a, size_t rs, u32 r, u32 t) : KMemoryRegion(a, rs, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
|
||||
private:
|
||||
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t la, uintptr_t p, u32 r, u32 t) {
|
||||
constexpr ALWAYS_INLINE void Reset(uintptr_t a, uintptr_t rs, uintptr_t p, u32 r, u32 t) {
|
||||
this->address = a;
|
||||
this->pair_address = p;
|
||||
this->last_address = la;
|
||||
this->region_size = rs;
|
||||
this->attributes = r;
|
||||
this->type_id = t;
|
||||
}
|
||||
@@ -67,16 +67,16 @@ namespace ams::kern {
|
||||
return this->pair_address;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->last_address;
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->region_size;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||
return this->GetLastAddress() + 1;
|
||||
return this->GetAddress() + this->GetSize();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->GetEndAddress() - this->GetAddress();
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->GetEndAddress() - 1;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetAttributes() const {
|
||||
@@ -93,7 +93,6 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(this->GetEndAddress() != 0);
|
||||
return this->GetAddress() <= address && address <= this->GetLastAddress();
|
||||
}
|
||||
|
||||
@@ -131,17 +130,17 @@ namespace ams::kern {
|
||||
return this->first_region->GetAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->last_region->GetLastAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
|
||||
return this->GetLastAddress() + 1;
|
||||
return this->last_region->GetEndAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const {
|
||||
return this->GetEndAddress() - this->GetAddress();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
|
||||
return this->GetEndAddress() - 1;
|
||||
}
|
||||
};
|
||||
private:
|
||||
using TreeType = util::IntrusiveRedBlackTreeBaseTraits<KMemoryRegion>::TreeType<KMemoryRegion>;
|
||||
@@ -161,7 +160,7 @@ namespace ams::kern {
|
||||
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
|
||||
public:
|
||||
KMemoryRegion *FindModifiable(uintptr_t address) {
|
||||
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->end()) {
|
||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) {
|
||||
return std::addressof(*it);
|
||||
} else {
|
||||
return nullptr;
|
||||
@@ -169,7 +168,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
const KMemoryRegion *Find(uintptr_t address) const {
|
||||
if (auto it = this->find(KMemoryRegion(address, address, 0, 0)); it != this->cend()) {
|
||||
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) {
|
||||
return std::addressof(*it);
|
||||
} else {
|
||||
return nullptr;
|
||||
@@ -235,7 +234,7 @@ namespace ams::kern {
|
||||
return extents;
|
||||
}
|
||||
public:
|
||||
NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr = 0, u32 type_id = 0);
|
||||
NOINLINE void InsertDirectly(uintptr_t address, size_t size, u32 attr = 0, u32 type_id = 0);
|
||||
NOINLINE bool Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
|
||||
|
||||
NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <mesosphere/kern_k_thread.hpp>
|
||||
#include <mesosphere/kern_k_thread_local_page.hpp>
|
||||
#include <mesosphere/kern_k_shared_memory_info.hpp>
|
||||
#include <mesosphere/kern_k_beta.hpp>
|
||||
#include <mesosphere/kern_k_worker_task.hpp>
|
||||
#include <mesosphere/kern_select_page_table.hpp>
|
||||
#include <mesosphere/kern_k_condition_variable.hpp>
|
||||
@@ -53,7 +52,6 @@ namespace ams::kern {
|
||||
static constexpr size_t AslrAlignment = KernelAslrAlignment;
|
||||
private:
|
||||
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
||||
using BetaList = util::IntrusiveListMemberTraits<&KBeta::process_list_node>::ListType;
|
||||
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
||||
using TLPIterator = TLPTree::iterator;
|
||||
private:
|
||||
@@ -97,7 +95,6 @@ namespace ams::kern {
|
||||
KThread *exception_thread{};
|
||||
ThreadList thread_list{};
|
||||
SharedMemoryInfoList shared_memory_list{};
|
||||
BetaList beta_list{};
|
||||
bool is_suspended{};
|
||||
bool is_jit_debug{};
|
||||
ams::svc::DebugEvent jit_debug_event_type{};
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace ams::kern {
|
||||
return this->owner_thread == GetCurrentThreadPointer();
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
ALWAYS_INLINE void Lock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
if (this->IsLockedByCurrentThread()) {
|
||||
@@ -67,7 +67,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
ALWAYS_INLINE void Unlock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||
MESOSPHERE_ASSERT(this->lock_count > 0);
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ams::kern {
|
||||
*out_timer = this->timer;
|
||||
}
|
||||
|
||||
~KScopedSchedulerLockAndSleep() {
|
||||
ALWAYS_INLINE ~KScopedSchedulerLockAndSleep() {
|
||||
/* Register the sleep. */
|
||||
if (this->timeout_tick > 0) {
|
||||
this->timer->RegisterAbsoluteTask(this->thread, this->timeout_tick);
|
||||
|
||||
@@ -45,10 +45,10 @@ namespace ams::kern {
|
||||
this->state = st;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetClientAddress() const { return this->client_address; }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetServerAddress() const { return this->server_address; }
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const { return this->size; }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetMemoryState() const { return this->state; }
|
||||
constexpr KProcessAddress GetClientAddress() const { return this->client_address; }
|
||||
constexpr KProcessAddress GetServerAddress() const { return this->server_address; }
|
||||
constexpr size_t GetSize() const { return this->size; }
|
||||
constexpr KMemoryState GetMemoryState() const { return this->state; }
|
||||
};
|
||||
private:
|
||||
Mapping static_mappings[NumStaticMappings];
|
||||
@@ -62,32 +62,32 @@ namespace ams::kern {
|
||||
void Initialize() { /* ... */ }
|
||||
void Finalize();
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSendCount() const { return this->num_send; }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveCount() const { return this->num_recv; }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeCount() const { return this->num_exch; }
|
||||
constexpr size_t GetSendCount() const { return this->num_send; }
|
||||
constexpr size_t GetReceiveCount() const { return this->num_recv; }
|
||||
constexpr size_t GetExchangeCount() const { return this->num_exch; }
|
||||
|
||||
Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state);
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendClientAddress(size_t i) const { return GetSendMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendServerAddress(size_t i) const { return GetSendMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetSendSize(size_t i) const { return GetSendMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetSendMemoryState(size_t i) const { return GetSendMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetSendClientAddress(size_t i) const { return GetSendMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetSendServerAddress(size_t i) const { return GetSendMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetSendSize(size_t i) const { return GetSendMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetSendMemoryState(size_t i) const { return GetSendMapping(i).GetMemoryState(); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveClientAddress(size_t i) const { return GetReceiveMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveServerAddress(size_t i) const { return GetReceiveMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveSize(size_t i) const { return GetReceiveMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetReceiveMemoryState(size_t i) const { return GetReceiveMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetReceiveClientAddress(size_t i) const { return GetReceiveMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetReceiveServerAddress(size_t i) const { return GetReceiveMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetReceiveSize(size_t i) const { return GetReceiveMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetReceiveMemoryState(size_t i) const { return GetReceiveMapping(i).GetMemoryState(); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeClientAddress(size_t i) const { return GetExchangeMapping(i).GetClientAddress(); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeServerAddress(size_t i) const { return GetExchangeMapping(i).GetServerAddress(); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeSize(size_t i) const { return GetExchangeMapping(i).GetSize(); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetExchangeMemoryState(size_t i) const { return GetExchangeMapping(i).GetMemoryState(); }
|
||||
constexpr KProcessAddress GetExchangeClientAddress(size_t i) const { return GetExchangeMapping(i).GetClientAddress(); }
|
||||
constexpr KProcessAddress GetExchangeServerAddress(size_t i) const { return GetExchangeMapping(i).GetServerAddress(); }
|
||||
constexpr size_t GetExchangeSize(size_t i) const { return GetExchangeMapping(i).GetSize(); }
|
||||
constexpr KMemoryState GetExchangeMemoryState(size_t i) const { return GetExchangeMapping(i).GetMemoryState(); }
|
||||
private:
|
||||
Result PushMap(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state, size_t index);
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetSendMapping(size_t i) const {
|
||||
constexpr const Mapping &GetSendMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_send);
|
||||
|
||||
const size_t index = i;
|
||||
@@ -98,7 +98,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetReceiveMapping(size_t i) const {
|
||||
constexpr const Mapping &GetReceiveMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_recv);
|
||||
|
||||
const size_t index = this->num_send + i;
|
||||
@@ -109,7 +109,7 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE const Mapping &GetExchangeMapping(size_t i) const {
|
||||
constexpr const Mapping &GetExchangeMapping(size_t i) const {
|
||||
MESOSPHERE_ASSERT(i < this->num_exch);
|
||||
|
||||
const size_t index = this->num_send + this->num_recv + i;
|
||||
@@ -176,50 +176,50 @@ namespace ams::kern {
|
||||
|
||||
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
|
||||
|
||||
constexpr ALWAYS_INLINE KThread *GetThread() const { return this->thread; }
|
||||
constexpr ALWAYS_INLINE KWritableEvent *GetEvent() const { return this->event; }
|
||||
constexpr ALWAYS_INLINE uintptr_t GetAddress() const { return this->address; }
|
||||
constexpr ALWAYS_INLINE size_t GetSize() const { return this->size; }
|
||||
constexpr ALWAYS_INLINE KProcess *GetServerProcess() const { return this->server; }
|
||||
constexpr KThread *GetThread() const { return this->thread; }
|
||||
constexpr KWritableEvent *GetEvent() const { return this->event; }
|
||||
constexpr uintptr_t GetAddress() const { return this->address; }
|
||||
constexpr size_t GetSize() const { return this->size; }
|
||||
constexpr KProcess *GetServerProcess() const { return this->server; }
|
||||
|
||||
void ALWAYS_INLINE SetServerProcess(KProcess *process) {
|
||||
void SetServerProcess(KProcess *process) {
|
||||
this->server = process;
|
||||
this->server->Open();
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE void ClearThread() { this->thread = nullptr; }
|
||||
constexpr ALWAYS_INLINE void ClearEvent() { this->event = nullptr; }
|
||||
constexpr void ClearThread() { this->thread = nullptr; }
|
||||
constexpr void ClearEvent() { this->event = nullptr; }
|
||||
|
||||
constexpr ALWAYS_INLINE size_t GetSendCount() const { return this->mappings.GetSendCount(); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveCount() const { return this->mappings.GetReceiveCount(); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeCount() const { return this->mappings.GetExchangeCount(); }
|
||||
constexpr size_t GetSendCount() const { return this->mappings.GetSendCount(); }
|
||||
constexpr size_t GetReceiveCount() const { return this->mappings.GetReceiveCount(); }
|
||||
constexpr size_t GetExchangeCount() const { return this->mappings.GetExchangeCount(); }
|
||||
|
||||
ALWAYS_INLINE Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushSend(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushSend(client, server, size, state);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushReceive(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushReceive(client, server, size, state);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
Result PushExchange(KProcessAddress client, KProcessAddress server, size_t size, KMemoryState state) {
|
||||
return this->mappings.PushExchange(client, server, size, state);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendClientAddress(size_t i) const { return this->mappings.GetSendClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetSendServerAddress(size_t i) const { return this->mappings.GetSendServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetSendSize(size_t i) const { return this->mappings.GetSendSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetSendMemoryState(size_t i) const { return this->mappings.GetSendMemoryState(i); }
|
||||
constexpr KProcessAddress GetSendClientAddress(size_t i) const { return this->mappings.GetSendClientAddress(i); }
|
||||
constexpr KProcessAddress GetSendServerAddress(size_t i) const { return this->mappings.GetSendServerAddress(i); }
|
||||
constexpr size_t GetSendSize(size_t i) const { return this->mappings.GetSendSize(i); }
|
||||
constexpr KMemoryState GetSendMemoryState(size_t i) const { return this->mappings.GetSendMemoryState(i); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveClientAddress(size_t i) const { return this->mappings.GetReceiveClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetReceiveServerAddress(size_t i) const { return this->mappings.GetReceiveServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetReceiveSize(size_t i) const { return this->mappings.GetReceiveSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetReceiveMemoryState(size_t i) const { return this->mappings.GetReceiveMemoryState(i); }
|
||||
constexpr KProcessAddress GetReceiveClientAddress(size_t i) const { return this->mappings.GetReceiveClientAddress(i); }
|
||||
constexpr KProcessAddress GetReceiveServerAddress(size_t i) const { return this->mappings.GetReceiveServerAddress(i); }
|
||||
constexpr size_t GetReceiveSize(size_t i) const { return this->mappings.GetReceiveSize(i); }
|
||||
constexpr KMemoryState GetReceiveMemoryState(size_t i) const { return this->mappings.GetReceiveMemoryState(i); }
|
||||
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeClientAddress(size_t i) const { return this->mappings.GetExchangeClientAddress(i); }
|
||||
constexpr ALWAYS_INLINE KProcessAddress GetExchangeServerAddress(size_t i) const { return this->mappings.GetExchangeServerAddress(i); }
|
||||
constexpr ALWAYS_INLINE size_t GetExchangeSize(size_t i) const { return this->mappings.GetExchangeSize(i); }
|
||||
constexpr ALWAYS_INLINE KMemoryState GetExchangeMemoryState(size_t i) const { return this->mappings.GetExchangeMemoryState(i); }
|
||||
constexpr KProcessAddress GetExchangeClientAddress(size_t i) const { return this->mappings.GetExchangeClientAddress(i); }
|
||||
constexpr KProcessAddress GetExchangeServerAddress(size_t i) const { return this->mappings.GetExchangeServerAddress(i); }
|
||||
constexpr size_t GetExchangeSize(size_t i) const { return this->mappings.GetExchangeSize(i); }
|
||||
constexpr KMemoryState GetExchangeMemoryState(size_t i) const { return this->mappings.GetExchangeMemoryState(i); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -124,21 +124,7 @@ namespace ams::kern {
|
||||
static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles));
|
||||
|
||||
struct ConditionVariableComparator {
|
||||
struct LightCompareType {
|
||||
uintptr_t cv_key;
|
||||
s32 priority;
|
||||
|
||||
constexpr ALWAYS_INLINE uintptr_t GetConditionVariableKey() const {
|
||||
return this->cv_key;
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE s32 GetPriority() const {
|
||||
return this->priority;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, LightCompareType>)
|
||||
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
|
||||
static constexpr ALWAYS_INLINE int Compare(const KThread &lhs, const KThread &rhs) {
|
||||
const uintptr_t l_key = lhs.GetConditionVariableKey();
|
||||
const uintptr_t r_key = rhs.GetConditionVariableKey();
|
||||
|
||||
@@ -153,8 +139,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
};
|
||||
static_assert(ams::util::HasLightCompareType<ConditionVariableComparator>);
|
||||
static_assert(std::same_as<ams::util::LightCompareType<ConditionVariableComparator, void>, ConditionVariableComparator::LightCompareType>);
|
||||
private:
|
||||
static inline std::atomic<u64> s_next_thread_id = 0;
|
||||
private:
|
||||
@@ -168,8 +152,7 @@ namespace ams::kern {
|
||||
|
||||
ConditionVariableThreadTree *condvar_tree{};
|
||||
uintptr_t condvar_key{};
|
||||
u64 virtual_affinity_mask{};
|
||||
KAffinityMask physical_affinity_mask{};
|
||||
KAffinityMask affinity_mask{};
|
||||
u64 thread_id{};
|
||||
std::atomic<s64> cpu_time{};
|
||||
KSynchronizationObject *synced_object{};
|
||||
@@ -198,13 +181,12 @@ namespace ams::kern {
|
||||
Result wait_result;
|
||||
Result debug_exception_result;
|
||||
s32 base_priority{};
|
||||
s32 physical_ideal_core_id{};
|
||||
s32 virtual_ideal_core_id{};
|
||||
s32 ideal_core_id{};
|
||||
s32 num_kernel_waiters{};
|
||||
s32 current_core_id{};
|
||||
s32 core_id{};
|
||||
KAffinityMask original_physical_affinity_mask{};
|
||||
s32 original_physical_ideal_core_id{};
|
||||
KAffinityMask original_affinity_mask{};
|
||||
s32 original_ideal_core_id{};
|
||||
s32 num_core_migration_disables{};
|
||||
ThreadState thread_state{};
|
||||
std::atomic<bool> termination_requested{};
|
||||
@@ -220,21 +202,21 @@ namespace ams::kern {
|
||||
|
||||
virtual ~KThread() { /* ... */ }
|
||||
|
||||
Result Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type);
|
||||
Result Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type);
|
||||
|
||||
private:
|
||||
static Result InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type);
|
||||
static Result InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type);
|
||||
public:
|
||||
static Result InitializeKernelThread(KThread *thread, KThreadFunction func, uintptr_t arg, s32 prio, s32 virt_core) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, prio, virt_core, nullptr, ThreadType_Kernel);
|
||||
static Result InitializeKernelThread(KThread *thread, KThreadFunction func, uintptr_t arg, s32 prio, s32 core) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, prio, core, nullptr, ThreadType_Kernel);
|
||||
}
|
||||
|
||||
static Result InitializeHighPriorityThread(KThread *thread, KThreadFunction func, uintptr_t arg) {
|
||||
return InitializeThread(thread, func, arg, Null<KProcessAddress>, 0, GetCurrentCoreId(), nullptr, ThreadType_HighPriority);
|
||||
}
|
||||
|
||||
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner) {
|
||||
return InitializeThread(thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType_User);
|
||||
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner) {
|
||||
return InitializeThread(thread, func, arg, user_stack_top, prio, core, owner, ThreadType_User);
|
||||
}
|
||||
|
||||
static void ResumeThreadsSuspendedForInit();
|
||||
@@ -341,14 +323,10 @@ namespace ams::kern {
|
||||
constexpr KThreadContext &GetContext() { return this->thread_context; }
|
||||
constexpr const KThreadContext &GetContext() const { return this->thread_context; }
|
||||
|
||||
constexpr u64 GetVirtualAffinityMask() const { return this->virtual_affinity_mask; }
|
||||
constexpr const KAffinityMask &GetAffinityMask() const { return this->physical_affinity_mask; }
|
||||
|
||||
constexpr const KAffinityMask &GetAffinityMask() const { return this->affinity_mask; }
|
||||
Result GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
Result SetCoreMask(int32_t ideal_core, u64 affinity_mask);
|
||||
|
||||
Result GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask);
|
||||
|
||||
constexpr ThreadState GetState() const { return static_cast<ThreadState>(this->thread_state & ThreadState_Mask); }
|
||||
constexpr ThreadState GetRawState() const { return this->thread_state; }
|
||||
NOINLINE void SetState(ThreadState state);
|
||||
@@ -358,6 +336,11 @@ namespace ams::kern {
|
||||
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
|
||||
constexpr uintptr_t GetAddressArbiterKey() const { return this->condvar_key; }
|
||||
|
||||
constexpr void SetupForConditionVariableCompare(uintptr_t cv_key, int priority) {
|
||||
this->condvar_key = cv_key;
|
||||
this->priority = priority;
|
||||
}
|
||||
|
||||
constexpr void SetConditionVariable(ConditionVariableThreadTree *tree, KProcessAddress address, uintptr_t cv_key, u32 value) {
|
||||
this->condvar_tree = tree;
|
||||
this->condvar_key = cv_key;
|
||||
@@ -373,6 +356,11 @@ namespace ams::kern {
|
||||
return this->condvar_tree != nullptr;
|
||||
}
|
||||
|
||||
constexpr void SetupForAddressArbiterCompare(uintptr_t address, int priority) {
|
||||
this->condvar_key = address;
|
||||
this->priority = priority;
|
||||
}
|
||||
|
||||
constexpr void SetAddressArbiter(ConditionVariableThreadTree *tree, uintptr_t address) {
|
||||
this->condvar_tree = tree;
|
||||
this->condvar_key = address;
|
||||
@@ -386,9 +374,7 @@ namespace ams::kern {
|
||||
return this->condvar_tree != nullptr;
|
||||
}
|
||||
|
||||
constexpr s32 GetIdealVirtualCore() const { return this->virtual_ideal_core_id; }
|
||||
constexpr s32 GetIdealPhysicalCore() const { return this->physical_ideal_core_id; }
|
||||
|
||||
constexpr s32 GetIdealCore() const { return this->ideal_core_id; }
|
||||
constexpr s32 GetActiveCore() const { return this->core_id; }
|
||||
constexpr void SetActiveCore(s32 core) { this->core_id = core; }
|
||||
|
||||
|
||||
@@ -28,24 +28,3 @@
|
||||
#else
|
||||
#error "Unknown architecture for CPU"
|
||||
#endif
|
||||
|
||||
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
|
||||
|
||||
#include <mesosphere/board/nintendo/nx/kern_cpu_map.hpp>
|
||||
|
||||
namespace ams::kern::cpu {
|
||||
|
||||
using namespace ams::kern::board::nintendo::nx::impl::cpu;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Unknown board for CPU Map"
|
||||
#endif
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
static_assert(cpu::NumCores <= static_cast<s32>(BITSIZEOF(u64)));
|
||||
static_assert(util::size(cpu::VirtualToPhysicalCoreMap) == BITSIZEOF(u64));
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace ams::kern {
|
||||
u32 prev_intr_state;
|
||||
public:
|
||||
ALWAYS_INLINE KScopedInterruptDisable() : prev_intr_state(KInterruptManager::DisableInterrupts()) { /* ... */ }
|
||||
ALWAYS_INLINE ~KScopedInterruptDisable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
~KScopedInterruptDisable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
};
|
||||
|
||||
class KScopedInterruptEnable {
|
||||
@@ -52,7 +52,7 @@ namespace ams::kern {
|
||||
u32 prev_intr_state;
|
||||
public:
|
||||
ALWAYS_INLINE KScopedInterruptEnable() : prev_intr_state(KInterruptManager::EnableInterrupts()) { /* ... */ }
|
||||
ALWAYS_INLINE ~KScopedInterruptEnable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
~KScopedInterruptEnable() { KInterruptManager::RestoreInterrupts(prev_intr_state); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ namespace ams::kern::svc {
|
||||
|
||||
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O2")
|
||||
#pragma GCC optimize ("omit-frame-pointer")
|
||||
|
||||
AMS_SVC_FOREACH_KERN_DEFINITION(DECLARE_SVC_STRUCT, _)
|
||||
|
||||
@@ -182,9 +182,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
const KMemoryRegion *region = KMemoryLayout::Find(KPhysicalAddress(address));
|
||||
if (AMS_LIKELY(region != nullptr)) {
|
||||
if (AMS_LIKELY(region->IsDerivedFrom(KMemoryRegionType_MemoryController))) {
|
||||
/* Check the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Get the offset within the region. */
|
||||
const size_t offset = address - region->GetAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(offset < region->GetSize());
|
||||
@@ -213,9 +210,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
region->IsDerivedFrom(KMemoryRegionType_MemoryController0) ||
|
||||
region->IsDerivedFrom(KMemoryRegionType_MemoryController1))
|
||||
{
|
||||
/* Check the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Get the offset within the region. */
|
||||
const size_t offset = address - region->GetAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(offset < region->GetSize());
|
||||
@@ -455,8 +449,6 @@ namespace ams::kern::board::nintendo::nx {
|
||||
/* Configure the Kernel Carveout region. */
|
||||
{
|
||||
const auto carveout = KMemoryLayout::GetCarveoutRegionExtents();
|
||||
MESOSPHERE_ABORT_UNLESS(carveout.GetEndAddress() != 0);
|
||||
|
||||
smc::ConfigureCarveout(0, carveout.GetAddress(), carveout.GetSize());
|
||||
}
|
||||
|
||||
@@ -553,12 +545,12 @@ namespace ams::kern::board::nintendo::nx {
|
||||
if (arg != nullptr) {
|
||||
/* Get the address of the legacy IRAM region. */
|
||||
const KVirtualAddress iram_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_LegacyLpsIram) + 64_KB;
|
||||
constexpr size_t RebootPayloadSize = 0x24000;
|
||||
constexpr size_t RebootPayloadSize = 0x2E000;
|
||||
|
||||
/* NOTE: Atmosphere extension; if we received an exception context from Panic(), */
|
||||
/* generate a fatal error report using it. */
|
||||
const KExceptionContext *e_ctx = static_cast<const KExceptionContext *>(arg);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + 0x2E000);
|
||||
auto *f_ctx = GetPointer<::ams::impl::FatalErrorContext>(iram_address + RebootPayloadSize);
|
||||
|
||||
/* Clear the fatal context. */
|
||||
std::memset(f_ctx, 0xCC, sizeof(*f_ctx));
|
||||
|
||||
@@ -58,30 +58,28 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
/* Disable interrupts while making the call. */
|
||||
KScopedInterruptDisable intr_disable;
|
||||
|
||||
{
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
__asm__ __volatile__("smc #1"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
}
|
||||
|
||||
/* Store arguments to output. */
|
||||
args.x[0] = x0;
|
||||
args.x[1] = x1;
|
||||
args.x[2] = x2;
|
||||
args.x[3] = x3;
|
||||
args.x[4] = x4;
|
||||
args.x[5] = x5;
|
||||
args.x[6] = x6;
|
||||
args.x[7] = x7;
|
||||
}
|
||||
|
||||
void CallUserSecureMonitorFunction(ams::svc::lp64::SecureMonitorArguments *args) {
|
||||
@@ -100,30 +98,28 @@ namespace ams::kern::board::nintendo::nx::smc {
|
||||
/* Disable interrupts while making the call. */
|
||||
KScopedInterruptDisable intr_disable;
|
||||
|
||||
{
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
/* Backup the current thread pointer. */
|
||||
const uintptr_t current_thread_pointer_value = cpu::GetCurrentThreadPointerValue();
|
||||
|
||||
__asm__ __volatile__("smc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
__asm__ __volatile__("smc #0"
|
||||
: "+r"(x0), "+r"(x1), "+r"(x2), "+r"(x3), "+r"(x4), "+r"(x5), "+r"(x6), "+r"(x7)
|
||||
:
|
||||
: "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "cc", "memory"
|
||||
);
|
||||
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
|
||||
/* Store arguments to output. */
|
||||
args->r[0] = x0;
|
||||
args->r[1] = x1;
|
||||
args->r[2] = x2;
|
||||
args->r[3] = x3;
|
||||
args->r[4] = x4;
|
||||
args->r[5] = x5;
|
||||
args->r[6] = x6;
|
||||
args->r[7] = x7;
|
||||
}
|
||||
/* Restore the current thread pointer into X18. */
|
||||
cpu::SetCurrentThreadPointerValue(current_thread_pointer_value);
|
||||
}
|
||||
|
||||
/* Store arguments to output. */
|
||||
args->r[0] = x0;
|
||||
args->r[1] = x1;
|
||||
args->r[2] = x2;
|
||||
args->r[3] = x3;
|
||||
args->r[4] = x4;
|
||||
args->r[5] = x5;
|
||||
args->r[6] = x6;
|
||||
args->r[7] = x7;
|
||||
}
|
||||
|
||||
void CallPrivilegedSecureMonitorFunctionForInit(SecureMonitorArguments &args) {
|
||||
|
||||
@@ -39,9 +39,7 @@ namespace ams::kern::init {
|
||||
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ## __VA_ARGS__) \
|
||||
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \
|
||||
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \
|
||||
HANDLER(KAlpha, (SLAB_COUNT(KAlpha)), ## __VA_ARGS__) \
|
||||
HANDLER(KBeta, (SLAB_COUNT(KBeta)), ## __VA_ARGS__)
|
||||
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__)
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -70,8 +68,6 @@ namespace ams::kern::init {
|
||||
constexpr size_t SlabCountKObjectName = 7;
|
||||
constexpr size_t SlabCountKResourceLimit = 5;
|
||||
constexpr size_t SlabCountKDebug = cpu::NumCores;
|
||||
constexpr size_t SlabCountKAlpha = 1;
|
||||
constexpr size_t SlabCountKBeta = 6;
|
||||
|
||||
constexpr size_t SlabCountExtraKThread = 160;
|
||||
|
||||
@@ -98,8 +94,6 @@ namespace ams::kern::init {
|
||||
.num_KObjectName = SlabCountKObjectName,
|
||||
.num_KResourceLimit = SlabCountKResourceLimit,
|
||||
.num_KDebug = SlabCountKDebug,
|
||||
.num_KAlpha = SlabCountKAlpha,
|
||||
.num_KBeta = SlabCountKBeta,
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -51,22 +51,37 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
bool KDebugLogImpl::Initialize() {
|
||||
/* Get the uart memory region. */
|
||||
const KMemoryRegion *uart_region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_Uart);
|
||||
if (uart_region == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the uart register base address. */
|
||||
g_uart_address = uart_region->GetPairAddress();
|
||||
if (g_uart_address == Null<KVirtualAddress>) {
|
||||
return false;
|
||||
}
|
||||
g_uart_address = KMemoryLayout::GetDeviceVirtualAddress(KMemoryRegionType_Uart);
|
||||
|
||||
/* NOTE: We assume here that UART init/config has been done by the Secure Monitor. */
|
||||
/* As such, we only need to disable interrupts. */
|
||||
/* Parameters for uart. */
|
||||
constexpr u32 BaudRate = 115200;
|
||||
constexpr u32 Pllp = 408000000;
|
||||
constexpr u32 Rate = 16 * BaudRate;
|
||||
constexpr u32 Divisor = (Pllp + Rate / 2) / Rate;
|
||||
|
||||
/* Initialize the UART registers. */
|
||||
/* Set Divisor Latch Access bit, to allow access to DLL/DLH */
|
||||
WriteUartRegister(UartRegister_LCR, 0x80);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Program the divisor into DLL/DLH. */
|
||||
WriteUartRegister(UartRegister_DLL, Divisor & 0xFF);
|
||||
WriteUartRegister(UartRegister_DLH, (Divisor >> 8) & 0xFF);
|
||||
ReadUartRegister(UartRegister_DLH);
|
||||
|
||||
/* Set word length to 3, clear Divisor Latch Access. */
|
||||
WriteUartRegister(UartRegister_LCR, 0x03);
|
||||
ReadUartRegister(UartRegister_LCR);
|
||||
|
||||
/* Disable UART interrupts. */
|
||||
WriteUartRegister(UartRegister_IER, 0x00);
|
||||
|
||||
/* Configure the FIFO to be enabled and clear receive. */
|
||||
WriteUartRegister(UartRegister_FCR, 0x03);
|
||||
WriteUartRegister(UartRegister_IRDA_CSR, 0x02);
|
||||
ReadUartRegister(UartRegister_FCR);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,7 @@ namespace ams::kern {
|
||||
};
|
||||
|
||||
KVirtualAddress GetInitialProcessBinaryAddress() {
|
||||
const uintptr_t end_address = KMemoryLayout::GetPageTableHeapRegion().GetEndAddress();
|
||||
MESOSPHERE_ABORT_UNLESS(end_address != 0);
|
||||
return end_address - InitialProcessBinarySizeMax;
|
||||
return KMemoryLayout::GetPageTableHeapRegion().GetEndAddress() - InitialProcessBinarySizeMax;
|
||||
}
|
||||
|
||||
void LoadInitialProcessBinaryHeader(InitialProcessBinaryHeader *header) {
|
||||
@@ -99,11 +97,8 @@ namespace ams::kern {
|
||||
/* Ensure that we do not leak pages. */
|
||||
ON_SCOPE_EXIT { pg.Close(); };
|
||||
|
||||
/* Get the temporary region. */
|
||||
const auto &temp_region = KMemoryLayout::GetTempRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(temp_region.GetEndAddress() != 0);
|
||||
|
||||
/* Map the process's memory into the temporary region. */
|
||||
const auto &temp_region = KMemoryLayout::GetTempRegion();
|
||||
KProcessAddress temp_address = Null<KProcessAddress>;
|
||||
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().MapPageGroup(std::addressof(temp_address), pg, temp_region.GetAddress(), temp_region.GetSize() / PageSize, KMemoryState_Kernel, KMemoryPermission_KernelReadWrite));
|
||||
|
||||
|
||||
@@ -50,8 +50,9 @@ namespace ams::kern {
|
||||
s32 num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
@@ -78,7 +79,10 @@ namespace ams::kern {
|
||||
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(user_value == value, svc::ResultInvalidState());
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
target_thread->SetSyncedObject(nullptr, ResultSuccess());
|
||||
@@ -99,8 +103,10 @@ namespace ams::kern {
|
||||
s32 num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
|
||||
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
|
||||
auto it = this->tree.nfind_light({ addr, -1 });
|
||||
/* Determine the updated value. */
|
||||
s32 new_value;
|
||||
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
constinit KThread g_cv_arbiter_compare_thread;
|
||||
|
||||
namespace {
|
||||
|
||||
ALWAYS_INLINE bool ReadFromUser(u32 *out, KProcessAddress address) {
|
||||
@@ -177,8 +179,9 @@ namespace ams::kern {
|
||||
int num_waiters = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
g_cv_arbiter_compare_thread.SetupForConditionVariableCompare(cv_key, -1);
|
||||
|
||||
auto it = this->tree.nfind_light({ cv_key, -1 });
|
||||
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
|
||||
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
||||
KThread *target_thread = std::addressof(*it);
|
||||
|
||||
@@ -194,12 +197,6 @@ namespace ams::kern {
|
||||
target_thread->ClearConditionVariable();
|
||||
++num_waiters;
|
||||
}
|
||||
|
||||
/* If we have no waiters, clear the has waiter flag. */
|
||||
if (it == this->tree.end() || it->GetConditionVariableKey() != cv_key) {
|
||||
const u32 has_waiter_flag = 0;
|
||||
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
||||
}
|
||||
}
|
||||
|
||||
/* Close threads in the array. */
|
||||
@@ -250,13 +247,6 @@ namespace ams::kern {
|
||||
next_owner_thread->Wakeup();
|
||||
}
|
||||
|
||||
/* Write to the cv key. */
|
||||
{
|
||||
const u32 has_waiter_flag = 1;
|
||||
WriteToUser(key, std::addressof(has_waiter_flag));
|
||||
cpu::DataMemoryBarrier();
|
||||
}
|
||||
|
||||
/* Write the value to userspace. */
|
||||
if (!WriteToUser(addr, std::addressof(next_value))) {
|
||||
slp.CancelSleep();
|
||||
|
||||
@@ -55,7 +55,6 @@ namespace ams::kern {
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(start, size, phys_type, attr));
|
||||
const KMemoryRegion *phys = KMemoryLayout::GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(phys_type, attr);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(phys != nullptr);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(phys->GetEndAddress() != 0);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size, virt_type, attr));
|
||||
}
|
||||
|
||||
@@ -105,7 +104,6 @@ namespace ams::kern {
|
||||
void SetupPoolPartitionMemoryRegions() {
|
||||
/* Start by identifying the extents of the DRAM memory region. */
|
||||
const auto dram_extents = KMemoryLayout::GetMainMemoryPhysicalExtents();
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(dram_extents.GetEndAddress() != 0);
|
||||
|
||||
/* Determine the end of the pool region. */
|
||||
const uintptr_t pool_end = dram_extents.GetEndAddress() - KTraceBufferSize;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace ams::kern {
|
||||
NON_COPYABLE(KMemoryRegionAllocator);
|
||||
NON_MOVEABLE(KMemoryRegionAllocator);
|
||||
public:
|
||||
static constexpr size_t MaxMemoryRegions = 200;
|
||||
static constexpr size_t MaxMemoryRegions = 1000;
|
||||
private:
|
||||
KMemoryRegion region_heap[MaxMemoryRegions];
|
||||
size_t num_regions;
|
||||
@@ -40,6 +40,8 @@ namespace ams::kern {
|
||||
new (region) KMemoryRegion(std::forward<Args>(args)...);
|
||||
|
||||
return region;
|
||||
|
||||
return &this->region_heap[this->num_regions++];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,8 +55,8 @@ namespace ams::kern {
|
||||
|
||||
}
|
||||
|
||||
void KMemoryRegionTree::InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr, u32 type_id) {
|
||||
this->insert(*AllocateRegion(address, last_address, attr, type_id));
|
||||
void KMemoryRegionTree::InsertDirectly(uintptr_t address, size_t size, u32 attr, u32 type_id) {
|
||||
this->insert(*AllocateRegion(address, size, attr, type_id));
|
||||
}
|
||||
|
||||
bool KMemoryRegionTree::Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr, u32 old_attr) {
|
||||
@@ -80,7 +82,9 @@ namespace ams::kern {
|
||||
|
||||
/* Cache information from the region before we remove it. */
|
||||
const uintptr_t old_address = found->GetAddress();
|
||||
const uintptr_t old_last = found->GetLastAddress();
|
||||
const size_t old_size = found->GetSize();
|
||||
const uintptr_t old_end = old_address + old_size;
|
||||
const uintptr_t old_last = old_end - 1;
|
||||
const uintptr_t old_pair = found->GetPairAddress();
|
||||
const u32 old_type = found->GetType();
|
||||
|
||||
@@ -88,24 +92,24 @@ namespace ams::kern {
|
||||
this->erase(this->iterator_to(*found));
|
||||
|
||||
/* Insert the new region into the tree. */
|
||||
const uintptr_t new_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (address - old_address) : old_pair;
|
||||
if (old_address == address) {
|
||||
/* Reuse the old object for the new region, if we can. */
|
||||
found->Reset(address, inserted_region_last, old_pair, new_attr, type_id);
|
||||
found->Reset(address, size, new_pair, new_attr, type_id);
|
||||
this->insert(*found);
|
||||
} else {
|
||||
/* If we can't re-use, adjust the old region. */
|
||||
found->Reset(old_address, address - 1, old_pair, old_attr, old_type);
|
||||
found->Reset(old_address, address - old_address, old_pair, old_attr, old_type);
|
||||
this->insert(*found);
|
||||
|
||||
/* Insert a new region for the split. */
|
||||
const uintptr_t new_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (address - old_address) : old_pair;
|
||||
this->insert(*AllocateRegion(address, inserted_region_last, new_pair, new_attr, type_id));
|
||||
this->insert(*AllocateRegion(address, size, new_pair, new_attr, type_id));
|
||||
}
|
||||
|
||||
/* If we need to insert a region after the region, do so. */
|
||||
if (old_last != inserted_region_last) {
|
||||
const uintptr_t after_pair = (old_pair != std::numeric_limits<uintptr_t>::max()) ? old_pair + (inserted_region_end - old_address) : old_pair;
|
||||
this->insert(*AllocateRegion(inserted_region_end, old_last, after_pair, old_attr, old_type));
|
||||
this->insert(*AllocateRegion(inserted_region_end, old_end - inserted_region_end, after_pair, old_attr, old_type));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -121,11 +125,8 @@ namespace ams::kern {
|
||||
const uintptr_t first_address = extents.GetAddress();
|
||||
const uintptr_t last_address = extents.GetLastAddress();
|
||||
|
||||
const uintptr_t first_index = first_address / alignment;
|
||||
const uintptr_t last_index = last_address / alignment;
|
||||
|
||||
while (true) {
|
||||
const uintptr_t candidate = KSystemControl::Init::GenerateRandomRange(first_index, last_index) * alignment;
|
||||
const uintptr_t candidate = util::AlignDown(KSystemControl::Init::GenerateRandomRange(first_address, last_address), alignment);
|
||||
|
||||
/* Ensure that the candidate doesn't overflow with the size. */
|
||||
if (!(candidate < candidate + size)) {
|
||||
@@ -156,13 +157,13 @@ namespace ams::kern {
|
||||
/* Initialize linear trees. */
|
||||
for (auto ®ion : GetPhysicalMemoryRegionTree()) {
|
||||
if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
|
||||
GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType());
|
||||
GetPhysicalLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto ®ion : GetVirtualMemoryRegionTree()) {
|
||||
if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
|
||||
GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetLastAddress(), region.GetAttributes(), region.GetType());
|
||||
GetVirtualLinearMemoryRegionTree().InsertDirectly(region.GetAddress(), region.GetSize(), region.GetAttributes(), region.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,16 +20,12 @@ namespace ams::kern {
|
||||
namespace {
|
||||
|
||||
constexpr KMemoryManager::Pool GetPoolFromMemoryRegionType(u32 type) {
|
||||
if ((type | KMemoryRegionType_VirtualDramApplicationPool) == type) {
|
||||
return KMemoryManager::Pool_Application;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramAppletPool) == type) {
|
||||
return KMemoryManager::Pool_Applet;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramSystemPool) == type) {
|
||||
return KMemoryManager::Pool_System;
|
||||
} else if ((type | KMemoryRegionType_VirtualDramSystemNonSecurePool) == type) {
|
||||
return KMemoryManager::Pool_SystemNonSecure;
|
||||
} else {
|
||||
MESOSPHERE_PANIC("InvalidMemoryRegionType for conversion to Pool");
|
||||
switch (type) {
|
||||
case KMemoryRegionType_VirtualDramApplicationPool: return KMemoryManager::Pool_Application;
|
||||
case KMemoryRegionType_VirtualDramAppletPool: return KMemoryManager::Pool_Applet;
|
||||
case KMemoryRegionType_VirtualDramSystemPool: return KMemoryManager::Pool_System;
|
||||
case KMemoryRegionType_VirtualDramSystemNonSecurePool: return KMemoryManager::Pool_SystemNonSecure;
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +37,9 @@ namespace ams::kern {
|
||||
std::memset(GetVoidPointer(management_region), 0, management_region_size);
|
||||
|
||||
/* Traverse the virtual memory layout tree, initializing each manager as appropriate. */
|
||||
while (this->num_managers != MaxManagerCount) {
|
||||
while (true) {
|
||||
/* Locate the region that should initialize the current manager. */
|
||||
uintptr_t region_address = 0;
|
||||
size_t region_size = 0;
|
||||
Pool region_pool = Pool_Count;
|
||||
const KMemoryRegion *region = nullptr;
|
||||
for (const auto &it : KMemoryLayout::GetVirtualMemoryRegionTree()) {
|
||||
/* We only care about regions that we need to create managers for. */
|
||||
if (!it.IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)) {
|
||||
@@ -57,62 +51,39 @@ namespace ams::kern {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Validate the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(it.GetEndAddress() != 0);
|
||||
MESOSPHERE_ASSERT(it.GetAddress() != Null<decltype(it.GetAddress())>);
|
||||
MESOSPHERE_ASSERT(it.GetSize() > 0);
|
||||
|
||||
/* Update the region's extents. */
|
||||
if (region_address == 0) {
|
||||
region_address = it.GetAddress();
|
||||
region_size = it.GetSize();
|
||||
region_pool = GetPoolFromMemoryRegionType(it.GetType());
|
||||
} else {
|
||||
MESOSPHERE_ASSERT(it.GetAddress() == region_address + region_size);
|
||||
|
||||
/* Update the size. */
|
||||
region_size = it.GetEndAddress() - region_address;
|
||||
MESOSPHERE_ABORT_UNLESS(GetPoolFromMemoryRegionType(it.GetType()) == region_pool);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we didn't find a region, we're done. */
|
||||
if (region_size == 0) {
|
||||
region = std::addressof(it);
|
||||
break;
|
||||
}
|
||||
|
||||
/* If we didn't find a region, then we're done initializing managers. */
|
||||
if (region == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ensure that the region is correct. */
|
||||
MESOSPHERE_ASSERT(region->GetAddress() != Null<decltype(region->GetAddress())>);
|
||||
MESOSPHERE_ASSERT(region->GetSize() > 0);
|
||||
MESOSPHERE_ASSERT(region->GetEndAddress() >= region->GetAddress());
|
||||
MESOSPHERE_ASSERT(region->IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool));
|
||||
MESOSPHERE_ASSERT(region->GetAttributes() == this->num_managers);
|
||||
|
||||
/* Initialize a new manager for the region. */
|
||||
const Pool pool = GetPoolFromMemoryRegionType(region->GetType());
|
||||
Impl *manager = std::addressof(this->managers[this->num_managers++]);
|
||||
MESOSPHERE_ABORT_UNLESS(this->num_managers <= util::size(this->managers));
|
||||
|
||||
const size_t cur_size = manager->Initialize(region_address, region_size, management_region, management_region_end, region_pool);
|
||||
const size_t cur_size = manager->Initialize(region, pool, management_region, management_region_end);
|
||||
management_region += cur_size;
|
||||
MESOSPHERE_ABORT_UNLESS(management_region <= management_region_end);
|
||||
|
||||
/* Insert the manager into the pool list. */
|
||||
if (this->pool_managers_tail[region_pool] == nullptr) {
|
||||
this->pool_managers_head[region_pool] = manager;
|
||||
if (this->pool_managers_tail[pool] == nullptr) {
|
||||
this->pool_managers_head[pool] = manager;
|
||||
} else {
|
||||
this->pool_managers_tail[region_pool]->SetNext(manager);
|
||||
manager->SetPrev(this->pool_managers_tail[region_pool]);
|
||||
this->pool_managers_tail[pool]->SetNext(manager);
|
||||
manager->SetPrev(this->pool_managers_tail[pool]);
|
||||
}
|
||||
this->pool_managers_tail[region_pool] = manager;
|
||||
}
|
||||
|
||||
/* Free each region to its corresponding heap. */
|
||||
for (const auto &it : KMemoryLayout::GetVirtualMemoryRegionTree()) {
|
||||
if (it.IsDerivedFrom(KMemoryRegionType_VirtualDramUserPool)) {
|
||||
/* Check the region. */
|
||||
MESOSPHERE_ABORT_UNLESS(it.GetEndAddress() != 0);
|
||||
|
||||
/* Free the memory to the heap. */
|
||||
this->managers[it.GetAttributes()].Free(it.GetAddress(), it.GetSize() / PageSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the used size for all managers. */
|
||||
for (size_t i = 0; i < this->num_managers; ++i) {
|
||||
this->managers[i].UpdateUsedHeapSize();
|
||||
this->pool_managers_tail[pool] = manager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,12 +354,12 @@ namespace ams::kern {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
size_t KMemoryManager::Impl::Initialize(uintptr_t address, size_t size, KVirtualAddress management, KVirtualAddress management_end, Pool p) {
|
||||
size_t KMemoryManager::Impl::Initialize(const KMemoryRegion *region, Pool p, KVirtualAddress management, KVirtualAddress management_end) {
|
||||
/* Calculate management sizes. */
|
||||
const size_t ref_count_size = (size / PageSize) * sizeof(u16);
|
||||
const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(size);
|
||||
const size_t ref_count_size = (region->GetSize() / PageSize) * sizeof(u16);
|
||||
const size_t optimize_map_size = CalculateOptimizedProcessOverheadSize(region->GetSize());
|
||||
const size_t manager_size = util::AlignUp(optimize_map_size + ref_count_size, PageSize);
|
||||
const size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(size);
|
||||
const size_t page_heap_size = KPageHeap::CalculateManagementOverheadSize(region->GetSize());
|
||||
const size_t total_management_size = manager_size + page_heap_size;
|
||||
MESOSPHERE_ABORT_UNLESS(manager_size <= total_management_size);
|
||||
MESOSPHERE_ABORT_UNLESS(management + total_management_size <= management_end);
|
||||
@@ -401,7 +372,13 @@ namespace ams::kern {
|
||||
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(this->management_region), PageSize));
|
||||
|
||||
/* Initialize the manager's KPageHeap. */
|
||||
this->heap.Initialize(address, size, management + manager_size, page_heap_size);
|
||||
this->heap.Initialize(region->GetAddress(), region->GetSize(), management + manager_size, page_heap_size);
|
||||
|
||||
/* Free the memory to the heap. */
|
||||
this->heap.Free(region->GetAddress(), region->GetSize() / PageSize);
|
||||
|
||||
/* Update the heap's used size. */
|
||||
this->heap.UpdateUsedSize();
|
||||
|
||||
return total_management_size;
|
||||
}
|
||||
|
||||
@@ -908,7 +908,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Check if we're done. */
|
||||
if (dst_address + size - 1 <= info.GetLastAddress()) {
|
||||
if (dst_address + size - 1 > info.GetLastAddress()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1807,9 +1807,6 @@ namespace ams::kern {
|
||||
const KMemoryRegion *region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(region_type);
|
||||
R_UNLESS(region != nullptr, svc::ResultOutOfRange());
|
||||
|
||||
/* Check that the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
/* Map the region. */
|
||||
R_TRY_CATCH(this->MapStatic(region->GetAddress(), region->GetSize(), perm)) {
|
||||
R_CONVERT(svc::ResultInvalidAddress, svc::ResultOutOfRange())
|
||||
@@ -3054,9 +3051,6 @@ namespace ams::kern {
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
Result KPageTableBase::SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state) {
|
||||
/* Validate pre-conditions. */
|
||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||
@@ -3710,8 +3704,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
Result KPageTableBase::MapPhysicalMemory(KProcessAddress address, size_t size) {
|
||||
/* Lock the physical memory lock. */
|
||||
KScopedLightLock phys_lk(this->map_physical_memory_lock);
|
||||
|
||||
@@ -129,17 +129,6 @@ namespace ams::kern {
|
||||
}
|
||||
}
|
||||
|
||||
/* Close all references to our betas. */
|
||||
{
|
||||
auto it = this->beta_list.begin();
|
||||
while (it != this->beta_list.end()) {
|
||||
KBeta *beta = std::addressof(*it);
|
||||
it = this->beta_list.erase(it);
|
||||
|
||||
beta->Close();
|
||||
}
|
||||
}
|
||||
|
||||
/* Our thread local page list must be empty at this point. */
|
||||
MESOSPHERE_ABORT_UNLESS(this->partially_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(this->fully_used_tlp_tree.empty());
|
||||
@@ -933,7 +922,7 @@ namespace ams::kern {
|
||||
mem_reservation.Commit();
|
||||
|
||||
/* Note for debug that we're running a new process. */
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetVirtualAffinityMask(), main_thread->GetIdealVirtualCore(), main_thread->GetActiveCore());
|
||||
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetAffinityMask().GetAffinityMask(), main_thread->GetIdealCore(), main_thread->GetActiveCore());
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
namespace ipc {
|
||||
|
||||
using MessageBuffer = ams::svc::ipc::MessageBuffer;
|
||||
@@ -1365,6 +1362,4 @@ namespace ams::kern {
|
||||
this->NotifyAvailable(svc::ResultSessionClosed());
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -38,17 +38,13 @@ namespace ams::kern {
|
||||
|
||||
}
|
||||
|
||||
Result KThread::Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess *owner, ThreadType type) {
|
||||
Result KThread::Initialize(KThreadFunction func, uintptr_t arg, void *kern_stack_top, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type) {
|
||||
/* Assert parameters are valid. */
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(kern_stack_top != nullptr);
|
||||
MESOSPHERE_ASSERT((type == ThreadType_Main) || (ams::svc::HighestThreadPriority <= prio && prio <= ams::svc::LowestThreadPriority));
|
||||
MESOSPHERE_ASSERT((owner != nullptr) || (type != ThreadType_User));
|
||||
MESOSPHERE_ASSERT(0 <= virt_core && virt_core < static_cast<s32>(BITSIZEOF(u64)));
|
||||
|
||||
/* Convert the virtual core to a physical core. */
|
||||
const s32 phys_core = cpu::VirtualToPhysicalCoreMap[virt_core];
|
||||
MESOSPHERE_ASSERT(0 <= phys_core && phys_core < static_cast<s32>(cpu::NumCores));
|
||||
MESOSPHERE_ASSERT(0 <= core && core < static_cast<s32>(cpu::NumCores));
|
||||
|
||||
/* First, clear the TLS address. */
|
||||
this->tls_address = Null<KProcessAddress>;
|
||||
@@ -63,8 +59,8 @@ namespace ams::kern {
|
||||
}
|
||||
[[fallthrough]];
|
||||
case ThreadType_HighPriority:
|
||||
if (type != ThreadType_Main) {
|
||||
MESOSPHERE_ASSERT(phys_core == GetCurrentCoreId());
|
||||
{
|
||||
MESOSPHERE_ASSERT(core == GetCurrentCoreId());
|
||||
}
|
||||
[[fallthrough]];
|
||||
case ThreadType_Kernel:
|
||||
@@ -75,8 +71,8 @@ namespace ams::kern {
|
||||
[[fallthrough]];
|
||||
case ThreadType_User:
|
||||
{
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ul << virt_core)) == owner->GetCoreMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetPriorityMask() | (1ul << prio)) == owner->GetPriorityMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetCoreMask() | (1ul << core)) == owner->GetCoreMask()));
|
||||
MESOSPHERE_ASSERT(((owner == nullptr) || (owner->GetPriorityMask() | (1ul << prio)) == owner->GetPriorityMask()));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -85,10 +81,8 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* Set the ideal core ID and affinity mask. */
|
||||
this->virtual_ideal_core_id = virt_core;
|
||||
this->physical_ideal_core_id = phys_core;
|
||||
this->virtual_affinity_mask = (static_cast<u64>(1) << virt_core);
|
||||
this->physical_affinity_mask.SetAffinity(phys_core, true);
|
||||
this->ideal_core_id = core;
|
||||
this->affinity_mask.SetAffinity(core, true);
|
||||
|
||||
/* Set the thread state. */
|
||||
this->thread_state = (type == ThreadType_Main) ? ThreadState_Runnable : ThreadState_Initialized;
|
||||
@@ -109,7 +103,7 @@ namespace ams::kern {
|
||||
this->cancellable = false;
|
||||
|
||||
/* Set core ID and wait result. */
|
||||
this->core_id = phys_core;
|
||||
this->core_id = this->ideal_core_id;
|
||||
this->wait_result = svc::ResultNoSynchronizationObject();
|
||||
|
||||
/* Set the stack top. */
|
||||
@@ -147,7 +141,7 @@ namespace ams::kern {
|
||||
this->num_kernel_waiters = 0;
|
||||
|
||||
/* Set our current core id. */
|
||||
this->current_core_id = phys_core;
|
||||
this->current_core_id = core;
|
||||
|
||||
/* We haven't released our resource limit hint, and we've spent no time on the cpu. */
|
||||
this->resource_limit_release_hint = 0;
|
||||
@@ -207,7 +201,6 @@ namespace ams::kern {
|
||||
Result KThread::InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type) {
|
||||
/* Get stack region for the thread. */
|
||||
const auto &stack_region = KMemoryLayout::GetKernelStackRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(stack_region.GetEndAddress() != 0);
|
||||
|
||||
/* Allocate a page to use as the thread. */
|
||||
KPageBuffer *page = KPageBuffer::Allocate();
|
||||
@@ -397,19 +390,20 @@ namespace ams::kern {
|
||||
++this->num_core_migration_disables;
|
||||
|
||||
/* Save our ideal state to restore when we're unpinned. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
this->original_ideal_core_id = this->ideal_core_id;
|
||||
this->original_affinity_mask = this->affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
const s32 current_core = GetCurrentCoreId();
|
||||
|
||||
this->SetActiveCore(current_core);
|
||||
this->physical_ideal_core_id = current_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
this->ideal_core_id = current_core;
|
||||
|
||||
if (active_core != current_core || this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
this->affinity_mask.SetAffinityMask(1ul << current_core);
|
||||
|
||||
if (active_core != current_core || this->affinity_mask.GetAffinityMask() != this->original_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,19 +438,19 @@ namespace ams::kern {
|
||||
--this->num_core_migration_disables;
|
||||
|
||||
/* Restore our original state. */
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
this->ideal_core_id = this->original_ideal_core_id;
|
||||
this->affinity_mask = this->original_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -498,16 +492,16 @@ namespace ams::kern {
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
if ((this->num_core_migration_disables++) == 0) {
|
||||
/* Save our ideal state to restore when we can migrate again. */
|
||||
this->original_physical_ideal_core_id = this->physical_ideal_core_id;
|
||||
this->original_physical_affinity_mask = this->physical_affinity_mask;
|
||||
this->original_ideal_core_id = this->ideal_core_id;
|
||||
this->original_affinity_mask = this->affinity_mask;
|
||||
|
||||
/* Bind ourselves to this core. */
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
this->physical_ideal_core_id = active_core;
|
||||
this->physical_affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
this->ideal_core_id = active_core;
|
||||
this->affinity_mask.SetAffinityMask(1ul << active_core);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != this->original_physical_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_physical_affinity_mask, active_core);
|
||||
if (this->affinity_mask.GetAffinityMask() != this->original_affinity_mask.GetAffinityMask()) {
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, this->original_affinity_mask, active_core);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -519,20 +513,20 @@ namespace ams::kern {
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables > 0);
|
||||
if ((--this->num_core_migration_disables) == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
/* Restore our ideals. */
|
||||
this->physical_ideal_core_id = this->original_physical_ideal_core_id;
|
||||
this->physical_affinity_mask = this->original_physical_affinity_mask;
|
||||
this->ideal_core_id = this->original_ideal_core_id;
|
||||
this->affinity_mask = this->original_affinity_mask;
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (!this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->physical_ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->physical_ideal_core_id);
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
if (this->ideal_core_id >= 0) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask()));
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
@@ -541,19 +535,6 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
Result KThread::GetCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
|
||||
/* Get the virtual mask. */
|
||||
*out_ideal_core = this->virtual_ideal_core_id;
|
||||
*out_affinity_mask = this->virtual_affinity_mask;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KThread::GetPhysicalCoreMask(int32_t *out_ideal_core, u64 *out_affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
@@ -561,72 +542,63 @@ namespace ams::kern {
|
||||
|
||||
/* Select between core mask and original core mask. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
*out_ideal_core = this->physical_ideal_core_id;
|
||||
*out_affinity_mask = this->physical_affinity_mask.GetAffinityMask();
|
||||
*out_ideal_core = this->ideal_core_id;
|
||||
*out_affinity_mask = this->affinity_mask.GetAffinityMask();
|
||||
} else {
|
||||
*out_ideal_core = this->original_physical_ideal_core_id;
|
||||
*out_affinity_mask = this->original_physical_affinity_mask.GetAffinityMask();
|
||||
*out_ideal_core = this->original_ideal_core_id;
|
||||
*out_affinity_mask = this->original_affinity_mask.GetAffinityMask();
|
||||
}
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KThread::SetCoreMask(int32_t core_id, u64 v_affinity_mask) {
|
||||
Result KThread::SetCoreMask(int32_t ideal_core, u64 affinity_mask) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(this->parent != nullptr);
|
||||
MESOSPHERE_ASSERT(v_affinity_mask != 0);
|
||||
MESOSPHERE_ASSERT(affinity_mask != 0);
|
||||
KScopedLightLock lk(this->activity_pause_lock);
|
||||
|
||||
/* Set the core mask. */
|
||||
u64 p_affinity_mask = 0;
|
||||
{
|
||||
KScopedSchedulerLock sl;
|
||||
MESOSPHERE_ASSERT(this->num_core_migration_disables >= 0);
|
||||
|
||||
/* If the core id is no-update magic, preserve the ideal core id. */
|
||||
if (core_id == ams::svc::IdealCoreNoUpdate) {
|
||||
core_id = this->virtual_ideal_core_id;
|
||||
R_UNLESS(((1ul << core_id) & v_affinity_mask) != 0, svc::ResultInvalidCombination());
|
||||
}
|
||||
if (ideal_core == ams::svc::IdealCoreNoUpdate) {
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
ideal_core = this->ideal_core_id;
|
||||
} else {
|
||||
ideal_core = this->original_ideal_core_id;
|
||||
}
|
||||
|
||||
/* Set the virtual core/affinity mask. */
|
||||
this->virtual_ideal_core_id = core_id;
|
||||
this->virtual_affinity_mask = v_affinity_mask;
|
||||
|
||||
/* Translate the virtual core to a physical core. */
|
||||
if (core_id >= 0) {
|
||||
core_id = cpu::VirtualToPhysicalCoreMap[core_id];
|
||||
}
|
||||
|
||||
/* Translate the virtual affinity mask to a physical one. */
|
||||
while (v_affinity_mask != 0) {
|
||||
const u64 next = __builtin_ctzll(v_affinity_mask);
|
||||
v_affinity_mask &= ~(1ul << next);
|
||||
p_affinity_mask |= (1ul << cpu::VirtualToPhysicalCoreMap[next]);
|
||||
R_UNLESS(((1ul << ideal_core) & affinity_mask) != 0, svc::ResultInvalidCombination());
|
||||
}
|
||||
|
||||
/* If we haven't disabled migration, perform an affinity change. */
|
||||
if (this->num_core_migration_disables == 0) {
|
||||
const KAffinityMask old_mask = this->physical_affinity_mask;
|
||||
const KAffinityMask old_mask = this->affinity_mask;
|
||||
|
||||
/* Set our new ideals. */
|
||||
this->physical_ideal_core_id = core_id;
|
||||
this->physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
this->ideal_core_id = ideal_core;
|
||||
this->affinity_mask.SetAffinityMask(affinity_mask);
|
||||
|
||||
if (this->physical_affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
if (this->affinity_mask.GetAffinityMask() != old_mask.GetAffinityMask()) {
|
||||
const s32 active_core = this->GetActiveCore();
|
||||
|
||||
if (active_core >= 0 && !this->physical_affinity_mask.GetAffinity(active_core)) {
|
||||
const s32 new_core = this->physical_ideal_core_id >= 0 ? this->physical_ideal_core_id : BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->physical_affinity_mask.GetAffinityMask());
|
||||
this->SetActiveCore(new_core);
|
||||
if (active_core >= 0) {
|
||||
if (!this->affinity_mask.GetAffinity(active_core)) {
|
||||
this->SetActiveCore(this->ideal_core_id);
|
||||
} else {
|
||||
this->SetActiveCore(BITSIZEOF(unsigned long long) - 1 - __builtin_clzll(this->affinity_mask.GetAffinityMask()));
|
||||
}
|
||||
}
|
||||
KScheduler::OnThreadAffinityMaskChanged(this, old_mask, active_core);
|
||||
}
|
||||
} else {
|
||||
/* Otherwise, we edit the original affinity for restoration later. */
|
||||
this->original_physical_ideal_core_id = core_id;
|
||||
this->original_physical_affinity_mask.SetAffinityMask(p_affinity_mask);
|
||||
this->original_ideal_core_id = ideal_core;
|
||||
this->original_affinity_mask.SetAffinityMask(affinity_mask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -655,7 +627,7 @@ namespace ams::kern {
|
||||
}
|
||||
|
||||
/* If the thread is currently running, check whether it's no longer allowed under the new mask. */
|
||||
if (thread_is_current && ((1ul << thread_core) & p_affinity_mask) == 0) {
|
||||
if (thread_is_current && ((1ul << thread_core) & affinity_mask) == 0) {
|
||||
/* If the thread is pinned, we want to wait until it's not pinned. */
|
||||
if (this->GetStackParameters().is_pinned) {
|
||||
/* Verify that the current thread isn't terminating. */
|
||||
@@ -1155,7 +1127,7 @@ namespace ams::kern {
|
||||
|
||||
/* If the thread is runnable, send a termination interrupt to other cores. */
|
||||
if (this->GetState() == ThreadState_Runnable) {
|
||||
if (const u64 core_mask = this->physical_affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
if (const u64 core_mask = this->affinity_mask.GetAffinityMask() & ~(1ul << GetCurrentCoreId()); core_mask != 0) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_ThreadTerminate, core_mask);
|
||||
}
|
||||
|
||||
@@ -52,8 +52,6 @@ namespace ams::kern {
|
||||
/* Initialize the memory manager and the KPageBuffer slabheap. */
|
||||
{
|
||||
const auto &management_region = KMemoryLayout::GetPoolManagementRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(management_region.GetEndAddress() != 0);
|
||||
|
||||
Kernel::GetMemoryManager().Initialize(management_region.GetAddress(), management_region.GetSize());
|
||||
init::InitializeKPageBufferSlabHeap();
|
||||
}
|
||||
@@ -70,8 +68,6 @@ namespace ams::kern {
|
||||
/* Initialize the Dynamic Slab Heaps. */
|
||||
{
|
||||
const auto &pt_heap_region = KMemoryLayout::GetPageTableHeapRegion();
|
||||
MESOSPHERE_ABORT_UNLESS(pt_heap_region.GetEndAddress() != 0);
|
||||
|
||||
Kernel::InitializeResourceManagers(pt_heap_region.GetAddress(), pt_heap_region.GetSize());
|
||||
}
|
||||
}
|
||||
@@ -128,13 +124,6 @@ namespace ams::kern {
|
||||
|
||||
/* Resume all threads suspended while we initialized. */
|
||||
KThread::ResumeThreadsSuspendedForInit();
|
||||
|
||||
/* Validate that all reserved dram blocks are valid. */
|
||||
for (const auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
|
||||
if (region.IsDerivedFrom(KMemoryRegionType_DramReservedBase)) {
|
||||
MESOSPHERE_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
|
||||
@@ -92,9 +92,6 @@ namespace ams::kern::svc {
|
||||
/* Ensure that we found the region. */
|
||||
R_UNLESS(region != nullptr, svc::ResultNotFound());
|
||||
|
||||
/* Chcek that the region is valid. */
|
||||
MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0);
|
||||
|
||||
R_TRY(pt.QueryStaticMapping(std::addressof(found_address), region->GetAddress(), region->GetSize()));
|
||||
found_size = region->GetSize();
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
/* ============================= Common ============================= */
|
||||
|
||||
namespace {
|
||||
|
||||
Result Unknown39() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown3A() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown46() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
Result Unknown47() {
|
||||
return svc::ResultNotImplemented();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ============================= 64 ABI ============================= */
|
||||
|
||||
Result Unknown3964() {
|
||||
return Unknown39();
|
||||
}
|
||||
|
||||
Result Unknown3A64() {
|
||||
/* NOTE: From official stubs, true API to this is something like Unknown3A(u64 *, u32_or_u64, u64, u64, u64_or_u32, u64_or_u32); */
|
||||
return Unknown3A();
|
||||
}
|
||||
|
||||
Result Unknown4664() {
|
||||
return Unknown46();
|
||||
}
|
||||
|
||||
Result Unknown4764() {
|
||||
return Unknown47();
|
||||
}
|
||||
|
||||
/* ============================= 64From32 ABI ============================= */
|
||||
|
||||
Result Unknown3964From32() {
|
||||
return Unknown39();
|
||||
}
|
||||
|
||||
Result Unknown3A64From32() {
|
||||
return Unknown3A();
|
||||
}
|
||||
|
||||
Result Unknown4664From32() {
|
||||
return Unknown46();
|
||||
}
|
||||
|
||||
Result Unknown4764From32() {
|
||||
return Unknown47();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -363,11 +363,7 @@ namespace ams::kern::svc {
|
||||
case ams::svc::DebugThreadParam_IdealCore:
|
||||
{
|
||||
/* Get the ideal core. */
|
||||
s32 core_id;
|
||||
u64 affinity_mask;
|
||||
thread->GetPhysicalCoreMask(std::addressof(core_id), std::addressof(affinity_mask));
|
||||
|
||||
*out_32 = core_id;
|
||||
*out_32 = thread->GetIdealCore();
|
||||
}
|
||||
break;
|
||||
case ams::svc::DebugThreadParam_CurrentCore:
|
||||
@@ -379,11 +375,7 @@ namespace ams::kern::svc {
|
||||
case ams::svc::DebugThreadParam_AffinityMask:
|
||||
{
|
||||
/* Get the affinity mask. */
|
||||
s32 core_id;
|
||||
u64 affinity_mask;
|
||||
thread->GetPhysicalCoreMask(std::addressof(core_id), std::addressof(affinity_mask));
|
||||
|
||||
*out_32 = affinity_mask;
|
||||
*out_32 = thread->GetAffinityMask().GetAffinityMask();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -206,35 +206,28 @@ namespace ams::kern::svc {
|
||||
case ams::svc::InfoType_ThreadTickCount:
|
||||
{
|
||||
/* Verify the requested core is valid. */
|
||||
const bool core_valid = (info_subtype == static_cast<u64>(-1ul)) || (info_subtype < util::size(cpu::VirtualToPhysicalCoreMap));
|
||||
const bool core_valid = (info_subtype == static_cast<u64>(-1ul)) || (info_subtype < cpu::NumCores);
|
||||
R_UNLESS(core_valid, svc::ResultInvalidCombination());
|
||||
|
||||
/* Get the thread from its handle. */
|
||||
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(handle);
|
||||
R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Disable interrupts while we get the tick count. */
|
||||
/* Get the tick count. */
|
||||
s64 tick_count;
|
||||
{
|
||||
KScopedInterruptDisable di;
|
||||
|
||||
if (info_subtype == static_cast<u64>(-1ul)) {
|
||||
tick_count = thread->GetCpuTime();
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
} else {
|
||||
const s32 phys_core = cpu::VirtualToPhysicalCoreMap[info_subtype];
|
||||
MESOSPHERE_ABORT_UNLESS(phys_core < static_cast<s32>(cpu::NumCores));
|
||||
|
||||
tick_count = thread->GetCpuTime(phys_core);
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe() && phys_core == GetCurrentCoreId()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
if (info_subtype == static_cast<u64>(-1ul)) {
|
||||
tick_count = thread->GetCpuTime();
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
} else {
|
||||
tick_count = thread->GetCpuTime(static_cast<s32>(info_subtype));
|
||||
if (GetCurrentThreadPointer() == thread.GetPointerUnsafe() && static_cast<s32>(info_subtype) == GetCurrentCoreId()) {
|
||||
const s64 cur_tick = KHardwareTimer::GetTick();
|
||||
const s64 prev_switch = Kernel::GetScheduler().GetLastContextSwitchTime();
|
||||
tick_count += (cur_tick - prev_switch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
/* ============================= Common ============================= */
|
||||
|
||||
namespace {
|
||||
@@ -307,6 +304,4 @@ namespace ams::kern::svc {
|
||||
return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
|
||||
}
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -22,31 +22,7 @@ namespace ams::kern::svc {
|
||||
namespace {
|
||||
|
||||
int32_t GetCurrentProcessorNumber() {
|
||||
/* Setup variables to track affinity information. */
|
||||
s32 current_phys_core;
|
||||
u64 v_affinity_mask = 0;
|
||||
|
||||
/* Forever try to get the affinity. */
|
||||
while (true) {
|
||||
/* Update affinity information if we've run out. */
|
||||
while (v_affinity_mask == 0) {
|
||||
current_phys_core = GetCurrentCoreId();
|
||||
v_affinity_mask = GetCurrentThread().GetVirtualAffinityMask();
|
||||
if ((v_affinity_mask & (1ul << current_phys_core)) != 0) {
|
||||
return current_phys_core;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the next virtual bit. */
|
||||
do {
|
||||
const s32 next_virt_core = static_cast<s32>(__builtin_ctzll(v_affinity_mask));
|
||||
if (current_phys_core == cpu::VirtualToPhysicalCoreMap[next_virt_core]) {
|
||||
return next_virt_core;
|
||||
}
|
||||
|
||||
v_affinity_mask &= ~(1ul << next_virt_core);
|
||||
} while (v_affinity_mask != 0);
|
||||
}
|
||||
return GetCurrentCoreId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace ams::kern::svc {
|
||||
R_UNLESS(resource_limit.IsNotNull(), svc::ResultInvalidHandle());
|
||||
|
||||
/* Get the peak value. */
|
||||
*out_peak_value = resource_limit->GetPeakValue(which);
|
||||
*out_peak_value = resource_limit->GetCurrentValue(which);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -164,10 +164,10 @@
|
||||
HANDLER(UsbStateInfo, 123) \
|
||||
HANDLER(NvHostErrInfo, 124) \
|
||||
HANDLER(RunningUlaInfo, 125) \
|
||||
HANDLER(InternalPanelInfo, 126) \
|
||||
HANDLER(ResourceLimitLimitInfo, 127) \
|
||||
HANDLER(ResourceLimitPeakInfo, 128) \
|
||||
HANDLER(TouchScreenInfo, 129) \
|
||||
HANDLER(Category_Unknown126, 126) \
|
||||
HANDLER(Category_Unknown127, 127) \
|
||||
HANDLER(Category_Unknown128, 128) \
|
||||
HANDLER(Category_Unknown129, 129) \
|
||||
|
||||
#define AMS_ERPT_FOREACH_FIELD(HANDLER) \
|
||||
HANDLER(TestU64, 0, Test, FieldType_NumericU64, FieldFlag_None ) \
|
||||
@@ -782,22 +782,22 @@
|
||||
HANDLER(NANDTotalSizeOfSystem, 609, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(NANDFreeSpaceOfSystem, 610, NANDFreeSpaceInfo, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(AccessPointSSIDAsHex, 611, AccessPointInfo, FieldType_String, FieldFlag_None ) \
|
||||
HANDLER(PanelVendorId, 612, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelRevisionId, 613, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelModelId, 614, InternalPanelInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelVendorId, 612, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelRevisionId, 613, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(PanelModelId, 614, Category_Unknown126, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(ErrorContext, 615, ErrorInfoAuto, FieldType_U8Array, FieldFlag_None ) \
|
||||
HANDLER(ErrorContextSize, 616, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(ErrorContextTotalSize, 617, ErrorInfoAuto, FieldType_NumericU64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryLimit, 618, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountLimit, 619, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountLimit, 620, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountLimit, 621, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountLimit, 622, ResourceLimitLimitInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryPeak, 623, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountPeak, 624, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountPeak, 625, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountPeak, 626, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountPeak, 627, ResourceLimitPeakInfo, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryLimit, 618, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountLimit, 619, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountLimit, 620, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountLimit, 621, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountLimit, 622, Category_Unknown127, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemPhysicalMemoryPeak, 623, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemThreadCountPeak, 624, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemEventCountPeak, 625, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemTransferMemoryCountPeak, 626, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(SystemSessionCountPeak, 627, Category_Unknown128, FieldType_NumericI64, FieldFlag_None ) \
|
||||
HANDLER(GpuCrashHash, 628, GpuCrashInfo, FieldType_U8Array, FieldFlag_None ) \
|
||||
HANDLER(TouchScreenPanelGpioValue, 629, TouchScreenInfo, FieldType_NumericU8, FieldFlag_None ) \
|
||||
HANDLER(TouchScreenPanelGpioValue, 629, Category_Unknown129, FieldType_NumericU8, FieldFlag_None ) \
|
||||
|
||||
|
||||
@@ -210,8 +210,7 @@ namespace ams::ldr {
|
||||
MetaFlag_AddressSpaceTypeShift = 1,
|
||||
MetaFlag_AddressSpaceTypeMask = (7 << MetaFlag_AddressSpaceTypeShift),
|
||||
|
||||
MetaFlag_OptimizeMemoryAllocation = (1 << 4),
|
||||
MetaFlag_DisableDeviceAddressSpaceMerge = (1 << 5),
|
||||
MetaFlag_OptimizeMemoryAllocation = (1 << 4),
|
||||
};
|
||||
|
||||
enum AddressSpaceType {
|
||||
|
||||
@@ -601,7 +601,7 @@ namespace ams::fssystem::save {
|
||||
this->base_storage = base_storage;
|
||||
this->buffer_manager = buffer_manager;
|
||||
this->block_size = block_size;
|
||||
this->cache_count = buffer_count;
|
||||
this->cache_count = cache_count;
|
||||
|
||||
/* Allocate the caches. */
|
||||
this->caches.reset(new Cache[buffer_count]);
|
||||
|
||||
@@ -400,8 +400,6 @@ struct { \
|
||||
RB_PROTOTYPE_REMOVE(name, type, attr); \
|
||||
RB_PROTOTYPE_FIND(name, type, attr); \
|
||||
RB_PROTOTYPE_NFIND(name, type, attr); \
|
||||
RB_PROTOTYPE_FIND_LIGHT(name, type, attr); \
|
||||
RB_PROTOTYPE_NFIND_LIGHT(name, type, attr); \
|
||||
RB_PROTOTYPE_NEXT(name, type, attr); \
|
||||
RB_PROTOTYPE_PREV(name, type, attr); \
|
||||
RB_PROTOTYPE_MINMAX(name, type, attr);
|
||||
@@ -417,10 +415,6 @@ struct { \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_NFIND(name, type, attr) \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_FIND_LIGHT(name, type, attr) \
|
||||
attr struct type *name##_RB_FIND_LIGHT(struct name *, const void *)
|
||||
#define RB_PROTOTYPE_NFIND_LIGHT(name, type, attr) \
|
||||
attr struct type *name##_RB_NFIND_LIGHT(struct name *, const void *)
|
||||
#define RB_PROTOTYPE_NEXT(name, type, attr) \
|
||||
attr struct type *name##_RB_NEXT(struct type *)
|
||||
#define RB_PROTOTYPE_PREV(name, type, attr) \
|
||||
@@ -442,17 +436,15 @@ struct { \
|
||||
RB_GENERATE_PREV(name, type, field, attr) \
|
||||
RB_GENERATE_MINMAX(name, type, field, attr)
|
||||
|
||||
#define RB_GENERATE_WITH_COMPARE(name, type, field, cmp, lcmp) \
|
||||
RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, lcmp,)
|
||||
#define RB_GENERATE_WITH_COMPARE_STATIC(name, type, field, cmp, lcmp) \
|
||||
RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, lcmp, __unused static)
|
||||
#define RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, lcmp, attr) \
|
||||
#define RB_GENERATE_WITH_COMPARE(name, type, field, cmp) \
|
||||
RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp,)
|
||||
#define RB_GENERATE_WITH_COMPARE_STATIC(name, type, field, cmp) \
|
||||
RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_GENERATE_WITH_COMPARE_INTERNAL(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
|
||||
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_FIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_FIND_LIGHT(name, type, field, lcmp, attr) \
|
||||
RB_GENERATE_NFIND_LIGHT(name, type, field, lcmp, attr)
|
||||
RB_GENERATE_NFIND(name, type, field, cmp, attr)
|
||||
|
||||
#define RB_GENERATE_ALL(name, type, field, cmp) \
|
||||
RB_GENERATE_ALL_INTERNAL(name, type, field, cmp,)
|
||||
@@ -727,47 +719,6 @@ name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
return (res); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_FIND_LIGHT(name, type, field, lcmp, attr) \
|
||||
/* Finds the node with the same key as elm */ \
|
||||
attr struct type * \
|
||||
name##_RB_FIND_LIGHT(struct name *head, const void *lelm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = lcmp(lelm, tmp); \
|
||||
if (comp < 0) \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NFIND_LIGHT(name, type, field, lcmp, attr) \
|
||||
/* Finds the first node greater than or equal to the search key */ \
|
||||
attr struct type * \
|
||||
name##_RB_NFIND_LIGHT(struct name *head, const void *lelm) \
|
||||
{ \
|
||||
struct type *tmp = RB_ROOT(head); \
|
||||
struct type *res = NULL; \
|
||||
int comp; \
|
||||
while (tmp) { \
|
||||
comp = lcmp(lelm, tmp); \
|
||||
if (comp < 0) { \
|
||||
res = tmp; \
|
||||
tmp = RB_LEFT(tmp, field); \
|
||||
} \
|
||||
else if (comp > 0) \
|
||||
tmp = RB_RIGHT(tmp, field); \
|
||||
else \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (res); \
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NEXT(name, type, field, attr) \
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
@@ -837,8 +788,6 @@ name##_RB_MINMAX(struct name *head, int val) \
|
||||
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
|
||||
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
|
||||
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
|
||||
#define RB_FIND_LIGHT(name, x, y) name##_RB_FIND_LIGHT(x, y)
|
||||
#define RB_NFIND_LIGHT(name, x, y) name##_RB_NFIND_LIGHT(x, y)
|
||||
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
|
||||
#define RB_PREV(name, x, y) name##_RB_PREV(y)
|
||||
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#pragma once
|
||||
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 0
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 16
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 15
|
||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0
|
||||
|
||||
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
||||
|
||||
@@ -528,7 +528,6 @@ namespace ams::svc::codegen::impl {
|
||||
|
||||
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O2")
|
||||
#pragma GCC optimize ("omit-frame-pointer")
|
||||
|
||||
static ALWAYS_INLINE ReturnType WrapSvcFunction() {
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace ams::svc::codegen {
|
||||
public:
|
||||
/* Set omit-frame-pointer to prevent GCC from emitting MOV X29, SP instructions. */
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O2")
|
||||
#pragma GCC optimize ("omit-frame-pointer")
|
||||
|
||||
static ALWAYS_INLINE void Call64() {
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
namespace ams::svc::ipc {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
ALWAYS_INLINE u32 *GetMessageBuffer() {
|
||||
return GetThreadLocalRegion()->message_buffer;
|
||||
}
|
||||
@@ -548,6 +545,4 @@ namespace ams::svc::ipc {
|
||||
}
|
||||
};
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -85,9 +85,6 @@
|
||||
HANDLER(0x36, void, SynchronizePreemptionState) \
|
||||
HANDLER(0x37, Result, GetResourceLimitPeakValue, OUTPUT(int64_t, out_peak_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \
|
||||
\
|
||||
HANDLER(0x39, Result, Unknown39) \
|
||||
HANDLER(0x3A, Result, Unknown3A) \
|
||||
\
|
||||
HANDLER(0x3C, void, KernelDebug, INPUT(::ams::svc::KernelDebugType, kern_debug_type), INPUT(uint64_t, arg0), INPUT(uint64_t, arg1), INPUT(uint64_t, arg2)) \
|
||||
HANDLER(0x3D, void, ChangeKernelTraceState, INPUT(::ams::svc::KernelTraceState, kern_trace_state)) \
|
||||
\
|
||||
@@ -97,8 +94,7 @@
|
||||
HANDLER(0x43, Result, ReplyAndReceive, OUTPUT(int32_t, out_index), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \
|
||||
HANDLER(0x44, Result, ReplyAndReceiveWithUserBuffer, OUTPUT(int32_t, out_index), INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \
|
||||
HANDLER(0x45, Result, CreateEvent, OUTPUT(::ams::svc::Handle, out_write_handle), OUTPUT(::ams::svc::Handle, out_read_handle)) \
|
||||
HANDLER(0x46, Result, Unknown46) \
|
||||
HANDLER(0x47, Result, Unknown47) \
|
||||
\
|
||||
HANDLER(0x48, Result, MapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \
|
||||
HANDLER(0x49, Result, UnmapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \
|
||||
HANDLER(0x4A, Result, SetUnsafeLimit, INPUT(::ams::svc::Size, limit)) \
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
/* Forward declare implementation class for Node. */
|
||||
namespace impl {
|
||||
|
||||
@@ -41,17 +38,17 @@ namespace ams::util {
|
||||
public:
|
||||
constexpr IntrusiveListNode() : prev(this), next(this) { /* ... */ }
|
||||
|
||||
constexpr ALWAYS_INLINE bool IsLinked() const {
|
||||
constexpr bool IsLinked() const {
|
||||
return this->next != this;
|
||||
}
|
||||
private:
|
||||
ALWAYS_INLINE void LinkPrev(IntrusiveListNode *node) {
|
||||
void LinkPrev(IntrusiveListNode *node) {
|
||||
/* We can't link an already linked node. */
|
||||
AMS_ASSERT(!node->IsLinked());
|
||||
this->SplicePrev(node, node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SplicePrev(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
void SplicePrev(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
/* Splice a range into the list. */
|
||||
auto last_prev = last->prev;
|
||||
first->prev = this->prev;
|
||||
@@ -60,13 +57,13 @@ namespace ams::util {
|
||||
this->prev = last_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void LinkNext(IntrusiveListNode *node) {
|
||||
void LinkNext(IntrusiveListNode *node) {
|
||||
/* We can't link an already linked node. */
|
||||
AMS_ASSERT(!node->IsLinked());
|
||||
return this->SpliceNext(node, node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SpliceNext(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
void SpliceNext(IntrusiveListNode *first, IntrusiveListNode *last) {
|
||||
/* Splice a range into the list. */
|
||||
auto last_prev = last->prev;
|
||||
first->prev = this;
|
||||
@@ -75,11 +72,11 @@ namespace ams::util {
|
||||
this->next = first;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlink() {
|
||||
void Unlink() {
|
||||
this->Unlink(this->next);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void Unlink(IntrusiveListNode *last) {
|
||||
void Unlink(IntrusiveListNode *last) {
|
||||
/* Unlink a node from a next node. */
|
||||
auto last_prev = last->prev;
|
||||
this->prev->next = last;
|
||||
@@ -88,19 +85,19 @@ namespace ams::util {
|
||||
this->prev = last_prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveListNode *GetPrev() {
|
||||
IntrusiveListNode *GetPrev() {
|
||||
return this->prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const IntrusiveListNode *GetPrev() const {
|
||||
const IntrusiveListNode *GetPrev() const {
|
||||
return this->prev;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveListNode *GetNext() {
|
||||
IntrusiveListNode *GetNext() {
|
||||
return this->next;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const IntrusiveListNode *GetNext() const {
|
||||
const IntrusiveListNode *GetNext() const {
|
||||
return this->next;
|
||||
}
|
||||
};
|
||||
@@ -139,149 +136,149 @@ namespace ams::util {
|
||||
private:
|
||||
pointer node;
|
||||
public:
|
||||
ALWAYS_INLINE explicit Iterator(pointer n) : node(n) { /* ... */ }
|
||||
explicit Iterator(pointer n) : node(n) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
bool operator==(const Iterator &rhs) const {
|
||||
return this->node == rhs.node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
pointer operator->() const {
|
||||
return this->node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
reference operator*() const {
|
||||
return *this->node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
Iterator &operator++() {
|
||||
this->node = this->node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
Iterator &operator--() {
|
||||
this->node = this->node->prev;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
operator Iterator<true>() const {
|
||||
return Iterator<true>(this->node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator<false> GetNonConstIterator() const {
|
||||
Iterator<false> GetNonConstIterator() const {
|
||||
return Iterator<false>(const_cast<IntrusiveListImpl::pointer>(this->node));
|
||||
}
|
||||
};
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveListImpl() : root_node() { /* ... */ }
|
||||
constexpr IntrusiveListImpl() : root_node() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
iterator begin() {
|
||||
return iterator(this->root_node.GetNext());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
const_iterator begin() const {
|
||||
return const_iterator(this->root_node.GetNext());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
iterator end() {
|
||||
return iterator(&this->root_node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
const_iterator end() const {
|
||||
return const_iterator(&this->root_node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
iterator iterator_to(reference v) {
|
||||
/* Only allow iterator_to for values in lists. */
|
||||
AMS_ASSERT(v.IsLinked());
|
||||
return iterator(&v);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
const_iterator iterator_to(const_reference v) const {
|
||||
/* Only allow iterator_to for values in lists. */
|
||||
AMS_ASSERT(v.IsLinked());
|
||||
return const_iterator(&v);
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
bool empty() const {
|
||||
return !this->root_node.IsLinked();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE size_type size() const {
|
||||
size_type size() const {
|
||||
return static_cast<size_type>(std::distance(this->begin(), this->end()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
reference back() {
|
||||
return *this->root_node.GetPrev();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
const_reference back() const {
|
||||
return *this->root_node.GetPrev();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
reference front() {
|
||||
return *this->root_node.GetNext();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
const_reference front() const {
|
||||
return *this->root_node.GetNext();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_back(reference node) {
|
||||
void push_back(reference node) {
|
||||
this->root_node.LinkPrev(&node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_front(reference node) {
|
||||
void push_front(reference node) {
|
||||
this->root_node.LinkNext(&node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_back() {
|
||||
void pop_back() {
|
||||
this->root_node.GetPrev()->Unlink();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_front() {
|
||||
void pop_front() {
|
||||
this->root_node.GetNext()->Unlink();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(const_iterator pos, reference node) {
|
||||
iterator insert(const_iterator pos, reference node) {
|
||||
pos.GetNonConstIterator()->LinkPrev(&node);
|
||||
return iterator(&node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o) {
|
||||
void splice(const_iterator pos, IntrusiveListImpl &o) {
|
||||
splice_impl(pos, o.begin(), o.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first) {
|
||||
void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first) {
|
||||
AMS_UNUSED(o);
|
||||
const_iterator last(first);
|
||||
std::advance(last, 1);
|
||||
splice_impl(pos, first, last);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first, const_iterator last) {
|
||||
void splice(const_iterator pos, IntrusiveListImpl &o, const_iterator first, const_iterator last) {
|
||||
AMS_UNUSED(o);
|
||||
splice_impl(pos, first, last);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
iterator erase(const_iterator pos) {
|
||||
if (pos == this->end()) {
|
||||
return this->end();
|
||||
}
|
||||
@@ -290,13 +287,13 @@ namespace ams::util {
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void clear() {
|
||||
void clear() {
|
||||
while (!this->empty()) {
|
||||
this->pop_front();
|
||||
}
|
||||
}
|
||||
private:
|
||||
ALWAYS_INLINE void splice_impl(const_iterator _pos, const_iterator _first, const_iterator _last) {
|
||||
void splice_impl(const_iterator _pos, const_iterator _first, const_iterator _last) {
|
||||
if (_first == _last) {
|
||||
return;
|
||||
}
|
||||
@@ -347,198 +344,198 @@ namespace ams::util {
|
||||
private:
|
||||
ImplIterator iterator;
|
||||
private:
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||
explicit Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
ImplIterator GetImplIterator() const {
|
||||
return this->iterator;
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
bool operator==(const Iterator &rhs) const {
|
||||
return this->iterator == rhs.iterator;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
pointer operator->() const {
|
||||
return &Traits::GetParent(*this->iterator);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
reference operator*() const {
|
||||
return Traits::GetParent(*this->iterator);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
Iterator &operator++() {
|
||||
++this->iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
Iterator &operator--() {
|
||||
--this->iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++this->iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--this->iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
operator Iterator<true>() const {
|
||||
return Iterator<true>(this->iterator);
|
||||
}
|
||||
};
|
||||
private:
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(reference ref) {
|
||||
static constexpr IntrusiveListNode &GetNode(reference ref) {
|
||||
return Traits::GetNode(ref);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode const &GetNode(const_reference ref) {
|
||||
static constexpr IntrusiveListNode const &GetNode(const_reference ref) {
|
||||
return Traits::GetNode(ref);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE reference GetParent(IntrusiveListNode &node) {
|
||||
static constexpr reference GetParent(IntrusiveListNode &node) {
|
||||
return Traits::GetParent(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE const_reference GetParent(IntrusiveListNode const &node) {
|
||||
static constexpr const_reference GetParent(IntrusiveListNode const &node) {
|
||||
return Traits::GetParent(node);
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveList() : impl() { /* ... */ }
|
||||
constexpr IntrusiveList() : impl() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
iterator begin() {
|
||||
return iterator(this->impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
const_iterator begin() const {
|
||||
return const_iterator(this->impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
iterator end() {
|
||||
return iterator(this->impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
const_iterator end() const {
|
||||
return const_iterator(this->impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reverse_iterator rbegin() {
|
||||
reverse_iterator rbegin() {
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator rbegin() const {
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reverse_iterator rend() {
|
||||
reverse_iterator rend() {
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator rend() const {
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator crbegin() const {
|
||||
const_reverse_iterator crbegin() const {
|
||||
return this->rbegin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reverse_iterator crend() const {
|
||||
const_reverse_iterator crend() const {
|
||||
return this->rend();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference v) {
|
||||
iterator iterator_to(reference v) {
|
||||
return iterator(this->impl.iterator_to(GetNode(v)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference v) const {
|
||||
const_iterator iterator_to(const_reference v) const {
|
||||
return const_iterator(this->impl.iterator_to(GetNode(v)));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
bool empty() const {
|
||||
return this->impl.empty();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE size_type size() const {
|
||||
size_type size() const {
|
||||
return this->impl.size();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
reference back() {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
return GetParent(this->impl.back());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
const_reference back() const {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
return GetParent(this->impl.back());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
reference front() {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
return GetParent(this->impl.front());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
const_reference front() const {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
return GetParent(this->impl.front());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_back(reference ref) {
|
||||
void push_back(reference ref) {
|
||||
this->impl.push_back(GetNode(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void push_front(reference ref) {
|
||||
void push_front(reference ref) {
|
||||
this->impl.push_front(GetNode(ref));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_back() {
|
||||
void pop_back() {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
this->impl.pop_back();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void pop_front() {
|
||||
void pop_front() {
|
||||
AMS_ASSERT(!this->impl.empty());
|
||||
this->impl.pop_front();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(const_iterator pos, reference ref) {
|
||||
iterator insert(const_iterator pos, reference ref) {
|
||||
return iterator(this->impl.insert(pos.GetImplIterator(), GetNode(ref)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o) {
|
||||
void splice(const_iterator pos, IntrusiveList &o) {
|
||||
this->impl.splice(pos.GetImplIterator(), o.impl);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first) {
|
||||
void splice(const_iterator pos, IntrusiveList &o, const_iterator first) {
|
||||
this->impl.splice(pos.GetImplIterator(), o.impl, first.GetImplIterator());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void splice(const_iterator pos, IntrusiveList &o, const_iterator first, const_iterator last) {
|
||||
void splice(const_iterator pos, IntrusiveList &o, const_iterator first, const_iterator last) {
|
||||
this->impl.splice(pos.GetImplIterator(), o.impl, first.GetImplIterator(), last.GetImplIterator());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(const_iterator pos) {
|
||||
iterator erase(const_iterator pos) {
|
||||
return iterator(this->impl.erase(pos.GetImplIterator()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void clear() {
|
||||
void clear() {
|
||||
this->impl.clear();
|
||||
}
|
||||
};
|
||||
@@ -553,19 +550,19 @@ namespace ams::util {
|
||||
private:
|
||||
friend class IntrusiveList<Derived, IntrusiveListMemberTraits>;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(Derived &parent) {
|
||||
static constexpr IntrusiveListNode &GetNode(Derived &parent) {
|
||||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
static constexpr IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
static constexpr Derived &GetParent(IntrusiveListNode &node) {
|
||||
return util::GetParentReference<Member, Derived>(&node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
static constexpr Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return util::GetParentReference<Member, Derived>(&node);
|
||||
}
|
||||
private:
|
||||
@@ -588,19 +585,19 @@ namespace ams::util {
|
||||
private:
|
||||
friend class IntrusiveList<Derived, IntrusiveListMemberTraitsDeferredAssert>;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(Derived &parent) {
|
||||
static constexpr IntrusiveListNode &GetNode(Derived &parent) {
|
||||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
static constexpr IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
return parent.*Member;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
static constexpr Derived &GetParent(IntrusiveListNode &node) {
|
||||
return util::GetParentReference<Member, Derived>(&node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
static constexpr Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return util::GetParentReference<Member, Derived>(&node);
|
||||
}
|
||||
};
|
||||
@@ -615,23 +612,21 @@ namespace ams::util {
|
||||
private:
|
||||
friend class IntrusiveList<Derived, IntrusiveListBaseTraits>;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode &GetNode(Derived &parent) {
|
||||
static constexpr IntrusiveListNode &GetNode(Derived &parent) {
|
||||
return static_cast<IntrusiveListNode &>(parent);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
static constexpr IntrusiveListNode const &GetNode(Derived const &parent) {
|
||||
return static_cast<const IntrusiveListNode &>(parent);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived &GetParent(IntrusiveListNode &node) {
|
||||
static constexpr Derived &GetParent(IntrusiveListNode &node) {
|
||||
return static_cast<Derived &>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
static constexpr Derived const &GetParent(IntrusiveListNode const &node) {
|
||||
return static_cast<const Derived &>(node);
|
||||
}
|
||||
};
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
@@ -22,9 +22,6 @@
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize ("-O3")
|
||||
|
||||
namespace impl {
|
||||
|
||||
class IntrusiveRedBlackTreeImpl;
|
||||
@@ -85,47 +82,47 @@ namespace ams::util {
|
||||
private:
|
||||
pointer node;
|
||||
public:
|
||||
explicit ALWAYS_INLINE Iterator(pointer n) : node(n) { /* ... */ }
|
||||
explicit Iterator(pointer n) : node(n) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
bool operator==(const Iterator &rhs) const {
|
||||
return this->node == rhs.node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
pointer operator->() const {
|
||||
return this->node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
reference operator*() const {
|
||||
return *this->node;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
Iterator &operator++() {
|
||||
this->node = GetNext(this->node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
Iterator &operator--() {
|
||||
this->node = GetPrev(this->node);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--(*this);
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
operator Iterator<true>() const {
|
||||
return Iterator<true>(this->node);
|
||||
}
|
||||
};
|
||||
@@ -138,27 +135,27 @@ namespace ams::util {
|
||||
RB_INIT(&this->root);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool EmptyImpl() const {
|
||||
bool EmptyImpl() const {
|
||||
return RB_EMPTY(&this->root);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
||||
IntrusiveRedBlackTreeNode *GetMinImpl() const {
|
||||
return RB_MIN(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
||||
IntrusiveRedBlackTreeNode *GetMaxImpl() const {
|
||||
return RB_MAX(IntrusiveRedBlackTreeRoot, const_cast<IntrusiveRedBlackTreeRoot *>(&this->root));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
IntrusiveRedBlackTreeNode *RemoveImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_REMOVE(IntrusiveRedBlackTreeRoot, &this->root, node);
|
||||
}
|
||||
public:
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
||||
static IntrusiveRedBlackTreeNode *GetNext(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_NEXT(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||
}
|
||||
|
||||
static ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
||||
static IntrusiveRedBlackTreeNode *GetPrev(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
|
||||
}
|
||||
|
||||
@@ -170,65 +167,65 @@ namespace ams::util {
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(GetPrev(const_cast<IntrusiveRedBlackTreeNode *>(node)));
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE constexpr IntrusiveRedBlackTreeImpl() : root() {
|
||||
constexpr IntrusiveRedBlackTreeImpl() : root() {
|
||||
this->InitializeImpl();
|
||||
}
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
iterator begin() {
|
||||
return iterator(this->GetMinImpl());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
const_iterator begin() const {
|
||||
return const_iterator(this->GetMinImpl());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
iterator end() {
|
||||
return iterator(static_cast<IntrusiveRedBlackTreeNode *>(nullptr));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
const_iterator end() const {
|
||||
return const_iterator(static_cast<const IntrusiveRedBlackTreeNode *>(nullptr));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
iterator iterator_to(reference ref) {
|
||||
return iterator(&ref);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(&ref);
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
bool empty() const {
|
||||
return this->EmptyImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
reference back() {
|
||||
return *this->GetMaxImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
const_reference back() const {
|
||||
return *this->GetMaxImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
reference front() {
|
||||
return *this->GetMinImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
const_reference front() const {
|
||||
return *this->GetMinImpl();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(iterator it) {
|
||||
iterator erase(iterator it) {
|
||||
auto cur = std::addressof(*it);
|
||||
auto next = GetNext(cur);
|
||||
this->RemoveImpl(cur);
|
||||
@@ -238,27 +235,6 @@ namespace ams::util {
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
concept HasLightCompareType = requires {
|
||||
{ std::is_same<typename T::LightCompareType, void>::value } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<typename T, typename Default>
|
||||
consteval auto *GetLightCompareType() {
|
||||
if constexpr (HasLightCompareType<T>) {
|
||||
return static_cast<typename T::LightCompareType *>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default *>(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename Default>
|
||||
using LightCompareType = typename std::remove_pointer<decltype(impl::GetLightCompareType<T, Default>())>::type;
|
||||
|
||||
template<class T, class Traits, class Comparator>
|
||||
class IntrusiveRedBlackTree {
|
||||
NON_COPYABLE(IntrusiveRedBlackTree);
|
||||
@@ -282,10 +258,6 @@ namespace ams::util {
|
||||
using iterator = Iterator<false>;
|
||||
using const_iterator = Iterator<true>;
|
||||
|
||||
using light_value_type = LightCompareType<Comparator, value_type>;
|
||||
using const_light_pointer = const light_value_type *;
|
||||
using const_light_reference = const light_value_type &;
|
||||
|
||||
template<bool Const>
|
||||
class Iterator {
|
||||
public:
|
||||
@@ -301,170 +273,150 @@ namespace ams::util {
|
||||
private:
|
||||
ImplIterator iterator;
|
||||
private:
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||
explicit Iterator(ImplIterator it) : iterator(it) { /* ... */ }
|
||||
|
||||
explicit ALWAYS_INLINE Iterator(ImplIterator::pointer p) : iterator(p) { /* ... */ }
|
||||
explicit Iterator(ImplIterator::pointer p) : iterator(p) { /* ... */ }
|
||||
|
||||
ALWAYS_INLINE ImplIterator GetImplIterator() const {
|
||||
ImplIterator GetImplIterator() const {
|
||||
return this->iterator;
|
||||
}
|
||||
public:
|
||||
ALWAYS_INLINE bool operator==(const Iterator &rhs) const {
|
||||
bool operator==(const Iterator &rhs) const {
|
||||
return this->iterator == rhs.iterator;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool operator!=(const Iterator &rhs) const {
|
||||
bool operator!=(const Iterator &rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE pointer operator->() const {
|
||||
pointer operator->() const {
|
||||
return Traits::GetParent(std::addressof(*this->iterator));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference operator*() const {
|
||||
reference operator*() const {
|
||||
return *Traits::GetParent(std::addressof(*this->iterator));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator++() {
|
||||
Iterator &operator++() {
|
||||
++this->iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator &operator--() {
|
||||
Iterator &operator--() {
|
||||
--this->iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator++(int) {
|
||||
Iterator operator++(int) {
|
||||
const Iterator it{*this};
|
||||
++this->iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE Iterator operator--(int) {
|
||||
Iterator operator--(int) {
|
||||
const Iterator it{*this};
|
||||
--this->iterator;
|
||||
return it;
|
||||
}
|
||||
|
||||
ALWAYS_INLINE operator Iterator<true>() const {
|
||||
operator Iterator<true>() const {
|
||||
return Iterator<true>(this->iterator);
|
||||
}
|
||||
};
|
||||
private:
|
||||
/* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */
|
||||
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl, LightCompareImpl);
|
||||
RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, entry, CompareImpl);
|
||||
private:
|
||||
static int CompareImpl(const IntrusiveRedBlackTreeNode *lhs, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
return Comparator::Compare(*Traits::GetParent(lhs), *Traits::GetParent(rhs));
|
||||
}
|
||||
|
||||
static int LightCompareImpl(const void *elm, const IntrusiveRedBlackTreeNode *rhs) {
|
||||
return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs));
|
||||
}
|
||||
|
||||
/* Define accessors using RB_* functions. */
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
IntrusiveRedBlackTreeNode *InsertImpl(IntrusiveRedBlackTreeNode *node) {
|
||||
return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, static_cast<IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root), node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
IntrusiveRedBlackTreeNode *FindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return RB_FIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
IntrusiveRedBlackTreeNode *NFindImpl(IntrusiveRedBlackTreeNode const *node) const {
|
||||
return RB_NFIND(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), const_cast<IntrusiveRedBlackTreeNode *>(node));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *FindLightImpl(const_light_pointer lelm) const {
|
||||
return RB_FIND_LIGHT(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), static_cast<const void *>(lelm));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE IntrusiveRedBlackTreeNode *NFindLightImpl(const_light_pointer lelm) const {
|
||||
return RB_NFIND_LIGHT(IntrusiveRedBlackTreeRootWithCompare, const_cast<IntrusiveRedBlackTreeRootWithCompare *>(static_cast<const IntrusiveRedBlackTreeRootWithCompare *>(&this->impl.root)), static_cast<const void *>(lelm));
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE IntrusiveRedBlackTree() : impl() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
ALWAYS_INLINE iterator begin() {
|
||||
iterator begin() {
|
||||
return iterator(this->impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator begin() const {
|
||||
const_iterator begin() const {
|
||||
return const_iterator(this->impl.begin());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator end() {
|
||||
iterator end() {
|
||||
return iterator(this->impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator end() const {
|
||||
const_iterator end() const {
|
||||
return const_iterator(this->impl.end());
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cbegin() const {
|
||||
const_iterator cbegin() const {
|
||||
return this->begin();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator cend() const {
|
||||
const_iterator cend() const {
|
||||
return this->end();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator iterator_to(reference ref) {
|
||||
iterator iterator_to(reference ref) {
|
||||
return iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_iterator iterator_to(const_reference ref) const {
|
||||
const_iterator iterator_to(const_reference ref) const {
|
||||
return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
/* Content management. */
|
||||
ALWAYS_INLINE bool empty() const {
|
||||
bool empty() const {
|
||||
return this->impl.empty();
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference back() {
|
||||
reference back() {
|
||||
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference back() const {
|
||||
const_reference back() const {
|
||||
return *Traits::GetParent(std::addressof(this->impl.back()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE reference front() {
|
||||
reference front() {
|
||||
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE const_reference front() const {
|
||||
const_reference front() const {
|
||||
return *Traits::GetParent(std::addressof(this->impl.front()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator erase(iterator it) {
|
||||
iterator erase(iterator it) {
|
||||
return iterator(this->impl.erase(it.GetImplIterator()));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator insert(reference ref) {
|
||||
iterator insert(reference ref) {
|
||||
ImplType::pointer node = Traits::GetNode(std::addressof(ref));
|
||||
this->InsertImpl(node);
|
||||
return iterator(node);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator find(const_reference ref) const {
|
||||
iterator find(const_reference ref) const {
|
||||
return iterator(this->FindImpl(Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator nfind(const_reference ref) const {
|
||||
iterator nfind(const_reference ref) const {
|
||||
return iterator(this->NFindImpl(Traits::GetNode(std::addressof(ref))));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator find_light(const_light_reference ref) const {
|
||||
return iterator(this->FindLightImpl(std::addressof(ref)));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE iterator nfind_light(const_light_reference ref) const {
|
||||
return iterator(this->NFindLightImpl(std::addressof(ref)));
|
||||
}
|
||||
};
|
||||
|
||||
template<auto T, class Derived = util::impl::GetParentType<T>>
|
||||
@@ -482,19 +434,19 @@ namespace ams::util {
|
||||
|
||||
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
static constexpr Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
static constexpr Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
private:
|
||||
@@ -522,19 +474,19 @@ namespace ams::util {
|
||||
|
||||
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
return std::addressof(parent->*Member);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
static constexpr Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
static constexpr Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return util::GetParentPointer<Member, Derived>(node);
|
||||
}
|
||||
};
|
||||
@@ -561,23 +513,21 @@ namespace ams::util {
|
||||
|
||||
friend class impl::IntrusiveRedBlackTreeImpl;
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode *GetNode(Derived *parent) {
|
||||
return static_cast<IntrusiveRedBlackTreeNode *>(parent);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
static constexpr IntrusiveRedBlackTreeNode const *GetNode(Derived const *parent) {
|
||||
return static_cast<const IntrusiveRedBlackTreeNode *>(parent);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
static constexpr Derived *GetParent(IntrusiveRedBlackTreeNode *node) {
|
||||
return static_cast<Derived *>(node);
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
static constexpr Derived const *GetParent(IntrusiveRedBlackTreeNode const *node) {
|
||||
return static_cast<const Derived *>(node);
|
||||
}
|
||||
};
|
||||
|
||||
#pragma GCC pop_options
|
||||
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ namespace ams::kern::init {
|
||||
/* Prototypes for functions declared in ASM that we need to reference. */
|
||||
void StartOtherCore(const ams::kern::init::KInitArguments *init_args);
|
||||
|
||||
size_t GetMiscUnknownDebugRegionSize();
|
||||
|
||||
namespace {
|
||||
|
||||
/* Global Allocator. */
|
||||
@@ -141,10 +139,10 @@ namespace ams::kern::init {
|
||||
InitializeSlabResourceCounts();
|
||||
|
||||
/* Insert the root region for the virtual memory tree, from which all other regions will derive. */
|
||||
KMemoryLayout::GetVirtualMemoryRegionTree().InsertDirectly(KernelVirtualAddressSpaceBase, KernelVirtualAddressSpaceBase + KernelVirtualAddressSpaceSize - 1);
|
||||
KMemoryLayout::GetVirtualMemoryRegionTree().InsertDirectly(KernelVirtualAddressSpaceBase, KernelVirtualAddressSpaceSize);
|
||||
|
||||
/* Insert the root region for the physical memory tree, from which all other regions will derive. */
|
||||
KMemoryLayout::GetPhysicalMemoryRegionTree().InsertDirectly(KernelPhysicalAddressSpaceBase, KernelPhysicalAddressSpaceBase + KernelPhysicalAddressSpaceSize - 1);
|
||||
KMemoryLayout::GetPhysicalMemoryRegionTree().InsertDirectly(KernelPhysicalAddressSpaceBase, KernelPhysicalAddressSpaceSize);
|
||||
|
||||
/* Save start and end for ease of use. */
|
||||
const uintptr_t code_start_virt_addr = reinterpret_cast<uintptr_t>(_start);
|
||||
@@ -167,42 +165,11 @@ namespace ams::kern::init {
|
||||
const size_t code_region_size = GetInteger(code_region_end) - GetInteger(code_region_start);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(code_region_start), code_region_size, KMemoryRegionType_KernelCode));
|
||||
|
||||
/* Setup board-specific device physical regions. */
|
||||
SetupDevicePhysicalMemoryRegions();
|
||||
|
||||
/* Determine the amount of space needed for the misc region. */
|
||||
size_t misc_region_needed_size;
|
||||
{
|
||||
/* Each core has a one page stack for all three stack types (Main, Idle, Exception). */
|
||||
misc_region_needed_size = cpu::NumCores * (3 * (PageSize + PageSize));
|
||||
|
||||
/* Account for each auto-map device. */
|
||||
for (const auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
|
||||
if (region.HasTypeAttribute(KMemoryRegionAttr_ShouldKernelMap)) {
|
||||
/* Check that the region is valid. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
|
||||
/* Account for the region. */
|
||||
misc_region_needed_size += PageSize + (util::AlignUp(region.GetLastAddress(), PageSize) - util::AlignDown(region.GetAddress(), PageSize));
|
||||
}
|
||||
}
|
||||
|
||||
/* Account for the unknown debug region. */
|
||||
misc_region_needed_size += GetMiscUnknownDebugRegionSize();
|
||||
|
||||
/* Multiply the needed size by three, to account for the need for guard space. */
|
||||
misc_region_needed_size *= 3;
|
||||
}
|
||||
|
||||
/* Decide on the actual size for the misc region. */
|
||||
constexpr size_t MiscRegionAlign = KernelAslrAlignment;
|
||||
constexpr size_t MiscRegionMinimumSize = 32_MB;
|
||||
const size_t misc_region_size = util::AlignUp(std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(misc_region_size > 0);
|
||||
|
||||
/* Setup the misc region. */
|
||||
const KVirtualAddress misc_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegion(misc_region_size, MiscRegionAlign, KMemoryRegionType_Kernel);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_region_start), misc_region_size, KMemoryRegionType_KernelMisc));
|
||||
constexpr size_t MiscRegionSize = 32_MB;
|
||||
constexpr size_t MiscRegionAlign = KernelAslrAlignment;
|
||||
const KVirtualAddress misc_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegion(MiscRegionSize, MiscRegionAlign, KMemoryRegionType_Kernel);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_region_start), MiscRegionSize, KMemoryRegionType_KernelMisc));
|
||||
|
||||
/* Setup the stack region. */
|
||||
constexpr size_t StackRegionSize = 14_MB;
|
||||
@@ -235,13 +202,16 @@ namespace ams::kern::init {
|
||||
|
||||
/* Setup the Misc Unknown Debug region, if it's not zero. */
|
||||
if (misc_unk_debug_phys_addr) {
|
||||
constexpr size_t MiscUnknownDebugRegionSize = PageSize;
|
||||
constexpr size_t MiscUnknownDebugRegionAlign = PageSize;
|
||||
const size_t misc_unk_debug_size = GetMiscUnknownDebugRegionSize();
|
||||
const KVirtualAddress misc_unk_debug_virt_addr = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(misc_unk_debug_size, MiscUnknownDebugRegionAlign, KMemoryRegionType_KernelMisc, PageSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_unk_debug_virt_addr), misc_unk_debug_size, KMemoryRegionType_KernelMiscUnknownDebug));
|
||||
ttbr1_table.Map(misc_unk_debug_virt_addr, misc_unk_debug_size, misc_unk_debug_phys_addr, KernelRoDataAttribute, g_initial_page_allocator);
|
||||
const KVirtualAddress misc_unk_debug_virt_addr = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(MiscUnknownDebugRegionSize, MiscUnknownDebugRegionAlign, KMemoryRegionType_KernelMisc, PageSize);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(GetInteger(misc_unk_debug_virt_addr), MiscUnknownDebugRegionSize, KMemoryRegionType_KernelMiscUnknownDebug));
|
||||
ttbr1_table.Map(misc_unk_debug_virt_addr, MiscUnknownDebugRegionSize, misc_unk_debug_phys_addr, KernelRoDataAttribute, g_initial_page_allocator);
|
||||
}
|
||||
|
||||
/* Setup board-specific device physical regions. */
|
||||
SetupDevicePhysicalMemoryRegions();
|
||||
|
||||
/* Automatically map in devices that have auto-map attributes. */
|
||||
for (auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
|
||||
/* We only care about kernel regions. */
|
||||
@@ -259,9 +229,6 @@ namespace ams::kern::init {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check that the region is valid. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
|
||||
/* Set the attribute to note we've mapped this region. */
|
||||
region.SetTypeAttribute(KMemoryRegionAttr_DidKernelMap);
|
||||
|
||||
@@ -291,6 +258,10 @@ namespace ams::kern::init {
|
||||
/* Physically randomize the slab region. */
|
||||
/* NOTE: Nintendo does this only on 10.0.0+ */
|
||||
ttbr1_table.PhysicallyRandomize(slab_region_start, slab_region_size, false);
|
||||
cpu::StoreEntireCacheForInit();
|
||||
|
||||
/* Clear the slab region. */
|
||||
std::memset(GetVoidPointer(slab_region_start), 0, slab_region_size);
|
||||
|
||||
/* Determine size available for kernel page table heaps, requiring > 8 MB. */
|
||||
const KPhysicalAddress resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
|
||||
@@ -311,22 +282,15 @@ namespace ams::kern::init {
|
||||
/* All DRAM regions that we haven't tagged by this point will be mapped under the linear mapping. Tag them. */
|
||||
for (auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
|
||||
if (region.GetType() == KMemoryRegionType_Dram) {
|
||||
/* Check that the region is valid. */
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
|
||||
/* Set the linear map attribute. */
|
||||
region.SetTypeAttribute(KMemoryRegionAttr_LinearMapped);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the linear region extents. */
|
||||
const auto linear_extents = KMemoryLayout::GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(linear_extents.GetEndAddress() != 0);
|
||||
|
||||
/* Setup the linear mapping region. */
|
||||
constexpr size_t LinearRegionAlign = 1_GB;
|
||||
const KPhysicalAddress aligned_linear_phys_start = util::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
|
||||
const size_t linear_region_size = util::AlignUp(linear_extents.GetEndAddress(), LinearRegionAlign) - GetInteger(aligned_linear_phys_start);
|
||||
const auto linear_extents = KMemoryLayout::GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped);
|
||||
const KPhysicalAddress aligned_linear_phys_start = util::AlignDown(linear_extents.first_region->GetAddress(), LinearRegionAlign);
|
||||
const size_t linear_region_size = util::AlignUp(linear_extents.last_region->GetEndAddress(), LinearRegionAlign) - GetInteger(aligned_linear_phys_start);
|
||||
const KVirtualAddress linear_region_start = KMemoryLayout::GetVirtualMemoryRegionTree().GetRandomAlignedRegionWithGuard(linear_region_size, LinearRegionAlign, KMemoryRegionType_None, LinearRegionAlign);
|
||||
|
||||
const uintptr_t linear_region_phys_to_virt_diff = GetInteger(linear_region_start) - GetInteger(aligned_linear_phys_start);
|
||||
@@ -340,8 +304,6 @@ namespace ams::kern::init {
|
||||
continue;
|
||||
}
|
||||
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0);
|
||||
|
||||
if (cur_size == 0) {
|
||||
cur_phys_addr = region.GetAddress();
|
||||
cur_size = region.GetSize();
|
||||
@@ -370,13 +332,6 @@ namespace ams::kern::init {
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the slab region. */
|
||||
std::memset(GetVoidPointer(slab_region_start), 0, slab_region_size);
|
||||
|
||||
/* NOTE: Unknown function is called here which is ifdef'd out on retail kernel. */
|
||||
/* The unknown function is immediately before the function which gets the unknown debug region size, inside this translation unit. */
|
||||
/* It's likely that this is some kind of initializer for the unknown debug region. */
|
||||
|
||||
/* Create regions for and map all core-specific stacks. */
|
||||
for (size_t i = 0; i < cpu::NumCores; i++) {
|
||||
MapStackForCore(ttbr1_table, KMemoryRegionType_KernelMiscMainStack, i);
|
||||
@@ -488,8 +443,4 @@ namespace ams::kern::init {
|
||||
cpu::EnsureInstructionConsistency();
|
||||
}
|
||||
|
||||
size_t GetMiscUnknownDebugRegionSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -249,27 +249,6 @@ _ZN3ams4kern4init16JumpFromEL2ToEL1Ev:
|
||||
bl _ZN3ams4kern4arch5arm643cpu32FlushEntireDataCacheWithoutStackEv
|
||||
|
||||
/* Setup system registers for deprivileging. */
|
||||
|
||||
/* Check if we're on cortex A57 or A53. If we are, set ACTLR_EL2. */
|
||||
mrs x1, midr_el1
|
||||
|
||||
/* Is the manufacturer ID 'A' (ARM)? */
|
||||
ubfx x2, x1, #0x18, #8
|
||||
cmp x2, #0x41
|
||||
b.ne 2f
|
||||
|
||||
/* Is the board ID Cortex-A57? */
|
||||
ubfx x2, x1, #4, #0xC
|
||||
mov x3, #0xD07
|
||||
cmp x2, x3
|
||||
b.eq 1f
|
||||
|
||||
/* Is the board ID Cortex-A53? */
|
||||
mov x3, #0xD03
|
||||
cmp x2, x3
|
||||
b.ne 2f
|
||||
|
||||
1:
|
||||
/* ACTLR_EL2: */
|
||||
/* - CPUACTLR access control = 1 */
|
||||
/* - CPUECTLR access control = 1 */
|
||||
@@ -279,7 +258,6 @@ _ZN3ams4kern4init16JumpFromEL2ToEL1Ev:
|
||||
mov x0, #0x73
|
||||
msr actlr_el2, x0
|
||||
|
||||
2:
|
||||
/* HCR_EL2: */
|
||||
/* - RW = 1 (el1 is aarch64) */
|
||||
mov x0, #0x80000000
|
||||
@@ -297,14 +275,6 @@ _ZN3ams4kern4init16JumpFromEL2ToEL1Ev:
|
||||
mov x0, #0xFFFFFFFF
|
||||
msr dacr32_el2, x0
|
||||
|
||||
/* Set VPIDR_EL2 = MIDR_EL1 */
|
||||
mrs x0, midr_el1
|
||||
msr vpidr_el2, x0
|
||||
|
||||
/* SET VMPIDR_EL2 = MPIDR_EL1 */
|
||||
mrs x0, mpidr_el1
|
||||
msr vmpidr_el2, x0
|
||||
|
||||
/* SPSR_EL2: */
|
||||
/* - EL1h */
|
||||
/* - IRQ masked */
|
||||
|
||||
@@ -303,6 +303,7 @@ namespace ams::kern::init::loader {
|
||||
/* On 10.0.0+, Physically randomize the kernel region. */
|
||||
if (kern::GetTargetFirmware() >= ams::TargetFirmware_10_0_0) {
|
||||
ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true);
|
||||
cpu::StoreEntireCacheForInit();
|
||||
}
|
||||
|
||||
/* Clear kernel .bss. */
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace ams::mitm::hid {
|
||||
|
||||
Result HidMitmService::SetSupportedNpadStyleSet(const sf::ClientAppletResourceUserId &client_aruid, u32 style_set) {
|
||||
/* This code applies only to hbl, guaranteed by the check in ShouldMitm. */
|
||||
style_set |= HidNpadStyleTag_NpadSystem | HidNpadStyleTag_NpadSystemExt;
|
||||
return hidSetSupportedNpadStyleSetFwd(this->forward_service.get(), static_cast<u64>(this->client_info.process_id), static_cast<u64>(client_aruid.GetValue()), style_set);
|
||||
style_set |= TYPE_SYSTEM | TYPE_SYSTEM_EXT;
|
||||
return hidSetSupportedNpadStyleSetFwd(this->forward_service.get(), static_cast<u64>(this->client_info.process_id), static_cast<u64>(client_aruid.GetValue()), static_cast<HidControllerType>(style_set));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
#include <stratosphere/sf/sf_mitm_dispatch.h>
|
||||
|
||||
/* Command forwarders. */
|
||||
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, u32 style_set) {
|
||||
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type) {
|
||||
const struct {
|
||||
u32 style_set;
|
||||
u32 type;
|
||||
u32 pad;
|
||||
u64 aruid;
|
||||
} in = { style_set, 0, aruid };
|
||||
} in = { type, 0, aruid };
|
||||
return serviceMitmDispatchIn(s, 100, in, .in_send_pid = true, .override_pid = process_id);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Command forwarders. */
|
||||
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, u32 style_set);
|
||||
Result hidSetSupportedNpadStyleSetFwd(Service* s, u64 process_id, u64 aruid, HidControllerType type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -180,7 +180,6 @@ constexpr const RegisterWrite DisplayConfigDsi01Init03[] = {
|
||||
{sizeof(u32) * DSI_PKT_SEQ_3_HI, 0},
|
||||
{sizeof(u32) * DSI_PKT_SEQ_4_HI, 0},
|
||||
{sizeof(u32) * DSI_PKT_SEQ_5_HI, 0},
|
||||
{sizeof(u32) * DSI_CONTROL, 0},
|
||||
};
|
||||
|
||||
constexpr const RegisterWrite DisplayConfigDsi01Init04Erista[] = {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0x0"
|
||||
},
|
||||
|
||||
@@ -55,20 +55,11 @@ namespace ams::ldr {
|
||||
R_UNLESS(npdm->magic == Npdm::Magic, ResultInvalidMeta());
|
||||
|
||||
/* Validate flags. */
|
||||
u32 mask;
|
||||
if (hos::GetVersion() >= hos::Version_11_0_0) {
|
||||
/* 11.0.0 added bit 5 = "DisableDeviceAddressSpaceMerge". */
|
||||
mask = ~0x3F;
|
||||
} else if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||
/* 7.0.0 added bit 4 = "UseOptimizedMemory" */
|
||||
mask = ~0x1F;
|
||||
} else {
|
||||
u32 mask = ~0x1F;
|
||||
if (hos::GetVersion() < hos::Version_7_0_0) {
|
||||
/* 7.0.0 added 0x10 as a valid bit to NPDM flags, so before that we only check 0xF. */
|
||||
mask = ~0xF;
|
||||
}
|
||||
|
||||
/* We set the "DisableDeviceAddressSpaceMerge" bit on all versions, so be permissive with it. */
|
||||
mask &= ~0x20;
|
||||
|
||||
R_UNLESS(!(npdm->flags & mask), ResultInvalidMeta());
|
||||
|
||||
/* Validate Acid extents. */
|
||||
|
||||
@@ -326,13 +326,6 @@ namespace ams::ldr {
|
||||
}
|
||||
}
|
||||
|
||||
/* 11.0.0+ Set Disable DAS merge. */
|
||||
if (hos::GetVersion() >= hos::Version_11_0_0 || svc::IsKernelMesosphere()) {
|
||||
if (meta_flags & Npdm::MetaFlag_DisableDeviceAddressSpaceMerge) {
|
||||
flags |= svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge;
|
||||
}
|
||||
}
|
||||
|
||||
*out = flags;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"pool_partition": 2,
|
||||
"is_64_bit": true,
|
||||
"address_space_type": 3,
|
||||
"disable_device_address_space_merge": true,
|
||||
"filesystem_access": {
|
||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
|
||||
@@ -217,10 +217,6 @@ CATEGORIES = {
|
||||
123 : 'UsbStateInfo',
|
||||
124 : 'NvHostErrInfo',
|
||||
125 : 'RunningUlaInfo',
|
||||
126 : 'InternalPanelInfo',
|
||||
127 : 'ResourceLimitLimitInfo',
|
||||
128 : 'ResourceLimitPeakInfo',
|
||||
129 : 'TouchScreenInfo',
|
||||
}
|
||||
|
||||
FIELD_TYPES = {
|
||||
|
||||
Reference in New Issue
Block a user