mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +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 u8 SdmmcAsid = 1;
|
||||
|
||||
constexpr u32 SdmmcAsidRegisterValue = [] {
|
||||
consteval u32 EncodeAsidRegisterValue(u8 asid) {
|
||||
u32 value = 0x80000000u;
|
||||
for (size_t t = 0; t < TableCount; t++) {
|
||||
value |= (SdmmcAsid << (BITSIZEOF(u8) * t));
|
||||
value |= (asid << (BITSIZEOF(u8) * t));
|
||||
}
|
||||
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 SdmmcL1PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L1DevicePageTable.GetAddress();
|
||||
|
||||
|
@ -195,7 +200,11 @@ namespace ams::secmon::fatal {
|
|||
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. */
|
||||
const bool read = true;
|
||||
const bool write = true;
|
||||
|
@ -207,7 +216,7 @@ namespace ams::secmon::fatal {
|
|||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
/* Get and validate l1. */
|
||||
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>());
|
||||
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(l0_table);
|
||||
AMS_ASSERT(l1 != nullptr);
|
||||
|
||||
/* Setup an l1 table/entry, if needed. */
|
||||
|
@ -222,8 +231,8 @@ namespace ams::secmon::fatal {
|
|||
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
|
||||
InvalidateTlbSection(asid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Advance. */
|
||||
|
@ -233,26 +242,32 @@ namespace ams::secmon::fatal {
|
|||
continue;
|
||||
} else {
|
||||
/* Make an l1 table. */
|
||||
std::memset(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
|
||||
hw::FlushDataCache(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), mmu::PageSize);
|
||||
AMS_ABORT_UNLESS(l1_table != nullptr);
|
||||
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. */
|
||||
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));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
InvalidatePtc(l0_phys + l1_index * sizeof(PageDirectoryEntry));
|
||||
InvalidateTlbSection(asid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get to this point, l1 must be a table. */
|
||||
AMS_ASSERT(l1[l1_index].IsTable());
|
||||
AMS_ABORT_UNLESS(l1_table != nullptr);
|
||||
AMS_ABORT_UNLESS(l1_phys != 0);
|
||||
|
||||
/* 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 map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
|
||||
|
@ -266,11 +281,11 @@ namespace ams::secmon::fatal {
|
|||
|
||||
/* 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) {
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical + i * sizeof(PageTableEntry));
|
||||
InvalidatePtc(l1_phys + i * sizeof(PageTableEntry));
|
||||
}
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
InvalidateTlbSection(asid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Advance. */
|
||||
|
@ -301,7 +316,37 @@ namespace ams::secmon::fatal {
|
|||
SetTable(SdmmcAsid, SdmmcL0PageTablePhysical);
|
||||
|
||||
/* 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 {
|
||||
|
||||
void InitializeDevicePageTableForSdmmc1();
|
||||
void InitializeDevicePageTableForDc();
|
||||
|
||||
}
|
||||
|
|
|
@ -86,6 +86,12 @@ namespace ams::secmon {
|
|||
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) {
|
||||
/* Clear the low part. */
|
||||
util::ClearMemory(reinterpret_cast<void *>(address), size / 2);
|
||||
|
@ -301,4 +307,16 @@ namespace ams::secmon {
|
|||
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);
|
||||
void UnmapAtmosphereUserPage();
|
||||
|
||||
void MapDramForMarikoProgram();
|
||||
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#include "secmon_map.hpp"
|
||||
#include "secmon_page_mapper.hpp"
|
||||
#include "secmon_user_power_management.hpp"
|
||||
|
||||
|
@ -93,6 +94,9 @@ namespace ams::secmon {
|
|||
|
||||
/* 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_LOG_FLUSH();
|
||||
|
||||
|
|
|
@ -75,6 +75,11 @@ namespace ams::secmon {
|
|||
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 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));
|
||||
static_assert(MemoryRegionDram.Contains(MemoryRegionDramGpuCarveout));
|
||||
|
||||
|
@ -259,14 +264,17 @@ namespace ams::secmon {
|
|||
static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualDramSecureDataStore));
|
||||
static_assert(MemoryRegionDram.Contains(MemoryRegionPhysicalDramSecureDataStore));
|
||||
|
||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L0DevicePageTable = MemoryRegion(UINT64_C(0x1F010F000), 0x1000);
|
||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L0DevicePageTable = MemoryRegion( UINT64_C(0x8001F000), 0x1000);
|
||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmcMappedData = MemoryRegion(UINT64_C(0x1F0100000), 0xC000);
|
||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmcMappedData = MemoryRegion(UINT64_C(0x80010000), 0xC000);
|
||||
|
||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L1DevicePageTable = MemoryRegion(UINT64_C(0x1F010E000), 0x1000);
|
||||
constexpr inline const MemoryRegion MemoryRegionPhysicalDramSdmmc1L1DevicePageTable = MemoryRegion( UINT64_C(0x8001E000), 0x1000);
|
||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramDcL0DevicePageTable = MemoryRegion(UINT64_C(0x1F010C000), 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 MemoryRegionPhysicalDramSdmmcMappedData = MemoryRegion(UINT64_C(0x80010000), 0xE000);
|
||||
constexpr inline const MemoryRegion MemoryRegionVirtualDramSdmmc1L0DevicePageTable = MemoryRegion(UINT64_C(0x1F010E000), 0x1000);
|
||||
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 MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware = MemoryRegion(UINT64_C(0x1F010E000), 0x17C0);
|
||||
|
|
Loading…
Reference in a new issue