| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #pragma once
- #include <bitset>
- #include <span>
- #include "common/bit_field.h"
- #include "common/common_types.h"
- #include "core/hle/kernel/svc_types.h"
- #include "core/hle/result.h"
- namespace Kernel {
- class KPageTable;
- class KernelCore;
- class KCapabilities {
- public:
- constexpr explicit KCapabilities() = default;
- Result InitializeForKip(std::span<const u32> kern_caps, KPageTable* page_table);
- Result InitializeForUser(std::span<const u32> user_caps, KPageTable* page_table);
- static Result CheckCapabilities(KernelCore& kernel, std::span<const u32> user_caps);
- constexpr u64 GetCoreMask() const {
- return m_core_mask;
- }
- constexpr u64 GetPhysicalCoreMask() const {
- return m_phys_core_mask;
- }
- constexpr u64 GetPriorityMask() const {
- return m_priority_mask;
- }
- constexpr s32 GetHandleTableSize() const {
- return m_handle_table_size;
- }
- constexpr const Svc::SvcAccessFlagSet& GetSvcPermissions() const {
- return m_svc_access_flags;
- }
- constexpr bool IsPermittedSvc(u32 id) const {
- return (id < m_svc_access_flags.size()) && m_svc_access_flags[id];
- }
- constexpr bool IsPermittedInterrupt(u32 id) const {
- return (id < m_irq_access_flags.size()) && m_irq_access_flags[id];
- }
- constexpr bool IsPermittedDebug() const {
- return DebugFlags{m_debug_capabilities}.allow_debug.Value() != 0;
- }
- constexpr bool CanForceDebug() const {
- return DebugFlags{m_debug_capabilities}.force_debug.Value() != 0;
- }
- constexpr u32 GetIntendedKernelMajorVersion() const {
- return KernelVersion{m_intended_kernel_version}.major_version;
- }
- constexpr u32 GetIntendedKernelMinorVersion() const {
- return KernelVersion{m_intended_kernel_version}.minor_version;
- }
- private:
- static constexpr size_t InterruptIdCount = 0x400;
- using InterruptFlagSet = std::bitset<InterruptIdCount>;
- enum class CapabilityType : u32 {
- CorePriority = (1U << 3) - 1,
- SyscallMask = (1U << 4) - 1,
- MapRange = (1U << 6) - 1,
- MapIoPage = (1U << 7) - 1,
- MapRegion = (1U << 10) - 1,
- InterruptPair = (1U << 11) - 1,
- ProgramType = (1U << 13) - 1,
- KernelVersion = (1U << 14) - 1,
- HandleTable = (1U << 15) - 1,
- DebugFlags = (1U << 16) - 1,
- Invalid = 0U,
- Padding = ~0U,
- };
- using RawCapabilityValue = u32;
- static constexpr CapabilityType GetCapabilityType(const RawCapabilityValue value) {
- return static_cast<CapabilityType>((~value & (value + 1)) - 1);
- }
- static constexpr u32 GetCapabilityFlag(CapabilityType type) {
- return static_cast<u32>(type) + 1;
- }
- template <CapabilityType Type>
- static constexpr inline u32 CapabilityFlag = static_cast<u32>(Type) + 1;
- template <CapabilityType Type>
- static constexpr inline u32 CapabilityId = std::countr_zero(CapabilityFlag<Type>);
- union CorePriority {
- static_assert(CapabilityId<CapabilityType::CorePriority> + 1 == 4);
- RawCapabilityValue raw;
- BitField<0, 4, CapabilityType> id;
- BitField<4, 6, u32> lowest_thread_priority;
- BitField<10, 6, u32> highest_thread_priority;
- BitField<16, 8, u32> minimum_core_id;
- BitField<24, 8, u32> maximum_core_id;
- };
- union SyscallMask {
- static_assert(CapabilityId<CapabilityType::SyscallMask> + 1 == 5);
- RawCapabilityValue raw;
- BitField<0, 5, CapabilityType> id;
- BitField<5, 24, u32> mask;
- BitField<29, 3, u32> index;
- };
- // #undef MESOSPHERE_ENABLE_LARGE_PHYSICAL_ADDRESS_CAPABILITIES
- static constexpr u64 PhysicalMapAllowedMask = (1ULL << 36) - 1;
- union MapRange {
- static_assert(CapabilityId<CapabilityType::MapRange> + 1 == 7);
- RawCapabilityValue raw;
- BitField<0, 7, CapabilityType> id;
- BitField<7, 24, u32> address;
- BitField<31, 1, u32> read_only;
- };
- union MapRangeSize {
- static_assert(CapabilityId<CapabilityType::MapRange> + 1 == 7);
- RawCapabilityValue raw;
- BitField<0, 7, CapabilityType> id;
- BitField<7, 20, u32> pages;
- BitField<27, 4, u32> reserved;
- BitField<31, 1, u32> normal;
- };
- union MapIoPage {
- static_assert(CapabilityId<CapabilityType::MapIoPage> + 1 == 8);
- RawCapabilityValue raw;
- BitField<0, 8, CapabilityType> id;
- BitField<8, 24, u32> address;
- };
- enum class RegionType : u32 {
- NoMapping = 0,
- KernelTraceBuffer = 1,
- OnMemoryBootImage = 2,
- DTB = 3,
- };
- union MapRegion {
- static_assert(CapabilityId<CapabilityType::MapRegion> + 1 == 11);
- RawCapabilityValue raw;
- BitField<0, 11, CapabilityType> id;
- BitField<11, 6, RegionType> region0;
- BitField<17, 1, u32> read_only0;
- BitField<18, 6, RegionType> region1;
- BitField<24, 1, u32> read_only1;
- BitField<25, 6, RegionType> region2;
- BitField<31, 1, u32> read_only2;
- };
- union InterruptPair {
- static_assert(CapabilityId<CapabilityType::InterruptPair> + 1 == 12);
- RawCapabilityValue raw;
- BitField<0, 12, CapabilityType> id;
- BitField<12, 10, u32> interrupt_id0;
- BitField<22, 10, u32> interrupt_id1;
- };
- union ProgramType {
- static_assert(CapabilityId<CapabilityType::ProgramType> + 1 == 14);
- RawCapabilityValue raw;
- BitField<0, 14, CapabilityType> id;
- BitField<14, 3, u32> type;
- BitField<17, 15, u32> reserved;
- };
- union KernelVersion {
- static_assert(CapabilityId<CapabilityType::KernelVersion> + 1 == 15);
- RawCapabilityValue raw;
- BitField<0, 15, CapabilityType> id;
- BitField<15, 4, u32> minor_version;
- BitField<19, 13, u32> major_version;
- };
- union HandleTable {
- static_assert(CapabilityId<CapabilityType::HandleTable> + 1 == 16);
- RawCapabilityValue raw;
- BitField<0, 16, CapabilityType> id;
- BitField<16, 10, u32> size;
- BitField<26, 6, u32> reserved;
- };
- union DebugFlags {
- static_assert(CapabilityId<CapabilityType::DebugFlags> + 1 == 17);
- RawCapabilityValue raw;
- BitField<0, 17, CapabilityType> id;
- BitField<17, 1, u32> allow_debug;
- BitField<18, 1, u32> force_debug;
- BitField<19, 13, u32> reserved;
- };
- static_assert(sizeof(CorePriority) == 4);
- static_assert(sizeof(SyscallMask) == 4);
- static_assert(sizeof(MapRange) == 4);
- static_assert(sizeof(MapRangeSize) == 4);
- static_assert(sizeof(MapIoPage) == 4);
- static_assert(sizeof(MapRegion) == 4);
- static_assert(sizeof(InterruptPair) == 4);
- static_assert(sizeof(ProgramType) == 4);
- static_assert(sizeof(KernelVersion) == 4);
- static_assert(sizeof(HandleTable) == 4);
- static_assert(sizeof(DebugFlags) == 4);
- static constexpr u32 InitializeOnceFlags =
- CapabilityFlag<CapabilityType::CorePriority> | CapabilityFlag<CapabilityType::ProgramType> |
- CapabilityFlag<CapabilityType::KernelVersion> |
- CapabilityFlag<CapabilityType::HandleTable> | CapabilityFlag<CapabilityType::DebugFlags>;
- static const u32 PaddingInterruptId = 0x3FF;
- static_assert(PaddingInterruptId < InterruptIdCount);
- private:
- constexpr bool SetSvcAllowed(u32 id) {
- if (id < m_svc_access_flags.size()) [[likely]] {
- m_svc_access_flags[id] = true;
- return true;
- } else {
- return false;
- }
- }
- constexpr bool SetInterruptPermitted(u32 id) {
- if (id < m_irq_access_flags.size()) [[likely]] {
- m_irq_access_flags[id] = true;
- return true;
- } else {
- return false;
- }
- }
- Result SetCorePriorityCapability(const u32 cap);
- Result SetSyscallMaskCapability(const u32 cap, u32& set_svc);
- Result MapRange_(const u32 cap, const u32 size_cap, KPageTable* page_table);
- Result MapIoPage_(const u32 cap, KPageTable* page_table);
- Result MapRegion_(const u32 cap, KPageTable* page_table);
- Result SetInterruptPairCapability(const u32 cap);
- Result SetProgramTypeCapability(const u32 cap);
- Result SetKernelVersionCapability(const u32 cap);
- Result SetHandleTableCapability(const u32 cap);
- Result SetDebugFlagsCapability(const u32 cap);
- template <typename F>
- static Result ProcessMapRegionCapability(const u32 cap, F f);
- static Result CheckMapRegion(KernelCore& kernel, const u32 cap);
- Result SetCapability(const u32 cap, u32& set_flags, u32& set_svc, KPageTable* page_table);
- Result SetCapabilities(std::span<const u32> caps, KPageTable* page_table);
- private:
- Svc::SvcAccessFlagSet m_svc_access_flags{};
- InterruptFlagSet m_irq_access_flags{};
- u64 m_core_mask{};
- u64 m_phys_core_mask{};
- u64 m_priority_mask{};
- u32 m_debug_capabilities{};
- s32 m_handle_table_size{};
- u32 m_intended_kernel_version{};
- u32 m_program_type{};
- };
- } // namespace Kernel
|