mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-05 01:03:43 -04:00
kern: implement process(pagetable) init
This commit is contained in:
parent
fba8fb539d
commit
05a3e95834
16 changed files with 502 additions and 24 deletions
|
@ -17,6 +17,85 @@
|
|||
|
||||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u64 EncodeTtbr(KPhysicalAddress table, u8 asid) {
|
||||
return (static_cast<u64>(asid) << 48) | (static_cast<u64>(GetInteger(table)));
|
||||
}
|
||||
|
||||
class KPageTableAsidManager {
|
||||
private:
|
||||
using WordType = u32;
|
||||
static constexpr u8 ReservedAsids[] = { 0 };
|
||||
static constexpr size_t NumReservedAsids = util::size(ReservedAsids);
|
||||
static constexpr size_t BitsPerWord = BITSIZEOF(WordType);
|
||||
static constexpr size_t AsidCount = 0x100;
|
||||
static constexpr size_t NumWords = AsidCount / BitsPerWord;
|
||||
static constexpr WordType FullWord = ~WordType(0u);
|
||||
private:
|
||||
WordType state[NumWords];
|
||||
KLightLock lock;
|
||||
u8 hint;
|
||||
private:
|
||||
constexpr bool TestImpl(u8 asid) const {
|
||||
return this->state[asid / BitsPerWord] & (1u << (asid % BitsPerWord));
|
||||
}
|
||||
constexpr void ReserveImpl(u8 asid) {
|
||||
MESOSPHERE_ASSERT(!this->TestImpl(asid));
|
||||
this->state[asid / BitsPerWord] |= (1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
constexpr void ReleaseImpl(u8 asid) {
|
||||
MESOSPHERE_ASSERT(this->TestImpl(asid));
|
||||
this->state[asid / BitsPerWord] &= ~(1u << (asid % BitsPerWord));
|
||||
}
|
||||
|
||||
constexpr u8 FindAvailable() const {
|
||||
for (size_t i = 0; i < util::size(this->state); i++) {
|
||||
if (this->state[i] == FullWord) {
|
||||
continue;
|
||||
}
|
||||
const WordType clear_bit = (this->state[i] + 1) ^ (this->state[i]);
|
||||
return BitsPerWord * i + BitsPerWord - 1 - ClearLeadingZero(clear_bit);
|
||||
}
|
||||
if (this->state[util::size(this->state)-1] == FullWord) {
|
||||
MESOSPHERE_PANIC("Unable to reserve ASID");
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE WordType ClearLeadingZero(WordType value) {
|
||||
return __builtin_clzll(value) - (BITSIZEOF(unsigned long long) - BITSIZEOF(WordType));
|
||||
}
|
||||
public:
|
||||
constexpr KPageTableAsidManager() : state(), lock(), hint() {
|
||||
for (size_t i = 0; i < NumReservedAsids; i++) {
|
||||
this->ReserveImpl(ReservedAsids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
u8 Reserve() {
|
||||
KScopedLightLock lk(this->lock);
|
||||
|
||||
if (this->TestImpl(this->hint)) {
|
||||
this->hint = this->FindAvailable();
|
||||
}
|
||||
|
||||
this->ReserveImpl(this->hint);
|
||||
|
||||
return this->hint++;
|
||||
}
|
||||
|
||||
void Release(u8 asid) {
|
||||
KScopedLightLock lk(this->lock);
|
||||
this->ReleaseImpl(asid);
|
||||
}
|
||||
};
|
||||
|
||||
KPageTableAsidManager g_asid_manager;
|
||||
|
||||
}
|
||||
|
||||
void KPageTable::Initialize(s32 core_id) {
|
||||
/* Nothing actually needed here. */
|
||||
}
|
||||
|
@ -39,6 +118,37 @@ namespace ams::kern::arch::arm64 {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KPageTable::InitializeForProcess(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
||||
/* Convert the address space type to a width. */
|
||||
|
||||
/* Get an ASID */
|
||||
this->asid = g_asid_manager.Reserve();
|
||||
auto asid_guard = SCOPE_GUARD { g_asid_manager.Release(this->asid); };
|
||||
|
||||
/* Set our manager. */
|
||||
this->manager = pt_manager;
|
||||
|
||||
/* Allocate a new table, and set our ttbr value. */
|
||||
const KVirtualAddress new_table = this->manager->Allocate();
|
||||
R_UNLESS(new_table != Null<KVirtualAddress>, svc::ResultOutOfResource());
|
||||
this->ttbr = EncodeTtbr(GetPageTablePhysicalAddress(new_table), asid);
|
||||
auto table_guard = SCOPE_GUARD { this->manager->Free(new_table); };
|
||||
|
||||
/* Initialize our base table. */
|
||||
const size_t as_width = GetAddressSpaceWidth(as_type);
|
||||
const KProcessAddress as_start = 0;
|
||||
const KProcessAddress as_end = (1ul << as_width);
|
||||
R_TRY(KPageTableBase::InitializeForProcess(as_type, enable_aslr, from_back, pool, GetVoidPointer(new_table), as_start, as_end, code_address, code_size, mem_block_slab_manager, block_info_manager));
|
||||
|
||||
/* We succeeded! */
|
||||
table_guard.Cancel();
|
||||
asid_guard.Cancel();
|
||||
|
||||
/* Note that we've updated the table (since we created it). */
|
||||
this->NoteUpdated();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KPageTable::Finalize() {
|
||||
MESOSPHERE_TODO_IMPLEMENT();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,12 @@ namespace ams::kern::arch::arm64 {
|
|||
this->num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
}
|
||||
|
||||
void KPageTableImpl::InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end) {
|
||||
this->table = static_cast<L1PageTableEntry *>(tb);
|
||||
this->is_kernel = false;
|
||||
this->num_entries = util::AlignUp(end - start, L1BlockSize) / L1BlockSize;
|
||||
}
|
||||
|
||||
L1PageTableEntry *KPageTableImpl::Finalize() {
|
||||
return this->table;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue