mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-21 18:35:13 -04:00
kern: use util::BitFlagSet for capability flags
This commit is contained in:
parent
273206f314
commit
d00cec38b0
4 changed files with 94 additions and 118 deletions
|
@ -23,8 +23,10 @@ namespace ams::kern {
|
|||
|
||||
class KCapabilities {
|
||||
private:
|
||||
static constexpr size_t SvcFlagCount = svc::NumSupervisorCalls / BITSIZEOF(u8);
|
||||
static constexpr size_t IrqFlagCount = /* TODO */0x80;
|
||||
static constexpr size_t InterruptIdCount = 0x400;
|
||||
|
||||
struct InterruptFlagSetTag{};
|
||||
using InterruptFlagSet = util::BitFlagSet<InterruptIdCount, InterruptFlagSetTag>;
|
||||
|
||||
enum class CapabilityType : u32 {
|
||||
CorePriority = (1u << 3) - 1,
|
||||
|
@ -154,6 +156,7 @@ namespace ams::kern {
|
|||
};
|
||||
|
||||
static const u32 PaddingInterruptId = 0x3FF;
|
||||
static_assert(PaddingInterruptId < InterruptIdCount);
|
||||
|
||||
struct InterruptPair {
|
||||
using IdBits = Field<0, CapabilityId<CapabilityType::InterruptPair> + 1>;
|
||||
|
@ -200,8 +203,8 @@ namespace ams::kern {
|
|||
CapabilityFlag<CapabilityType::HandleTable> |
|
||||
CapabilityFlag<CapabilityType::DebugFlags>;
|
||||
private:
|
||||
u8 m_svc_access_flags[SvcFlagCount]{};
|
||||
u8 m_irq_access_flags[IrqFlagCount]{};
|
||||
svc::SvcAccessFlagSet m_svc_access_flags{};
|
||||
InterruptFlagSet m_irq_access_flags{};
|
||||
u64 m_core_mask{};
|
||||
u64 m_priority_mask{};
|
||||
util::BitPack32 m_debug_capabilities{0};
|
||||
|
@ -209,37 +212,19 @@ namespace ams::kern {
|
|||
util::BitPack32 m_intended_kernel_version{0};
|
||||
u32 m_program_type{};
|
||||
private:
|
||||
static constexpr ALWAYS_INLINE void SetSvcAllowedImpl(u8 *data, u32 id) {
|
||||
constexpr size_t BitsPerWord = BITSIZEOF(*data);
|
||||
MESOSPHERE_ASSERT(id < svc::SvcId_Count);
|
||||
data[id / BitsPerWord] |= (1ul << (id % BitsPerWord));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE void ClearSvcAllowedImpl(u8 *data, u32 id) {
|
||||
constexpr size_t BitsPerWord = BITSIZEOF(*data);
|
||||
MESOSPHERE_ASSERT(id < svc::SvcId_Count);
|
||||
data[id / BitsPerWord] &= ~(1ul << (id % BitsPerWord));
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE bool GetSvcAllowedImpl(const u8 *data, u32 id) {
|
||||
constexpr size_t BitsPerWord = BITSIZEOF(*data);
|
||||
MESOSPHERE_ASSERT(id < svc::SvcId_Count);
|
||||
return (data[id / BitsPerWord] & (1ul << (id % BitsPerWord))) != 0;
|
||||
}
|
||||
|
||||
bool SetSvcAllowed(u32 id) {
|
||||
if (id < BITSIZEOF(m_svc_access_flags)) {
|
||||
SetSvcAllowedImpl(m_svc_access_flags, id);
|
||||
constexpr bool SetSvcAllowed(u32 id) {
|
||||
if (AMS_LIKELY(id < m_svc_access_flags.GetCount())) {
|
||||
m_svc_access_flags[id] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SetInterruptPermitted(u32 id) {
|
||||
constexpr bool SetInterruptPermitted(u32 id) {
|
||||
constexpr size_t BitsPerWord = BITSIZEOF(m_irq_access_flags[0]);
|
||||
if (id < BITSIZEOF(m_irq_access_flags)) {
|
||||
m_irq_access_flags[id / BitsPerWord] |= (1ul << (id % BitsPerWord));
|
||||
if (AMS_LIKELY(id < m_irq_access_flags.GetCount())) {
|
||||
m_irq_access_flags[id] = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -271,94 +256,80 @@ namespace ams::kern {
|
|||
constexpr s32 GetHandleTableSize() const { return m_handle_table_size; }
|
||||
|
||||
ALWAYS_INLINE void CopySvcPermissionsTo(KThread::StackParameters &sp) const {
|
||||
static_assert(sizeof(m_svc_access_flags) == sizeof(sp.svc_permission));
|
||||
/* Copy permissions. */
|
||||
std::memcpy(sp.svc_permission, m_svc_access_flags, sizeof(m_svc_access_flags));
|
||||
sp.svc_access_flags = m_svc_access_flags;
|
||||
|
||||
/* Clear specific SVCs based on our state. */
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_SynchronizePreemptionState);
|
||||
sp.svc_access_flags[svc::SvcId_ReturnFromException] = false;
|
||||
sp.svc_access_flags[svc::SvcId_SynchronizePreemptionState] = false;
|
||||
if (sp.is_pinned) {
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_GetInfo);
|
||||
sp.svc_access_flags[svc::SvcId_GetInfo] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void CopyPinnedSvcPermissionsTo(KThread::StackParameters &sp) const {
|
||||
static_assert(sizeof(m_svc_access_flags) == sizeof(sp.svc_permission));
|
||||
/* Get whether we have access to return from exception. */
|
||||
const bool return_from_exception = GetSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
const bool return_from_exception = sp.svc_access_flags[svc::SvcId_ReturnFromException];
|
||||
|
||||
/* Clear all permissions. */
|
||||
std::memset(sp.svc_permission, 0, sizeof(m_svc_access_flags));
|
||||
sp.svc_access_flags.Reset();
|
||||
|
||||
/* Set SynchronizePreemptionState if allowed. */
|
||||
if (GetSvcAllowedImpl(m_svc_access_flags, svc::SvcId_SynchronizePreemptionState)) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_SynchronizePreemptionState);
|
||||
if (m_svc_access_flags[svc::SvcId_SynchronizePreemptionState]) {
|
||||
sp.svc_access_flags[svc::SvcId_SynchronizePreemptionState] = true;
|
||||
}
|
||||
|
||||
/* If we previously had ReturnFromException, potentially grant it and GetInfo. */
|
||||
if (return_from_exception) {
|
||||
/* Set ReturnFromException if allowed. */
|
||||
if (GetSvcAllowedImpl(m_svc_access_flags, svc::SvcId_ReturnFromException)) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
}
|
||||
/* Set ReturnFromException (guaranteed allowed, if we're here). */
|
||||
sp.svc_access_flags[svc::SvcId_ReturnFromException] = true;
|
||||
|
||||
/* Set GetInfo if allowed. */
|
||||
if (GetSvcAllowedImpl(m_svc_access_flags, svc::SvcId_GetInfo)) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_GetInfo);
|
||||
if (m_svc_access_flags[svc::SvcId_GetInfo]) {
|
||||
sp.svc_access_flags[svc::SvcId_GetInfo] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void CopyUnpinnedSvcPermissionsTo(KThread::StackParameters &sp) const {
|
||||
static_assert(sizeof(m_svc_access_flags) == sizeof(sp.svc_permission));
|
||||
/* Get whether we have access to return from exception. */
|
||||
const bool return_from_exception = GetSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
const bool return_from_exception = sp.svc_access_flags[svc::SvcId_ReturnFromException];
|
||||
|
||||
/* Copy permissions. */
|
||||
std::memcpy(sp.svc_permission, m_svc_access_flags, sizeof(m_svc_access_flags));
|
||||
sp.svc_access_flags = m_svc_access_flags;
|
||||
|
||||
/* Clear/Set specific SVCs based on our state. */
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_SynchronizePreemptionState);
|
||||
if (return_from_exception) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
/* Clear specific SVCs based on our state. */
|
||||
sp.svc_access_flags[svc::SvcId_SynchronizePreemptionState] = false;
|
||||
|
||||
if (!return_from_exception) {
|
||||
sp.svc_access_flags[svc::SvcId_ReturnFromException] = false;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void CopyEnterExceptionSvcPermissionsTo(KThread::StackParameters &sp) const {
|
||||
static_assert(sizeof(m_svc_access_flags) == sizeof(sp.svc_permission));
|
||||
|
||||
/* Set ReturnFromException if allowed. */
|
||||
if (GetSvcAllowedImpl(m_svc_access_flags, svc::SvcId_ReturnFromException)) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
if (m_svc_access_flags[svc::SvcId_ReturnFromException]) {
|
||||
sp.svc_access_flags[svc::SvcId_ReturnFromException] = true;
|
||||
}
|
||||
|
||||
/* Set GetInfo if allowed. */
|
||||
if (GetSvcAllowedImpl(m_svc_access_flags, svc::SvcId_GetInfo)) {
|
||||
SetSvcAllowedImpl(sp.svc_permission, svc::SvcId_GetInfo);
|
||||
if (m_svc_access_flags[svc::SvcId_GetInfo]) {
|
||||
sp.svc_access_flags[svc::SvcId_GetInfo] = true;
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void CopyLeaveExceptionSvcPermissionsTo(KThread::StackParameters &sp) const {
|
||||
static_assert(sizeof(m_svc_access_flags) == sizeof(sp.svc_permission));
|
||||
|
||||
/* Clear ReturnFromException. */
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_ReturnFromException);
|
||||
sp.svc_access_flags[svc::SvcId_ReturnFromException] = false;
|
||||
|
||||
/* If pinned, clear GetInfo. */
|
||||
if (sp.is_pinned) {
|
||||
ClearSvcAllowedImpl(sp.svc_permission, svc::SvcId_GetInfo);
|
||||
sp.svc_access_flags[svc::SvcId_GetInfo] = false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool IsPermittedInterrupt(u32 id) const {
|
||||
constexpr size_t BitsPerWord = BITSIZEOF(m_irq_access_flags[0]);
|
||||
if (id < BITSIZEOF(m_irq_access_flags)) {
|
||||
return (m_irq_access_flags[id / BitsPerWord] & (1ul << (id % BitsPerWord))) != 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return (id < m_irq_access_flags.GetCount()) && m_irq_access_flags[id];
|
||||
}
|
||||
|
||||
constexpr bool IsPermittedDebug() const {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue