kernelldr: miscellaneous fixes

This commit is contained in:
Michael Scire 2019-12-17 05:30:29 -08:00
parent c85fac4c43
commit fcae4af5f7
5 changed files with 33 additions and 35 deletions

View File

@ -77,11 +77,11 @@ namespace ams::kern::init {
} }
protected: protected:
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const { constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
return (this->attributes >> offset) & ((1 << count) - 1); return (this->attributes >> offset) & ((1ul << count) - 1);
} }
constexpr ALWAYS_INLINE u64 SelectBits(size_t offset, size_t count) const { constexpr ALWAYS_INLINE u64 SelectBits(size_t offset, size_t count) const {
return this->attributes & (((1 << count) - 1) << offset); return this->attributes & (((1ul << count) - 1) << offset);
} }
public: public:
constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; } constexpr ALWAYS_INLINE bool IsUserExecuteNever() const { return this->GetBits(54, 1) != 0; }
@ -128,9 +128,9 @@ namespace ams::kern::init {
return this->SelectBits(12, 36); return this->SelectBits(12, 36);
} }
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs) const { constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
/* Check whether this has the same permission/etc as the desired attributes. */ /* Check whether this has the same permission/etc as the desired attributes. */
return (this->GetBlock() | rhs.GetRawAttributes()) == this->GetRawAttributes(); return L1PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
} }
}; };
@ -156,16 +156,16 @@ namespace ams::kern::init {
return this->SelectBits(12, 36); return this->SelectBits(12, 36);
} }
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs) const { constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
/* Check whether this has the same permission/etc as the desired attributes. */ /* Check whether this has the same permission/etc as the desired attributes. */
return (this->GetBlock() | rhs.GetRawAttributes()) == this->GetRawAttributes(); return L2PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
} }
}; };
class L3PageTableEntry : public PageTableEntry { class L3PageTableEntry : public PageTableEntry {
public: public:
constexpr ALWAYS_INLINE L3PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig) constexpr ALWAYS_INLINE L3PageTableEntry(KPhysicalAddress phys_addr, const PageTableEntry &attr, bool contig)
: PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x1) : PageTableEntry(attr, (static_cast<u64>(contig) << 52) | GetInteger(phys_addr) | 0x3)
{ {
/* ... */ /* ... */
} }
@ -176,9 +176,9 @@ namespace ams::kern::init {
return this->SelectBits(12, 36); return this->SelectBits(12, 36);
} }
constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs) const { constexpr ALWAYS_INLINE bool IsCompatibleWithAttribute(const PageTableEntry &rhs, bool contig) const {
/* Check whether this has the same permission/etc as the desired attributes. */ /* Check whether this has the same permission/etc as the desired attributes. */
return (this->GetBlock() | rhs.GetRawAttributes()) == this->GetRawAttributes(); return L3PageTableEntry(this->GetBlock(), rhs, contig).GetRawAttributes() == this->GetRawAttributes();
} }
}; };
@ -247,7 +247,7 @@ namespace ams::kern::init {
if (!l1_entry->IsTable()) { if (!l1_entry->IsTable()) {
KPhysicalAddress new_table = allocator.Allocate(); KPhysicalAddress new_table = allocator.Allocate();
ClearNewPageTable(new_table); ClearNewPageTable(new_table);
*l1_entry = L1PageTableEntry(phys_addr, attr.IsPrivilegedExecuteNever()); *l1_entry = L1PageTableEntry(new_table, attr.IsPrivilegedExecuteNever());
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
} }
@ -281,7 +281,7 @@ namespace ams::kern::init {
if (!l2_entry->IsTable()) { if (!l2_entry->IsTable()) {
KPhysicalAddress new_table = allocator.Allocate(); KPhysicalAddress new_table = allocator.Allocate();
ClearNewPageTable(new_table); ClearNewPageTable(new_table);
*l2_entry = L2PageTableEntry(phys_addr, attr.IsPrivilegedExecuteNever()); *l2_entry = L2PageTableEntry(new_table, attr.IsPrivilegedExecuteNever());
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
} }
@ -373,7 +373,7 @@ namespace ams::kern::init {
const KPhysicalAddress block = l1_entry->GetBlock(); const KPhysicalAddress block = l1_entry->GetBlock();
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L1BlockSize));
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L1BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L1BlockSize));
MESOSPHERE_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before)); MESOSPHERE_ABORT_UNLESS(l1_entry->IsCompatibleWithAttribute(attr_before, false));
/* Invalidate the existing L1 block. */ /* Invalidate the existing L1 block. */
*static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry; *static_cast<PageTableEntry *>(l1_entry) = InvalidPageTableEntry;
@ -404,7 +404,7 @@ namespace ams::kern::init {
/* Invalidate the existing contiguous L2 block. */ /* Invalidate the existing contiguous L2 block. */
for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) { for (size_t i = 0; i < L2ContiguousBlockSize / L2BlockSize; i++) {
/* Ensure that the entry is valid. */ /* Ensure that the entry is valid. */
MESOSPHERE_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before)); MESOSPHERE_ABORT_UNLESS(l2_entry[i].IsCompatibleWithAttribute(attr_before, true));
static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry; static_cast<PageTableEntry *>(l2_entry)[i] = InvalidPageTableEntry;
} }
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
@ -422,7 +422,7 @@ namespace ams::kern::init {
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L2BlockSize));
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L2BlockSize));
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L2BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L2BlockSize));
MESOSPHERE_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before)); MESOSPHERE_ABORT_UNLESS(l2_entry->IsCompatibleWithAttribute(attr_before, false));
/* Invalidate the existing L2 block. */ /* Invalidate the existing L2 block. */
*static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry; *static_cast<PageTableEntry *>(l2_entry) = InvalidPageTableEntry;
@ -456,7 +456,7 @@ namespace ams::kern::init {
/* Invalidate the existing contiguous L3 block. */ /* Invalidate the existing contiguous L3 block. */
for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) { for (size_t i = 0; i < L3ContiguousBlockSize / L3BlockSize; i++) {
/* Ensure that the entry is valid. */ /* Ensure that the entry is valid. */
MESOSPHERE_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before)); MESOSPHERE_ABORT_UNLESS(l3_entry[i].IsCompatibleWithAttribute(attr_before, true));
static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry; static_cast<PageTableEntry *>(l3_entry)[i] = InvalidPageTableEntry;
} }
cpu::DataSynchronizationBarrierInnerShareable(); cpu::DataSynchronizationBarrierInnerShareable();
@ -474,7 +474,7 @@ namespace ams::kern::init {
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(virt_addr), L3BlockSize));
MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(GetInteger(block), L3BlockSize));
MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L3BlockSize)); MESOSPHERE_ABORT_UNLESS(util::IsAligned(size, L3BlockSize));
MESOSPHERE_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before)); MESOSPHERE_ABORT_UNLESS(l3_entry->IsCompatibleWithAttribute(attr_before, false));
/* Invalidate the existing L3 block. */ /* Invalidate the existing L3 block. */
*static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry; *static_cast<PageTableEntry *>(l3_entry) = InvalidPageTableEntry;

View File

@ -55,7 +55,7 @@ namespace ams::kern::arm64::cpu {
ALWAYS_INLINE GenericRegisterAccessor(u64 v) : value(v) { /* ... */ } ALWAYS_INLINE GenericRegisterAccessor(u64 v) : value(v) { /* ... */ }
protected: protected:
constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const { constexpr ALWAYS_INLINE u64 GetBits(size_t offset, size_t count) const {
return (this->value >> offset) & ((1 << count) - 1); return (this->value >> offset) & ((1ul << count) - 1);
} }
}; };

View File

@ -86,13 +86,11 @@ namespace ams::kern {
} }
u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) { u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
/* This is a biased random, but this is okay for now. */
/* TODO: unbiased random? */
const u64 range_size = ((max + 1) - min); const u64 range_size = ((max + 1) - min);
const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size; const u64 effective_max = (std::numeric_limits<u64>::max() / range_size) * range_size;
while (true) { while (true) {
if (const u64 rnd = GenerateRandomU64(); rnd < effective_max) { if (const u64 rnd = GenerateRandomU64(); rnd < effective_max) {
return rnd % effective_max; return min + (rnd % range_size);
} }
} }
} }

View File

@ -83,7 +83,7 @@ namespace ams::kern::smc {
void GenerateRandomBytes(void *dst, size_t size) { void GenerateRandomBytes(void *dst, size_t size) {
/* Call SmcGenerateRandomBytes() */ /* Call SmcGenerateRandomBytes() */
/* TODO: Lock this to ensure only one core calls at once. */ /* TODO: Lock this to ensure only one core calls at once. */
SecureMonitorArguments args = { FunctionId_GetConfig, size }; SecureMonitorArguments args = { FunctionId_GenerateRandomBytes, size };
MESOSPHERE_ABORT_UNLESS(size <= sizeof(args) - sizeof(args.x[0])); MESOSPHERE_ABORT_UNLESS(size <= sizeof(args) - sizeof(args.x[0]));
CallPrivilegedSecureMonitorFunction(args); CallPrivilegedSecureMonitorFunction(args);
MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success)); MESOSPHERE_ABORT_UNLESS((static_cast<SmcResult>(args.x[0]) == SmcResult::Success));

View File

@ -21,20 +21,6 @@ namespace ams::util {
template<char A, char B, char C, char D> template<char A, char B, char C, char D>
struct FourCC { struct FourCC {
/* TODO: C++20 std::endian */
static constexpr u32 Code = (static_cast<u32>(A) << 0x18) |
(static_cast<u32>(B) << 0x10) |
(static_cast<u32>(C) << 0x08) |
(static_cast<u32>(D) << 0x00);
static constexpr const char String[] = {D, C, B, A};
static_assert(sizeof(Code) == 4);
static_assert(sizeof(String) == 4);
};
template<char A, char B, char C, char D>
struct ReverseFourCC {
/* TODO: C++20 std::endian */ /* TODO: C++20 std::endian */
static constexpr u32 Code = (static_cast<u32>(A) << 0x00) | static constexpr u32 Code = (static_cast<u32>(A) << 0x00) |
(static_cast<u32>(B) << 0x08) | (static_cast<u32>(B) << 0x08) |
@ -47,4 +33,18 @@ namespace ams::util {
static_assert(sizeof(String) == 4); static_assert(sizeof(String) == 4);
}; };
template<char A, char B, char C, char D>
struct ReverseFourCC {
/* TODO: C++20 std::endian */
static constexpr u32 Code = (static_cast<u32>(A) << 0x18) |
(static_cast<u32>(B) << 0x10) |
(static_cast<u32>(C) << 0x08) |
(static_cast<u32>(D) << 0x00);
static constexpr const char String[] = {D, C, B, A};
static_assert(sizeof(Code) == 4);
static_assert(sizeof(String) == 4);
};
} }