kern: implement smmu init

This commit is contained in:
Michael Scire 2020-02-15 00:00:35 -08:00
parent 2c496e94d5
commit 30d6b359f9
21 changed files with 1368 additions and 36 deletions

View file

@ -16,6 +16,7 @@
#pragma once
#include <vapours.hpp>
#include <mesosphere/arch/arm64/kern_cpu_system_registers.hpp>
#include <mesosphere/arch/arm64/kern_userspace_memory_access.hpp>
namespace ams::kern::arch::arm64::cpu {
@ -156,6 +157,11 @@ namespace ams::kern::arch::arm64::cpu {
void FlushEntireDataCacheSharedForInit();
void FlushEntireDataCacheLocalForInit();
Result InvalidateDataCache(void *addr, size_t size);
Result StoreDataCache(const void *addr, size_t size);
Result FlushDataCache(const void *addr, size_t size);
Result InvalidateInstructionCache(void *addr, size_t size);
ALWAYS_INLINE void ClearPageToZero(void *page) {
MESOSPHERE_ASSERT(util::IsAligned(reinterpret_cast<uintptr_t>(page), PageSize));
MESOSPHERE_ASSERT(page != nullptr);

View file

@ -20,6 +20,11 @@ namespace ams::kern::arch::arm64 {
void UserspaceMemoryAccessFunctionAreaBegin();
bool StoreDataCache(uintptr_t start, uintptr_t end);
bool FlushDataCache(uintptr_t start, uintptr_t end);
bool InvalidateDataCache(uintptr_t start, uintptr_t end);
bool InvalidateInstructionCache(uintptr_t start, uintptr_t end);
void UserspaceMemoryAccessFunctionAreaEnd();
}

View file

@ -0,0 +1,59 @@
/*
* 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::nintendo::nx {
using KDeviceVirtualAddress = u64;
class KDevicePageTable {
private:
static constexpr size_t TableCount = 4;
private:
KVirtualAddress tables[TableCount];
u8 table_asids[TableCount];
u64 attached_device;
u32 attached_value;
u32 detached_value;
u32 hs_attached_value;
u32 hs_detached_value;
private:
static ALWAYS_INLINE KVirtualAddress GetHeapVirtualAddress(KPhysicalAddress addr) {
return KPageTable::GetHeapVirtualAddress(addr);
}
static ALWAYS_INLINE KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) {
return KPageTable::GetHeapPhysicalAddress(addr);
}
static ALWAYS_INLINE KVirtualAddress GetPageTableVirtualAddress(KPhysicalAddress addr) {
return KPageTable::GetPageTableVirtualAddress(addr);
}
static ALWAYS_INLINE KPhysicalAddress GetPageTablePhysicalAddress(KVirtualAddress addr) {
return KPageTable::GetPageTablePhysicalAddress(addr);
}
public:
constexpr KDevicePageTable() : tables(), table_asids(), attached_device(), attached_value(), detached_value(), hs_attached_value(), hs_detached_value() { /* ... */ }
static void Initialize();
};
}

View file

@ -45,6 +45,21 @@ namespace ams::kern::board::nintendo::nx {
static void GenerateRandomBytes(void *dst, size_t size);
static u64 GenerateRandomRange(u64 min, u64 max);
/* Privileged Access. */
static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
static void ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
static ALWAYS_INLINE u32 ReadRegisterPrivileged(ams::svc::PhysicalAddress address) {
u32 v;
ReadWriteRegisterPrivileged(std::addressof(v), address, 0x00000000u, 0);
return v;
}
static ALWAYS_INLINE void WriteRegisterPrivileged(ams::svc::PhysicalAddress address, u32 value) {
u32 v;
ReadWriteRegisterPrivileged(std::addressof(v), address, 0xFFFFFFFFu, value);
}
/* Power management. */
static void SleepSystem();
static NORETURN void StopSystem();

View file

@ -17,12 +17,15 @@
#include <mesosphere/kern_common.hpp>
#include <mesosphere/kern_k_auto_object.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_select_device_page_table.hpp>
namespace ams::kern {
class KDeviceAddressSpace final : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> {
MESOSPHERE_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject);
public:
static void Initialize();
/* TODO: This is a placeholder definition. */
};

View file

@ -463,6 +463,10 @@ namespace ams::kern {
return GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_Uart)->GetPairAddress();
}
static NOINLINE KMemoryRegion &GetMemoryControllerRegion() {
return *GetPhysicalMemoryRegionTree().FindFirstDerivedRegion(KMemoryRegionType_MemoryController);
}
static NOINLINE KMemoryRegion &GetMetadataPoolRegion() {
return *GetVirtualMemoryRegionTree().FindFirstRegionByType(KMemoryRegionType_VirtualDramMetadataPool);
}

View file

@ -216,6 +216,10 @@ namespace ams::kern {
return GetLinearVirtualAddress(addr);
}
static ALWAYS_INLINE KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress addr) {
return GetLinearPhysicalAddress(addr);
}
static ALWAYS_INLINE KVirtualAddress GetPageTableVirtualAddress(KPhysicalAddress addr) {
return GetLinearVirtualAddress(addr);
}

View file

@ -33,6 +33,8 @@ namespace ams::kern {
class KPageTableManager : public KDynamicSlabHeap<impl::PageTablePage> {
public:
using RefCount = u16;
static constexpr size_t PageTableSize = sizeof(impl::PageTablePage);
static_assert(PageTableSize == PageSize);
private:
using BaseHeap = KDynamicSlabHeap<impl::PageTablePage>;
private:

View file

@ -231,6 +231,9 @@ namespace ams::kern {
this->GetStackParameters().disable_count--;
}
NOINLINE void DisableCoreMigration();
NOINLINE void EnableCoreMigration();
ALWAYS_INLINE void SetInExceptionHandler() {
MESOSPHERE_ASSERT_THIS();
this->GetStackParameters().is_in_exception_handler = true;

View file

@ -0,0 +1,28 @@
/*
* 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>
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
#include <mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp>
namespace ams::kern {
using ams::kern::board::nintendo::nx::KDevicePageTable;
}
#else
#error "Unknown board for KDevicePageTable"
#endif