mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-23 04:12:02 +00:00
mariko fatal: map 0xC0000000 for framebuffer usage
This commit is contained in:
parent
898fe61034
commit
a2c89a8f3f
6 changed files with 102 additions and 24 deletions
|
@ -48,16 +48,21 @@ namespace ams::secmon::fatal {
|
||||||
|
|
||||||
constexpr size_t TableCount = (1ul << DeviceVirtualAddressBits) / DeviceRegionSize;
|
constexpr size_t TableCount = (1ul << DeviceVirtualAddressBits) / DeviceRegionSize;
|
||||||
|
|
||||||
constexpr u8 SdmmcAsid = 1;
|
consteval u32 EncodeAsidRegisterValue(u8 asid) {
|
||||||
|
|
||||||
constexpr u32 SdmmcAsidRegisterValue = [] {
|
|
||||||
u32 value = 0x80000000u;
|
u32 value = 0x80000000u;
|
||||||
for (size_t t = 0; t < TableCount; t++) {
|
for (size_t t = 0; t < TableCount; t++) {
|
||||||
value |= (SdmmcAsid << (BITSIZEOF(u8) * t));
|
value |= (asid << (BITSIZEOF(u8) * t));
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}();
|
}
|
||||||
|
|
||||||
|
constexpr u8 SdmmcAsid = 1;
|
||||||
|
constexpr u8 DcAsid = 2;
|
||||||
|
|
||||||
|
constexpr u32 SdmmcAsidRegisterValue = EncodeAsidRegisterValue(SdmmcAsid);
|
||||||
|
constexpr u32 DcAsidRegisterValue = EncodeAsidRegisterValue(DcAsid);
|
||||||
|
|
||||||
|
constexpr dd::PhysicalAddress DcL0PageTablePhysical = MemoryRegionPhysicalDramDcL0DevicePageTable.GetAddress();
|
||||||
constexpr dd::PhysicalAddress SdmmcL0PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L0DevicePageTable.GetAddress();
|
constexpr dd::PhysicalAddress SdmmcL0PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L0DevicePageTable.GetAddress();
|
||||||
constexpr dd::PhysicalAddress SdmmcL1PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L1DevicePageTable.GetAddress();
|
constexpr dd::PhysicalAddress SdmmcL1PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L1DevicePageTable.GetAddress();
|
||||||
|
|
||||||
|
@ -195,7 +200,11 @@ namespace ams::secmon::fatal {
|
||||||
SmmuSynchronizationBarrier();
|
SmmuSynchronizationBarrier();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapImpl(dd::PhysicalAddress phys_addr, size_t size, DeviceVirtualAddress address) {
|
void MapImpl(dd::PhysicalAddress phys_addr, size_t size, DeviceVirtualAddress address, u8 asid, void *l0_table, dd::PhysicalAddress l0_phys, void *l1_table, dd::PhysicalAddress l1_phys) {
|
||||||
|
/* Validate L0. */
|
||||||
|
AMS_ABORT_UNLESS(l0_table != nullptr);
|
||||||
|
AMS_ABORT_UNLESS(l0_phys != 0);
|
||||||
|
|
||||||
/* Cache permissions. */
|
/* Cache permissions. */
|
||||||
const bool read = true;
|
const bool read = true;
|
||||||
const bool write = true;
|
const bool write = true;
|
||||||
|
@ -207,7 +216,7 @@ namespace ams::secmon::fatal {
|
||||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||||
|
|
||||||
/* Get and validate l1. */
|
/* Get and validate l1. */
|
||||||
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>());
|
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(l0_table);
|
||||||
AMS_ASSERT(l1 != nullptr);
|
AMS_ASSERT(l1 != nullptr);
|
||||||
|
|
||||||
/* Setup an l1 table/entry, if needed. */
|
/* Setup an l1 table/entry, if needed. */
|
||||||
|
@ -222,8 +231,8 @@ namespace ams::secmon::fatal {
|
||||||
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||||
|
|
||||||
/* Synchronize. */
|
/* Synchronize. */
|
||||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
|
||||||
InvalidateTlbSection(SdmmcAsid, address);
|
InvalidateTlbSection(asid, address);
|
||||||
SmmuSynchronizationBarrier();
|
SmmuSynchronizationBarrier();
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
|
@ -233,26 +242,32 @@ namespace ams::secmon::fatal {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* Make an l1 table. */
|
/* Make an l1 table. */
|
||||||
std::memset(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
|
AMS_ABORT_UNLESS(l1_table != nullptr);
|
||||||
hw::FlushDataCache(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), mmu::PageSize);
|
AMS_ABORT_UNLESS(l1_phys != 0);
|
||||||
|
|
||||||
|
/* Clear the l1 table. */
|
||||||
|
std::memset(l1_table, 0, mmu::PageSize);
|
||||||
|
hw::FlushDataCache(l1_table, mmu::PageSize);
|
||||||
|
|
||||||
/* Set the l1 table. */
|
/* Set the l1 table. */
|
||||||
l1[l1_index].SetTable(true, true, true, SdmmcL1PageTablePhysical);
|
l1[l1_index].SetTable(true, true, true, l1_phys);
|
||||||
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||||
|
|
||||||
/* Synchronize. */
|
/* Synchronize. */
|
||||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
|
||||||
InvalidateTlbSection(SdmmcAsid, address);
|
InvalidateTlbSection(asid, address);
|
||||||
SmmuSynchronizationBarrier();
|
SmmuSynchronizationBarrier();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we get to this point, l1 must be a table. */
|
/* If we get to this point, l1 must be a table. */
|
||||||
AMS_ASSERT(l1[l1_index].IsTable());
|
AMS_ASSERT(l1[l1_index].IsTable());
|
||||||
|
AMS_ABORT_UNLESS(l1_table != nullptr);
|
||||||
|
AMS_ABORT_UNLESS(l1_phys != 0);
|
||||||
|
|
||||||
/* Map l2 entries. */
|
/* Map l2 entries. */
|
||||||
{
|
{
|
||||||
PageTableEntry *l2 = static_cast<PageTableEntry *>(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>());
|
PageTableEntry *l2 = static_cast<PageTableEntry *>(l1_table);
|
||||||
|
|
||||||
const size_t remaining_in_entry = (PageTableSize / sizeof(PageTableEntry)) - l2_index;
|
const size_t remaining_in_entry = (PageTableSize / sizeof(PageTableEntry)) - l2_index;
|
||||||
const size_t map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
|
const size_t map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
|
||||||
|
@ -266,11 +281,11 @@ namespace ams::secmon::fatal {
|
||||||
|
|
||||||
/* Invalidate the page table cache. */
|
/* Invalidate the page table cache. */
|
||||||
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
|
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
|
||||||
InvalidatePtc(SdmmcL1PageTablePhysical + i * sizeof(PageTableEntry));
|
InvalidatePtc(l1_phys + i * sizeof(PageTableEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Synchronize. */
|
/* Synchronize. */
|
||||||
InvalidateTlbSection(SdmmcAsid, address);
|
InvalidateTlbSection(asid, address);
|
||||||
SmmuSynchronizationBarrier();
|
SmmuSynchronizationBarrier();
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
|
@ -301,7 +316,37 @@ namespace ams::secmon::fatal {
|
||||||
SetTable(SdmmcAsid, SdmmcL0PageTablePhysical);
|
SetTable(SdmmcAsid, SdmmcL0PageTablePhysical);
|
||||||
|
|
||||||
/* Map the appropriate region into the asid. */
|
/* Map the appropriate region into the asid. */
|
||||||
MapImpl(MemoryRegionPhysicalDramSdmmcMappedData.GetAddress(), MemoryRegionPhysicalDramSdmmcMappedData.GetSize(), MemoryRegionVirtualDramSdmmcMappedData.GetAddress());
|
MapImpl(MemoryRegionPhysicalDramSdmmcMappedData.GetAddress(), MemoryRegionPhysicalDramSdmmcMappedData.GetSize(), MemoryRegionVirtualDramSdmmcMappedData.GetAddress(),
|
||||||
|
SdmmcAsid,
|
||||||
|
MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), SdmmcL0PageTablePhysical,
|
||||||
|
MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), SdmmcL1PageTablePhysical);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitializeDevicePageTableForDc() {
|
||||||
|
/* Configure dc to use our new page table. */
|
||||||
|
WriteMcRegister(MC_SMMU_DC_ASID, DcAsidRegisterValue);
|
||||||
|
SmmuSynchronizationBarrier();
|
||||||
|
|
||||||
|
/* Ensure consistency. */
|
||||||
|
InvalidatePtc();
|
||||||
|
InvalidateTlb();
|
||||||
|
SmmuSynchronizationBarrier();
|
||||||
|
|
||||||
|
/* Clear the L0 Page Table. */
|
||||||
|
std::memset(MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
|
||||||
|
hw::FlushDataCache(MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), mmu::PageSize);
|
||||||
|
|
||||||
|
/* Set the page table for the dc asid. */
|
||||||
|
SetTable(DcAsid, DcL0PageTablePhysical);
|
||||||
|
|
||||||
|
/* Map the appropriate region into the asid. */
|
||||||
|
static_assert(util::IsAligned(MemoryRegionDramDcFramebuffer.GetAddress(), DeviceLargePageSize));
|
||||||
|
static_assert(util::IsAligned(MemoryRegionDramDcFramebuffer.GetSize(), DeviceLargePageSize));
|
||||||
|
|
||||||
|
MapImpl(MemoryRegionDramDcFramebuffer.GetAddress(), MemoryRegionDramDcFramebuffer.GetSize(), MemoryRegionDramDcFramebuffer.GetAddress(),
|
||||||
|
DcAsid,
|
||||||
|
MemoryRegionVirtualDramDcL0DevicePageTable.GetPointer<void>(), DcL0PageTablePhysical,
|
||||||
|
nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,6 @@
|
||||||
namespace ams::secmon::fatal {
|
namespace ams::secmon::fatal {
|
||||||
|
|
||||||
void InitializeDevicePageTableForSdmmc1();
|
void InitializeDevicePageTableForSdmmc1();
|
||||||
|
void InitializeDevicePageTableForDc();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,12 @@ namespace ams::secmon {
|
||||||
InvalidateL3Entries(l3, MemoryRegionVirtualAtmosphereUserPage.GetAddress(), MemoryRegionVirtualAtmosphereUserPage.GetSize());
|
InvalidateL3Entries(l3, MemoryRegionVirtualAtmosphereUserPage.GetAddress(), MemoryRegionVirtualAtmosphereUserPage.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr void MapDramForMarikoProgramImpl(u64 *l1, u64 *l2, u64 *l3) {
|
||||||
|
/* Map the L1 entry corresponding to the mariko program dram entry. */
|
||||||
|
AMS_UNUSED(l2, l3);
|
||||||
|
SetL1BlockEntry(l1, MemoryRegionDramForMarikoProgram.GetAddress(), MemoryRegionDramForMarikoProgram.GetAddress(), MemoryRegionDramForMarikoProgram.GetSize(), MappingAttributesEl3NonSecureRwData);
|
||||||
|
}
|
||||||
|
|
||||||
void ClearLow(uintptr_t address, size_t size) {
|
void ClearLow(uintptr_t address, size_t size) {
|
||||||
/* Clear the low part. */
|
/* Clear the low part. */
|
||||||
util::ClearMemory(reinterpret_cast<void *>(address), size / 2);
|
util::ClearMemory(reinterpret_cast<void *>(address), size / 2);
|
||||||
|
@ -301,4 +307,16 @@ namespace ams::secmon {
|
||||||
ReleaseSpinLock(g_ams_user_page_spin_lock);
|
ReleaseSpinLock(g_ams_user_page_spin_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapDramForMarikoProgram() {
|
||||||
|
/* Get the tables. */
|
||||||
|
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
|
||||||
|
u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer<u64>();
|
||||||
|
|
||||||
|
/* Map. */
|
||||||
|
MapDramForMarikoProgramImpl(l1, l2_l3, l2_l3);
|
||||||
|
|
||||||
|
/* Ensure the mappings are consistent. */
|
||||||
|
secmon::EnsureMappingConsistency();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,4 +32,6 @@ namespace ams::secmon {
|
||||||
uintptr_t MapAtmosphereUserPage(uintptr_t address);
|
uintptr_t MapAtmosphereUserPage(uintptr_t address);
|
||||||
void UnmapAtmosphereUserPage();
|
void UnmapAtmosphereUserPage();
|
||||||
|
|
||||||
|
void MapDramForMarikoProgram();
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,6 +14,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <exosphere.hpp>
|
#include <exosphere.hpp>
|
||||||
|
#include "secmon_map.hpp"
|
||||||
#include "secmon_page_mapper.hpp"
|
#include "secmon_page_mapper.hpp"
|
||||||
#include "secmon_user_power_management.hpp"
|
#include "secmon_user_power_management.hpp"
|
||||||
|
|
||||||
|
@ -93,6 +94,9 @@ namespace ams::secmon {
|
||||||
|
|
||||||
/* TODO: On cores other than 3, halt/wfi. */
|
/* TODO: On cores other than 3, halt/wfi. */
|
||||||
|
|
||||||
|
/* Map Dram for the mariko program. */
|
||||||
|
MapDramForMarikoProgram();
|
||||||
|
|
||||||
AMS_SECMON_LOG("%s\n", "Jumping to Mariko Fatal.");
|
AMS_SECMON_LOG("%s\n", "Jumping to Mariko Fatal.");
|
||||||
AMS_LOG_FLUSH();
|
AMS_LOG_FLUSH();
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,11 @@ namespace ams::secmon {
|
||||||
constexpr inline const MemoryRegion MemoryRegionDram = MemoryRegion(UINT64_C( 0x80000000), 2_GB);
|
constexpr inline const MemoryRegion MemoryRegionDram = MemoryRegion(UINT64_C( 0x80000000), 2_GB);
|
||||||
constexpr inline const MemoryRegion MemoryRegionDramHigh = MemoryRegion(MemoryRegionDram.GetEndAddress(), 2_GB);
|
constexpr inline const MemoryRegion MemoryRegionDramHigh = MemoryRegion(MemoryRegionDram.GetEndAddress(), 2_GB);
|
||||||
|
|
||||||
|
constexpr inline const MemoryRegion MemoryRegionDramForMarikoProgram = MemoryRegion(UINT64_C(0xC0000000), 1_GB);
|
||||||
|
constexpr inline const MemoryRegion MemoryRegionDramDcFramebuffer = MemoryRegion(UINT64_C(0xC0000000), 4_MB);
|
||||||
|
static_assert(MemoryRegionDram.Contains(MemoryRegionDramForMarikoProgram));
|
||||||
|
static_assert(MemoryRegionDramForMarikoProgram.Contains(MemoryRegionDramDcFramebuffer));
|
||||||
|
|
||||||
constexpr inline const MemoryRegion MemoryRegionDramGpuCarveout = MemoryRegion(UINT64_C(0x80020000), UINT64_C(0x40000));
|
constexpr inline const MemoryRegion MemoryRegionDramGpuCarveout = MemoryRegion(UINT64_C(0x80020000), UINT64_C(0x40000));
|
||||||
static_assert(MemoryRegionDram.Contains(MemoryRegionDramGpuCarveout));
|
static_assert(MemoryRegionDram.Contains(MemoryRegionDramGpuCarveout));
|
||||||
|
|
||||||
|
@ -259,14 +264,17 @@ namespace ams::secmon {
|
||||||
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualDramSecureDataStore));
|
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualDramSecureDataStore));
|
||||||
static_assert(MemoryRegionDram.Contains(MemoryRegionPhysicalDramSecureDataStore));
|
static_assert(MemoryRegionDram.Contains(MemoryRegionPhysicalDramSecureDataStore));
|
||||||
|
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L0DevicePageTable = MemoryRegion(UINT64_C(0x1F010F000), 0x1000);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmcMappedData = MemoryRegion(UINT64_C(0x1F0100000), 0xC000);
|
||||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L0DevicePageTable = MemoryRegion( UINT64_C(0x8001F000), 0x1000);
|
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmcMappedData = MemoryRegion(UINT64_C(0x80010000), 0xC000);
|
||||||
|
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L1DevicePageTable = MemoryRegion(UINT64_C(0x1F010E000), 0x1000);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramDcL0DevicePageTable = MemoryRegion(UINT64_C(0x1F010C000), 0x1000);
|
||||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L1DevicePageTable = MemoryRegion( UINT64_C(0x8001E000), 0x1000);
|
constexpr inline const MemoryRegion MemoryRegionPhysicalDramDcL0DevicePageTable = MemoryRegion( UINT64_C(0x8001C000), 0x1000);
|
||||||
|
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmcMappedData = MemoryRegion(UINT64_C(0x1F0100000), 0xE000);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L0DevicePageTable = MemoryRegion(UINT64_C(0x1F010E000), 0x1000);
|
||||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmcMappedData = MemoryRegion(UINT64_C(0x80010000), 0xE000);
|
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L0DevicePageTable = MemoryRegion( UINT64_C(0x8001E000), 0x1000);
|
||||||
|
|
||||||
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L1DevicePageTable = MemoryRegion(UINT64_C(0x1F010F000), 0x1000);
|
||||||
|
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L1DevicePageTable = MemoryRegion( UINT64_C(0x8001F000), 0x1000);
|
||||||
|
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreTzram = MemoryRegion(UINT64_C(0x1F0100000), 0xE000);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreTzram = MemoryRegion(UINT64_C(0x1F0100000), 0xE000);
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware = MemoryRegion(UINT64_C(0x1F010E000), 0x17C0);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware = MemoryRegion(UINT64_C(0x1F010E000), 0x17C0);
|
||||||
|
|
Loading…
Reference in a new issue