Compare commits

..

116 Commits

Author SHA1 Message Date
fincs
4d4523041f libstratosphere: fix building after PCH related build changes 2020-10-27 21:38:19 +01:00
Michael Scire
e26e1df07f meso: correct .o dependencies in kernel/kldr 2020-10-27 13:08:07 -07:00
Michael Scire
f92de24164 meso: commit mostly-working build system 2020-10-27 12:59:40 -07:00
Michael Scire
a8a90e6324 meso: commit wip (thanks fincs) rewrite to support build targets 2020-10-27 11:48:59 -07:00
Michael Scire
1c71d12d9d ams.mitm: avoid inadvertently breaking ftpd/file listers 2020-10-27 10:28:51 -07:00
Michael Scire
37738699f2 docs: edit terminology to be hip to the jive 2020-10-26 16:14:25 -07:00
Michael Scire
e973ef7533 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "10e9e0e8"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "10e9e0e8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-10-26 16:03:40 -07:00
Michael Scire
2ee2a4f1ac docs/fatal error: update for 0.15.0 2020-10-26 16:00:34 -07:00
Michael Scire
2a2bffeb35 ams: fix building debug elf zip 2020-10-15 09:47:06 -07:00
Michael Scire
d04046ecaf ams: bump version to 0.15.0 (release slated for post-crown-tundra) 2020-10-15 09:41:49 -07:00
Michael Scire
f24171dc41 ams: build experimental zip in addition to standard one 2020-10-15 09:41:01 -07:00
Michael Scire
5b02c77400 ams: fix updater misbehavior before 0.15.0 releases 2020-10-14 12:28:26 -07:00
Michael Scire
2e7214b6fa kern: perform rescheduling on dispatch re-enable (closes #1169) 2020-10-13 23:07:51 -07:00
Michael Scire
d52179c708 util: follow 90fd771 to its natural conclusion (generic base rbtree) 2020-10-12 01:06:19 -07:00
Michael Scire
388f9e6455 kern: minor behavioral fixes to condvar/address arbiter 2020-10-12 01:06:19 -07:00
SciresM
c547c7f0e7 Note that we are a python 2 project. 2020-10-09 17:37:51 -07:00
Michael Scire
4138abbefa erpt: fix attachment-in-save paths (closes #1124, #1145) 2020-09-23 19:49:20 -07:00
Michael Scire
1275eb0bf3 erpt: add fixed-width format option 2020-09-23 17:52:08 -07:00
Michael Scire
5ac9e45d86 erpt: support older erpt binaries 2020-09-23 17:36:46 -07:00
Michael Scire
feba788bc6 erpt.py: remove idaapi usage 2020-09-23 16:05:27 -07:00
Michael Scire
f4d10a4481 set.mitm: much more aggressively cache locale (#1160) 2020-09-23 02:01:07 -07:00
Michael Scire
ff310a0647 fusee: try to alleviate a little suffering 2020-09-22 13:54:23 -07:00
Michael Scire
85505db9b7 loader: adjust thread priority for applet-hbl 2020-09-22 12:01:28 -07:00
Michael Scire
48b4dd48a4 ams: expose reboot payload for kernel panic 2020-09-18 00:43:55 -07:00
Michael Scire
8d46d901d9 ams: make mesosphere usage user-visible in display version 2020-09-17 21:18:44 -07:00
Michael Scire
1930880270 fusee: change ncm from opt-in to opt-out 2020-09-17 21:04:43 -07:00
Michael Scire
fa0df994ba git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "f6dac1e6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "f6dac1e6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-17 08:34:48 -07:00
Michael Scire
909a1767a6 ams: bump version to 0.14.4 2020-09-17 08:34:02 -07:00
Michael Scire
dbe59fd041 kern: fix KCodeMemory SVCs when Owner process != Generator process 2020-09-17 08:26:08 -07:00
Michael Scire
9b65daf439 kern: default to release config 2020-09-17 08:26:08 -07:00
Michael Scire
4acdc899f5 kern: generate fatal error on panic 2020-09-17 08:26:08 -07:00
Michael Scire
76957e502d kern: add build-define for logging to iram ringbuffer 2020-09-17 08:26:08 -07:00
Michael Scire
909397233c sm: Fix atmosphere-extension interaction with official JIT sysmodule usage 2020-09-17 08:24:47 -07:00
Michael Scire
211a828730 ro: fix process handle leak when using JitPlugin NROs 2020-09-17 08:17:11 -07:00
Michael Scire
28ceedb533 git subrepo push emummc
subrepo:
  subdir:   "emummc"
  merged:   "6a814ebb"
upstream:
  origin:   "https://github.com/m4xw/emuMMC"
  branch:   "exo2"
  commit:   "6a814ebb"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-14 18:21:38 -07:00
Michael Scire
f551ca4461 emummc: manually fix .gitrepo 2020-09-14 18:17:32 -07:00
Michael Scire
2cf5c65bc5 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "48dbf480"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "48dbf480"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-14 18:14:05 -07:00
Michael Scire
47d0d5c6ab ams: support 10.2.0 (bump vers to 0.14.3) 2020-09-14 18:13:18 -07:00
Michael Scire
fd0e3e2160 docs: update changelog 2020-09-14 18:12:48 -07:00
Michael Scire
074364753f loader: improve verification terminology 2020-09-08 15:34:22 -07:00
Michael Scire
b7d99b732a ro: rename ModuleType to reflect reality 2020-09-08 15:05:15 -07:00
Michael Scire
1cccb6efc4 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "04ef9bf8"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "04ef9bf8"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-09-07 10:52:49 -07:00
Michael Scire
f4cd4bcf03 ams: bump version to 0.14.2 2020-09-07 10:51:15 -07:00
Michael Scire
e36fe62fca kern: lps driver fixes, sleep confirmed working on 1.0.0 2020-09-07 10:43:35 -07:00
Michael Scire
870b589379 kern: fix c/p error 2020-09-07 10:43:35 -07:00
Michael Scire
acdce230da kern: add debug logging on smmu error interrupt 2020-09-07 10:43:35 -07:00
Michael Scire
34dc062c11 kern: finish 1.x lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
ab2568ddfb kern: add most of 1.x lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
4dc728824f kern: skeleton legacy lps driver 2020-09-07 10:43:35 -07:00
Michael Scire
cc6b8ea4d1 exo/kern: 1.0.0 requires access to bpmp smmu regs, userland (am) needs to map bpmp exception vectors 2020-09-07 10:43:35 -07:00
Michael Scire
49af4fae32 kern: begin 1.0.0 backwards compat changes (kips run, full boot fails) 2020-09-07 10:43:35 -07:00
Michael Scire
e8ffbe630f kern: support 2-pool layout on 2.x-4.x instead of modern 4-pool layout 2020-09-07 10:43:35 -07:00
Michael Scire
ce95af89ef kern: change terminology metadata -> management 2020-09-07 10:43:35 -07:00
Michael Scire
546e2de300 kern: pool management should be within carveout 2020-09-07 10:43:35 -07:00
Michael Scire
11b120b667 kern: fix phys/virt pool management mixup 2020-09-07 10:43:35 -07:00
Michael Scire
4da1fe545c kern: fix linear mapped dram -> pool partition check 2020-09-07 10:43:35 -07:00
Michael Scire
1983f86875 kern: revamp KMemoryRegionType to better encode derivation hierarchies 2020-09-07 10:43:35 -07:00
Michael Scire
d50c7c5c79 kern: PMC must be user-mappable for 1.0.0 compat 2020-09-07 10:43:35 -07:00
Michael Scire
496f93ccdb kern: expose mesosphere meta over GetInfo instead of GetSystemInfo 2020-09-07 10:43:35 -07:00
Michael Scire
25ba61adae loader: extend memory region descriptors a touch more gracefully 2020-09-07 10:43:35 -07:00
Michael Scire
79c9bed528 kern/pm: support for 5.x under mesosphere 2020-09-07 10:43:35 -07:00
Michael Scire
657470830f loader: support MapRegion capability as an atmosphere extension (normally kips-only) 2020-09-07 10:43:35 -07:00
Michael Scire
cd62d83586 fusee: fix sleep/wake on 6.x 2020-09-07 10:43:35 -07:00
Michael Scire
bb11c57e7d kern: fix warn-errors 2020-09-07 10:43:35 -07:00
Michael Scire
bb1cdd8c87 fusee: fixes for sd meso on lower firmwares 2020-09-07 10:43:35 -07:00
Michael Scire
ff9b9fc5ff fusee: change meso loading to parse INI from Nintendo's kernel 2020-09-07 10:43:35 -07:00
Michael Scire
99b5458539 sm: fix deadlock semantics surrounding mitm installation 2020-09-07 10:40:57 -07:00
Michael Scire
fac502aaa3 kern: fix KTypedAddress, strengthen assertions 2020-08-18 15:17:40 -07:00
Michael Scire
47f2e93a42 kern: add version bounds checking 2020-08-18 15:17:40 -07:00
Michael Scire
56ec55f3c4 kern: avoid hardcoding maximum board memory size 2020-08-18 15:17:40 -07:00
Michael Scire
1a262c1063 kern: improve resource region size definitions/calculations 2020-08-18 15:17:40 -07:00
Michael Scire
79201428b0 kern: resolve NonSecure definition TODO 2020-08-18 15:17:40 -07:00
Michael Scire
a75c16226e kern: correct thread termination atomicity 2020-08-18 15:17:40 -07:00
Michael Scire
e5d30217d3 kern: fix reference leak in KThread::GetThreadFromId callers 2020-08-18 15:17:40 -07:00
Michael Scire
f77a4fbf98 kern: non-loop cas-weak -> cas-strong 2020-08-18 15:17:40 -07:00
Michael Scire
717265a54c kern: fix bug in KScheduler::ClearPreviousThread 2020-08-18 15:17:40 -07:00
fincs
3ace441b1c arm64: set -march in cpu specific configuration 2020-08-18 15:17:40 -07:00
fincs
2effe130e3 kern: use size instead of phys addr as sentinel value in InitializeCore linear mapping logic 2020-08-18 15:17:40 -07:00
fincs
2cedf2bcf0 kern: remove accidentally copypasted code 2020-08-18 15:17:40 -07:00
fincs
68e29b56b6 kern: add stubbed KDevicePageTable implementation for systems without iommu 2020-08-18 15:17:40 -07:00
fincs
8e688de570 kern: move SetupPoolPartitionMemoryRegions into board specific implementation 2020-08-18 15:17:40 -07:00
fincs
b917ea283e kern: make GetTargetFirmware a compile-time constant when not building for Switch 2020-08-18 15:17:40 -07:00
Michael Scire
3c85e37667 kern: use std::atomic_ref instead of reinterpret_cast to std::atomic 2020-08-18 15:17:40 -07:00
Michael Scire
48e8562033 kern: use common GIC implementation for arm/arm64 2020-08-18 15:17:40 -07:00
Michael Scire
f07bd0e337 kern: correct flushing of init arguments 2020-08-18 15:17:40 -07:00
Michael Scire
4a35904d73 kern: simplify SetupForIpcClient cleanup 2020-08-18 15:17:40 -07:00
Michael Scire
b8c2782ede kern: SvcLegacyGetFutureThreadInfo 2020-08-18 15:17:40 -07:00
Michael Scire
3ec9a9e59f kern: rename CacheHelper operation for accuracy 2020-08-18 15:17:40 -07:00
Michael Scire
595c6dbe8f kern: KPageTableBase::WriteDebugMemory stores/invalidates cache 2020-08-18 15:17:40 -07:00
Michael Scire
b5f2698bf0 kern: fix multicore instruction cache invalidation 2020-08-18 15:17:40 -07:00
Michael Scire
f058536b59 kern: add tracing for irq/scheduling 2020-08-18 15:17:40 -07:00
Michael Scire
8e5c0a9663 kern: cleanup some KMemoryManager functions 2020-08-18 15:17:40 -07:00
Michael Scire
1b63002f91 kern: refactor KMemoryLayout 2020-08-18 15:17:40 -07:00
Michael Scire
90fd771fce IntrusiveRedBlackTree: refactor to add ->GetPrev(), ->GetNext() to BaseNode inheritors 2020-08-18 15:17:40 -07:00
Michael Scire
c3fa3bd5d6 kern: N reduced the slabheap gap size in 10.0.0 2020-08-18 15:17:40 -07:00
Michael Scire
cda15f08d8 kern: mark KThread/KProcess.GetId() final to save virtual calls 2020-08-18 15:17:40 -07:00
Michael Scire
e5b7eb89e5 kern: fix built-in usage for libc 2020-08-18 15:17:40 -07:00
Michael Scire
e1bd6fb874 kern: fix missing scheduler updates in KLightLock/Exception, fix RequestScheduleOnInterrupt 2020-08-18 15:17:40 -07:00
Michael Scire
920b017677 kern: implement svc trace 2020-08-18 15:17:40 -07:00
Michael Scire
f9d68db3f6 kern: SvcChangeKernelTraceState 2020-08-18 15:17:40 -07:00
Michael Scire
89f1c0ce33 kern: remove stray log in SetHeapSize 2020-08-18 15:17:40 -07:00
Michael Scire
e435f56367 exo: build with -Wextra 2020-08-17 14:39:18 -07:00
Michael Scire
73798cb812 kern: build with -Wextra 2020-08-17 14:20:24 -07:00
Michael Scire
d3014f6ed9 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "2d522dc6"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "2d522dc6"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-15 09:20:46 -07:00
Michael Scire
35fffade4e libstrat: fix building of source/os/* 2020-08-15 09:20:11 -07:00
Michael Scire
2c6b7ce6c2 git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "5a60240f"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "5a60240f"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-14 17:37:03 -07:00
Michael Scire
7658c07492 strat: fix inclusion/ordering for some c headers 2020-08-14 17:33:49 -07:00
Michael Scire
51b5c3d87d ams: avoid UB infinite loops 2020-08-13 17:28:29 -07:00
Michael Scire
874208b44a sf: handle serialization errors more accurately and gracefully 2020-08-11 16:40:57 -07:00
Michael Scire
44c5cb9789 ams: add support for cpu-extension specific source files 2020-08-11 11:43:34 -07:00
Michael Scire
420bc7df9b ams: update build system to add generic-fallback support 2020-08-11 11:22:56 -07:00
Michael Scire
ee3e0fa537 fatal: use TimeSpan for timing 2020-08-03 19:52:53 -07:00
Aurora Wright
501280b6e5 fatal: Fix autoreboot logic 2020-08-03 19:44:14 -07:00
Michael Scire
ee5a095c1a git subrepo push libraries
subrepo:
  subdir:   "libraries"
  merged:   "cac5957d"
upstream:
  origin:   "https://github.com/Atmosphere-NX/Atmosphere-libs"
  branch:   "master"
  commit:   "cac5957d"
git-subrepo:
  version:  "0.4.1"
  origin:   "???"
  commit:   "???"
2020-08-02 15:03:17 -07:00
Michael Scire
3726def6ec ams: dump version to 0.14.1 2020-08-02 15:02:43 -07:00
Michael Scire
29358dc593 kernel_ldr: use unoptimized memcpy before mmu bringup (closes #1102)
Before the MMU is up, all reads/writes must be aligned; the optimized
memcpy implementation does not guarantee all reads/writes it performs
are aligned.

This commit splits the libc impl to be separate for kernel/kernel_ldr,
and so now only kernel will use the optimized impl. This is safe,
as the MMU is brought up before kernel begins executing.
2020-08-02 14:40:28 -07:00
288 changed files with 7324 additions and 3158 deletions

View File

@@ -70,8 +70,8 @@ dist-no-debug: all
mkdir -p atmosphere-$(AMSVER)/atmosphere/config
cp fusee/fusee-primary/fusee-primary.bin atmosphere-$(AMSVER)/atmosphere/reboot_payload.bin
cp fusee/fusee-mtc/fusee-mtc.bin atmosphere-$(AMSVER)/atmosphere/fusee-mtc.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary-experimental.bin atmosphere-$(AMSVER)/sept/payload.bin
cp sept/sept-primary/sept-primary.bin atmosphere-$(AMSVER)/sept/sept-primary.bin
cp sept/sept-secondary/sept-secondary.bin atmosphere-$(AMSVER)/sept/sept-secondary.bin
cp sept/sept-secondary/sept-secondary_00.enc atmosphere-$(AMSVER)/sept/sept-secondary_00.enc
@@ -99,9 +99,13 @@ dist-no-debug: all
touch atmosphere-$(AMSVER)/atmosphere/contents/0100000000000037/flags/boot2.flag
cp troposphere/reboot_to_payload/reboot_to_payload.nro atmosphere-$(AMSVER)/switch/reboot_to_payload.nro
cp troposphere/daybreak/daybreak.nro atmosphere-$(AMSVER)/switch/daybreak.nro
cd atmosphere-$(AMSVER); zip -r ../atmosphere-EXPERIMENTAL-$(AMSVER).zip ./*; cd ../;
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/atmosphere/fusee-secondary.bin
cp fusee/fusee-secondary/fusee-secondary.bin atmosphere-$(AMSVER)/sept/payload.bin
cd atmosphere-$(AMSVER); zip -r ../atmosphere-$(AMSVER).zip ./*; cd ../;
rm -r atmosphere-$(AMSVER)
mkdir out
mv atmosphere-EXPERIMENTAL-$(AMSVER).zip out/atmosphere-EXPERIMENTAL-$(AMSVER).zip
mv atmosphere-$(AMSVER).zip out/atmosphere-$(AMSVER).zip
cp fusee/fusee-primary/fusee-primary.bin out/fusee-primary.bin
@@ -120,7 +124,7 @@ dist: dist-no-debug
mkdir atmosphere-$(AMSVER)-debug
cp fusee/fusee-primary/fusee-primary.elf atmosphere-$(AMSVER)-debug/fusee-primary.elf
cp fusee/fusee-mtc/fusee-mtc.elf atmosphere-$(AMSVER)-debug/fusee-mtc.elf
cp fusee/fusee-secondary/fusee-secondary.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
cp fusee/fusee-secondary/fusee-secondary-experimental.elf atmosphere-$(AMSVER)-debug/fusee-secondary.elf
cp sept/sept-primary/sept-primary.elf atmosphere-$(AMSVER)-debug/sept-primary.elf
cp sept/sept-secondary/sept-secondary.elf atmosphere-$(AMSVER)-debug/sept-secondary.elf
cp sept/sept-secondary/key_derivation/key_derivation.elf atmosphere-$(AMSVER)-debug/sept-secondary-key-derivation.elf

View File

@@ -9,4 +9,4 @@ stage2_entrypoint = 0xF0000000
; To force-enable nogc, add nogc = 1
; To force-disable nogc, add nogc = 0
; To opt in to using Atmosphere's NCM reimplementation, add enable_ncm = 1
; To opt out of using Atmosphere's NCM reimplementation, add disable_ncm = 1

View File

@@ -4,7 +4,7 @@ Building Atmosphère is a very straightforward process that relies almost exclus
## Dependencies
+ [devkitA64](https://devkitpro.org)
+ [devkitARM](https://devkitpro.org)
+ [Python 2 or 3](https://www.python.org) (optional)
+ [Python 2](https://www.python.org) (Python 3 may work as well, but this is not guaranteed)
+ [PyCryptodome](https://pypi.org/project/pycryptodome) (optional)
## Instructions

View File

@@ -1,4 +1,57 @@
# Changelog
## 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.
+ Beginning in this release and until it is stable and well-tested, atmosphère will distribute two zips.
+ Users who wish to opt-in to mesosphere should download and extract the "cool kids" zip ("atmosphere-EXPERIMENTAL-").
+ Users who do not wish to use mesosphere should continue using the normal zip ("atmosphere-").
+ Users may detect whether mesosphere is active in system settings.
+ When mesosphere is active, the system version string will display "M.15.0" rather than "0.15.0", and so on for future releases.
+ Crash reports and the like will contain information on whether or not the user is using mesosphere, as well.
+ There are "probably" no material user-facing benefits to using mesosphere at this time.
+ Developers may be interested in the fact that mesosphere provides many newer SVC APIs even when on lower firmware versions.
+ The primary benefit to using mesosphere is that any issues you may encounter and report to me will be fixed.
+ All users who choose to opt in to using mesosphere have my deepest gratitude.
+ **Note:** If using hekate instead of fusee-primary, you will have to wait for the next hekate release for mesosphere to function, as hekate's support has not yet been included in an official release build.
+ This will be updated in the release notes when hekate provides a new release.
+ As mentioned in previous release notes, when mesosphere is stable and well-tested, it will be enabled by default and atmosphère's version will transition to 1.0.0.
+ Having been tested sufficiently over the last half-year, Atmosphere's NCM implementation is now opt-out, rather than opt in.
+ In the unlikely event that any issues are encountered, please report them to @SciresM.
+ Users interested in opting out of using our implementation should set `stratosphere!disable_ncm = 1` in BCT.ini.
+ The NCM implementation will stop being opt-out in a future update, probably around the same time that mesosphere becomes opt-out instead of opt-in.
+ Several bugs were fixed, including:
+ Loader now sets HBL's thread priority to a higher value when loading it in applet mode.
+ This fixes an extremely-slow launch ("hang") when using applet-HBL with certain games that do not suspend while inactive (e.g. Super Mario Sunshine).
+ set.mitm now caches user language configuration much more heavily.
+ This severely reduces lag in certain games which misuse the "nn::oe::GetDesiredLanguage()" API.
+ A bug was fixed that could cause erpt to fatal when loading an official save file that had error report attachments in it.
+ General system stability improvements to enhance the user's experience.
## 0.14.4
+ Several bugs were fixed involving the official jit sysmodule added in 10.0.0.
+ A Process handle leak was fixed when JitPlugin NRRs were registered with the `ro` sysmodule.
+ This prevented processes using jit from being able to exit, causing a full system freeze.
+ The `sm` atmosphere extension to not unregister services when the server's connection is closed was special-case disabled for `jit:u`.
+ This extension is normally desirable in order to allow more concurrent processes to exist (as only 0x40 sm connections may ever be concurrently open), but official jit sysmodule relies on the behavior.
+ This would cause crashes on attempts to launch a program using jit services more than once per reboot.
+ General system stability improvements to enhance the user's experience.
## 0.14.3
+ Support was added for 10.2.0.
+ General system stability improvements to enhance the user's experience.
## 0.14.2
+ A bug was fixed that could cause a deadlock when installing mitm services.
+ Fixing this required a breaking change to the client behavior when installing a mitm service, and so custom sysmodules which use mitm will need to be re-compiled to function properly.
+ A bug was fixed that caused atmosphere sysmodules to respond incorrectly when receiving invalid messages.
+ A bug was fixed that caused fatal auto-reboot timing to work improperly.
+ Support was added to fusee for loading binaries for `mesosphere`, atmosphère's reimplementation of the Nintendo Switch kernel.
+ 0.14.2 does not include mesosphere, but those who are especially interested can build and test mesosphere themselves.
+ In the future, to enable a sufficient testing period Atmosphère releases will distribute two zips for some time.
+ One zip will use mesosphere, and the other will not.
+ This will allow users who are interested to opt-in to mesosphere usage before it has been tested to be stable.
+ When mesosphere is stable and well-tested, it will be enabled by default and Atmosphère's version will transition to 1.0.0.
+ General system stability improvements to enhance the user's experience.
## 0.14.1
+ An issue was fixed in 0.14.0 that would cause a black screen on boot when the INI1's size was not aligned to 8 bytes.
+ General system stability improvements to enhance the user's experience.
## 0.14.0
+ An API (`ams:su`) was added to allow homebrew to safely install system upgrades or downgrades.
+ This is a re-implementation of the logic that `ns` uses to install gamecard system updates.

View File

@@ -9,7 +9,7 @@ This file is located under the `/atmosphere/config/` folder on your SD card and
Atmosphère provides its own default splashscreen which is displayed at boot time. However, this can be replaced at will.
The boot splashscreen must be a BMP file, it must be 720x1280 (1280x720 rotated 90 degrees left/counterclockwise/anti-clockwise) resolution, and be in 32-bit ARGB format. You can use image editing software such as GIMP or Photoshop to export the image in this format.
Add the following lines to BCT.ini and change the value of `custom_splash` to the actual path and filename of your boot splashscreen:
```
[stage2]
@@ -29,11 +29,11 @@ nogc = X
0 = force-disable nogc, so Atmosphère will always enable the Game Card reader.
```
### NCM opt-in
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module, but currently this is not enabled by default. If you wish to enable this reimplementation add the following line to the `stratosphere` section:
### NCM opt-out
Atmosphère provides a reimplementation of the [ncm](../components/modules/ncm.md) system module. If you wish to disable this reimplementation add the following line to the `stratosphere` section:
```
[stratosphere]
enable_ncm = 1
disable_ncm = 1
```
### Logging

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/m4xw/emuMMC
branch = exo2
commit = 06ab9b895c4264ecc14d3bf9be1260e2096f6037
parent = dccd41f6d25498c191a157123a27724203d3bc37
commit = 6a814ebbe72cf5245b863b9edea9cd3801437a12
parent = f551ca4461a79908c37307db10cd8cacf8b98f17
method = rebase
cmdver = 0.4.1

View File

@@ -47,6 +47,8 @@
#include "offsets/910_exfat.h"
#include "offsets/1000.h"
#include "offsets/1000_exfat.h"
#include "offsets/1020.h"
#include "offsets/1020_exfat.h"
#include "../utils/fatal.h"
#define GET_OFFSET_STRUCT_NAME(vers) g_offsets##vers
@@ -104,6 +106,8 @@ DEFINE_OFFSET_STRUCT(_910);
DEFINE_OFFSET_STRUCT(_910_EXFAT);
DEFINE_OFFSET_STRUCT(_1000);
DEFINE_OFFSET_STRUCT(_1000_EXFAT);
DEFINE_OFFSET_STRUCT(_1020);
DEFINE_OFFSET_STRUCT(_1020_EXFAT);
const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
switch (version) {
@@ -169,6 +173,10 @@ const fs_offsets_t *get_fs_offsets(enum FS_VER version) {
return &(GET_OFFSET_STRUCT_NAME(_1000));
case FS_VER_10_0_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1000_EXFAT));
case FS_VER_10_2_0:
return &(GET_OFFSET_STRUCT_NAME(_1020));
case FS_VER_10_2_0_EXFAT:
return &(GET_OFFSET_STRUCT_NAME(_1020_EXFAT));
default:
fatal_abort(Fatal_UnknownVersion);
}

View File

@@ -68,6 +68,9 @@ enum FS_VER
FS_VER_10_0_0,
FS_VER_10_0_0_EXFAT,
FS_VER_10_2_0,
FS_VER_10_2_0_EXFAT,
FS_VER_MAX,
};

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1020_H__
#define __FS_1020_H__
// Accessor vtable getters
#define FS_OFFSET_1020_SDMMC_ACCESSOR_GC 0x14E0F0
#define FS_OFFSET_1020_SDMMC_ACCESSOR_SD 0x14C200
#define FS_OFFSET_1020_SDMMC_ACCESSOR_NAND 0x147080
// Hooks
#define FS_OFFSET_1020_SDMMC_WRAPPER_READ 0x1427E0
#define FS_OFFSET_1020_SDMMC_WRAPPER_WRITE 0x1428C0
#define FS_OFFSET_1020_RTLD 0x634
#define FS_OFFSET_1020_RTLD_DESTINATION 0x9C
#define FS_OFFSET_1020_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
// Misc funcs
#define FS_OFFSET_1020_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data
#define FS_OFFSET_1020_SD_MUTEX 0xE273E8
#define FS_OFFSET_1020_NAND_MUTEX 0xE22DA0
#define FS_OFFSET_1020_ACTIVE_PARTITION 0xE22DE0
#define FS_OFFSET_1020_SDMMC_DAS_HANDLE 0xE0AB90
// NOPs
#define FS_OFFSET_1020_SD_DAS_INIT 0x15214C
// Nintendo Paths
#define FS_OFFSET_1020_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1020_H__

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FS_1020_EXFAT_H__
#define __FS_1020_EXFAT_H__
// Accessor vtable getters
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_GC 0x14E0F0
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_SD 0x14C200
#define FS_OFFSET_1020_EXFAT_SDMMC_ACCESSOR_NAND 0x147080
// Hooks
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_READ 0x1427E0
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_WRITE 0x1428C0
#define FS_OFFSET_1020_EXFAT_RTLD 0x634
#define FS_OFFSET_1020_EXFAT_RTLD_DESTINATION 0x9C
#define FS_OFFSET_1020_EXFAT_CLKRST_SET_MIN_V_CLK_RATE 0x141A00
// Misc funcs
#define FS_OFFSET_1020_EXFAT_LOCK_MUTEX 0x28910
#define FS_OFFSET_1020_EXFAT_UNLOCK_MUTEX 0x28960
#define FS_OFFSET_1020_EXFAT_SDMMC_WRAPPER_CONTROLLER_CLOSE 0x142740
// Misc Data
#define FS_OFFSET_1020_EXFAT_SD_MUTEX 0xE353E8
#define FS_OFFSET_1020_EXFAT_NAND_MUTEX 0xE30DA0
#define FS_OFFSET_1020_EXFAT_ACTIVE_PARTITION 0xE30DE0
#define FS_OFFSET_1020_EXFAT_SDMMC_DAS_HANDLE 0xE18B90
// NOPs
#define FS_OFFSET_1020_EXFAT_SD_DAS_INIT 0x15214C
// Nintendo Paths
#define FS_OFFSET_1020_EXFAT_NINTENDO_PATHS \
{ \
{.opcode_reg = 3, .adrp_offset = 0x0006BBA4, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x00078520, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 3, .adrp_offset = 0x0007ED0C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 4, .adrp_offset = 0x0009115C, .add_rel_offset = 0x00000004}, \
{.opcode_reg = 0, .adrp_offset = 0, .add_rel_offset = 0}, \
}
#endif // __FS_1020_EXFAT_H__

View File

@@ -24,23 +24,9 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(TOPDIR)/../program
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES := program.lz4 boot_code.lz4

View File

@@ -19,10 +19,12 @@
namespace ams::diag {
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) {
AMS_UNUSED(file, line, func, expr, value, format);
ams::secmon::loader::ErrorReboot();
}
NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) {
AMS_UNUSED(file, line, func, expr, value);
ams::secmon::loader::ErrorReboot();
}

View File

@@ -25,23 +25,9 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(TOPDIR)/sc7fw \
$(TOPDIR)/rebootstub
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
BINFILES := sc7fw.bin rebootstub.bin

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -90,7 +90,7 @@ namespace ams::sc7fw {
reg::ReadWrite(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_ON, ENABLE));
/* Wait forever until we're asleep. */
while (true) { /* ... */ }
AMS_INFINITE_LOOP();
}
}
@@ -102,7 +102,9 @@ namespace ams::sc7fw {
NORETURN void ExceptionHandler() {
/* Write enable to MAIN_RESET. */
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
while (true) { /* ... */ }
/* Wait forever until we're reset. */
AMS_INFINITE_LOOP();
}
}

View File

@@ -85,6 +85,8 @@ namespace ams::secmon::boot {
if constexpr (false) {
/* TODO: Consider implementing this as a reference. */
}
AMS_UNUSED(is_prod);
}
/* NOTE: These are just latest-master-kek encrypted with BEK. */
@@ -406,6 +408,7 @@ namespace ams::secmon::boot {
constexpr void UnmapDramImpl(u64 *l1, u64 *l2, u64 *l3) {
/* Unmap the L1 entry corresponding to to the Dram entries. */
AMS_UNUSED(l2, l3);
InvalidateL1Entries(l1, MemoryRegionDram.GetAddress(), MemoryRegionDram.GetSize());
}

View File

@@ -41,6 +41,7 @@ namespace ams::secmon {
constexpr void UnmapBootCodeImpl(u64 *l1, u64 *l2, u64 *l3, uintptr_t boot_code, size_t boot_code_size) {
/* Unmap the L3 entries corresponding to the boot code. */
AMS_UNUSED(l1, l2);
InvalidateL3Entries(l3, boot_code, boot_code_size);
}
@@ -95,10 +96,6 @@ namespace ams::secmon {
util::ClearMemory(reinterpret_cast<void *>(address + size / 2), size / 2);
}
bool IsPhysicalMemoryAddress(uintptr_t address) {
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
}
}
void ClearBootCodeHigh() {
@@ -129,6 +126,10 @@ namespace ams::secmon {
}
}
bool IsPhysicalMemoryAddress(uintptr_t address) {
return (address - MemoryRegionDram.GetAddress()) < GetPhysicalMemorySize();
}
void UnmapTzram() {
/* Get the tables. */
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();

View File

@@ -18,6 +18,7 @@
namespace ams::secmon {
bool IsPhysicalMemoryAddress(uintptr_t address);
size_t GetPhysicalMemorySize();
void UnmapTzram();

View File

@@ -141,6 +141,9 @@ namespace ams::secmon::smc {
{ 0xC3000006, Restriction_Normal, SmcShowError },
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
{ 0xC3000409, Restriction_Normal, SmcSetConfig },
};
constinit HandlerInfo g_ams_handlers[] = {

View File

@@ -15,6 +15,7 @@
*/
#include <exosphere.hpp>
#include "../secmon_error.hpp"
#include "../secmon_map.hpp"
#include "../secmon_misc.hpp"
#include "../secmon_page_mapper.hpp"
#include "../secmon_user_power_management.hpp"
@@ -157,6 +158,8 @@ namespace ams::secmon::smc {
return value.value;
}
constinit u64 g_payload_address = 0;
SmcResult GetConfig(SmcArguments &args, bool kern) {
switch (static_cast<ConfigItem>(args.r[1])) {
case ConfigItem::DisableProgramVerification:
@@ -267,6 +270,14 @@ namespace ams::secmon::smc {
/* NOTE: This may return values other than 1 in the future. */
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0);
break;
case ConfigItem::ExospherePayloadAddress:
/* Gets the physical address of the reboot payload buffer, if one exists. */
if (g_payload_address != 0) {
args.r[1] = g_payload_address;
} else {
return SmcResult::NotInitialized;
}
break;
default:
return SmcResult::InvalidArgument;
}
@@ -309,6 +320,17 @@ namespace ams::secmon::smc {
return SmcResult::NotImplemented;
}
break;
case ConfigItem::ExospherePayloadAddress:
if (g_payload_address == 0) {
if (secmon::IsPhysicalMemoryAddress(args.r[2])) {
g_payload_address = args.r[2];
} else {
return SmcResult::InvalidArgument;
}
} else {
return SmcResult::Busy;
}
break;
default:
return SmcResult::InvalidArgument;
}

View File

@@ -48,6 +48,7 @@ namespace ams::secmon::smc {
ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006,
ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008,
};
SmcResult SmcGetConfigUser(SmcArguments &args);

View File

@@ -69,6 +69,7 @@ namespace ams::secmon::smc {
SmcResult SmcWriteAddress(SmcArguments &args) {
/* NOTE: This smc was deprecated in Atmosphère 0.13.0. */
AMS_UNUSED(args);
return SmcResult::NotImplemented;
}

View File

@@ -492,6 +492,8 @@ namespace ams::secmon::smc {
}
SmcResult SmcPowerOffCpu(SmcArguments &args) {
AMS_UNUSED(args);
/* Get the current core id. */
const auto core_id = hw::GetCurrentCoreId();

View File

@@ -155,10 +155,27 @@ namespace ams::secmon::smc {
/* Find the access table. */
const AccessTableEntry * const entry = GetAccessTableEntry(address);
/* If we have a table, perform the write. */
/* Translate our entry into an address to access. */
uintptr_t virtual_address = 0;
if (entry != nullptr) {
/* Get the address to read or write. */
const uintptr_t virtual_address = entry->virtual_address + (address - entry->address);
virtual_address = entry->virtual_address + (address - entry->address);
} else {
/* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */
/* when accessing the SMMU controls for the BPMP and for APB-DMA. */
/* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */
/* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */
constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress();
SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument);
/* For backwards compatibility, we'll allow access to these devices on 1.0.0. */
if (GetTargetFirmware() < TargetFirmware_2_0_0) {
virtual_address = MemoryRegionVirtualDeviceMemoryController.GetAddress() + (address - MC);
}
}
/* Perform the read or write, if we should. */
if (virtual_address != 0) {
u32 out = 0;
if (mask != ~static_cast<u32>(0)) {
@@ -169,13 +186,6 @@ namespace ams::secmon::smc {
}
args.r[1] = out;
} else {
/* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */
/* when accessing the SMMU controls for the BPMP and for APB-DMA. */
/* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */
/* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */
constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress();
SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument);
}
return SmcResult::Success;

View File

@@ -75,6 +75,7 @@ namespace ams::secmon::smc {
u8 msg[se::RsaSize];
public:
void Set(const void *m, size_t m_size) {
AMS_UNUSED(m_size);
std::memcpy(this->msg, m, sizeof(this->msg));
}

View File

@@ -23,23 +23,9 @@ export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -90,7 +90,9 @@ namespace ams::warmboot {
NORETURN void ExceptionHandler() {
/* Write enable to MAIN_RESET. */
reg::Write(PMC + APBDEV_PMC_CNTRL, PMC_REG_BITS_ENUM(CNTRL_MAIN_RESET, ENABLE));
while (true) { /* ... */ }
/* Wait forever until we're reset. */
AMS_INFINITE_LOOP();
}
}

View File

@@ -24,6 +24,9 @@
#include "lib/log.h"
#include "display/video_fb.h"
#define PROGRAM_ID_AMS_MITM 0x010041544D530000ull
#define PROGRAM_ID_BOOT 0x0100000000000005ull
static uint32_t g_panic_code = 0;
static const char *get_error_desc_str(uint32_t error_desc) {
@@ -42,6 +45,8 @@ static const char *get_error_desc_str(uint32_t error_desc) {
return "SError";
case 0x301:
return "Bad SVC";
case 0xF00:
return "Kernel Panic";
case 0xFFD:
return "Stack overflow";
case 0xFFE:
@@ -51,6 +56,61 @@ static const char *get_error_desc_str(uint32_t error_desc) {
}
}
static void _try_suggest_fix(const atmosphere_fatal_error_ctx *ctx) {
/* Try to recognize certain errors automatically, and suggest fixes for them. */
const char *suggestion = NULL;
if (ctx->error_desc == 0xFFE) {
if (ctx->program_id == PROGRAM_ID_AMS_MITM) {
/* When a user has archive bits set improperly, attempting to create an automatic backup will fail */
/* to create the file path with error 0x202 (fs::ResultPathNotFound()) */
if (ctx->gprs[0] == 0x202) {
/* When the archive bit error is occurring, it manifests as failure to create automatic backup. */
/* Thus, we can search the stack for the automatic backups path. */
const char * const automatic_backups_prefix = "automatic_backups/X" /* ..... */;
const int prefix_len = strlen(automatic_backups_prefix);
for (size_t i = 0; i + prefix_len < ctx->stack_dump_size; ++i) {
if (memcmp(&ctx->stack_dump[i], automatic_backups_prefix, prefix_len) == 0) {
suggestion = "The atmosphere directory may improperly have archive\n"
"bits set. Please try running an archive bit fixer tool\n"
"(for example, the one in Hekate).\n";
break;
}
}
} else if (ctx->gprs[0] == 0x249A02) { /* fs::ResultResultExFatUnavailable() */
/* When a user installs non-exFAT firm but has an exFAT formatted SD card, this error will */
/* be returned on attempt to access the SD card. */
suggestion = "Your console has non-exFAT firmware installed, but your SD card\n"
"is formatted as exFAT. Format your SD card as FAT32, or manually\n"
"flash exFAT firmware to package2.\n";
}
} else if (ctx->program_id == PROGRAM_ID_BOOT) {
/* 9.x -> 10.x updated the API for SvcQueryIoMapping. */
/* This can cause the kernel to reject incorrect-ABI calls by boot when a partial update is applied */
/* (older kernel in package2, for some reason). */
for (size_t i = 0; i < 8; ++i) {
if (ctx->gprs[i] == 0xF201) {
suggestion = "A partial update may have been improperly performed.\n"
"To fix, try manually flashing latest package2 to MMC.\n"
"\n"
"For help doing this, seek support in the ReSwitched or\n"
"Nintendo Homebrew discord servers.\n";
break;
}
}
}
} else if (ctx->error_desc == 0xF00) { /* Kernel Panic */
suggestion = "Please contact SciresM#0524 on Discord, or create an issue\n"
"on the Atmosphere GitHub issue tracker. Thank you very much\n"
"for helping to test mesosphere.\n";
}
if (suggestion != NULL) {
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\n%s", suggestion);
}
}
static void _check_and_display_atmosphere_fatal_error(void) {
/* Check for valid magic. */
if (ATMOSPHERE_FATAL_ERROR_CONTEXT->magic != ATMOSPHERE_REBOOT_TO_FATAL_MAGIC &&
@@ -84,7 +144,7 @@ static void _check_and_display_atmosphere_fatal_error(void) {
ATMOSPHERE_FATAL_ERROR_CONTEXT->magic = 0xCCCCCCCC;
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "A fatal error occurred when running Atmosph\xe8re.\n");
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Title ID: %016llx\n", ctx.title_id);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Program ID: %016llx\n", ctx.program_id);
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "Error Desc: %s (0x%x)\n", get_error_desc_str(ctx.error_desc), ctx.error_desc);
/* Save context to the SD card. */
@@ -99,6 +159,9 @@ static void _check_and_display_atmosphere_fatal_error(void) {
}
}
/* Try to print a fix suggestion via automatic error detection. */
_try_suggest_fix(&ctx);
/* Display error. */
print(SCREEN_LOG_LEVEL_ERROR | SCREEN_LOG_LEVEL_NO_PREFIX, "\nPress POWER to reboot\n");
}

View File

@@ -36,7 +36,7 @@
typedef struct {
uint32_t magic;
uint32_t error_desc;
uint64_t title_id;
uint64_t program_id;
union {
uint64_t gprs[32];
struct {

View File

@@ -89,7 +89,7 @@ export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
$(AMS)/exosphere $(AMS)/exosphere/warmboot $(AMS)/exosphere/program/rebootstub \
$(AMS)/thermosphere $(AMS)/fusee/fusee-primary $(AMS)/sept/sept-primary \
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
$(AMS)/sept/sept-secondary $(AMS)/emummc $(AMS)/mesosphere $(AMS)/mesosphere/kernel_ldr $(KIPDIRS)
export DEPSDIR := $(CURDIR)/$(BUILD)
@@ -100,7 +100,7 @@ KIPFILES := loader.kip ncm.kip pm.kip sm.kip ams_mitm.kip spl.kip boot.kip
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin \
exosphere.bin warmboot.bin rebootstub.bin thermosphere.bin splash_screen.bmp \
sept-primary.bin sept-secondary_00.enc sept-secondary_01.enc emummc.kip \
sept-secondary_dev_00.enc sept-secondary_dev_01.enc kernel_ldr.bin $(KIPFILES)
sept-secondary_dev_00.enc sept-secondary_dev_01.enc mesosphere.bin kernel_ldr.bin $(KIPFILES)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@@ -186,11 +186,15 @@ DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
all : $(OUTPUT).bin
$(OUTPUT).bin : $(OUTPUT).elf
$(OUTPUT).bin : $(OUTPUT)-experimental.bin
@python $(TOPDIR)/fusee_make_standard.py $(OUTPUT)-experimental.bin $(OUTPUT).bin
@echo built ... $(notdir $@)
$(OUTPUT)-experimental.bin : $(OUTPUT)-experimental.elf
$(OBJCOPY) -S -O binary $< $@
@echo built ... $(notdir $@)
$(OUTPUT).elf : $(OFILES)
$(OUTPUT)-experimental.elf : $(OFILES)
%.elf: $(OFILES)
@echo linking $(notdir $@)

View File

@@ -0,0 +1,37 @@
#!/usr/bin/env python
import sys, os
from struct import pack as pk, unpack as up
def make_standard(exp):
std = exp[:]
_, metadata_offset, is_exp = up('<III', exp[:12])
assert is_exp == 1
# Patch the experimental flag to zero.
std = std[:8] + pk('<I', 0) + std[12:]
# Locate the mesosphere content header, patch to be experimental.
magic, size, code_ofs, content_ofs, num_contents, ver, sup_ver, rev = up('<IIIIIIII', exp[metadata_offset:metadata_offset + 0x20])
for i in range(num_contents):
start, size, cnt_type, flag0, flag1, flag2, pad = up('<IIBBBBI', exp[content_ofs + 0x20 * i:content_ofs + 0x20 * i + 0x10])
if cnt_type == 10: # CONTENT_TYPE_KRN
assert exp[content_ofs + 0x20 * i + 0x10:content_ofs + 0x20 * i + 0x10 + len(b'mesosphere') + 1] == (b'mesosphere\x00')
assert flag0 == 0 and flag1 == 0 and flag2 == 0
std = std[:content_ofs + 0x20 * i] + pk('<IIBBBBI', start, size, cnt_type, flag0 | 0x1, flag1, flag2, pad) + std[content_ofs + 0x20 * i + 0x10:]
return std
def main(argc, argv):
if argc != 3:
print('Usage: %s input output' % argv[0])
return 1
with open(argv[1], 'rb') as f:
experimental = f.read()
with open(argv[2], 'wb') as f:
f.write(make_standard(experimental))
return 0
if __name__ == '__main__':
sys.exit(main(len(sys.argv), sys.argv))

View File

@@ -254,4 +254,6 @@ SECTIONS
PROVIDE(__emummc_kip_size__ = emummc_kip_end - emummc_kip);
PROVIDE(__kernel_ldr_bin_start__ = kernel_ldr_bin - __start__);
PROVIDE(__kernel_ldr_bin_size__ = kernel_ldr_bin_end - kernel_ldr_bin);
PROVIDE(__mesosphere_bin_start__ = mesosphere_bin - __start__);
PROVIDE(__mesosphere_bin_size__ = mesosphere_bin_end - mesosphere_bin);
}

View File

@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FUSEE_CAR_H
#define FUSEE_CAR_H
@@ -37,23 +37,27 @@
/* Clock and reset devices. */
typedef enum {
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_BPMP = ((0 << 5) | 0x1),
CARDEVICE_UARTA = ((0 << 5) | 0x6),
CARDEVICE_UARTB = ((0 << 5) | 0x7),
CARDEVICE_I2C1 = ((0 << 5) | 0xC),
CARDEVICE_USBD = ((0 << 5) | 0x16),
CARDEVICE_HOST1X = ((0 << 5) | 0x1C),
CARDEVICE_AHBDMA = ((1 << 5) | 0x1),
CARDEVICE_APBDMA = ((1 << 5) | 0x2),
CARDEVICE_KFUSE = ((1 << 5) | 0x8),
CARDEVICE_I2C5 = ((1 << 5) | 0xF),
CARDEVICE_UARTC = ((1 << 5) | 0x17),
CARDEVICE_USB2 = ((1 << 5) | 0x1A),
CARDEVICE_CORESIGHT = ((2 << 5) | 0x9),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_BPMP = ((0 << 5) | 0x1)
CARDEVICE_TSEC = ((2 << 5) | 0x13),
CARDEVICE_ACTMON = ((3 << 5) | 0x17),
CARDEVICE_TZRAM = ((3 << 5) | 0x1E),
CARDEVICE_SE = ((3 << 5) | 0x1F),
CARDEVICE_CL_DVFS = ((4 << 5) | 0x1B),
CARDEVICE_SOR0 = ((5 << 5) | 0x16),
CARDEVICE_SOR1 = ((5 << 5) | 0x17),
CARDEVICE_SOR_SAFE = ((6 << 5) | 0x1E),
} CarDevice;
/* Clock/Reset Controller (CLK_RST_CONTROLLER_) regs */
@@ -97,31 +101,31 @@ typedef struct {
uint32_t pllc_out;
uint32_t pllc_misc0;
uint32_t pllc_misc1;
/* PLLM 0x90-0x9c */
uint32_t pllm_base;
uint32_t pllm_out;
uint32_t pllm_misc1;
uint32_t pllm_misc2;
/* PLLP 0xa0-0xac */
uint32_t pllp_base;
uint32_t pllp_outa;
uint32_t pllp_outb;
uint32_t pllp_misc;
/* PLLA 0xb0-0xbc */
uint32_t plla_base;
uint32_t plla_out;
uint32_t plla_misc0;
uint32_t plla_misc1;
/* PLLU 0xc0-0xcc */
uint32_t pllu_base;
uint32_t pllu_out;
uint32_t pllu_misc1;
uint32_t pllu_misc2;
/* PLLD 0xd0-0xdc */
uint32_t plld_base;
uint32_t plld_out;
@@ -131,13 +135,13 @@ typedef struct {
/* PLLX 0xe0-0xe4 */
uint32_t pllx_base;
uint32_t pllx_misc;
/* PLLE 0xe8-0xf4 */
uint32_t plle_base;
uint32_t plle_misc;
uint32_t plle_ss_cntl1;
uint32_t plle_ss_cntl2;
uint32_t lvl2_clk_gate_ovra; /* _LVL2_CLK_GATE_OVRA_0, 0xf8 */
uint32_t lvl2_clk_gate_ovrb; /* _LVL2_CLK_GATE_OVRB_0, 0xfc */
@@ -188,7 +192,7 @@ typedef struct {
uint32_t _0x1e0[5];
uint32_t clk_source_tsec; /* _CLK_SOURCE_TSEC_0, 0x1f4 */
uint32_t _0x1f8;
uint32_t clk_spare2; /* _CLK_SPARE2_0, 0x1fc */
uint32_t _0x200[32];
@@ -257,7 +261,7 @@ typedef struct {
uint32_t lvl2_clk_gate_ovrc; /* _LVL2_CLK_GATE_OVRC, 0x3a0 */
uint32_t lvl2_clk_gate_ovrd; /* _LVL2_CLK_GATE_OVRD, 0x3a4 */
uint32_t _0x3a8[2];
uint32_t _0x3b0;
uint32_t clk_source_mselect; /* _CLK_SOURCE_MSELECT_0, 0x3b4 */
uint32_t clk_source_tsensor; /* _CLK_SOURCE_TSENSOR_0, 0x3b8 */
@@ -371,13 +375,13 @@ typedef struct {
uint32_t spare_reg0; /* _SPARE_REG0_0, 0x55c */
uint32_t audio_sync_clk_dmic1; /* _AUDIO_SYNC_CLK_DMIC1_0, 0x560 */
uint32_t audio_sync_clk_dmic2; /* _AUDIO_SYNC_CLK_DMIC2_0, 0x564 */
uint32_t _0x568[2];
uint32_t plld2_ss_cfg; /* _PLLD2_SS_CFG, 0x570 */
uint32_t plld2_ss_ctrl1; /* _PLLD2_SS_CTRL1_0, 0x574 */
uint32_t plld2_ss_ctrl2; /* _PLLD2_SS_CTRL2_0, 0x578 */
uint32_t _0x57c[5];
uint32_t plldp_base; /* _PLLDP_BASE, 0x590*/
uint32_t plldp_misc; /* _PLLDP_MISC, 0x594 */
uint32_t plldp_ss_cfg; /* _PLLDP_SS_CFG, 0x598 */
@@ -399,7 +403,7 @@ typedef struct {
uint32_t pllx_misc4; /* _PLLX_MISC_4_0, 0x5f0 */
uint32_t pllx_misc5; /* _PLLX_MISC_5_0, 0x5f4 */
uint32_t _0x5f8[2];
uint32_t clk_source_xusb_core_host; /* _CLK_SOURCE_XUSB_CORE_HOST_0, 0x600 */
uint32_t clk_source_xusb_falcon; /* _CLK_SOURCE_XUSB_FALCON_0, 0x604 */
uint32_t clk_source_xusb_fs; /* _CLK_SOURCE_XUSB_FS_0, 0x608 */
@@ -428,7 +432,7 @@ typedef struct {
uint32_t clk_source_uart_fst_mipi_cal; /* _CLK_SOURCE_UART_FST_MIPI_CAL_0, 0x66c */
uint32_t _0x670[2];
uint32_t clk_source_vic; /* _CLK_SOURCE_VIC_0, 0x678 */
uint32_t pllp_outc; /* _PLLP_OUTC_0, 0x67c */
uint32_t pllp_misc1; /* _PLLP_MISC1_0, 0x680 */
uint32_t _0x684[2];
@@ -439,14 +443,14 @@ typedef struct {
uint32_t clk_source_nvdec; /* _CLK_SOURCE_NVDEC_0, 0x698 */
uint32_t clk_source_nvjpg; /* _CLK_SOURCE_NVJPG_0, 0x69c */
uint32_t clk_source_nvenc; /* _CLK_SOURCE_NVENC_0, 0x6a0 */
uint32_t plla1_base; /* _PLLA1_BASE_0, 0x6a4 */
uint32_t plla1_misc0; /* _PLLA1_MISC_0_0, 0x6a8 */
uint32_t plla1_misc1; /* _PLLA1_MISC_1_0, 0x6ac */
uint32_t plla1_misc2; /* _PLLA1_MISC_2_0, 0x6b0 */
uint32_t plla1_misc3; /* _PLLA1_MISC_3_0, 0x6b4 */
uint32_t audio_sync_clk_dmic3; /* _AUDIO_SYNC_CLK_DMIC3_0, 0x6b8 */
uint32_t clk_source_dmic3; /* _CLK_SOURCE_DMIC3_0, 0x6bc */
uint32_t clk_source_ape; /* _CLK_SOURCE_APE_0, 0x6c0 */
uint32_t clk_source_qspi; /* _CLK_SOURCE_QSPI_0, 0x6c4 */
@@ -455,11 +459,11 @@ typedef struct {
uint32_t clk_source_pex_sata_usb_rx_byp; /* _CLK_SOURCE_PEX_SATA_USB_RX_BYP_0, 0x6d0 */
uint32_t clk_source_maud; /* _CLK_SOURCE_MAUD_0, 0x6d4 */
uint32_t clk_source_tsecb; /* _CLK_SOURCE_TSECB_0, 0x6d8 */
uint32_t clk_cpug_misc1; /* _CLK_CPUG_MISC1_0, 0x6dc */
uint32_t aclk_burst_policy; /* _ACLK_BURST_POLICY_0, 0x6e0 */
uint32_t super_aclk_divider; /* _SUPER_ACLK_DIVIDER_0, 0x6e4 */
uint32_t nvenc_super_clk_divider; /* _NVENC_SUPER_CLK_DIVIDER_0, 0x6e8 */
uint32_t vi_super_clk_divider; /* _VI_SUPER_CLK_DIVIDER_0, 0x6ec */
uint32_t vic_super_clk_divider; /* _VIC_SUPER_CLK_DIVIDER_0, 0x6f0 */
@@ -470,7 +474,7 @@ typedef struct {
uint32_t se_super_clk_divider; /* _SE_SUPER_CLK_DIVIDER_0, 0x704 */
uint32_t tsec_super_clk_divider; /* _TSEC_SUPER_CLK_DIVIDER_0, 0x708 */
uint32_t tsecb_super_clk_divider; /* _TSECB_SUPER_CLK_DIVIDER_0, 0x70c */
uint32_t clk_source_uartape; /* _CLK_SOURCE_UARTAPE_0, 0x710 */
uint32_t clk_cpug_misc2; /* _CLK_CPUG_MISC2_0, 0x714 */
uint32_t clk_source_dbgapb; /* _CLK_SOURCE_DBGAPB_0, 0x718 */
@@ -484,7 +488,7 @@ typedef struct {
uint32_t sdmmc4_pllc4_out0_shaper_ctrl; /* _SDMMC4_PLLC4_OUT0_SHAPER_CTRL_0, 0x738 */
uint32_t sdmmc4_pllc4_out1_shaper_ctrl; /* _SDMMC4_PLLC4_OUT1_SHAPER_CTRL_0, 0x73c */
uint32_t sdmmc4_pllc4_out2_shaper_ctrl; /* _SDMMC4_PLLC4_OUT2_SHAPER_CTRL_0, 0x740 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
uint32_t sdmmc4_div_clk_shaper_ctrl; /* _SDMMC4_DIV_CLK_SHAPER_CTRL_0, 0x744 */
} tegra_car_t;
static inline volatile tegra_car_t *car_get_regs(void) {

View File

@@ -85,6 +85,9 @@ typedef enum {
FS_VER_10_0_0,
FS_VER_10_0_0_EXFAT,
FS_VER_10_2_0,
FS_VER_10_2_0_EXFAT,
FS_VER_MAX,
} emummc_fs_ver_t;

View File

@@ -420,6 +420,9 @@ static const uint8_t g_fs_hashes[FS_VER_MAX][0x8] = {
"\x3E\xEB\xD9\xB7\xBC\xD1\xB5\xE0", /* FS_VER_10_0_0 */
"\x81\x7E\xA2\xB0\xB7\x02\xC1\xF3", /* FS_VER_10_0_0_EXFAT */
"\xA9\x52\xB6\x57\xAD\xF9\xC2\xBA", /* FS_VER_10_2_0 */
"\x16\x0D\x3E\x10\x4E\xAD\x61\x76", /* FS_VER_10_2_0_EXFAT */
};
kip1_header_t *apply_kip_ips_patches(kip1_header_t *kip, size_t kip_size, emummc_fs_ver_t *out_fs_ver) {

View File

@@ -963,11 +963,6 @@ void package2_patch_kernel(void *_kernel, size_t *kernel_size, bool is_sd_kernel
}
if (kernel_info == NULL && is_sd_kernel) {
/* If the kernel is mesosphere, patch it. */
if (*(volatile uint32_t *)((uintptr_t)_kernel + 4) == 0x3053534D) {
*out_ini1 = (void *)((uintptr_t)_kernel + *(volatile uint32_t *)((uintptr_t)_kernel + 8));
*(volatile uint64_t *)((uintptr_t)_kernel + 8) = (uint64_t)*kernel_size;
}
return;
}

View File

@@ -24,6 +24,7 @@
#include "nxboot.h"
#include "nxfs.h"
#include "bct.h"
#include "car.h"
#include "di.h"
#include "mc.h"
#include "se.h"
@@ -54,6 +55,7 @@
#define u8 uint8_t
#define u32 uint32_t
#include "exosphere_bin.h"
#include "mesosphere_bin.h"
#include "sept_secondary_00_enc.h"
#include "sept_secondary_01_enc.h"
#include "sept_secondary_dev_00_enc.h"
@@ -65,6 +67,8 @@
extern const uint8_t warmboot_bin[];
extern int fusee_is_experimental(void);
static const uint8_t retail_pkc_modulus[0x100] = {
0xF7, 0x86, 0x47, 0xAB, 0x71, 0x89, 0x81, 0xB5, 0xCF, 0x0C, 0xB0, 0xE8, 0x48, 0xA7, 0xFD, 0xAD,
0xCB, 0x4E, 0x4A, 0x52, 0x0B, 0x1A, 0x8E, 0xDE, 0x41, 0x87, 0x6F, 0xB7, 0x31, 0x05, 0x5F, 0xAA,
@@ -208,11 +212,11 @@ static int stratosphere_ini_handler(void *user, const char *section, const char
strat_cfg->has_nogc_config = true;
sscanf(value, "%d", &tmp);
strat_cfg->enable_nogc = tmp != 0;
} else if (strcmp(name, STRATOSPHERE_ENABLE_NCM_KEY) == 0) {
} else if (strcmp(name, STRATOSPHERE_DISABLE_NCM_KEY) == 0) {
sscanf(value, "%d", &tmp);
strat_cfg->ncm_enabled = tmp != 0;
if (strat_cfg->ncm_enabled) {
stratosphere_enable_ncm();
strat_cfg->ncm_disabled = tmp != 0;
if (strat_cfg->ncm_disabled) {
stratosphere_disable_ncm();
}
} else {
return 0;
@@ -235,6 +239,7 @@ static uint32_t nxboot_get_specific_target_firmware(uint32_t target_firmware){
#define CHECK_NCA(NCA_ID, VERSION) do { if (is_nca_present(NCA_ID)) { return ATMOSPHERE_TARGET_FIRMWARE_##VERSION; } } while(0)
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_10_0_0) {
CHECK_NCA("26325de4db3909e0ef2379787c7e671d", 10_2_0);
CHECK_NCA("5077973537f6735b564dd7475b779f87", 10_1_1); /* Exclusive to China. */
CHECK_NCA("fd1faed0ca750700d254c0915b93d506", 10_1_0);
CHECK_NCA("34728c771299443420820d8ae490ea41", 10_0_4);
@@ -622,6 +627,7 @@ static nx_keyblob_t __attribute__((aligned(16))) g_keyblobs[32];
uint32_t nxboot_main(void) {
volatile tegra_pmc_t *pmc = pmc_get_regs();
loader_ctx_t *loader_ctx = get_loader_ctx();
const bool is_experimental = fusee_is_experimental();
package2_header_t *package2;
size_t package2_size;
void *tsec_fw;
@@ -633,6 +639,8 @@ uint32_t nxboot_main(void) {
void *warmboot_memaddr;
void *package1loader;
size_t package1loader_size;
void *mesosphere;
size_t mesosphere_size;
void *emummc;
size_t emummc_size;
uint32_t available_revision;
@@ -928,6 +936,41 @@ uint32_t nxboot_main(void) {
pmc->scratch1 = (uint32_t)warmboot_memaddr;
}
/* Configure mesosphere. */
{
size_t sd_meso_size = get_file_size("atmosphere/mesosphere.bin");
if (sd_meso_size != 0) {
if (sd_meso_size > PACKAGE2_SIZE_MAX) {
fatal_error("Error: atmosphere/mesosphere.bin is too large!\n");
}
mesosphere = malloc(sd_meso_size);
if (mesosphere == NULL) {
fatal_error("Error: failed to allocate mesosphere!\n");
}
if (read_from_file(mesosphere, sd_meso_size, "atmosphere/mesosphere.bin") != sd_meso_size) {
fatal_error("Error: failed to read atmosphere/mesosphere.bin!\n");
}
mesosphere_size = sd_meso_size;
} else if (is_experimental) {
mesosphere_size = mesosphere_bin_size;
mesosphere = malloc(mesosphere_size);
if (mesosphere == NULL) {
fatal_error("[NXBOOT] Out of memory!\n");
}
memcpy(mesosphere, mesosphere_bin, mesosphere_size);
if (mesosphere_size == 0) {
fatal_error("[NXBOOT] Could not read embedded mesosphere!\n");
}
} else {
mesosphere = NULL;
mesosphere_size = 0;
}
}
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT] Rebuilding package2...\n");
/* Parse stratosphere config. */
@@ -936,7 +979,7 @@ uint32_t nxboot_main(void) {
print(SCREEN_LOG_LEVEL_INFO, u8"[NXBOOT] Configured Stratosphere...\n");
/* Patch package2, adding Thermosphère + custom KIPs. */
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, emummc, emummc_size);
package2_rebuild_and_copy(package2, MAILBOX_EXOSPHERE_CONFIGURATION->target_firmware, mesosphere, mesosphere_size, emummc, emummc_size);
/* Set detected FS version. */
MAILBOX_EXOSPHERE_CONFIGURATION->emummc_cfg.base_cfg.fs_version = stratosphere_get_fs_version();
@@ -991,6 +1034,12 @@ uint32_t nxboot_main(void) {
/* Wait for the splash screen to have been displayed for as long as it should be. */
splash_screen_wait_delay();
/* Set reset for USBD, USB2, AHBDMA, and APBDMA. */
rst_enable(CARDEVICE_USBD);
rst_enable(CARDEVICE_USB2);
rst_enable(CARDEVICE_AHBDMA);
rst_enable(CARDEVICE_APBDMA);
/* Return the memory address for booting CPU0. */
return (uint32_t)exosphere_memaddr;
}

View File

@@ -44,7 +44,7 @@ static inline size_t align_to_4(size_t s) {
return ((s + 3) >> 2) << 2;
}
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size) {
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *mesosphere, size_t mesosphere_size, void *emummc, size_t emummc_size) {
package2_header_t *rebuilt_package2;
size_t rebuilt_package2_size;
void *kernel;
@@ -95,10 +95,28 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm
fatal_error("Error: inappropriate kernel embedded ini context");
}
/* Use mesosphere instead of Nintendo's kernel when present. */
const bool is_mesosphere = mesosphere != NULL && mesosphere_size != 0;
if (is_mesosphere) {
kernel = mesosphere;
kernel_size = mesosphere_size;
/* Patch mesosphere to use our rebuilt ini. */
*(volatile uint64_t *)((uintptr_t)mesosphere + 8) = (uint64_t)mesosphere_size;
/* Place the kernel section at the correct location. */
package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] = 0x60000;
package2->metadata.entrypoint = 0x60000;
print(SCREEN_LOG_LEVEL_DEBUG, "Using Mesosphere...\n");
}
print(SCREEN_LOG_LEVEL_DEBUG, "Rebuilding the INI1 section...\n");
if (target_firmware < ATMOSPHERE_TARGET_FIRMWARE_8_0_0) {
package2_get_src_section((void *)&orig_ini1, package2, PACKAGE2_SECTION_INI1);
} else {
}
if (target_firmware >= ATMOSPHERE_TARGET_FIRMWARE_8_0_0 || is_mesosphere) {
/* On 8.0.0, place INI1 right after kernelldr for our sanity. */
package2->metadata.section_offsets[PACKAGE2_SECTION_INI1] = package2->metadata.section_offsets[PACKAGE2_SECTION_KERNEL] + kernel_size;
}

View File

@@ -94,6 +94,6 @@ static inline uint8_t package2_meta_get_header_version(const package2_meta_t *me
return (uint8_t)((metadata->ctr_dwords[1] ^ (metadata->ctr_dwords[1] >> 16) ^ (metadata->ctr_dwords[1] >> 24)) & 0xFF);
}
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *emummc, size_t emummc_size);
void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firmware, void *mesosphere, size_t mesosphere_size, void *emummc, size_t emummc_size);
#endif

View File

@@ -30,6 +30,9 @@ _start:
.word (_metadata - _start)
_is_experimental:
.word 0x00000001 /* is experimental */
_crt0:
/* Switch to system mode, mask all interrupts, clear all flags */
msr cpsr_cxsf, #0xDF
@@ -68,6 +71,14 @@ _crt0:
ldr r1, [r1]
b main
.arm
.global fusee_is_experimental
.type fusee_is_experimental, %function
fusee_is_experimental:
ldr r0, =_is_experimental
ldr r0, [r0]
bx lr
/* Fusee-secondary header. */
.align 5
_metadata:
@@ -135,6 +146,17 @@ _content_headers:
.asciz "exosphere"
.align 5
/* mesosphere content header */
.word __mesosphere_bin_start__
.word __mesosphere_bin_size__
.byte CONTENT_TYPE_KRN
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "mesosphere"
.align 5
/* fusee_primary content header */
.word __fusee_primary_bin_start__
.word __fusee_primary_bin_size__
@@ -249,7 +271,7 @@ _content_headers:
.word __ncm_kip_start__
.word __ncm_kip_size__
.byte CONTENT_TYPE_KIP
.byte CONTENT_FLAG0_EXPERIMENTAL
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
@@ -267,17 +289,6 @@ _content_headers:
.asciz "emummc"
.align 5
/* kernel_ldr content header */
.word __kernel_ldr_bin_start__
.word __kernel_ldr_bin_size__
.byte CONTENT_TYPE_KLD
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.byte CONTENT_FLAG_NONE
.word 0xCCCCCCCC
.asciz "kernel_ldr"
.align 5
/* splash_screen content header */
.word __splash_screen_bmp_start__
.word __splash_screen_bmp_size__

View File

@@ -48,7 +48,7 @@ static bool g_stratosphere_pm_enabled = true;
static bool g_stratosphere_ams_mitm_enabled = true;
static bool g_stratosphere_spl_enabled = true;
static bool g_stratosphere_boot_enabled = true;
static bool g_stratosphere_ncm_enabled = false;
static bool g_stratosphere_ncm_enabled = true;
extern const uint8_t loader_kip[], pm_kip[], sm_kip[], spl_kip[], boot_kip[], ncm_kip[], ams_mitm_kip[];
@@ -58,17 +58,17 @@ emummc_fs_ver_t stratosphere_get_fs_version(void) {
return g_fs_ver;
}
void stratosphere_enable_ncm(void) {
void stratosphere_disable_ncm(void) {
/* The Atmosphere team believes our implementation of NCM to be extremely accurate, */
/* and does not think it likely there is any possibility of undesirable behavior */
/* when using the NCM reimplementation. However, because NCM manages critical save games */
/* the implementation will default to off for some time, until the code has been thoroughly */
/* tested in practice. */
/* the implementation may be optionally disabled for those not comfortable using it. */
/* PLEASE NOTE: The default behavior will be NCM on in a future atmosphere release, */
/* and this opt-in functionality will be removed at that time. */
g_stratosphere_ncm_enabled = true;
/* PLEASE NOTE: The NCM reimplementation has been well-tested, and correspondingly opt-out */
/* functionality will be removed in Atmosphere 1.0.0. */
g_stratosphere_ncm_enabled = false;
}
/* GCC doesn't consider the size as const... we have to write it ourselves. */

View File

@@ -30,7 +30,7 @@ ini1_header_t *stratosphere_get_ini1(uint32_t target_firmware);
ini1_header_t *stratosphere_get_sd_files_ini1(void);
void stratosphere_free_ini1(void);
void stratosphere_enable_ncm(void);
void stratosphere_disable_ncm(void);
emummc_fs_ver_t stratosphere_get_fs_version(void);
@@ -39,10 +39,10 @@ ini1_header_t *stratosphere_merge_inis(ini1_header_t **inis, unsigned int num_in
typedef struct {
bool has_nogc_config;
bool enable_nogc;
bool ncm_enabled;
bool ncm_disabled;
} stratosphere_cfg_t;
#define STRATOSPHERE_NOGC_KEY "nogc"
#define STRATOSPHERE_ENABLE_NCM_KEY "enable_ncm"
#define STRATOSPHERE_DISABLE_NCM_KEY "disable_ncm"
#endif

View File

@@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/Atmosphere-NX/Atmosphere-libs
branch = master
commit = f288b81b237199ac742032cafda43312c2c153ae
parent = 0508b5d31bc6f53a1df3fe61e80aedefbb93a3f0
commit = 10e9e0e8f926b11c2c7de16ffe15bea7d7ec2cdf
parent = 2ee2a4f1ac04bc7f15de8be8d57ad04d7e73f735
method = merge
cmdver = 0.4.1

View File

@@ -5,7 +5,7 @@ endif
include $(DEVKITPRO)/devkitA64/base_rules
export ATMOSPHERE_DEFINES += -DATMOSPHERE_ARCH_ARM64
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtp=soft
export ATMOSPHERE_SETTINGS += -mtp=soft
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@@ -1,5 +1,5 @@
export ATMOSPHERE_DEFINES += -DATMOSPHERE_CPU_ARM_CORTEX_A57
export ATMOSPHERE_SETTINGS += -mtune=cortex-a57
export ATMOSPHERE_SETTINGS += -march=armv8-a+crc+crypto -mtune=cortex-a57
export ATMOSPHERE_CFLAGS +=
export ATMOSPHERE_CXXFLAGS +=
export ATMOSPHERE_ASFLAGS +=

View File

@@ -10,13 +10,15 @@ ifeq ($(strip $(ATMOSPHERE_BOARD)),)
export ATMOSPHERE_BOARD := nx-hac-001
ifeq ($(strip $(ATMOSPHERE_CPU)),)
export ATMOSPHERE_CPU := arm-cortex-a57
export ATMOSPHERE_CPU := arm-cortex-a57
endif
endif
ATMOSPHERE_BUILD_SETTINGS ?=
export ATMOSPHERE_DEFINES := -DATMOSPHERE
export ATMOSPHERE_SETTINGS := -fPIE -g
export ATMOSPHERE_SETTINGS := -fPIE -g $(ATMOSPHERE_BUILD_SETTINGS)
export ATMOSPHERE_CFLAGS := -Wall -ffunction-sections -fdata-sections -fno-strict-aliasing -fwrapv \
-fno-asynchronous-unwind-tables -fno-unwind-tables -fno-stack-protector \
-Wno-format-truncation -Wno-format-zero-length -Wno-stringop-truncation
@@ -28,40 +30,44 @@ export ATMOSPHERE_ASFLAGS :=
ifeq ($(ATMOSPHERE_BOARD),nx-hac-001)
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
export ATMOSPHERE_ARCH_DIR := arch/arm64
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx
export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_DIR := arm64
export ATMOSPHERE_BOARD_DIR := nintendo/nx
export ATMOSPHERE_OS_DIR := horizon
export ATMOSPHERE_ARCH_NAME := arm64
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_CPU_EXTENSIONS := arm_crypto_extension aarch64_crypto_extension
else ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_ARCH_DIR := arch/arm
export ATMOSPHERE_BOARD_DIR := board/nintendo/nx_bpmp
export ATMOSPHERE_OS_DIR := os/horizon
export ATMOSPHERE_ARCH_DIR := arm
export ATMOSPHERE_BOARD_DIR := nintendo/nx_bpmp
export ATMOSPHERE_OS_DIR := horizon
export ATMOSPHERE_ARCH_NAME := arm
export ATMOSPHERE_BOARD_NAME := nintendo_nx
export ATMOSPHERE_OS_NAME := horizon
export ATMOSPHERE_CPU_EXTENSIONS :=
endif
endif
ifeq ($(ATMOSPHERE_CPU),arm-cortex-a57)
export ATMOSPHERE_CPU_DIR := arch/arm64/cpu/cortex_a57
export ATMOSPHERE_CPU_DIR := cortex_a57
export ATMOSPHERE_CPU_NAME := arm_cortex_a57
endif
ifeq ($(ATMOSPHERE_CPU),arm7tdmi)
export ATMOSPHERE_CPU_DIR := arch/arm/cpu/arm7tdmi
export ATMOSPHERE_CPU_DIR := arm7tdmi
export ATMOSPHERE_CPU_NAME := arm7tdmi
endif
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_BOARD_DIR)
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_OS_DIR)
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/$(ATMOSPHERE_CPU_DIR)
export ATMOSPHERE_ARCH_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/arch/$(ATMOSPHERE_ARCH_DIR)
export ATMOSPHERE_BOARD_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/board/$(ATMOSPHERE_BOARD_DIR)
export ATMOSPHERE_OS_MAKE_DIR := $(ATMOSPHERE_CONFIG_MAKE_DIR)/os/$(ATMOSPHERE_OS_DIR)
export ATMOSPHERE_CPU_MAKE_DIR := $(ATMOSPHERE_ARCH_MAKE_DIR)/cpu/$(ATMOSPHERE_CPU_DIR)
export ATMOSPHERE_LIBRARY_DIR := lib_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
export ATMOSPHERE_BUILD_DIR := build_$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)
@@ -102,16 +108,41 @@ BUILD := build
DATA := data
INCLUDES := include
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/.*),$1/$2 $(call DIR_WILDCARD,$1/$2),)
ALL_SOURCE_DIRS=$(call GENERAL_SOURCE_DIRS,$1) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_ARCH_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_BOARD_DIR)) $(call SPECIFIC_SOURCE_DIRS,$1,$(ATMOSPHERE_OS_DIR))
GENERAL_SOURCE_DIRS=$1 $(foreach d,$(filter-out $1/arch $1/board $1/os $1/cpu $1,$(wildcard $1/*)),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
SPECIFIC_SOURCE_DIRS=$(if $(wildcard $1/$2/$3/.*),$1/$2/$3 $(call DIR_WILDCARD,$1/$2/$3),$(if $(wildcard $1/$2/generic/.*), $1/$2/generic $(call DIR_WILDCARD,$1/$2/generic),))
UNFILTERED_SOURCE_DIRS=$1 $(foreach d,$(wildcard $1/*),$(if $(wildcard $d/.),$(call DIR_WILDCARD,$d) $d,))
ALL_SOURCE_DIRS=$(call GENERAL_SOURCE_DIRS,$1) \
$(call SPECIFIC_SOURCE_DIRS,$1,arch,$(ATMOSPHERE_ARCH_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,board,$(ATMOSPHERE_BOARD_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,os,$(ATMOSPHERE_OS_DIR)) \
$(call SPECIFIC_SOURCE_DIRS,$1,cpu,$(ATMOSPHERE_ARCH_DIR)/$(ATMOSPHERE_CPU_DIR))
SOURCES ?= $(call ALL_SOURCE_DIRS,source)
FIND_SPECIFIC_SOURCE_FILES= $(notdir $(wildcard $1/*.$2.$3.$4)) $(filter-out $(subst .$2.$3.,.$2.generic.,$(notdir $(wildcard $1/*.$2.$3.$4))),$(notdir $(wildcard $1/*.$2.generic.$4)))
FIND_SPECIFIC_SOURCE_FILES_EX=$(foreach ext,$3,$(notdir $(wildcard $1/*.$2.$(ext).$4))) $(filter-out $(foreach ext,$3,$(subst .$2.$(ext).,.$2.generic.,$(notdir $(wildcard $1/*.$2.$(ext).$4)))),$(notdir $(wildcard $1/*.$2.generic.$4)))
FIND_SOURCE_FILES=$(foreach dir,$1,$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.$2)) \
$(notdir $(wildcard $(dir)/*.board.*.$2)) \
$(notdir $(wildcard $(dir)/*.os.*.$2)) \
$(notdir $(wildcard $(dir)/.cpu.*.$2)), \
$(notdir $(wildcard $(dir)/*.$2)))) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),arch,$(ATMOSPHERE_ARCH_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),board,$(ATMOSPHERE_BOARD_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES,$(dir),os,$(ATMOSPHERE_OS_NAME),$2)) \
$(foreach dir,$1,$(call FIND_SPECIFIC_SOURCE_FILES_EX,$(dir),cpu,$(ATMOSPHERE_CPU_NAME) $(ATMOSPHERE_CPU_EXTENSIONS),$2))
ATMOSPHERE_GCH_IDENTIFIER ?= ams_placeholder_gch_identifier
#---------------------------------------------------------------------------------
# Rules for compiling pre-compiled headers
#---------------------------------------------------------------------------------
%.gch: %.hpp
@echo $<
$(CXX) -w -x c++-header -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
@cp $@ $(<).gch
%.hpp.gch/$(ATMOSPHERE_GCH_IDENTIFIER): %.hpp | %.hpp.gch
$(SILENTMSG) Precompiling $(notdir $<) for $(ATMOSPHERE_GCH_IDENTIFIER)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)
%.hpp.gch: %.hpp
$(SILENTMSG) Precompiling $(notdir $<)
$(SILENTCMD)$(CXX) -w -x c++-header -MMD -MP -MQ$@ -MF $(DEPSDIR)/$(notdir $*).d $(CXXFLAGS) -c $< -o $@ $(ERROR_FILTER)

View File

@@ -8,7 +8,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
#---------------------------------------------------------------------------------
ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm64)
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)

View File

@@ -7,10 +7,10 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../common.mk
# options for code generation
#---------------------------------------------------------------------------------
export DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
export SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -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)
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
@@ -29,7 +29,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
-Wl,--wrap,_ZSt20__throw_length_errorPKc \
-Wl,--wrap,_ZNSt11logic_errorC2EPKc
export LIBS := -lmesosphere
export LIBS := -l$(LIBMESOSPHERE_NAME)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing

View File

@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -flto -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Wextra -Werror -flto -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
@@ -39,23 +39,9 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -14,7 +14,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
#---------------------------------------------------------------------------------
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Werror -fno-non-call-exceptions
SETTINGS := $(ATMOSPHERE_SETTINGS) -mgeneral-regs-only -ffixed-x18 -Os -Wextra -Werror -fno-non-call-exceptions
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
@@ -39,23 +39,9 @@ ifneq ($(BUILD),$(notdir $(CURDIR)))
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C

View File

@@ -89,7 +89,13 @@ namespace ams::secmon {
constexpr inline const SecureMonitorConfiguration DefaultSecureMonitorConfiguration = {
.target_firmware = ams::TargetFirmware_Current,
.key_generation = {},
.hardware_type = {},
.soc_type = {},
.hardware_state = {},
.pad_0B = {},
.flags = SecureMonitorConfigurationFlag_Default,
.reserved = {},
};
}

View File

@@ -203,12 +203,12 @@ DEFINE_CLK_RST_REG_BIT_ENUM(RST_CPUG_CMPLX_CLR_CLR_NONCPURESET, 29, DISABLE, ENA
HANDLER(H, MEM, 1, 0) \
HANDLER(H, AHBDMA, 1, 1) \
HANDLER(H, APBDMA, 1, 2) \
HANDLER(H, USB2, 1, 26) \
HANDLER(H, PMC, 1, 6) \
HANDLER(H, FUSE, 1, 7) \
HANDLER(H, KFUSE, 1, 8) \
HANDLER(H, I2C5, 1, 15) \
HANDLER(H, EMC, 1, 25) \
HANDLER(H, USB2, 1, 26) \
HANDLER(U, CSITE, 2, 9) \
HANDLER(U, IRAMA, 2, 20) \
HANDLER(U, IRAMB, 2, 21) \

View File

@@ -33,6 +33,8 @@ namespace ams::crypto::impl {
template<size_t KeySize>
void AesImpl<KeySize>::Initialize(const void *key, size_t key_size, bool is_encrypt) {
static_assert(IsSupportedKeySize(KeySize));
AMS_ASSERT(key_size == sizeof(int));
AMS_UNUSED(is_encrypt);
/* Set the security engine keyslot. */
this->slot = *static_cast<const int *>(key);
@@ -50,9 +52,11 @@ namespace ams::crypto::impl {
} else if constexpr (KeySize == 24) {
/* Aes 192. */
/* TODO: se::EncryptAes192(dst, dst_size, this->slot, src, src_size); */
AMS_UNUSED(dst, dst_size, src, src_size);
} else if constexpr (KeySize == 32) {
/* Aes 256. */
/* TODO: se::EncryptAes256(dst, dst_size, this->slot, src, src_size); */
AMS_UNUSED(dst, dst_size, src, src_size);
} else {
/* Invalid key size. */
static_assert(!std::is_same<AesImpl<KeySize>, AesImpl<KeySize>>::value);
@@ -71,9 +75,11 @@ namespace ams::crypto::impl {
} else if constexpr (KeySize == 24) {
/* Aes 192. */
/* TODO: se::DecryptAes192(dst, dst_size, this->slot, src, src_size); */
AMS_UNUSED(dst, dst_size, src, src_size);
} else if constexpr (KeySize == 32) {
/* Aes 256. */
/* TODO: se::DecryptAes256(dst, dst_size, this->slot, src, src_size); */
AMS_UNUSED(dst, dst_size, src, src_size);
} else {
/* Invalid key size. */
static_assert(!std::is_same<AesImpl<KeySize>, AesImpl<KeySize>>::value);

View File

@@ -88,6 +88,8 @@ namespace ams::i2c {
}
bool Write(uintptr_t base_address, Port port, int address, const void *src, size_t src_size, bool unused) {
AMS_UNUSED(port, unused);
/* Ensure we don't write too much. */
u32 data = 0;
if (src_size > MaxTransferSize) {
@@ -125,6 +127,8 @@ namespace ams::i2c {
}
bool Read(uintptr_t base_address, Port port, void *dst, size_t dst_size, int address, bool unused) {
AMS_UNUSED(port, unused);
/* Ensure we don't read too much. */
if (dst_size > MaxTransferSize) {
return false;

View File

@@ -81,7 +81,8 @@ namespace ams::wdt {
/* Enable the counters. */
reg::Write(registers + 0x188, 0x1);
while (true) { /* ... */ }
/* Wait forever until the reboot takes. */
AMS_INFINITE_LOOP();
}
#endif

View File

@@ -1,18 +1,20 @@
#---------------------------------------------------------------------------------
# pull in common atmosphere configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
include $(CURRENT_DIRECTORY)/../config/common.mk
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
PRECOMPILED_HEADERS := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/include/mesosphere.hpp
PRECOMPILED_HEADERS := include/mesosphere.hpp
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_MESOSPHERE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -mgeneral-regs-only -ffixed-x18 -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)
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
SOURCES += $(call ALL_SOURCE_DIRS,../libvapours/source)
@@ -28,29 +30,15 @@ LIBDIRS := $(ATMOSPHERE_LIBRARIES_DIR)/libvapours
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
ifneq ($(__RECURSIVE__),1)
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c)
CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp)
SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s)
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@@ -68,7 +56,7 @@ endif
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.gch),$(notdir $(hdr)))
export GCH_DIRS := $(PRECOMPILED_HEADERS:.hpp=.hpp.gch)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
@@ -76,41 +64,70 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I.
.PHONY: clean all
#---------------------------------------------------------------------------------
ATMOSPHERE_BUILD_CONFIGS :=
all: release
define ATMOSPHERE_ADD_TARGET
ATMOSPHERE_BUILD_CONFIGS += $(strip $1)
$(strip $1): $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
$$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2) : $$(ATMOSPHERE_LIBRARY_DIR) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(SOURCES) $$(INCLUDES) $$(GCH_DIRS)
@$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(CURDIR)/$$@ $(3) \
ATMOSPHERE_GCH_IDENTIFIER="$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1)" \
DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
--no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \
-f $$(THIS_MAKEFILE)
clean-$(strip $1):
@echo clean $(strip $1) ...
@rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(ATMOSPHERE_LIBRARY_DIR)/$(strip $2)
@rm -fr $$(foreach hdr,$$(GCH_DIRS),$$(hdr)/$$(ATMOSPHERE_BOARD_NAME)_$$(ATMOSPHERE_ARCH_NAME)_$(strip $1))
@for i in $$(GCH_DIRS) $$(ATMOSPHERE_BUILD_DIR) $$(ATMOSPHERE_LIBRARY_DIR); do [ -d $$$$i ] && rmdir --ignore-fail-on-non-empty $$$$i || true; done
endef
$(eval $(call ATMOSPHERE_ADD_TARGET, release, $(TARGET).a, \
ATMOSPHERE_BUILD_SETTINGS="" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, debug, $(TARGET)_debug.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_DEBUGGING" \
))
$(eval $(call ATMOSPHERE_ADD_TARGET, audit, $(TARGET)_audit.a, \
ATMOSPHERE_BUILD_SETTINGS="-DMESOSPHERE_BUILD_FOR_AUDITING" \
))
#---------------------------------------------------------------------------------
all: lib/$(TARGET).a
lib:
-include $(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME).mk
ALL_GCH_IDENTIFIERS := $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(ATMOSPHERE_BOARD_NAME)_$(ATMOSPHERE_ARCH_NAME)_$(config))
ALL_GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(foreach id,$(ALL_GCH_IDENTIFIERS),$(hdr)/$(id)))
.PHONY: clean all $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config))
$(ATMOSPHERE_LIBRARY_DIR) $(GCH_DIRS):
@[ -d $@ ] || mkdir -p $@
release:
$(ATMOSPHERE_BUILD_DIR)/%:
@[ -d $@ ] || mkdir -p $@
lib/$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
dist-bin: all
@tar --exclude=*~ -cjf $(TARGET).tar.bz2 include lib
dist-src:
@tar --exclude=*~ -cjf $(TARGET)-src.tar.bz2 include source Makefile
dist: dist-src dist-bin
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release lib *.bz2
@rm -fr $(ATMOSPHERE_BUILD_DIR) $(ATMOSPHERE_LIBRARY_DIR) *.bz2 $(ALL_GCH_FILES)
@for i in $(GCH_DIRS); do [ -d $$i ] && rmdir --ignore-fail-on-non-empty $$i || true; done
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d) $(GCH_FILES:.gch=.d)
GCH_FILES := $(foreach hdr,$(PRECOMPILED_HEADERS:.hpp=.hpp.gch),$(CURRENT_DIRECTORY)/$(hdr)/$(ATMOSPHERE_GCH_IDENTIFIER))
DEPENDS := $(OFILES:.o=.d) $(foreach hdr,$(GCH_FILES),$(notdir $(patsubst %.hpp.gch/,%.d,$(dir $(hdr)))))
#---------------------------------------------------------------------------------
# main targets

View File

@@ -27,6 +27,9 @@
#include <mesosphere/kern_initial_process.hpp>
#include <mesosphere/kern_k_exception_context.hpp>
/* Tracing functionality. */
#include <mesosphere/kern_k_trace.hpp>
/* Core pre-initialization includes. */
#include <mesosphere/kern_select_cpu.hpp>
#include <mesosphere/kern_select_system_control.hpp>

View File

@@ -0,0 +1,279 @@
/*
* 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 <vapours.hpp>
#include <mesosphere/kern_select_cpu.hpp>
#include <mesosphere/kern_k_typed_address.hpp>
namespace ams::kern::arch::arm {
struct GicDistributor {
u32 ctlr;
u32 typer;
u32 iidr;
u32 reserved_0x0c;
u32 statusr;
u32 reserved_0x14[3];
u32 impldef_0x20[8];
u32 setspi_nsr;
u32 reserved_0x44;
u32 clrspi_nsr;
u32 reserved_0x4c;
u32 setspi_sr;
u32 reserved_0x54;
u32 clrspi_sr;
u32 reserved_0x5c[9];
u32 igroupr[32];
u32 isenabler[32];
u32 icenabler[32];
u32 ispendr[32];
u32 icpendr[32];
u32 isactiver[32];
u32 icactiver[32];
union {
u8 bytes[1020];
u32 words[255];
} ipriorityr;
u32 _0x7fc;
union {
u8 bytes[1020];
u32 words[255];
} itargetsr;
u32 _0xbfc;
u32 icfgr[64];
u32 igrpmodr[32];
u32 _0xd80[32];
u32 nsacr[64];
u32 sgir;
u32 _0xf04[3];
u32 cpendsgir[4];
u32 spendsgir[4];
u32 reserved_0xf30[52];
static constexpr size_t SgirCpuTargetListShift = 16;
enum SgirTargetListFilter : u32 {
SgirTargetListFilter_CpuTargetList = (0 << 24),
SgirTargetListFilter_Others = (1 << 24),
SgirTargetListFilter_Self = (2 << 24),
SgirTargetListFilter_Reserved = (3 << 24),
};
};
static_assert(util::is_pod<GicDistributor>::value);
static_assert(sizeof(GicDistributor) == 0x1000);
struct GicCpuInterface {
u32 ctlr;
u32 pmr;
u32 bpr;
u32 iar;
u32 eoir;
u32 rpr;
u32 hppir;
u32 abpr;
u32 aiar;
u32 aeoir;
u32 ahppir;
u32 statusr;
u32 reserved_30[4];
u32 impldef_40[36];
u32 apr[4];
u32 nsapr[4];
u32 reserved_f0[3];
u32 iidr;
u32 reserved_100[960];
u32 dir;
u32 _0x1004[1023];
};
static_assert(util::is_pod<GicCpuInterface>::value);
static_assert(sizeof(GicCpuInterface) == 0x2000);
struct KInterruptController {
NON_COPYABLE(KInterruptController);
NON_MOVEABLE(KInterruptController);
public:
static constexpr s32 NumSoftwareInterrupts = 16;
static constexpr s32 NumLocalInterrupts = NumSoftwareInterrupts + 16;
static constexpr s32 NumGlobalInterrupts = 988;
static constexpr s32 NumInterrupts = NumLocalInterrupts + NumGlobalInterrupts;
static constexpr s32 NumPriorityLevels = 4;
public:
struct LocalState {
u32 isenabler[NumLocalInterrupts / 32];
u32 ipriorityr[NumLocalInterrupts / 4];
u32 itargetsr[NumLocalInterrupts / 4];
u32 icfgr[NumLocalInterrupts / 16];
};
struct GlobalState {
u32 isenabler[NumGlobalInterrupts / 32];
u32 ipriorityr[NumGlobalInterrupts / 4];
u32 itargetsr[NumGlobalInterrupts / 4];
u32 icfgr[NumGlobalInterrupts / 16];
};
enum PriorityLevel : u8 {
PriorityLevel_High = 0,
PriorityLevel_Low = NumPriorityLevels - 1,
PriorityLevel_Timer = 1,
PriorityLevel_Scheduler = 2,
};
private:
static inline u32 s_mask[cpu::NumCores];
private:
volatile GicDistributor *gicd;
volatile GicCpuInterface *gicc;
public:
constexpr KInterruptController() : gicd(nullptr), gicc(nullptr) { /* ... */ }
void Initialize(s32 core_id);
void Finalize(s32 core_id);
void SaveCoreLocal(LocalState *state) const;
void SaveGlobal(GlobalState *state) const;
void RestoreCoreLocal(const LocalState *state) const;
void RestoreGlobal(const GlobalState *state) const;
public:
u32 GetIrq() const {
return this->gicc->iar;
}
static constexpr s32 ConvertRawIrq(u32 irq) {
return (irq == 0x3FF) ? -1 : (irq & 0x3FF);
}
void Enable(s32 irq) const {
this->gicd->isenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void Disable(s32 irq) const {
this->gicd->icenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void Clear(s32 irq) const {
this->gicd->icpendr[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void SetTarget(s32 irq, s32 core_id) const {
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] | GetGicMask(core_id);
}
void ClearTarget(s32 irq, s32 core_id) const {
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] & ~GetGicMask(core_id);
}
void SetPriorityLevel(s32 irq, s32 level) const {
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
this->gicd->ipriorityr.bytes[irq] = ToGicPriorityValue(level);
}
s32 GetPriorityLevel(s32 irq) const {
return FromGicPriorityValue(this->gicd->ipriorityr.bytes[irq]);
}
void SetPriorityLevel(s32 level) const {
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
this->gicc->pmr = ToGicPriorityValue(level);
}
void SetEdge(s32 irq) const {
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
cfg |= (0x2 << (2 * (irq % (BITSIZEOF(u32) / 2))));
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
}
void SetLevel(s32 irq) const {
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
cfg |= (0x0 << (2 * (irq % (BITSIZEOF(u32) / 2))));
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
}
void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
MESOSPHERE_ASSERT(IsSoftware(irq));
this->gicd->sgir = GetCpuTargetListMask(irq, core_mask);
}
void SendInterProcessorInterrupt(s32 irq) {
MESOSPHERE_ASSERT(IsSoftware(irq));
this->gicd->sgir = GicDistributor::SgirTargetListFilter_Others | irq;
}
void EndOfInterrupt(u32 irq) const {
this->gicc->eoir = irq;
}
bool IsInterruptDefined(s32 irq) const {
const s32 num_interrupts = std::min(32 + 32 * (this->gicd->typer & 0x1F), static_cast<u32>(NumInterrupts));
return (0 <= irq && irq < num_interrupts);
}
public:
static constexpr ALWAYS_INLINE bool IsSoftware(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return id < NumSoftwareInterrupts;
}
static constexpr ALWAYS_INLINE bool IsLocal(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return id < NumLocalInterrupts;
}
static constexpr ALWAYS_INLINE bool IsGlobal(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return NumLocalInterrupts <= id;
}
static constexpr size_t GetGlobalInterruptIndex(s32 id) {
MESOSPHERE_ASSERT(IsGlobal(id));
return id - NumLocalInterrupts;
}
static constexpr size_t GetLocalInterruptIndex(s32 id) {
MESOSPHERE_ASSERT(IsLocal(id));
return id;
}
private:
static constexpr size_t PriorityShift = BITSIZEOF(u8) - __builtin_ctz(NumPriorityLevels);
static_assert(PriorityShift < BITSIZEOF(u8));
static constexpr ALWAYS_INLINE u8 ToGicPriorityValue(s32 level) {
return (level << PriorityShift) | ((1 << PriorityShift) - 1);
}
static constexpr ALWAYS_INLINE s32 FromGicPriorityValue(u8 priority) {
return (priority >> PriorityShift) & (NumPriorityLevels - 1);
}
static constexpr ALWAYS_INLINE s32 GetCpuTargetListMask(s32 irq, u64 core_mask) {
MESOSPHERE_ASSERT(IsSoftware(irq));
MESOSPHERE_ASSERT(core_mask < (1ul << cpu::NumCores));
return GicDistributor::SgirTargetListFilter_CpuTargetList | irq | (static_cast<u16>(core_mask) << GicDistributor::SgirCpuTargetListShift);
}
static ALWAYS_INLINE s32 GetGicMask(s32 core_id) {
return s_mask[core_id];
}
ALWAYS_INLINE void SetGicMask(s32 core_id) const {
s_mask[core_id] = this->gicd->itargetsr.bytes[0];
}
NOINLINE void SetupInterruptLines(s32 core_id) const;
};
}

View File

@@ -0,0 +1,29 @@
/*
* 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 <vapours.hpp>
#include <mesosphere/kern_select_cpu.hpp>
#include <mesosphere/kern_k_typed_address.hpp>
#if 1
#include <mesosphere/arch/arm/kern_generic_interrupt_controller.hpp>
#else
#error "Unknown board for KInterruptController"
#endif

View File

@@ -0,0 +1,25 @@
/*
* 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/>.
*/
/* All architectures must define NumArchitectureDeviceRegions. */
constexpr inline const auto NumArchitectureDeviceRegions = 3;
constexpr inline const auto KMemoryRegionType_Uart = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0);
constexpr inline const auto KMemoryRegionType_InterruptCpuInterface = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap);
constexpr inline const auto KMemoryRegionType_InterruptDistributor = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_Uart .GetValue() == (0x1D));
static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() == (0x2D | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_InterruptDistributor .GetValue() == (0x4D | KMemoryRegionAttr_NoUserMap));

View File

@@ -74,6 +74,10 @@ namespace ams::kern::arch::arm64::init {
static ALWAYS_INLINE void ClearNewPageTable(KPhysicalAddress address) {
ClearPhysicalMemory(address, PageSize);
}
public:
static consteval size_t GetMaximumOverheadSize(size_t size) {
return (util::DivideUp(size, L1BlockSize) + util::DivideUp(size, L2BlockSize)) * PageSize;
}
private:
size_t NOINLINE GetBlockCount(KVirtualAddress virt_addr, size_t size, size_t block_size) {
const KVirtualAddress end_virt_addr = virt_addr + size;

View File

@@ -59,11 +59,6 @@ namespace ams::kern::arch::arm64::cpu {
InstructionMemoryBarrier();
}
ALWAYS_INLINE void InvalidateEntireInstructionCache() {
__asm__ __volatile__("ic iallu" ::: "memory");
EnsureInstructionConsistency();
}
ALWAYS_INLINE void Yield() {
__asm__ __volatile__("yield" ::: "memory");
}
@@ -179,6 +174,7 @@ namespace ams::kern::arch::arm64::cpu {
void ClearPageToZeroImpl(void *);
void FlushEntireDataCacheSharedForInit();
void FlushEntireDataCacheLocalForInit();
void InvalidateEntireInstructionCacheForInit();
void StoreEntireCacheForInit();
void FlushEntireDataCache();
@@ -188,6 +184,8 @@ namespace ams::kern::arch::arm64::cpu {
Result FlushDataCache(const void *addr, size_t size);
Result InvalidateInstructionCache(void *addr, size_t size);
void InvalidateEntireInstructionCache();
ALWAYS_INLINE void ClearPageToZero(void *page) {
MESOSPHERE_ASSERT(util::IsAligned(reinterpret_cast<uintptr_t>(page), PageSize));
MESOSPHERE_ASSERT(page != nullptr);

View File

@@ -33,7 +33,7 @@ namespace ams::kern::arch::arm64 {
explicit KDebug() { /* ... */ }
virtual ~KDebug() { /* ... */ }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
public:
virtual Result GetThreadContextImpl(ams::svc::ThreadContext *out, KThread *thread, u32 context_flags) override;
virtual Result SetThreadContextImpl(const ams::svc::ThreadContext &ctx, KThread *thread, u32 context_flags) override;

View File

@@ -18,261 +18,19 @@
#include <mesosphere/kern_select_cpu.hpp>
#include <mesosphere/kern_k_typed_address.hpp>
namespace ams::kern::arch::arm64 {
#if 1
struct GicDistributor {
u32 ctlr;
u32 typer;
u32 iidr;
u32 reserved_0x0c;
u32 statusr;
u32 reserved_0x14[3];
u32 impldef_0x20[8];
u32 setspi_nsr;
u32 reserved_0x44;
u32 clrspi_nsr;
u32 reserved_0x4c;
u32 setspi_sr;
u32 reserved_0x54;
u32 clrspi_sr;
u32 reserved_0x5c[9];
u32 igroupr[32];
u32 isenabler[32];
u32 icenabler[32];
u32 ispendr[32];
u32 icpendr[32];
u32 isactiver[32];
u32 icactiver[32];
union {
u8 bytes[1020];
u32 words[255];
} ipriorityr;
u32 _0x7fc;
union {
u8 bytes[1020];
u32 words[255];
} itargetsr;
u32 _0xbfc;
u32 icfgr[64];
u32 igrpmodr[32];
u32 _0xd80[32];
u32 nsacr[64];
u32 sgir;
u32 _0xf04[3];
u32 cpendsgir[4];
u32 spendsgir[4];
u32 reserved_0xf30[52];
#include <mesosphere/arch/arm/kern_generic_interrupt_controller.hpp>
namespace ams::kern::arch::arm64 {
static constexpr size_t SgirCpuTargetListShift = 16;
using ams::kern::arch::arm::GicDistributor;
using ams::kern::arch::arm::GicCpuInterface;
using ams::kern::arch::arm::KInterruptController;
enum SgirTargetListFilter : u32 {
SgirTargetListFilter_CpuTargetList = (0 << 24),
SgirTargetListFilter_Others = (1 << 24),
SgirTargetListFilter_Self = (2 << 24),
SgirTargetListFilter_Reserved = (3 << 24),
};
};
static_assert(util::is_pod<GicDistributor>::value);
static_assert(sizeof(GicDistributor) == 0x1000);
}
struct GicCpuInterface {
u32 ctlr;
u32 pmr;
u32 bpr;
u32 iar;
u32 eoir;
u32 rpr;
u32 hppir;
u32 abpr;
u32 aiar;
u32 aeoir;
u32 ahppir;
u32 statusr;
u32 reserved_30[4];
u32 impldef_40[36];
u32 apr[4];
u32 nsapr[4];
u32 reserved_f0[3];
u32 iidr;
u32 reserved_100[960];
u32 dir;
u32 _0x1004[1023];
};
static_assert(util::is_pod<GicCpuInterface>::value);
static_assert(sizeof(GicCpuInterface) == 0x2000);
#else
struct KInterruptController {
NON_COPYABLE(KInterruptController);
NON_MOVEABLE(KInterruptController);
public:
static constexpr s32 NumSoftwareInterrupts = 16;
static constexpr s32 NumLocalInterrupts = NumSoftwareInterrupts + 16;
static constexpr s32 NumGlobalInterrupts = 988;
static constexpr s32 NumInterrupts = NumLocalInterrupts + NumGlobalInterrupts;
static constexpr s32 NumPriorityLevels = 4;
public:
struct LocalState {
u32 isenabler[NumLocalInterrupts / 32];
u32 ipriorityr[NumLocalInterrupts / 4];
u32 itargetsr[NumLocalInterrupts / 4];
u32 icfgr[NumLocalInterrupts / 16];
};
#error "Unknown board for KInterruptController"
struct GlobalState {
u32 isenabler[NumGlobalInterrupts / 32];
u32 ipriorityr[NumGlobalInterrupts / 4];
u32 itargetsr[NumGlobalInterrupts / 4];
u32 icfgr[NumGlobalInterrupts / 16];
};
enum PriorityLevel : u8 {
PriorityLevel_High = 0,
PriorityLevel_Low = NumPriorityLevels - 1,
PriorityLevel_Timer = 1,
PriorityLevel_Scheduler = 2,
};
private:
static inline u32 s_mask[cpu::NumCores];
private:
volatile GicDistributor *gicd;
volatile GicCpuInterface *gicc;
public:
constexpr KInterruptController() : gicd(nullptr), gicc(nullptr) { /* ... */ }
void Initialize(s32 core_id);
void Finalize(s32 core_id);
void SaveCoreLocal(LocalState *state) const;
void SaveGlobal(GlobalState *state) const;
void RestoreCoreLocal(const LocalState *state) const;
void RestoreGlobal(const GlobalState *state) const;
public:
u32 GetIrq() const {
return this->gicc->iar;
}
static constexpr s32 ConvertRawIrq(u32 irq) {
return (irq == 0x3FF) ? -1 : (irq & 0x3FF);
}
void Enable(s32 irq) const {
this->gicd->isenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void Disable(s32 irq) const {
this->gicd->icenabler[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void Clear(s32 irq) const {
this->gicd->icpendr[irq / BITSIZEOF(u32)] = (1u << (irq % BITSIZEOF(u32)));
}
void SetTarget(s32 irq, s32 core_id) const {
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] | GetGicMask(core_id);
}
void ClearTarget(s32 irq, s32 core_id) const {
this->gicd->itargetsr.bytes[irq] = this->gicd->itargetsr.bytes[irq] & ~GetGicMask(core_id);
}
void SetPriorityLevel(s32 irq, s32 level) const {
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
this->gicd->ipriorityr.bytes[irq] = ToGicPriorityValue(level);
}
s32 GetPriorityLevel(s32 irq) const {
return FromGicPriorityValue(this->gicd->ipriorityr.bytes[irq]);
}
void SetPriorityLevel(s32 level) const {
MESOSPHERE_ASSERT(PriorityLevel_High <= level && level <= PriorityLevel_Low);
this->gicc->pmr = ToGicPriorityValue(level);
}
void SetEdge(s32 irq) const {
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
cfg |= (0x2 << (2 * (irq % (BITSIZEOF(u32) / 2))));
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
}
void SetLevel(s32 irq) const {
u32 cfg = this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)];
cfg &= ~(0x3 << (2 * (irq % (BITSIZEOF(u32) / 2))));
cfg |= (0x0 << (2 * (irq % (BITSIZEOF(u32) / 2))));
this->gicd->icfgr[irq / (BITSIZEOF(u32) / 2)] = cfg;
}
void SendInterProcessorInterrupt(s32 irq, u64 core_mask) {
MESOSPHERE_ASSERT(IsSoftware(irq));
this->gicd->sgir = GetCpuTargetListMask(irq, core_mask);
}
void SendInterProcessorInterrupt(s32 irq) {
MESOSPHERE_ASSERT(IsSoftware(irq));
this->gicd->sgir = GicDistributor::SgirTargetListFilter_Others | irq;
}
void EndOfInterrupt(u32 irq) const {
this->gicc->eoir = irq;
}
bool IsInterruptDefined(s32 irq) const {
const s32 num_interrupts = std::min(32 + 32 * (this->gicd->typer & 0x1F), static_cast<u32>(NumInterrupts));
return (0 <= irq && irq < num_interrupts);
}
public:
static constexpr ALWAYS_INLINE bool IsSoftware(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return id < NumSoftwareInterrupts;
}
static constexpr ALWAYS_INLINE bool IsLocal(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return id < NumLocalInterrupts;
}
static constexpr ALWAYS_INLINE bool IsGlobal(s32 id) {
MESOSPHERE_ASSERT(0 <= id && id < NumInterrupts);
return NumLocalInterrupts <= id;
}
static constexpr size_t GetGlobalInterruptIndex(s32 id) {
MESOSPHERE_ASSERT(IsGlobal(id));
return id - NumLocalInterrupts;
}
static constexpr size_t GetLocalInterruptIndex(s32 id) {
MESOSPHERE_ASSERT(IsLocal(id));
return id;
}
private:
static constexpr size_t PriorityShift = BITSIZEOF(u8) - __builtin_ctz(NumPriorityLevels);
static_assert(PriorityShift < BITSIZEOF(u8));
static constexpr ALWAYS_INLINE u8 ToGicPriorityValue(s32 level) {
return (level << PriorityShift) | ((1 << PriorityShift) - 1);
}
static constexpr ALWAYS_INLINE s32 FromGicPriorityValue(u8 priority) {
return (priority >> PriorityShift) & (NumPriorityLevels - 1);
}
static constexpr ALWAYS_INLINE s32 GetCpuTargetListMask(s32 irq, u64 core_mask) {
MESOSPHERE_ASSERT(IsSoftware(irq));
MESOSPHERE_ASSERT(core_mask < (1ul << cpu::NumCores));
return GicDistributor::SgirTargetListFilter_CpuTargetList | irq | (static_cast<u16>(core_mask) << GicDistributor::SgirCpuTargetListShift);
}
static ALWAYS_INLINE s32 GetGicMask(s32 core_id) {
return s_mask[core_id];
}
ALWAYS_INLINE void SetGicMask(s32 core_id) const {
s_mask[core_id] = this->gicd->itargetsr.bytes[0];
}
NOINLINE void SetupInterruptLines(s32 core_id) const;
};
}
#endif

View File

@@ -0,0 +1,25 @@
/*
* 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/>.
*/
/* All architectures must define NumArchitectureDeviceRegions. */
constexpr inline const auto NumArchitectureDeviceRegions = 3;
constexpr inline const auto KMemoryRegionType_Uart = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 0);
constexpr inline const auto KMemoryRegionType_InterruptCpuInterface = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap);
constexpr inline const auto KMemoryRegionType_InterruptDistributor = KMemoryRegionType_ArchDeviceBase.DeriveSparse(0, NumArchitectureDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_Uart .GetValue() == (0x1D));
static_assert(KMemoryRegionType_InterruptCpuInterface.GetValue() == (0x2D | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_InterruptDistributor .GetValue() == (0x4D | KMemoryRegionAttr_NoUserMap));

View File

@@ -0,0 +1,47 @@
/*
* 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_page_group.hpp>
#include <mesosphere/kern_k_memory_manager.hpp>
#include <mesosphere/kern_select_page_table.hpp>
namespace ams::kern::board::generic {
using KDeviceVirtualAddress = u64;
class KDevicePageTable {
public:
constexpr KDevicePageTable() { /* ... */ }
Result ALWAYS_INLINE Initialize(u64 space_address, u64 space_size) { return ams::kern::svc::ResultNotImplemented(); }
void ALWAYS_INLINE Finalize() { /* ... */ }
Result ALWAYS_INLINE Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) { return ams::kern::svc::ResultNotImplemented(); }
Result ALWAYS_INLINE Detach(ams::svc::DeviceName device_name) { return ams::kern::svc::ResultNotImplemented(); }
Result ALWAYS_INLINE Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) { return ams::kern::svc::ResultNotImplemented(); }
Result ALWAYS_INLINE Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address) { return ams::kern::svc::ResultNotImplemented(); }
public:
static ALWAYS_INLINE void Initialize() { /* ... */ }
static ALWAYS_INLINE void Lock() { /* ... */ }
static ALWAYS_INLINE void Unlock() { /* ... */ }
static ALWAYS_INLINE void Sleep() { /* ... */ }
static ALWAYS_INLINE void Wakeup() { /* ... */ }
};
}

View File

@@ -36,11 +36,13 @@ namespace ams::kern::board::nintendo::nx {
u32 hs_detached_value;
private:
static ALWAYS_INLINE bool IsHeapVirtualAddress(KVirtualAddress addr) {
return KMemoryLayout::IsHeapVirtualAddress(nullptr, addr);
const KMemoryRegion *hint = nullptr;
return KMemoryLayout::IsHeapVirtualAddress(hint, addr);
}
static ALWAYS_INLINE bool IsHeapPhysicalAddress(KPhysicalAddress addr) {
return KMemoryLayout::IsHeapPhysicalAddress(nullptr, addr);
const KMemoryRegion *hint = nullptr;
return KMemoryLayout::IsHeapPhysicalAddress(hint, addr);
}
static ALWAYS_INLINE KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) {

View File

@@ -18,6 +18,7 @@
namespace ams::kern {
constexpr inline size_t MainMemorySize = 4_GB;
constexpr inline size_t MainMemorySize = 4_GB;
constexpr inline size_t MainMemorySizeMax = 8_GB;
}

View File

@@ -0,0 +1,46 @@
/*
* 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/>.
*/
/* All architectures must define NumBoardDeviceRegions. */
constexpr inline const auto NumBoardDeviceRegions = 6;
/* UNUSED: .Derive(NumBoardDeviceRegions, 0); */
constexpr inline const auto KMemoryRegionType_MemoryController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 1).SetAttribute(KMemoryRegionAttr_NoUserMap);
constexpr inline const auto KMemoryRegionType_MemoryController1 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 2).SetAttribute(KMemoryRegionAttr_NoUserMap);
constexpr inline const auto KMemoryRegionType_MemoryController0 = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 3).SetAttribute(KMemoryRegionAttr_NoUserMap);
constexpr inline const auto KMemoryRegionType_PowerManagementController = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 4).DeriveTransition();
constexpr inline const auto KMemoryRegionType_LegacyLpsDevices = KMemoryRegionType_BoardDeviceBase.Derive(NumBoardDeviceRegions, 5);
static_assert(KMemoryRegionType_MemoryController .GetValue() == (0x55 | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_MemoryController1 .GetValue() == (0x65 | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_MemoryController0 .GetValue() == (0x95 | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_PowerManagementController.GetValue() == (0x1A5));
static_assert(KMemoryRegionType_LegacyLpsDevices.GetValue() == 0xC5);
constexpr inline const auto NumLegacyLpsDevices = 7;
constexpr inline const auto KMemoryRegionType_LegacyLpsExceptionVectors = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 0);
constexpr inline const auto KMemoryRegionType_LegacyLpsIram = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 1);
constexpr inline const auto KMemoryRegionType_LegacyLpsFlowController = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 2);
constexpr inline const auto KMemoryRegionType_LegacyLpsPrimaryICtlr = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 3);
constexpr inline const auto KMemoryRegionType_LegacyLpsSemaphore = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 4);
constexpr inline const auto KMemoryRegionType_LegacyLpsAtomics = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 5);
constexpr inline const auto KMemoryRegionType_LegacyLpsClkRst = KMemoryRegionType_LegacyLpsDevices.Derive(NumLegacyLpsDevices, 6);
static_assert(KMemoryRegionType_LegacyLpsExceptionVectors.GetValue() == 0x3C5);
static_assert(KMemoryRegionType_LegacyLpsIram .GetValue() == 0x5C5);
static_assert(KMemoryRegionType_LegacyLpsFlowController .GetValue() == 0x6C5);
static_assert(KMemoryRegionType_LegacyLpsPrimaryICtlr .GetValue() == 0x9C5);
static_assert(KMemoryRegionType_LegacyLpsSemaphore .GetValue() == 0xAC5);
static_assert(KMemoryRegionType_LegacyLpsAtomics .GetValue() == 0xCC5);
static_assert(KMemoryRegionType_LegacyLpsClkRst .GetValue() == 0x11C5);

View File

@@ -39,7 +39,7 @@ namespace ams::kern::board::nintendo::nx {
/* Initialization. */
static NOINLINE void InitializePhase1();
static NOINLINE void InitializePhase2();
static NOINLINE u32 GetInitialProcessBinaryPool();
static NOINLINE u32 GetCreateProcessMemoryPool();
/* Randomness. */
static void GenerateRandomBytes(void *dst, size_t size);
@@ -63,7 +63,7 @@ namespace ams::kern::board::nintendo::nx {
/* Power management. */
static void SleepSystem();
static NORETURN void StopSystem();
static NORETURN void StopSystem(void *arg = nullptr);
/* User access. */
static void CallSecureMonitorFromUser(ams::svc::lp64::SecureMonitorArguments *args);

View File

@@ -26,6 +26,5 @@ namespace ams::kern::init {
KPhysicalAddress GetInitArgumentsAddress(s32 core_id);
void SetInitArguments(s32 core_id, KPhysicalAddress address, uintptr_t arg);
void StoreInitArguments();
}

View File

@@ -0,0 +1,32 @@
/*
* 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
#if defined(AMS_BUILD_FOR_AUDITING)
#define MESOSPHERE_BUILD_FOR_AUDITING
#endif
#if defined(MESOSPHERE_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#define MESOSPHERE_BUILD_FOR_DEBUGGING
#endif
#ifdef MESOSPHERE_BUILD_FOR_DEBUGGING
#define MESOSPHERE_ENABLE_ASSERTIONS
#define MESOSPHERE_ENABLE_DEBUG_PRINT
#endif
//#define MESOSPHERE_BUILD_FOR_TRACING
#define MESOSPHERE_ENABLE_PANIC_REGISTER_DUMP

View File

@@ -15,26 +15,19 @@
*/
#pragma once
#include <vapours.hpp>
#include <mesosphere/kern_build_config.hpp>
#include <mesosphere/svc/kern_svc_results.hpp>
namespace ams::kern {
constexpr size_t PageSize = 4_KB;
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
ams::TargetFirmware GetTargetFirmware();
#else
consteval ALWAYS_INLINE ams::TargetFirmware GetTargetFirmware() {
return ams::TargetFirmware_Current;
}
#endif
}
#if 1 || defined(AMS_BUILD_FOR_AUDITING)
#define MESOSPHERE_BUILD_FOR_AUDITING
#endif
#if defined(MESOSPHERE_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#define MESOSPHERE_BUILD_FOR_DEBUGGING
#endif
#ifdef MESOSPHERE_BUILD_FOR_DEBUGGING
#define MESOSPHERE_ENABLE_ASSERTIONS
#define MESOSPHERE_ENABLE_DEBUG_PRINT
#endif
#include <mesosphere/svc/kern_svc_results.hpp>

View File

@@ -40,7 +40,7 @@ namespace ams::kern {
#ifndef MESOSPHERE_DEBUG_LOG_SELECTED
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
#define MESOSPHERE_DEBUG_LOG_USE_UART_C
#define MESOSPHERE_DEBUG_LOG_USE_UART_A
#else
#error "Unknown board for Default Debug Log Source"
#endif

View File

@@ -20,7 +20,7 @@
namespace ams::kern {
constexpr u32 InitialProcessBinaryMagic = util::FourCC<'I','N','I','1'>::Code;
constexpr size_t InitialProcessBinarySizeMax = 0xC00000;
constexpr size_t InitialProcessBinarySizeMax = 12_MB;
struct InitialProcessBinaryHeader {
u32 magic;
@@ -34,5 +34,6 @@ namespace ams::kern {
u64 GetInitialProcessIdMin();
u64 GetInitialProcessIdMax();
size_t GetInitialProcessesSecureMemorySize();
}

View File

@@ -354,6 +354,10 @@ namespace ams::kern {
constexpr bool CanForceDebug() const {
return this->debug_capabilities.Get<DebugFlags::ForceDebug>();
}
constexpr u32 GetIntendedKernelMajorVersion() const { return this->intended_kernel_version.Get<KernelVersion::MajorVersion>(); }
constexpr u32 GetIntendedKernelMinorVersion() const { return this->intended_kernel_version.Get<KernelVersion::MinorVersion>(); }
constexpr u32 GetIntendedKernelVersion() const { return ams::svc::EncodeKernelVersion(this->GetIntendedKernelMajorVersion(), this->GetIntendedKernelMinorVersion()); }
};
}

View File

@@ -35,7 +35,7 @@ namespace ams::kern {
}
virtual void Destroy() override;
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr KSession *GetParent() const { return this->parent; }

View File

@@ -46,7 +46,7 @@ namespace ams::kern {
Result UnmapFromOwner(KProcessAddress address, size_t size);
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
KProcess *GetOwner() const { return this->owner; }
KProcessAddress GetSourceAddress() { return this->address; }

View File

@@ -37,7 +37,7 @@ namespace ams::kern {
virtual void Finalize() override;
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
Result Attach(ams::svc::DeviceName device_name);
Result Detach(ams::svc::DeviceName device_name);

View File

@@ -46,9 +46,9 @@ namespace ams::kern {
/* We need to have positive size. */
R_UNLESS(sz > 0, svc::ResultOutOfMemory());
/* Calculate metadata overhead. */
const size_t metadata_size = KPageBitmap::CalculateMetadataOverheadSize(sz / sizeof(PageBuffer));
const size_t allocatable_size = sz - metadata_size;
/* Calculate management overhead. */
const size_t management_size = KPageBitmap::CalculateManagementOverheadSize(sz / sizeof(PageBuffer));
const size_t allocatable_size = sz - management_size;
/* Set tracking fields. */
this->address = memory;
@@ -56,12 +56,12 @@ namespace ams::kern {
this->count = allocatable_size / sizeof(PageBuffer);
R_UNLESS(this->count > 0, svc::ResultOutOfMemory());
/* Clear the metadata region. */
u64 *metadata_ptr = GetPointer<u64>(this->address + allocatable_size);
std::memset(metadata_ptr, 0, metadata_size);
/* Clear the management region. */
u64 *management_ptr = GetPointer<u64>(this->address + allocatable_size);
std::memset(management_ptr, 0, management_size);
/* Initialize the bitmap. */
this->page_bitmap.Initialize(metadata_ptr, this->count);
this->page_bitmap.Initialize(management_ptr, this->count);
/* Free the pages to the bitmap. */
std::memset(GetPointer<PageBuffer>(this->address), 0, this->count * sizeof(PageBuffer));

View File

@@ -41,7 +41,7 @@ namespace ams::kern {
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr s32 GetInterruptId() const { return this->interrupt_id; }
};

View File

@@ -35,7 +35,7 @@ namespace ams::kern {
}
virtual void Destroy() override;
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr const KLightSession *GetParent() const { return this->parent; }

View File

@@ -41,7 +41,7 @@ namespace ams::kern {
}
virtual void Destroy() override;
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr const KLightSession *GetParent() const { return this->parent; }

View File

@@ -197,6 +197,7 @@ namespace ams::kern {
.perm = static_cast<ams::svc::MemoryPermission>(this->perm & KMemoryPermission_UserMask),
.ipc_refcount = this->ipc_lock_count,
.device_refcount = this->device_use_count,
.padding = {},
};
}
@@ -396,6 +397,9 @@ namespace ams::kern {
}
constexpr void ShareToDevice(KMemoryPermission new_perm) {
/* New permission isn't used. */
MESOSPHERE_UNUSED(new_perm);
/* We must either be shared or have a zero lock count. */
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_DeviceShared) == KMemoryAttribute_DeviceShared || this->device_use_count == 0);
@@ -407,6 +411,9 @@ namespace ams::kern {
}
constexpr void UnshareToDevice(KMemoryPermission new_perm) {
/* New permission isn't used. */
MESOSPHERE_UNUSED(new_perm);
/* We must be shared. */
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_DeviceShared) == KMemoryAttribute_DeviceShared);
@@ -439,6 +446,9 @@ namespace ams::kern {
}
constexpr void UnlockForIpc(KMemoryPermission new_perm) {
/* New permission isn't used. */
MESOSPHERE_UNUSED(new_perm);
/* We must be locked. */
MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == KMemoryAttribute_IpcLocked);

View File

@@ -16,9 +16,10 @@
#pragma once
#include <mesosphere/kern_common.hpp>
#include <mesosphere/init/kern_init_page_table_select.hpp>
#include <mesosphere/kern_k_memory_region.hpp>
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
#include <mesosphere/board/nintendo/nx/kern_k_memory_layout.board.nintendo_nx.hpp>
#include <mesosphere/board/nintendo/nx/kern_k_memory_layout.hpp>
#else
#error "Unknown board for KMemoryLayout"
#endif
@@ -39,657 +40,136 @@ namespace ams::kern {
constexpr size_t KernelPhysicalAddressSpaceLast = KernelPhysicalAddressSpaceEnd - 1ul;
constexpr size_t KernelPhysicalAddressSpaceSize = KernelPhysicalAddressSpaceEnd - KernelPhysicalAddressSpaceBase;
enum KMemoryRegionType : u32 {
KMemoryRegionAttr_CarveoutProtected = 0x04000000,
KMemoryRegionAttr_DidKernelMap = 0x08000000,
KMemoryRegionAttr_ShouldKernelMap = 0x10000000,
KMemoryRegionAttr_UserReadOnly = 0x20000000,
KMemoryRegionAttr_NoUserMap = 0x40000000,
KMemoryRegionAttr_LinearMapped = 0x80000000,
constexpr size_t KernelPageTableHeapSize = init::KInitialPageTable::GetMaximumOverheadSize(kern::MainMemorySizeMax);
constexpr size_t KernelInitialPageHeapSize = 128_KB;
KMemoryRegionType_None = 0,
KMemoryRegionType_Kernel = 1,
KMemoryRegionType_Dram = 2,
KMemoryRegionType_CoreLocal = 4,
constexpr size_t KernelSlabHeapDataSize = 5_MB;
constexpr size_t KernelSlabHeapGapsSize = 2_MB - 64_KB;
constexpr size_t KernelSlabHeapGapsSizeDeprecated = 2_MB;
constexpr size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSize;
KMemoryRegionType_VirtualKernelPtHeap = 0x2A,
KMemoryRegionType_VirtualKernelTraceBuffer = 0x4A,
KMemoryRegionType_VirtualKernelInitPt = 0x19A,
/* NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860. */
constexpr size_t KernelSlabHeapAdditionalSize = 0x68000;
KMemoryRegionType_VirtualDramMetadataPool = 0x29A,
KMemoryRegionType_VirtualDramManagedPool = 0x31A,
KMemoryRegionType_VirtualDramApplicationPool = 0x271A,
KMemoryRegionType_VirtualDramAppletPool = 0x1B1A,
KMemoryRegionType_VirtualDramSystemPool = 0x2B1A,
KMemoryRegionType_VirtualDramSystemNonSecurePool = 0x331A,
KMemoryRegionType_Uart = 0x1D,
KMemoryRegionType_InterruptDistributor = 0x4D | KMemoryRegionAttr_NoUserMap,
KMemoryRegionType_InterruptCpuInterface = 0x2D | KMemoryRegionAttr_NoUserMap,
KMemoryRegionType_MemoryController = 0x55,
KMemoryRegionType_MemoryController0 = 0x95,
KMemoryRegionType_MemoryController1 = 0x65,
KMemoryRegionType_PowerManagementController = 0x1A5,
KMemoryRegionType_KernelAutoMap = KMemoryRegionType_Kernel | KMemoryRegionAttr_ShouldKernelMap,
KMemoryRegionType_KernelTemp = 0x31,
KMemoryRegionType_KernelCode = 0x19,
KMemoryRegionType_KernelStack = 0x29,
KMemoryRegionType_KernelMisc = 0x49,
KMemoryRegionType_KernelSlab = 0x89,
KMemoryRegionType_KernelMiscMainStack = 0xB49,
KMemoryRegionType_KernelMiscMappedDevice = 0xD49,
KMemoryRegionType_KernelMiscIdleStack = 0x1349,
KMemoryRegionType_KernelMiscUnknownDebug = 0x1549,
KMemoryRegionType_KernelMiscExceptionStack = 0x2349,
KMemoryRegionType_DramLinearMapped = KMemoryRegionType_Dram | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramReservedEarly = 0x16 | KMemoryRegionAttr_NoUserMap,
KMemoryRegionType_DramPoolPartition = 0x26 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramMetadataPool = 0x166 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_CarveoutProtected,
KMemoryRegionType_DramNonKernel = 0x1A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramApplicationPool = 0x7A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramAppletPool = 0xBA6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramSystemNonSecurePool = 0xDA6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramSystemPool = 0x13A6 | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_CarveoutProtected,
KMemoryRegionType_DramKernel = 0xE | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected,
KMemoryRegionType_DramKernelCode = 0xCE | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected,
KMemoryRegionType_DramKernelSlab = 0x14E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected,
KMemoryRegionType_DramKernelPtHeap = 0x24E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_DramKernelInitPt = 0x44E | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_LinearMapped,
/* These regions aren't normally mapped in retail kernel. */
KMemoryRegionType_KernelTraceBuffer = 0xA6 | KMemoryRegionAttr_UserReadOnly | KMemoryRegionAttr_LinearMapped,
KMemoryRegionType_OnMemoryBootImage = 0x156,
KMemoryRegionType_DTB = 0x256,
};
constexpr ALWAYS_INLINE KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) {
if (type_id == (type_id | KMemoryRegionType_KernelTraceBuffer)) {
return KMemoryRegionType_VirtualKernelTraceBuffer;
} else if (type_id == (type_id | KMemoryRegionType_DramKernelPtHeap)) {
return KMemoryRegionType_VirtualKernelPtHeap;
} else {
return KMemoryRegionType_Dram;
}
}
class KMemoryRegion : public util::IntrusiveRedBlackTreeBaseNode<KMemoryRegion> {
NON_COPYABLE(KMemoryRegion);
NON_MOVEABLE(KMemoryRegion);
private:
uintptr_t address;
uintptr_t pair_address;
size_t region_size;
u32 attributes;
u32 type_id;
public:
static constexpr ALWAYS_INLINE int Compare(const KMemoryRegion &lhs, const KMemoryRegion &rhs) {
if (lhs.GetAddress() < rhs.GetAddress()) {
return -1;
} else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
return 0;
} else {
return 1;
}
}
public:
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 rs, u32 r, u32 t) : KMemoryRegion(a, rs, std::numeric_limits<uintptr_t>::max(), r, t) { /* ... */ }
constexpr ALWAYS_INLINE uintptr_t GetAddress() const {
return this->address;
}
constexpr ALWAYS_INLINE uintptr_t GetPairAddress() const {
return this->pair_address;
}
constexpr ALWAYS_INLINE size_t GetSize() const {
return this->region_size;
}
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
return this->GetAddress() + this->GetSize();
}
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
return this->GetEndAddress() - 1;
}
constexpr ALWAYS_INLINE u32 GetAttributes() const {
return this->attributes;
}
constexpr ALWAYS_INLINE u32 GetType() const {
return this->type_id;
}
constexpr ALWAYS_INLINE void SetType(u32 type) {
MESOSPHERE_INIT_ABORT_UNLESS(this->CanDerive(type));
this->type_id = type;
}
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
return this->GetAddress() <= address && address <= this->GetLastAddress();
}
constexpr ALWAYS_INLINE bool IsDerivedFrom(u32 type) const {
return (this->GetType() | type) == this->GetType();
}
constexpr ALWAYS_INLINE bool HasTypeAttribute(KMemoryRegionType attr) const {
return (this->GetType() | attr) == this->GetType();
}
constexpr ALWAYS_INLINE bool CanDerive(u32 type) const {
return (this->GetType() | type) == type;
}
constexpr ALWAYS_INLINE void SetPairAddress(uintptr_t a) {
this->pair_address = a;
}
constexpr ALWAYS_INLINE void SetTypeAttribute(KMemoryRegionType attr) {
this->type_id |= attr;
}
};
static_assert(std::is_trivially_destructible<KMemoryRegion>::value);
class KMemoryRegionTree {
public:
struct DerivedRegionExtents {
const KMemoryRegion *first_region;
const KMemoryRegion *last_region;
constexpr DerivedRegionExtents() : first_region(nullptr), last_region(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE uintptr_t GetAddress() const {
return this->first_region->GetAddress();
}
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
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>;
public:
using value_type = TreeType::value_type;
using size_type = TreeType::size_type;
using difference_type = TreeType::difference_type;
using pointer = TreeType::pointer;
using const_pointer = TreeType::const_pointer;
using reference = TreeType::reference;
using const_reference = TreeType::const_reference;
using iterator = TreeType::iterator;
using const_iterator = TreeType::const_iterator;
private:
TreeType tree;
public:
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
public:
iterator FindContainingRegion(uintptr_t address) {
return this->find(KMemoryRegion(address, 1, 0, 0));
}
iterator FindFirstRegionByTypeAttr(u32 type_id, u32 attr = 0) {
for (auto it = this->begin(); it != this->end(); it++) {
if (it->GetType() == type_id && it->GetAttributes() == attr) {
return it;
}
}
MESOSPHERE_INIT_ABORT();
}
iterator FindFirstRegionByType(u32 type_id) {
for (auto it = this->begin(); it != this->end(); it++) {
if (it->GetType() == type_id) {
return it;
}
}
MESOSPHERE_INIT_ABORT();
}
iterator TryFindFirstRegionByType(u32 type_id) {
for (auto it = this->begin(); it != this->end(); it++) {
if (it->GetType() == type_id) {
return it;
}
}
return this->end();
}
iterator FindFirstDerivedRegion(u32 type_id) {
for (auto it = this->begin(); it != this->end(); it++) {
if (it->IsDerivedFrom(type_id)) {
return it;
}
}
MESOSPHERE_INIT_ABORT();
}
iterator TryFindFirstDerivedRegion(u32 type_id) {
for (auto it = this->begin(); it != this->end(); it++) {
if (it->IsDerivedFrom(type_id)) {
return it;
}
}
return this->end();
}
DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const {
DerivedRegionExtents extents;
MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region == nullptr);
MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region == nullptr);
for (auto it = this->cbegin(); it != this->cend(); it++) {
if (it->IsDerivedFrom(type_id)) {
if (extents.first_region == nullptr) {
extents.first_region = std::addressof(*it);
}
extents.last_region = std::addressof(*it);
}
}
MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region != nullptr);
MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region != nullptr);
return extents;
}
public:
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);
ALWAYS_INLINE KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, size_t guard_size) {
return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
}
public:
/* Iterator accessors. */
iterator begin() {
return this->tree.begin();
}
const_iterator begin() const {
return this->tree.begin();
}
iterator end() {
return this->tree.end();
}
const_iterator end() const {
return this->tree.end();
}
const_iterator cbegin() const {
return this->begin();
}
const_iterator cend() const {
return this->end();
}
iterator iterator_to(reference ref) {
return this->tree.iterator_to(ref);
}
const_iterator iterator_to(const_reference ref) const {
return this->tree.iterator_to(ref);
}
/* Content management. */
bool empty() const {
return this->tree.empty();
}
reference back() {
return this->tree.back();
}
const_reference back() const {
return this->tree.back();
}
reference front() {
return this->tree.front();
}
const_reference front() const {
return this->tree.front();
}
/* GCC over-eagerly inlines this operation. */
NOINLINE iterator insert(reference ref) {
return this->tree.insert(ref);
}
NOINLINE iterator erase(iterator it) {
return this->tree.erase(it);
}
iterator find(const_reference ref) const {
return this->tree.find(ref);
}
iterator nfind(const_reference ref) const {
return this->tree.nfind(ref);
}
};
class KMemoryRegionAllocator {
NON_COPYABLE(KMemoryRegionAllocator);
NON_MOVEABLE(KMemoryRegionAllocator);
public:
static constexpr size_t MaxMemoryRegions = 1000;
friend class KMemoryLayout;
private:
KMemoryRegion region_heap[MaxMemoryRegions];
size_t num_regions;
private:
constexpr ALWAYS_INLINE KMemoryRegionAllocator() : region_heap(), num_regions() { /* ... */ }
public:
ALWAYS_INLINE KMemoryRegion *Allocate() {
/* Ensure we stay within the bounds of our heap. */
MESOSPHERE_INIT_ABORT_UNLESS(this->num_regions < MaxMemoryRegions);
return &this->region_heap[this->num_regions++];
}
template<typename... Args>
ALWAYS_INLINE KMemoryRegion *Create(Args&&... args) {
KMemoryRegion *region = this->Allocate();
new (region) KMemoryRegion(std::forward<Args>(args)...);
return region;
}
};
constexpr size_t KernelResourceSize = KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;
class KMemoryLayout {
private:
static /* constinit */ inline uintptr_t s_linear_phys_to_virt_diff;
static /* constinit */ inline uintptr_t s_linear_virt_to_phys_diff;
static /* constinit */ inline KMemoryRegionAllocator s_region_allocator;
static /* constinit */ inline KMemoryRegionTree s_virtual_tree;
static /* constinit */ inline KMemoryRegionTree s_physical_tree;
static /* constinit */ inline KMemoryRegionTree s_virtual_linear_tree;
static /* constinit */ inline KMemoryRegionTree s_physical_linear_tree;
private:
static ALWAYS_INLINE auto GetVirtualLinearExtents(const KMemoryRegionTree::DerivedRegionExtents physical) {
return KMemoryRegion(GetInteger(GetLinearVirtualAddress(physical.GetAddress())), physical.GetSize(), 0, KMemoryRegionType_None);
template<typename AddressType> requires IsKTypedAddress<AddressType>
static ALWAYS_INLINE bool IsTypedAddress(const KMemoryRegion *&region, AddressType address, KMemoryRegionTree &tree, KMemoryRegionType type) {
/* Check if the cached region already contains the address. */
if (region != nullptr && region->Contains(GetInteger(address))) {
return true;
}
/* Find the containing region, and update the cache. */
if (const KMemoryRegion *found = tree.Find(GetInteger(address)); found != nullptr && found->IsDerivedFrom(type)) {
region = found;
return true;
} else {
return false;
}
}
template<typename AddressType> requires IsKTypedAddress<AddressType>
static ALWAYS_INLINE bool IsTypedAddress(const KMemoryRegion *&region, AddressType address, size_t size, KMemoryRegionTree &tree, KMemoryRegionType type) {
/* Get the end of the checked region. */
const uintptr_t last_address = GetInteger(address) + size - 1;
/* Walk the tree to verify the region is correct. */
const KMemoryRegion *cur = (region != nullptr && region->Contains(GetInteger(address))) ? region : tree.Find(GetInteger(address));
while (cur != nullptr && cur->IsDerivedFrom(type)) {
if (last_address <= cur->GetLastAddress()) {
region = cur;
return true;
}
cur = cur->GetNext();
}
return false;
}
template<typename AddressType> requires IsKTypedAddress<AddressType>
static ALWAYS_INLINE const KMemoryRegion *Find(AddressType address, const KMemoryRegionTree &tree) {
return tree.Find(GetInteger(address));
}
static ALWAYS_INLINE KMemoryRegion &Dereference(KMemoryRegion *region) {
MESOSPHERE_INIT_ABORT_UNLESS(region != nullptr);
return *region;
}
static ALWAYS_INLINE const KMemoryRegion &Dereference(const KMemoryRegion *region) {
MESOSPHERE_INIT_ABORT_UNLESS(region != nullptr);
return *region;
}
static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) {
return Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast<u32>(core_id))).GetEndAddress();
}
public:
static ALWAYS_INLINE KMemoryRegionAllocator &GetMemoryRegionAllocator() { return s_region_allocator; }
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetPhysicalMemoryRegionTree() { return s_physical_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualLinearMemoryRegionTree() { return s_virtual_linear_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetPhysicalLinearMemoryRegionTree() { return s_physical_linear_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetPhysicalMemoryRegionTree() { return s_physical_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetVirtualLinearMemoryRegionTree() { return s_virtual_linear_tree; }
static ALWAYS_INLINE KMemoryRegionTree &GetPhysicalLinearMemoryRegionTree() { return s_physical_linear_tree; }
static ALWAYS_INLINE KMemoryRegionTree::iterator GetEnd(KVirtualAddress) {
return GetVirtualLinearMemoryRegionTree().end();
}
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress address) { return GetInteger(address) + s_linear_phys_to_virt_diff; }
static ALWAYS_INLINE KPhysicalAddress GetLinearPhysicalAddress(KVirtualAddress address) { return GetInteger(address) + s_linear_virt_to_phys_diff; }
static ALWAYS_INLINE KMemoryRegionTree::iterator GetEnd(KPhysicalAddress) {
return GetPhysicalMemoryRegionTree().end();
}
static NOINLINE const KMemoryRegion *Find(KVirtualAddress address) { return Find(address, GetVirtualMemoryRegionTree()); }
static NOINLINE const KMemoryRegion *Find(KPhysicalAddress address) { return Find(address, GetPhysicalMemoryRegionTree()); }
static NOINLINE KMemoryRegionTree::iterator FindContainingRegion(KVirtualAddress address) {
return GetVirtualMemoryRegionTree().FindContainingRegion(GetInteger(address));
}
static NOINLINE const KMemoryRegion *FindLinear(KVirtualAddress address) { return Find(address, GetVirtualLinearMemoryRegionTree()); }
static NOINLINE const KMemoryRegion *FindLinear(KPhysicalAddress address) { return Find(address, GetPhysicalLinearMemoryRegionTree()); }
static NOINLINE KMemoryRegionTree::iterator FindContainingRegion(KPhysicalAddress address) {
return GetPhysicalMemoryRegionTree().FindContainingRegion(GetInteger(address));
}
static NOINLINE KVirtualAddress GetMainStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscMainStack); }
static NOINLINE KVirtualAddress GetIdleStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscIdleStack); }
static NOINLINE KVirtualAddress GetExceptionStackTopAddress(s32 core_id) { return GetStackTopAddress(core_id, KMemoryRegionType_KernelMiscExceptionStack); }
static ALWAYS_INLINE KVirtualAddress GetLinearVirtualAddress(KPhysicalAddress address) {
return GetInteger(address) + s_linear_phys_to_virt_diff;
}
static NOINLINE KVirtualAddress GetSlabRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelSlab)).GetAddress(); }
static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)).GetAddress(); }
static ALWAYS_INLINE KPhysicalAddress GetLinearPhysicalAddress(KVirtualAddress address) {
return GetInteger(address) + s_linear_virt_to_phys_diff;
}
static NOINLINE const KMemoryRegion &GetDeviceRegion(KMemoryRegionType type) { return Dereference(GetPhysicalMemoryRegionTree().FindFirstDerived(type)); }
static KPhysicalAddress GetDevicePhysicalAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetAddress(); }
static KVirtualAddress GetDeviceVirtualAddress(KMemoryRegionType type) { return GetDeviceRegion(type).GetPairAddress(); }
static NOINLINE KVirtualAddress GetMainStackTopAddress(s32 core_id) {
return GetVirtualMemoryRegionTree().FindFirstRegionByTypeAttr(KMemoryRegionType_KernelMiscMainStack, static_cast<u32>(core_id))->GetEndAddress();
}
static NOINLINE const KMemoryRegion &GetPoolManagementRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramPoolManagement)); }
static NOINLINE const KMemoryRegion &GetPageTableHeapRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelPtHeap)); }
static NOINLINE const KMemoryRegion &GetKernelStackRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelStack)); }
static NOINLINE const KMemoryRegion &GetTempRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_KernelTemp)); }
static NOINLINE const KMemoryRegion &GetCoreLocalRegion() { return Dereference(GetVirtualMemoryRegionTree().FindByType(KMemoryRegionType_CoreLocalRegion)); }
static NOINLINE KVirtualAddress GetIdleStackTopAddress(s32 core_id) {
return GetVirtualMemoryRegionTree().FindFirstRegionByTypeAttr(KMemoryRegionType_KernelMiscIdleStack, static_cast<u32>(core_id))->GetEndAddress();
}
static NOINLINE const KMemoryRegion &GetKernelTraceBufferRegion() { return Dereference(GetVirtualLinearMemoryRegionTree().FindByType(KMemoryRegionType_VirtualDramKernelTraceBuffer)); }
static NOINLINE KVirtualAddress GetExceptionStackTopAddress(s32 core_id) {
return GetVirtualMemoryRegionTree().FindFirstRegionByTypeAttr(KMemoryRegionType_KernelMiscExceptionStack, static_cast<u32>(core_id))->GetEndAddress();
}
static NOINLINE const KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) { return Dereference(FindLinear(address)); }
static NOINLINE KVirtualAddress GetSlabRegionAddress() {
return GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_KernelSlab)->GetAddress();
}
static NOINLINE const KMemoryRegion *GetPhysicalKernelTraceBufferRegion() { return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_KernelTraceBuffer); }
static NOINLINE const KMemoryRegion *GetPhysicalOnMemoryBootImageRegion() { return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_OnMemoryBootImage); }
static NOINLINE const KMemoryRegion *GetPhysicalDTBRegion() { return GetPhysicalMemoryRegionTree().FindFirstDerived(KMemoryRegionType_DTB); }
static NOINLINE KVirtualAddress GetCoreLocalRegionAddress() {
return GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_CoreLocal)->GetAddress();
}
static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *&region, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramUserPool); }
static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *&region, KVirtualAddress address) { return IsTypedAddress(region, address, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramUserPool); }
static NOINLINE KVirtualAddress GetInterruptDistributorAddress() {
return GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_InterruptDistributor)->GetPairAddress();
}
static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion *&region, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), KMemoryRegionType_DramUserPool); }
static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion *&region, KVirtualAddress address, size_t size) { return IsTypedAddress(region, address, size, GetVirtualLinearMemoryRegionTree(), KMemoryRegionType_VirtualDramUserPool); }
static NOINLINE KVirtualAddress GetInterruptCpuInterfaceAddress() {
return GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_InterruptCpuInterface)->GetPairAddress();
}
static NOINLINE KVirtualAddress GetUartAddress() {
return GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_Uart)->GetPairAddress();
}
static NOINLINE KMemoryRegion &GetMemoryControllerRegion() {
return *GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_MemoryController);
}
static NOINLINE KMemoryRegion &GetMetadataPoolRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_VirtualDramMetadataPool);
}
static NOINLINE KMemoryRegion &GetPageTableHeapRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_VirtualKernelPtHeap);
}
static NOINLINE KMemoryRegion &GetKernelStackRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_KernelStack);
}
static NOINLINE KMemoryRegion &GetTempRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_KernelTemp);
}
static NOINLINE KMemoryRegion &GetVirtualLinearRegion(KVirtualAddress address) {
return *GetVirtualLinearMemoryRegionTree().FindContainingRegion(GetInteger(address));
}
static NOINLINE const KMemoryRegion *TryGetKernelTraceBufferRegion() {
auto &tree = GetPhysicalMemoryRegionTree();
if (KMemoryRegionTree::const_iterator it = tree.TryFindFirstDerivedRegion(KMemoryRegionType_KernelTraceBuffer); it != tree.end()) {
return std::addressof(*it);
} else {
return nullptr;
}
}
static NOINLINE const KMemoryRegion *TryGetOnMemoryBootImageRegion() {
auto &tree = GetPhysicalMemoryRegionTree();
if (KMemoryRegionTree::const_iterator it = tree.TryFindFirstDerivedRegion(KMemoryRegionType_OnMemoryBootImage); it != tree.end()) {
return std::addressof(*it);
} else {
return nullptr;
}
}
static NOINLINE const KMemoryRegion *TryGetDTBRegion() {
auto &tree = GetPhysicalMemoryRegionTree();
if (KMemoryRegionTree::const_iterator it = tree.TryFindFirstDerivedRegion(KMemoryRegionType_DTB); it != tree.end()) {
return std::addressof(*it);
} else {
return nullptr;
}
}
static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion **out, KPhysicalAddress address, const KMemoryRegion *hint = nullptr) {
auto &tree = GetPhysicalLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_DramNonKernel)) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
return false;
}
static NOINLINE bool IsHeapPhysicalAddress(const KMemoryRegion **out, KPhysicalAddress address, size_t size, const KMemoryRegion *hint = nullptr) {
auto &tree = GetPhysicalLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_DramNonKernel)) {
const uintptr_t last_address = GetInteger(address) + size - 1;
do {
if (last_address <= it->GetLastAddress()) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
it++;
} while (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_DramNonKernel));
}
return false;
}
static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion **out, KPhysicalAddress address, const KMemoryRegion *hint = nullptr) {
auto &tree = GetPhysicalLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionAttr_LinearMapped)) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
return false;
}
static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion **out, KPhysicalAddress address, size_t size, const KMemoryRegion *hint = nullptr) {
auto &tree = GetPhysicalLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionAttr_LinearMapped)) {
const uintptr_t last_address = GetInteger(address) + size - 1;
do {
if (last_address <= it->GetLastAddress()) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
it++;
} while (it != tree.end() && it->IsDerivedFrom(KMemoryRegionAttr_LinearMapped));
}
return false;
}
static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion **out, KVirtualAddress address, const KMemoryRegion *hint = nullptr) {
auto &tree = GetVirtualLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_VirtualDramManagedPool)) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
return false;
}
static NOINLINE bool IsHeapVirtualAddress(const KMemoryRegion **out, KVirtualAddress address, size_t size, const KMemoryRegion *hint = nullptr) {
auto &tree = GetVirtualLinearMemoryRegionTree();
KMemoryRegionTree::const_iterator it = tree.end();
if (hint != nullptr) {
it = tree.iterator_to(*hint);
}
if (it == tree.end() || !it->Contains(GetInteger(address))) {
it = tree.FindContainingRegion(GetInteger(address));
}
if (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_VirtualDramManagedPool)) {
const uintptr_t last_address = GetInteger(address) + size - 1;
do {
if (last_address <= it->GetLastAddress()) {
if (out) {
*out = std::addressof(*it);
}
return true;
}
it++;
} while (it != tree.end() && it->IsDerivedFrom(KMemoryRegionType_VirtualDramManagedPool));
}
return false;
}
static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *&region, KPhysicalAddress address) { return IsTypedAddress(region, address, GetPhysicalLinearMemoryRegionTree(), static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); }
static NOINLINE bool IsLinearMappedPhysicalAddress(const KMemoryRegion *&region, KPhysicalAddress address, size_t size) { return IsTypedAddress(region, address, size, GetPhysicalLinearMemoryRegionTree(), static_cast<KMemoryRegionType>(KMemoryRegionAttr_LinearMapped)); }
static NOINLINE std::tuple<size_t, size_t> GetTotalAndKernelMemorySizes() {
size_t total_size = 0, kernel_size = 0;
for (auto it = GetPhysicalMemoryRegionTree().cbegin(); it != GetPhysicalMemoryRegionTree().cend(); it++) {
if (it->IsDerivedFrom(KMemoryRegionType_Dram)) {
total_size += it->GetSize();
if (!it->IsDerivedFrom(KMemoryRegionType_DramNonKernel)) {
kernel_size += it->GetSize();
for (const auto &region : GetPhysicalMemoryRegionTree()) {
if (region.IsDerivedFrom(KMemoryRegionType_Dram)) {
total_size += region.GetSize();
if (!region.IsDerivedFrom(KMemoryRegionType_DramUserPool)) {
kernel_size += region.GetSize();
}
}
}
@@ -697,86 +177,39 @@ namespace ams::kern {
}
static void InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start);
static size_t GetResourceRegionSizeForInit();
static NOINLINE auto GetKernelRegionExtents() {
return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel);
static NOINLINE auto GetKernelRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); }
static NOINLINE auto GetKernelCodeRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode); }
static NOINLINE auto GetKernelStackRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelStack); }
static NOINLINE auto GetKernelMiscRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelMisc); }
static NOINLINE auto GetKernelSlabRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelSlab); }
static NOINLINE auto GetLinearRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped); }
static NOINLINE auto GetLinearRegionVirtualExtents() {
auto physical = GetLinearRegionPhysicalExtents();
return KMemoryRegion(GetInteger(GetLinearVirtualAddress(physical.GetAddress())), physical.GetSize(), 0, KMemoryRegionType_None);
}
static NOINLINE auto GetKernelCodeRegionExtents() {
return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelCode);
}
static NOINLINE auto GetMainMemoryPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Dram); }
static NOINLINE auto GetCarveoutRegionExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_CarveoutProtected); }
static NOINLINE auto GetKernelStackRegionExtents() {
return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelStack);
}
static NOINLINE auto GetKernelRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelBase); }
static NOINLINE auto GetKernelCodeRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode); }
static NOINLINE auto GetKernelSlabRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab); }
static NOINLINE auto GetKernelPageTableHeapRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap); }
static NOINLINE auto GetKernelInitPageTableRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt); }
static NOINLINE auto GetKernelMiscRegionExtents() {
return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelMisc);
}
static NOINLINE auto GetKernelPoolManagementRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramPoolManagement); }
static NOINLINE auto GetKernelPoolPartitionRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramPoolPartition); }
static NOINLINE auto GetKernelSystemPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemPool); }
static NOINLINE auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemNonSecurePool); }
static NOINLINE auto GetKernelAppletPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramAppletPool); }
static NOINLINE auto GetKernelApplicationPoolRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramApplicationPool); }
static NOINLINE auto GetKernelSlabRegionExtents() {
return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelSlab);
}
static NOINLINE const KMemoryRegion &GetCoreLocalRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_CoreLocal);
}
static NOINLINE auto GetLinearRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_LinearMapped);
}
static NOINLINE auto GetLinearRegionExtents() {
return GetVirtualLinearExtents(GetLinearRegionPhysicalExtents());
}
static NOINLINE auto GetCarveoutRegionExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionAttr_CarveoutProtected);
}
static NOINLINE auto GetKernelRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernel);
}
static NOINLINE auto GetKernelCodeRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelCode);
}
static NOINLINE auto GetKernelSlabRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelSlab);
}
static NOINLINE auto GetKernelPageTableHeapRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelPtHeap);
}
static NOINLINE auto GetKernelInitPageTableRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramKernelInitPt);
}
static NOINLINE auto GetKernelPoolPartitionRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramPoolPartition);
}
static NOINLINE auto GetKernelMetadataPoolRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramMetadataPool);
}
static NOINLINE auto GetKernelSystemPoolRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemPool);
}
static NOINLINE auto GetKernelSystemNonSecurePoolRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramSystemNonSecurePool);
}
static NOINLINE auto GetKernelAppletPoolRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramAppletPool);
}
static NOINLINE auto GetKernelApplicationPoolRegionPhysicalExtents() {
return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_DramApplicationPool);
}
static NOINLINE auto GetKernelTraceBufferRegionPhysicalExtents() { return GetPhysicalMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_KernelTraceBuffer); }
};

View File

@@ -38,6 +38,7 @@ namespace ams::kern {
/* Aliases. */
Pool_Unsafe = Pool_Application,
Pool_Secure = Pool_System,
};
enum Direction {
@@ -54,7 +55,7 @@ namespace ams::kern {
private:
using RefCount = u16;
public:
static size_t CalculateMetadataOverheadSize(size_t region_size);
static size_t CalculateManagementOverheadSize(size_t region_size);
static constexpr size_t CalculateOptimizedProcessOverheadSize(size_t region_size) {
return (util::AlignUp((region_size / PageSize), BITSIZEOF(u64)) / BITSIZEOF(u64)) * sizeof(u64);
@@ -62,24 +63,24 @@ namespace ams::kern {
private:
KPageHeap heap;
RefCount *page_reference_counts;
KVirtualAddress metadata_region;
KVirtualAddress management_region;
Pool pool;
Impl *next;
Impl *prev;
public:
Impl() : heap(), page_reference_counts(), metadata_region(), pool(), next(), prev() { /* ... */ }
Impl() : heap(), page_reference_counts(), management_region(), pool(), next(), prev() { /* ... */ }
size_t Initialize(const KMemoryRegion *region, Pool pool, KVirtualAddress metadata_region, KVirtualAddress metadata_region_end);
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 InitializeOptimizedMemory() { std::memset(GetVoidPointer(this->metadata_region), 0, CalculateOptimizedProcessOverheadSize(this->heap.GetSize())); }
void InitializeOptimizedMemory() { std::memset(GetVoidPointer(this->management_region), 0, CalculateOptimizedProcessOverheadSize(this->heap.GetSize())); }
void TrackUnoptimizedAllocation(KVirtualAddress block, size_t num_pages);
size_t TrackOptimizedAllocation(KVirtualAddress block, size_t num_pages);
void TrackOptimizedAllocation(KVirtualAddress block, size_t num_pages);
size_t ProcessOptimizedAllocation(bool *out_any_new, KVirtualAddress block, size_t num_pages, u8 fill_pattern);
bool ProcessOptimizedAllocation(KVirtualAddress block, size_t num_pages, u8 fill_pattern);
constexpr Pool GetPool() const { return this->pool; }
constexpr size_t GetSize() const { return this->heap.GetSize(); }
@@ -87,15 +88,16 @@ namespace ams::kern {
size_t GetFreeSize() const { return this->heap.GetFreeSize(); }
constexpr size_t GetPageOffset(KVirtualAddress address) const { return this->heap.GetPageOffset(address); }
constexpr size_t GetPageOffsetToEnd(KVirtualAddress address) const { return this->heap.GetPageOffsetToEnd(address); }
constexpr void SetNext(Impl *n) { this->next = n; }
constexpr void SetPrev(Impl *n) { this->prev = n; }
constexpr Impl *GetNext() const { return this->next; }
constexpr Impl *GetPrev() const { return this->prev; }
void Open(KLightLock *pool_locks, KVirtualAddress address, size_t num_pages) {
KScopedLightLock lk(pool_locks[this->pool]);
size_t index = this->heap.GetPageOffset(address);
void Open(KVirtualAddress address, size_t num_pages) {
size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages;
while (index < end) {
const RefCount ref_count = (++this->page_reference_counts[index]);
@@ -105,10 +107,8 @@ namespace ams::kern {
}
}
void Close(KLightLock *pool_locks, KVirtualAddress address, size_t num_pages) {
KScopedLightLock lk(pool_locks[this->pool]);
size_t index = this->heap.GetPageOffset(address);
void Close(KVirtualAddress address, size_t num_pages) {
size_t index = this->GetPageOffset(address);
const size_t end = index + num_pages;
size_t free_start = 0;
@@ -173,7 +173,7 @@ namespace ams::kern {
/* ... */
}
NOINLINE void Initialize(KVirtualAddress metadata_region, size_t metadata_region_size);
NOINLINE void Initialize(KVirtualAddress management_region, size_t management_region_size);
NOINLINE Result InitializeOptimizedMemory(u64 process_id, Pool pool);
NOINLINE void FinalizeOptimizedMemory(u64 process_id, Pool pool);
@@ -186,8 +186,13 @@ namespace ams::kern {
/* Repeatedly open references until we've done so for all pages. */
while (num_pages) {
auto &manager = this->GetManager(address);
const size_t cur_pages = std::min(num_pages, (manager.GetEndAddress() - address) / PageSize);
manager.Open(this->pool_locks, address, cur_pages);
const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
{
KScopedLightLock lk(this->pool_locks[manager.GetPool()]);
manager.Open(address, cur_pages);
}
num_pages -= cur_pages;
address += cur_pages * PageSize;
}
@@ -197,8 +202,13 @@ namespace ams::kern {
/* Repeatedly close references until we've done so for all pages. */
while (num_pages) {
auto &manager = this->GetManager(address);
const size_t cur_pages = std::min(num_pages, (manager.GetEndAddress() - address) / PageSize);
manager.Close(this->pool_locks, address, cur_pages);
const size_t cur_pages = std::min(num_pages, manager.GetPageOffsetToEnd(address));
{
KScopedLightLock lk(this->pool_locks[manager.GetPool()]);
manager.Close(address, cur_pages);
}
num_pages -= cur_pages;
address += cur_pages * PageSize;
}
@@ -238,8 +248,8 @@ namespace ams::kern {
return total;
}
public:
static size_t CalculateMetadataOverheadSize(size_t region_size) {
return Impl::CalculateMetadataOverheadSize(region_size);
static size_t CalculateManagementOverheadSize(size_t region_size) {
return Impl::CalculateManagementOverheadSize(region_size);
}
static constexpr ALWAYS_INLINE u32 EncodeOption(Pool pool, Direction dir) {

View File

@@ -0,0 +1,318 @@
/*
* 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_memory_region_type.hpp>
namespace ams::kern {
class KMemoryRegionTree;
class KMemoryRegion : public util::IntrusiveRedBlackTreeBaseNode<KMemoryRegion> {
NON_COPYABLE(KMemoryRegion);
NON_MOVEABLE(KMemoryRegion);
private:
friend class KMemoryRegionTree;
private:
uintptr_t address;
uintptr_t pair_address;
size_t region_size;
u32 attributes;
u32 type_id;
public:
static constexpr ALWAYS_INLINE int Compare(const KMemoryRegion &lhs, const KMemoryRegion &rhs) {
if (lhs.GetAddress() < rhs.GetAddress()) {
return -1;
} else if (lhs.GetAddress() <= rhs.GetLastAddress()) {
return 0;
} else {
return 1;
}
}
public:
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 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 rs, uintptr_t p, u32 r, u32 t) {
this->address = a;
this->pair_address = p;
this->region_size = rs;
this->attributes = r;
this->type_id = t;
}
public:
constexpr ALWAYS_INLINE uintptr_t GetAddress() const {
return this->address;
}
constexpr ALWAYS_INLINE uintptr_t GetPairAddress() const {
return this->pair_address;
}
constexpr ALWAYS_INLINE size_t GetSize() const {
return this->region_size;
}
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
return this->GetAddress() + this->GetSize();
}
constexpr ALWAYS_INLINE uintptr_t GetLastAddress() const {
return this->GetEndAddress() - 1;
}
constexpr ALWAYS_INLINE u32 GetAttributes() const {
return this->attributes;
}
constexpr ALWAYS_INLINE u32 GetType() const {
return this->type_id;
}
constexpr ALWAYS_INLINE void SetType(u32 type) {
MESOSPHERE_INIT_ABORT_UNLESS(this->CanDerive(type));
this->type_id = type;
}
constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const {
return this->GetAddress() <= address && address <= this->GetLastAddress();
}
constexpr ALWAYS_INLINE bool IsDerivedFrom(u32 type) const {
return (this->GetType() | type) == this->GetType();
}
constexpr ALWAYS_INLINE bool HasTypeAttribute(KMemoryRegionAttr attr) const {
return (this->GetType() | attr) == this->GetType();
}
constexpr ALWAYS_INLINE bool CanDerive(u32 type) const {
return (this->GetType() | type) == type;
}
constexpr ALWAYS_INLINE void SetPairAddress(uintptr_t a) {
this->pair_address = a;
}
constexpr ALWAYS_INLINE void SetTypeAttribute(KMemoryRegionAttr attr) {
this->type_id |= attr;
}
};
static_assert(std::is_trivially_destructible<KMemoryRegion>::value);
class KMemoryRegionTree {
public:
struct DerivedRegionExtents {
const KMemoryRegion *first_region;
const KMemoryRegion *last_region;
constexpr DerivedRegionExtents() : first_region(nullptr), last_region(nullptr) { /* ... */ }
constexpr ALWAYS_INLINE uintptr_t GetAddress() const {
return this->first_region->GetAddress();
}
constexpr ALWAYS_INLINE uintptr_t GetEndAddress() const {
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>;
public:
using value_type = TreeType::value_type;
using size_type = TreeType::size_type;
using difference_type = TreeType::difference_type;
using pointer = TreeType::pointer;
using const_pointer = TreeType::const_pointer;
using reference = TreeType::reference;
using const_reference = TreeType::const_reference;
using iterator = TreeType::iterator;
using const_iterator = TreeType::const_iterator;
private:
TreeType tree;
public:
constexpr ALWAYS_INLINE KMemoryRegionTree() : tree() { /* ... */ }
public:
KMemoryRegion *FindModifiable(uintptr_t address) {
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->end()) {
return std::addressof(*it);
} else {
return nullptr;
}
}
const KMemoryRegion *Find(uintptr_t address) const {
if (auto it = this->find(KMemoryRegion(address, 1, 0, 0)); it != this->cend()) {
return std::addressof(*it);
} else {
return nullptr;
}
}
const KMemoryRegion *FindByType(u32 type_id) const {
for (auto it = this->cbegin(); it != this->cend(); ++it) {
if (it->GetType() == type_id) {
return std::addressof(*it);
}
}
return nullptr;
}
const KMemoryRegion *FindByTypeAndAttribute(u32 type_id, u32 attr) const {
for (auto it = this->cbegin(); it != this->cend(); ++it) {
if (it->GetType() == type_id && it->GetAttributes() == attr) {
return std::addressof(*it);
}
}
return nullptr;
}
const KMemoryRegion *FindFirstDerived(u32 type_id) const {
for (auto it = this->cbegin(); it != this->cend(); it++) {
if (it->IsDerivedFrom(type_id)) {
return std::addressof(*it);
}
}
return nullptr;
}
const KMemoryRegion *FindLastDerived(u32 type_id) const {
const KMemoryRegion *region = nullptr;
for (auto it = this->begin(); it != this->end(); it++) {
if (it->IsDerivedFrom(type_id)) {
region = std::addressof(*it);
}
}
return region;
}
DerivedRegionExtents GetDerivedRegionExtents(u32 type_id) const {
DerivedRegionExtents extents;
MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region == nullptr);
MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region == nullptr);
for (auto it = this->cbegin(); it != this->cend(); it++) {
if (it->IsDerivedFrom(type_id)) {
if (extents.first_region == nullptr) {
extents.first_region = std::addressof(*it);
}
extents.last_region = std::addressof(*it);
}
}
MESOSPHERE_INIT_ABORT_UNLESS(extents.first_region != nullptr);
MESOSPHERE_INIT_ABORT_UNLESS(extents.last_region != nullptr);
return extents;
}
public:
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);
ALWAYS_INLINE KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, size_t guard_size) {
return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
}
public:
/* Iterator accessors. */
iterator begin() {
return this->tree.begin();
}
const_iterator begin() const {
return this->tree.begin();
}
iterator end() {
return this->tree.end();
}
const_iterator end() const {
return this->tree.end();
}
const_iterator cbegin() const {
return this->begin();
}
const_iterator cend() const {
return this->end();
}
iterator iterator_to(reference ref) {
return this->tree.iterator_to(ref);
}
const_iterator iterator_to(const_reference ref) const {
return this->tree.iterator_to(ref);
}
/* Content management. */
bool empty() const {
return this->tree.empty();
}
reference back() {
return this->tree.back();
}
const_reference back() const {
return this->tree.back();
}
reference front() {
return this->tree.front();
}
const_reference front() const {
return this->tree.front();
}
/* GCC over-eagerly inlines this operation. */
NOINLINE iterator insert(reference ref) {
return this->tree.insert(ref);
}
NOINLINE iterator erase(iterator it) {
return this->tree.erase(it);
}
iterator find(const_reference ref) const {
return this->tree.find(ref);
}
iterator nfind(const_reference ref) const {
return this->tree.nfind(ref);
}
};
}

View File

@@ -0,0 +1,300 @@
/*
* 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 {
enum KMemoryRegionType : u32 {};
enum KMemoryRegionAttr : typename std::underlying_type<KMemoryRegionType>::type {
KMemoryRegionAttr_CarveoutProtected = 0x04000000,
KMemoryRegionAttr_DidKernelMap = 0x08000000,
KMemoryRegionAttr_ShouldKernelMap = 0x10000000,
KMemoryRegionAttr_UserReadOnly = 0x20000000,
KMemoryRegionAttr_NoUserMap = 0x40000000,
KMemoryRegionAttr_LinearMapped = 0x80000000,
};
namespace impl {
consteval size_t BitsForDeriveSparse(size_t n) {
return n + 1;
}
consteval size_t BitsForDeriveDense(size_t n) {
AMS_ASSUME(n > 0);
size_t low = 0, high = 1;
for (size_t i = 0; i < n - 1; ++i) {
if ((++low) == high) {
++high;
low = 0;
}
}
return high + 1;
}
class KMemoryRegionTypeValue {
private:
using ValueType = typename std::underlying_type<KMemoryRegionType>::type;
private:
ValueType value;
size_t next_bit;
bool finalized;
bool sparse_only;
bool dense_only;
private:
consteval KMemoryRegionTypeValue(ValueType v) : value(v), next_bit(0), finalized(false), sparse_only(false), dense_only(false) { /* ... */ }
public:
consteval KMemoryRegionTypeValue() : KMemoryRegionTypeValue(0) { /* ... */ }
consteval operator KMemoryRegionType() const { return static_cast<KMemoryRegionType>(this->value); }
consteval ValueType GetValue() const { return this->value; }
consteval const KMemoryRegionTypeValue &Finalize() { this->finalized = true; return *this; }
consteval const KMemoryRegionTypeValue &SetSparseOnly() { this->sparse_only = true; return *this; }
consteval const KMemoryRegionTypeValue &SetDenseOnly() { this->dense_only = true; return *this; }
consteval KMemoryRegionTypeValue &SetAttribute(KMemoryRegionAttr attr) { AMS_ASSUME(!this->finalized); this->value |= attr; return *this; }
consteval KMemoryRegionTypeValue DeriveInitial(size_t i, size_t next = BITSIZEOF(ValueType)) const {
AMS_ASSUME(!this->finalized);
AMS_ASSUME(!this->value);
AMS_ASSUME(!this->next_bit);
AMS_ASSUME(next > i);
KMemoryRegionTypeValue new_type = *this;
new_type.value = (ValueType{1} << i);
new_type.next_bit = next;
return new_type;
}
consteval KMemoryRegionTypeValue DeriveAttribute(KMemoryRegionAttr attr) const {
AMS_ASSUME(!this->finalized);
KMemoryRegionTypeValue new_type = *this;
new_type.value |= attr;
return new_type;
}
consteval KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const {
AMS_ASSUME(!this->finalized);
AMS_ASSUME(ofs < adv);
AMS_ASSUME(this->next_bit + adv <= BITSIZEOF(ValueType));
KMemoryRegionTypeValue new_type = *this;
new_type.value |= (ValueType{1} << (this->next_bit + ofs));
new_type.next_bit += adv;
return new_type;
}
consteval KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const {
AMS_ASSUME(!this->finalized);
AMS_ASSUME(!this->dense_only);
AMS_ASSUME(this->next_bit + ofs + n + 1 <= BITSIZEOF(ValueType));
AMS_ASSUME(i < n);
KMemoryRegionTypeValue new_type = *this;
new_type.value |= (ValueType{1} << (this->next_bit + ofs));
new_type.value |= (ValueType{1} << (this->next_bit + ofs + 1 + i));
new_type.next_bit += ofs + n + 1;
return new_type;
}
consteval KMemoryRegionTypeValue Derive(size_t n, size_t i) const {
AMS_ASSUME(!this->finalized);
AMS_ASSUME(!this->sparse_only);
AMS_ASSUME(this->next_bit + BitsForDeriveDense(n) <= BITSIZEOF(ValueType));
AMS_ASSUME(i < n);
size_t low = 0, high = 1;
for (size_t j = 0; j < i; ++j) {
if ((++low) == high) {
++high;
low = 0;
}
}
AMS_ASSUME(high < BitsForDeriveDense(n));
KMemoryRegionTypeValue new_type = *this;
new_type.value |= (ValueType{1} << (this->next_bit + low));
new_type.value |= (ValueType{1} << (this->next_bit + high));
new_type.next_bit += BitsForDeriveDense(n);
return new_type;
}
consteval KMemoryRegionTypeValue Advance(size_t n) const {
AMS_ASSUME(!this->finalized);
AMS_ASSUME(this->next_bit + n <= BITSIZEOF(ValueType));
KMemoryRegionTypeValue new_type = *this;
new_type.next_bit += n;
return new_type;
}
constexpr ALWAYS_INLINE bool IsAncestorOf(ValueType v) const {
return (this->value | v) == v;
}
};
}
constexpr inline const auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
constexpr inline const auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
constexpr inline const auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
constexpr inline const auto KMemoryRegionType_CoreLocalRegion = KMemoryRegionType_None.DeriveInitial(2).Finalize();
static_assert(KMemoryRegionType_Kernel .GetValue() == 0x1);
static_assert(KMemoryRegionType_Dram .GetValue() == 0x2);
static_assert(KMemoryRegionType_CoreLocalRegion.GetValue() == 0x4);
constexpr inline const auto KMemoryRegionType_DramKernelBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 0).SetAttribute(KMemoryRegionAttr_NoUserMap).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
constexpr inline const auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
constexpr inline const auto KMemoryRegionType_DramHeapBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr_LinearMapped);
static_assert(KMemoryRegionType_DramKernelBase .GetValue() == (0xE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16));
static_assert(KMemoryRegionType_DramHeapBase .GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramKernelCode = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0);
constexpr inline const auto KMemoryRegionType_DramKernelSlab = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1);
constexpr inline const auto KMemoryRegionType_DramKernelPtHeap = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute(KMemoryRegionAttr_LinearMapped);
constexpr inline const auto KMemoryRegionType_DramKernelInitPt = KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute(KMemoryRegionAttr_LinearMapped);
static_assert(KMemoryRegionType_DramKernelCode .GetValue() == (0xCE | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramKernelSlab .GetValue() == (0x14E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramKernelPtHeap.GetValue() == (0x24E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
static_assert(KMemoryRegionType_DramKernelInitPt.GetValue() == (0x44E | KMemoryRegionAttr_CarveoutProtected | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_LinearMapped));
constexpr inline const auto KMemoryRegionType_DramReservedEarly = KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_DramReservedEarly.GetValue() == (0x16 | KMemoryRegionAttr_NoUserMap));
/* UNUSED: DeriveSparse(0, 3, 0); */
constexpr inline const auto KMemoryRegionType_OnMemoryBootImage = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1);
constexpr inline const auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2);
static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156);
static_assert(KMemoryRegionType_DTB.GetValue() == 0x256);
constexpr inline const auto KMemoryRegionType_KernelTraceBuffer = KMemoryRegionType_DramHeapBase.DeriveTransition(1, 3).SetAttribute(KMemoryRegionAttr_UserReadOnly);
static_assert(KMemoryRegionType_KernelTraceBuffer.GetValue() == (0xA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_UserReadOnly));
constexpr inline const auto KMemoryRegionType_DramPoolPartition = KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr_NoUserMap);
static_assert(KMemoryRegionType_DramPoolPartition.GetValue() == (0x26 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
constexpr inline const auto KMemoryRegionType_DramPoolManagement = KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition().SetAttribute(KMemoryRegionAttr_CarveoutProtected);
constexpr inline const auto KMemoryRegionType_DramUserPool = KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition();
static_assert(KMemoryRegionType_DramPoolManagement.GetValue() == (0x166 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected));
static_assert(KMemoryRegionType_DramUserPool.GetValue() == (0x1A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
constexpr inline const auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0);
constexpr inline const auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1);
constexpr inline const auto KMemoryRegionType_DramSystemNonSecurePool = KMemoryRegionType_DramUserPool.Derive(4, 2);
constexpr inline const auto KMemoryRegionType_DramSystemPool = KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr_CarveoutProtected);
static_assert(KMemoryRegionType_DramApplicationPool .GetValue() == (0x7A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramAppletPool .GetValue() == (0xBA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramSystemNonSecurePool.GetValue() == (0xDA6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap));
static_assert(KMemoryRegionType_DramSystemPool .GetValue() == (0x13A6 | KMemoryRegionAttr_LinearMapped | KMemoryRegionAttr_NoUserMap | KMemoryRegionAttr_CarveoutProtected));
constexpr inline const auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0);
constexpr inline const auto KMemoryRegionType_VirtualDramKernelPtHeap = KMemoryRegionType_Dram.DeriveSparse(1, 3, 1);
constexpr inline const auto KMemoryRegionType_VirtualDramKernelTraceBuffer = KMemoryRegionType_Dram.DeriveSparse(1, 3, 2);
static_assert(KMemoryRegionType_VirtualDramHeapBase .GetValue() == 0x1A);
static_assert(KMemoryRegionType_VirtualDramKernelPtHeap .GetValue() == 0x2A);
static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A);
constexpr inline const auto KMemoryRegionType_VirtualDramKernelInitPt = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
constexpr inline const auto KMemoryRegionType_VirtualDramPoolManagement = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
constexpr inline const auto KMemoryRegionType_VirtualDramUserPool = KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
static_assert(KMemoryRegionType_VirtualDramKernelInitPt .GetValue() == 0x19A);
static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A);
static_assert(KMemoryRegionType_VirtualDramUserPool .GetValue() == 0x31A);
/* NOTE: For unknown reason, the pools are derived out-of-order here. */
/* It's worth eventually trying to understand why Nintendo made this choice. */
/* UNUSED: .Derive(6, 0); */
/* UNUSED: .Derive(6, 1); */
constexpr inline const auto KMemoryRegionType_VirtualDramAppletPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 2);
constexpr inline const auto KMemoryRegionType_VirtualDramApplicationPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 3);
constexpr inline const auto KMemoryRegionType_VirtualDramSystemNonSecurePool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 4);
constexpr inline const auto KMemoryRegionType_VirtualDramSystemPool = KMemoryRegionType_VirtualDramUserPool.Derive(6, 5);
static_assert(KMemoryRegionType_VirtualDramAppletPool .GetValue() == 0x1B1A);
static_assert(KMemoryRegionType_VirtualDramApplicationPool .GetValue() == 0x271A);
static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A);
static_assert(KMemoryRegionType_VirtualDramSystemPool .GetValue() == 0x331A);
constexpr inline const auto KMemoryRegionType_ArchDeviceBase = KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly();
constexpr inline const auto KMemoryRegionType_BoardDeviceBase = KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly();
static_assert(KMemoryRegionType_ArchDeviceBase .GetValue() == 0x5);
static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5);
#if defined(ATMOSPHERE_ARCH_ARM64)
#include <mesosphere/arch/arm64/kern_k_memory_region_device_types.inc>
#elif defined(ATMOSPHERE_ARCH_ARM)
#include <mesosphere/arch/arm/kern_k_memory_region_device_types.inc>
#else
/* Default to no architecture devices. */
constexpr inline const auto NumArchitectureDeviceRegions = 0;
#endif
static_assert(NumArchitectureDeviceRegions >= 0);
#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
#include <mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc>
#else
/* Default to no board devices. */
constexpr inline const auto NumBoardDeviceRegions = 0;
#endif
static_assert(NumBoardDeviceRegions >= 0);
constexpr inline const auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0);
constexpr inline const auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1);
constexpr inline const auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2);
constexpr inline const auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3);
static_assert(KMemoryRegionType_KernelCode .GetValue() == 0x19);
static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29);
static_assert(KMemoryRegionType_KernelMisc .GetValue() == 0x49);
static_assert(KMemoryRegionType_KernelSlab .GetValue() == 0x89);
constexpr inline const auto KMemoryRegionType_KernelMiscDerivedBase = KMemoryRegionType_KernelMisc.DeriveTransition();
static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149);
/* UNUSED: .Derive(7, 0); */
constexpr inline const auto KMemoryRegionType_KernelMiscMainStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
constexpr inline const auto KMemoryRegionType_KernelMiscMappedDevice = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
constexpr inline const auto KMemoryRegionType_KernelMiscIdleStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
constexpr inline const auto KMemoryRegionType_KernelMiscUnknownDebug = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
/* UNUSED: .Derive(7, 5); */
constexpr inline const auto KMemoryRegionType_KernelMiscExceptionStack = KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
static_assert(KMemoryRegionType_KernelMiscMainStack .GetValue() == 0xB49);
static_assert(KMemoryRegionType_KernelMiscMappedDevice .GetValue() == 0xD49);
static_assert(KMemoryRegionType_KernelMiscIdleStack .GetValue() == 0x1349);
static_assert(KMemoryRegionType_KernelMiscUnknownDebug .GetValue() == 0x1549);
static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x2349);
constexpr inline const auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
constexpr ALWAYS_INLINE KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) {
if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelTraceBuffer;
} else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
return KMemoryRegionType_VirtualDramKernelPtHeap;
} else {
return KMemoryRegionType_Dram;
}
}
}

View File

@@ -254,7 +254,7 @@ namespace ams::kern {
}
}
public:
static constexpr size_t CalculateMetadataOverheadSize(size_t region_size) {
static constexpr size_t CalculateManagementOverheadSize(size_t region_size) {
size_t overhead_bits = 0;
for (s32 depth = GetRequiredDepth(region_size) - 1; depth >= 0; depth--) {
region_size = util::AlignUp(region_size, BITSIZEOF(u64)) / BITSIZEOF(u64);

View File

@@ -115,11 +115,11 @@ namespace ams::kern {
return this->heap_address + (offset << this->GetShift());
}
public:
static constexpr size_t CalculateMetadataOverheadSize(size_t region_size, size_t cur_block_shift, size_t next_block_shift) {
static constexpr size_t CalculateManagementOverheadSize(size_t region_size, size_t cur_block_shift, size_t next_block_shift) {
const size_t cur_block_size = (u64(1) << cur_block_shift);
const size_t next_block_size = (u64(1) << next_block_shift);
const size_t align = (next_block_shift != 0) ? next_block_size : cur_block_size;
return KPageBitmap::CalculateMetadataOverheadSize((align * 2 + util::AlignUp(region_size, align)) / cur_block_size);
return KPageBitmap::CalculateManagementOverheadSize((align * 2 + util::AlignUp(region_size, align)) / cur_block_size);
}
};
private:
@@ -129,7 +129,7 @@ namespace ams::kern {
size_t num_blocks;
Block blocks[NumMemoryBlockPageShifts];
private:
void Initialize(KVirtualAddress heap_address, size_t heap_size, KVirtualAddress metadata_address, size_t metadata_size, const size_t *block_shifts, size_t num_block_shifts);
void Initialize(KVirtualAddress heap_address, size_t heap_size, KVirtualAddress management_address, size_t management_size, const size_t *block_shifts, size_t num_block_shifts);
size_t GetNumFreePages() const;
void FreeBlock(KVirtualAddress block, s32 index);
@@ -142,8 +142,8 @@ namespace ams::kern {
constexpr size_t GetPageOffset(KVirtualAddress block) const { return (block - this->GetAddress()) / PageSize; }
constexpr size_t GetPageOffsetToEnd(KVirtualAddress block) const { return (this->GetEndAddress() - block) / PageSize; }
void Initialize(KVirtualAddress heap_address, size_t heap_size, KVirtualAddress metadata_address, size_t metadata_size) {
return Initialize(heap_address, heap_size, metadata_address, metadata_size, MemoryBlockPageShifts, NumMemoryBlockPageShifts);
void Initialize(KVirtualAddress heap_address, size_t heap_size, KVirtualAddress management_address, size_t management_size) {
return Initialize(heap_address, heap_size, management_address, management_size, MemoryBlockPageShifts, NumMemoryBlockPageShifts);
}
size_t GetFreeSize() const { return this->GetNumFreePages() * PageSize; }
@@ -155,10 +155,10 @@ namespace ams::kern {
KVirtualAddress AllocateBlock(s32 index, bool random);
void Free(KVirtualAddress addr, size_t num_pages);
private:
static size_t CalculateMetadataOverheadSize(size_t region_size, const size_t *block_shifts, size_t num_block_shifts);
static size_t CalculateManagementOverheadSize(size_t region_size, const size_t *block_shifts, size_t num_block_shifts);
public:
static size_t CalculateMetadataOverheadSize(size_t region_size) {
return CalculateMetadataOverheadSize(region_size, MemoryBlockPageShifts, NumMemoryBlockPageShifts);
static size_t CalculateManagementOverheadSize(size_t region_size) {
return CalculateManagementOverheadSize(region_size, MemoryBlockPageShifts, NumMemoryBlockPageShifts);
}
};

View File

@@ -205,43 +205,43 @@ namespace ams::kern {
bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsLinearMappedPhysicalAddress(std::addressof(this->cached_physical_linear_region), phys_addr, this->cached_physical_linear_region);
return KMemoryLayout::IsLinearMappedPhysicalAddress(this->cached_physical_linear_region, phys_addr);
}
bool IsLinearMappedPhysicalAddress(KPhysicalAddress phys_addr, size_t size) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsLinearMappedPhysicalAddress(std::addressof(this->cached_physical_linear_region), phys_addr, size, this->cached_physical_linear_region);
return KMemoryLayout::IsLinearMappedPhysicalAddress(this->cached_physical_linear_region, phys_addr, size);
}
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapPhysicalAddress(std::addressof(this->cached_physical_heap_region), phys_addr, this->cached_physical_heap_region);
}
bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) {
MESOSPHERE_ASSERT(!this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapPhysicalAddress(std::addressof(this->cached_physical_heap_region), phys_addr, this->cached_physical_heap_region);
return KMemoryLayout::IsHeapPhysicalAddress(this->cached_physical_heap_region, phys_addr);
}
bool IsHeapPhysicalAddress(KPhysicalAddress phys_addr, size_t size) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapPhysicalAddress(std::addressof(this->cached_physical_heap_region), phys_addr, size, this->cached_physical_heap_region);
return KMemoryLayout::IsHeapPhysicalAddress(this->cached_physical_heap_region, phys_addr, size);
}
bool IsHeapPhysicalAddressForFinalize(KPhysicalAddress phys_addr) {
MESOSPHERE_ASSERT(!this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapPhysicalAddress(this->cached_physical_heap_region, phys_addr);
}
bool IsHeapVirtualAddress(KVirtualAddress virt_addr) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapVirtualAddress(std::addressof(this->cached_virtual_heap_region), virt_addr, this->cached_virtual_heap_region);
return KMemoryLayout::IsHeapVirtualAddress(this->cached_virtual_heap_region, virt_addr);
}
bool IsHeapVirtualAddress(KVirtualAddress virt_addr, size_t size) {
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
return KMemoryLayout::IsHeapVirtualAddress(std::addressof(this->cached_virtual_heap_region), virt_addr, size, this->cached_virtual_heap_region);
return KMemoryLayout::IsHeapVirtualAddress(this->cached_virtual_heap_region, virt_addr, size);
}
bool ContainsPages(KProcessAddress addr, size_t num_pages) const {

View File

@@ -44,7 +44,7 @@ namespace ams::kern {
constexpr KPort() : server(), client(), name(), state(State::Invalid), is_light() { /* ... */ }
virtual ~KPort() { /* ... */ }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
void Initialize(s32 max_sessions, bool is_light, uintptr_t name);
void OnClientClosed();

View File

@@ -123,6 +123,20 @@ namespace ams::kern {
void StartTermination();
void FinishTermination();
void PinThread(s32 core_id, KThread *thread) {
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
MESOSPHERE_ASSERT(thread != nullptr);
MESOSPHERE_ASSERT(this->pinned_threads[core_id] == nullptr);
this->pinned_threads[core_id] = thread;
}
void UnpinThread(s32 core_id, KThread *thread) {
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
MESOSPHERE_ASSERT(thread != nullptr);
MESOSPHERE_ASSERT(this->pinned_threads[core_id] == thread);
this->pinned_threads[core_id] = nullptr;
}
public:
KProcess() { /* ... */ }
virtual ~KProcess() { /* ... */ }
@@ -207,20 +221,6 @@ namespace ams::kern {
return this->pinned_threads[core_id];
}
void PinThread(s32 core_id, KThread *thread) {
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
MESOSPHERE_ASSERT(thread != nullptr);
MESOSPHERE_ASSERT(this->pinned_threads[core_id] == nullptr);
this->pinned_threads[core_id] = thread;
}
void UnpinThread(s32 core_id, KThread *thread) {
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
MESOSPHERE_ASSERT(thread != nullptr);
MESOSPHERE_ASSERT(this->pinned_threads[core_id] == thread);
this->pinned_threads[core_id] = nullptr;
}
void CopySvcPermissionsTo(KThread::StackParameters &sp) {
this->capabilities.CopySvcPermissionsTo(sp);
}
@@ -327,6 +327,7 @@ namespace ams::kern {
Result SetActivity(ams::svc::ProcessActivity activity);
void PinCurrentThread();
void UnpinCurrentThread();
Result SignalToAddress(KProcessAddress address) {
return this->cond_var.SignalToAddress(address);
@@ -358,6 +359,8 @@ namespace ams::kern {
static Result GetProcessList(s32 *out_num_processes, ams::kern::svc::KUserPointer<u64 *> out_process_ids, s32 max_out_count);
static void Switch(KProcess *cur_process, KProcess *next_process) {
MESOSPHERE_UNUSED(cur_process);
/* Set the current process pointer. */
SetCurrentProcess(next_process);
@@ -372,11 +375,11 @@ namespace ams::kern {
/* Overridden parent functions. */
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
virtual void Finalize() override;
virtual u64 GetId() const override { return this->GetProcessId(); }
virtual u64 GetId() const override final { return this->GetProcessId(); }
virtual bool IsSignaled() const override {
MESOSPHERE_ASSERT_THIS();

View File

@@ -35,7 +35,7 @@ namespace ams::kern {
constexpr ALWAYS_INLINE KResourceLimit() : limit_values(), current_values(), current_hints(), lock(), waiter_count(), cond_var() { /* ... */ }
virtual ~KResourceLimit() { /* ... */ }
static ALWAYS_INLINE void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
void Initialize();
virtual void Finalize() override;

View File

@@ -48,6 +48,7 @@ namespace ams::kern {
private:
friend class KScopedSchedulerLock;
friend class KScopedSchedulerLockAndSleep;
friend class KScopedDisableDispatch;
private:
SchedulingState state;
bool is_active;
@@ -76,7 +77,7 @@ namespace ams::kern {
}
ALWAYS_INLINE void RequestScheduleOnInterrupt() {
SetSchedulerUpdateNeeded();
this->state.needs_scheduling = true;
if (CanSchedule()) {
this->ScheduleOnInterrupt();
@@ -100,11 +101,7 @@ namespace ams::kern {
}
private:
/* Static private API. */
static ALWAYS_INLINE bool IsSchedulerUpdateNeeded() { return s_scheduler_update_needed; }
static ALWAYS_INLINE void SetSchedulerUpdateNeeded() { s_scheduler_update_needed = true; }
static ALWAYS_INLINE void ClearSchedulerUpdateNeeded() { s_scheduler_update_needed = false; }
static ALWAYS_INLINE KSchedulerPriorityQueue &GetPriorityQueue() { return s_priority_queue; }
static NOINLINE u64 UpdateHighestPriorityThreadsImpl();
static NOINLINE void InterruptTaskThreadToRunnable();
@@ -113,6 +110,10 @@ namespace ams::kern {
static ALWAYS_INLINE bool CanSchedule() { return GetCurrentThread().GetDisableDispatchCount() == 0; }
static ALWAYS_INLINE bool IsSchedulerLockedByCurrentThread() { return s_scheduler_lock.IsLockedByCurrentThread(); }
static ALWAYS_INLINE bool IsSchedulerUpdateNeeded() { return s_scheduler_update_needed; }
static ALWAYS_INLINE void SetSchedulerUpdateNeeded() { s_scheduler_update_needed = true; }
static ALWAYS_INLINE void ClearSchedulerUpdateNeeded() { s_scheduler_update_needed = false; }
static ALWAYS_INLINE void DisableScheduling() {
MESOSPHERE_ASSERT(GetCurrentThread().GetDisableDispatchCount() >= 0);
GetCurrentThread().DisableDispatch();
@@ -139,9 +140,6 @@ namespace ams::kern {
static NOINLINE void ClearPreviousThread(KThread *thread);
static NOINLINE void PinCurrentThread(KProcess *cur_process);
static NOINLINE void UnpinCurrentThread(KProcess *cur_process);
static NOINLINE void OnThreadStateChanged(KThread *thread, KThread::ThreadState old_state);
static NOINLINE void OnThreadPriorityChanged(KThread *thread, s32 old_priority);
static NOINLINE void OnThreadAffinityMaskChanged(KThread *thread, const KAffinityMask &old_affinity, s32 old_core);
@@ -164,8 +162,9 @@ namespace ams::kern {
}
ALWAYS_INLINE void ScheduleOnInterrupt() {
KScopedDisableDispatch dd;
GetCurrentThread().DisableDispatch();
this->Schedule();
GetCurrentThread().EnableDispatch();
}
void RescheduleOtherCores(u64 cores_needing_scheduling);

View File

@@ -174,7 +174,7 @@ namespace ams::kern {
}
}
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
constexpr KThread *GetThread() const { return this->thread; }
constexpr KWritableEvent *GetEvent() const { return this->event; }

View File

@@ -47,7 +47,7 @@ namespace ams::kern {
virtual void Finalize() override;
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ }
Result Map(KProcessPageTable *table, KProcessAddress address, size_t size, KProcess *process, ams::svc::MemoryPermission map_perm);
Result Unmap(KProcessPageTable *table, KProcessAddress address, size_t size, KProcess *process);

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