[project] Lose the battle between tabs & spaces

I'm a tabs guy. I like tabs, it's an elegant way to represent
indentation instead of brute-forcing it. But I have to admit that the
world seems to be going towards spaces, and tooling tends not to play
nice with tabs. So here we go, changing the whole repo to spaces since
I'm getting tired of all the inconsistent formatting.
This commit is contained in:
F in Chat for Tabs
2021-08-01 17:46:16 -07:00
committed by Justin C. Miller
parent d36b2d8057
commit 8f529046a9
161 changed files with 7958 additions and 7958 deletions

View File

@@ -11,184 +11,184 @@ struct free_page_header;
/// Struct to allow easy accessing of a memory page being used as a page table.
struct page_table
{
/// Enum representing the table levels in 4-level paging
enum class level : unsigned { pml4, pdp, pd, pt, page };
/// Enum representing the table levels in 4-level paging
enum class level : unsigned { pml4, pdp, pd, pt, page };
/// Page entry flags
enum class flag : uint64_t
{
none = 0x0000,
present = 0x0001, /// Entry is present in the table
write = 0x0002, /// Section may be written
user = 0x0004, /// User-accessible
pat0 = 0x0008, /// PAT selector bit 0
pat1 = 0x0010, /// PAT selector bit 1
accessed = 0x0020, /// Entry has been accessed
dirty = 0x0040, /// Page has been written to
page = 0x0080, /// Entry is a large page
pat2 = 0x0080, /// PAT selector bit 2 on PT entries
global = 0x0100, /// Entry is not PCID-specific
pat2_lg = 0x1000, /// PAT selector bit 2 on large/huge pages
/// Page entry flags
enum class flag : uint64_t
{
none = 0x0000,
present = 0x0001, /// Entry is present in the table
write = 0x0002, /// Section may be written
user = 0x0004, /// User-accessible
pat0 = 0x0008, /// PAT selector bit 0
pat1 = 0x0010, /// PAT selector bit 1
accessed = 0x0020, /// Entry has been accessed
dirty = 0x0040, /// Page has been written to
page = 0x0080, /// Entry is a large page
pat2 = 0x0080, /// PAT selector bit 2 on PT entries
global = 0x0100, /// Entry is not PCID-specific
pat2_lg = 0x1000, /// PAT selector bit 2 on large/huge pages
wb = none,
wt = pat0,
uc_ = pat1,
uc = pat0 | pat1,
wc = pat0 | pat1 | pat2,
wc_lg = pat0 | pat1 | pat2_lg,
};
wb = none,
wt = pat0,
uc_ = pat1,
uc = pat0 | pat1,
wc = pat0 | pat1 | pat2,
wc_lg = pat0 | pat1 | pat2_lg,
};
/// Helper for getting the next level value
inline static level deeper(level l) {
return static_cast<level>(static_cast<unsigned>(l) + 1);
}
/// Helper for getting the next level value
inline static level deeper(level l) {
return static_cast<level>(static_cast<unsigned>(l) + 1);
}
static constexpr size_t entry_sizes[] = {
0x8000000000, // PML4 entry: 512 GiB
0x40000000, // PDP entry: 1 GiB
0x200000, // PD entry: 2 MiB
0x1000}; // PT entry: 4 KiB
static constexpr size_t entry_sizes[] = {
0x8000000000, // PML4 entry: 512 GiB
0x40000000, // PDP entry: 1 GiB
0x200000, // PD entry: 2 MiB
0x1000}; // PT entry: 4 KiB
/// Iterator over page table entries.
class iterator
{
/// The number of levels
static constexpr unsigned D = 4;
/// Iterator over page table entries.
class iterator
{
/// The number of levels
static constexpr unsigned D = 4;
public:
/// Constructor.
/// \arg virt Virtual address this iterator is starting at
/// \arg pml4 Root of the page tables to iterate
iterator(uintptr_t virt, page_table *pml4);
public:
/// Constructor.
/// \arg virt Virtual address this iterator is starting at
/// \arg pml4 Root of the page tables to iterate
iterator(uintptr_t virt, page_table *pml4);
/// Copy constructor.
iterator(const iterator &o);
/// Copy constructor.
iterator(const iterator &o);
/// Get the starting address of pages mapped by the current table
/// of level l.
uintptr_t start(level l) const;
/// Get the starting address of pages mapped by the current table
/// of level l.
uintptr_t start(level l) const;
/// Get the ending address of pages mapped by the current table
/// of level l.
uintptr_t end(level l) const;
/// Get the ending address of pages mapped by the current table
/// of level l.
uintptr_t end(level l) const;
/// Get the widest table type the current address is aligned to
level align() const;
/// Get the widest table type the current address is aligned to
level align() const;
/// Get the current virtual address
inline uintptr_t vaddress() const { return start(level::pt); }
/// Get the current virtual address
inline uintptr_t vaddress() const { return start(level::pt); }
/// Get the nth page table of the current address
inline page_table *& table(level l) const { return m_table[unsigned(l)]; }
/// Get the nth page table of the current address
inline page_table *& table(level l) const { return m_table[unsigned(l)]; }
/// Get the index in the nth page table of the current address
inline uint16_t & index(level l) { return m_index[unsigned(l)]; }
/// Get the index in the nth page table of the current address
inline uint16_t & index(level l) { return m_index[unsigned(l)]; }
/// Get the index in the nth page table of the current address
inline uint16_t index(level l) const { return m_index[unsigned(l)]; }
/// Get the index in the nth page table of the current address
inline uint16_t index(level l) const { return m_index[unsigned(l)]; }
/// Get the current table entry of the table at the given level.
inline uint64_t entry(level l) const {
for (unsigned i = 1; i <= unsigned(l); ++i)
if (!check_table(level(i))) return 0;
return table(l)->entries[index(l)];
}
/// Get the current table entry of the table at the given level.
inline uint64_t entry(level l) const {
for (unsigned i = 1; i <= unsigned(l); ++i)
if (!check_table(level(i))) return 0;
return table(l)->entries[index(l)];
}
/// Get a *non-const* reference to the current table entry of
/// the table at the given level.
inline uint64_t & entry(level l) {
for (unsigned i = 1; i <= unsigned(l); ++i) ensure_table(level(i));
return table(l)->entries[index(l)];
}
/// Get a *non-const* reference to the current table entry of
/// the table at the given level.
inline uint64_t & entry(level l) {
for (unsigned i = 1; i <= unsigned(l); ++i) ensure_table(level(i));
return table(l)->entries[index(l)];
}
/// Get the depth of tables that actually exist for the current address
level depth() const;
/// Get the depth of tables that actually exist for the current address
level depth() const;
/// Increment iteration to the next entry aligned to the given level
void next(level l);
/// Increment iteration to the next entry aligned to the given level
void next(level l);
/// Increment iteration to the next entry at the deepest level
inline void increment() { next(level::page); }
/// Increment iteration to the next entry at the deepest level
inline void increment() { next(level::page); }
inline uint64_t & operator*() { return entry(level::pt); }
inline iterator & operator++() { increment(); return *this; }
inline iterator operator++(int) { iterator old {*this}; increment(); return old; }
inline uint64_t & operator*() { return entry(level::pt); }
inline iterator & operator++() { increment(); return *this; }
inline iterator operator++(int) { iterator old {*this}; increment(); return old; }
bool operator!=(const iterator &o) const;
bool operator!=(const iterator &o) const;
bool check_table(level l) const;
void ensure_table(level l);
bool check_table(level l) const;
void ensure_table(level l);
private:
// The table array is mutable because we might update it with existing
// tables; a 'view switch'. therefore, be careful not to modify table
// contents in const functions.
mutable page_table *m_table[D];
uint16_t m_index[D];
};
private:
// The table array is mutable because we might update it with existing
// tables; a 'view switch'. therefore, be careful not to modify table
// contents in const functions.
mutable page_table *m_table[D];
uint16_t m_index[D];
};
/// Allocate a page for a page table, or pull one from the cache
/// \returns An empty page, mapped in the linear offset area
static page_table * get_table_page();
/// Allocate a page for a page table, or pull one from the cache
/// \returns An empty page, mapped in the linear offset area
static page_table * get_table_page();
/// Return a page table's page to the page cache.
/// \arg pt The page to be returned
static void free_table_page(page_table *pt);
/// Return a page table's page to the page cache.
/// \arg pt The page to be returned
static void free_table_page(page_table *pt);
// Ensure the page table page cache has a minimum number of pages
// in it.
static void fill_table_page_cache();
// Ensure the page table page cache has a minimum number of pages
// in it.
static void fill_table_page_cache();
static free_page_header *s_page_cache; ///< Cache of free pages to use for tables
static size_t s_cache_count; ///< Number of pages in s_page_cache
static free_page_header *s_page_cache; ///< Cache of free pages to use for tables
static size_t s_cache_count; ///< Number of pages in s_page_cache
/// Get an entry in the page table as a page_table pointer
/// \arg i Index of the entry in this page table
/// \arg flags [out] If set, this will receive the entry's flags
/// \returns The corresponding entry, offset into page-offset memory
page_table * get(int i, uint16_t *flags = nullptr) const;
/// Get an entry in the page table as a page_table pointer
/// \arg i Index of the entry in this page table
/// \arg flags [out] If set, this will receive the entry's flags
/// \returns The corresponding entry, offset into page-offset memory
page_table * get(int i, uint16_t *flags = nullptr) const;
/// Set an entry in the page table as a page_table pointer
/// \arg i Index of the entry in this page table
/// \arg flags The flags for the entry
void set(int i, page_table *p, uint16_t flags);
/// Set an entry in the page table as a page_table pointer
/// \arg i Index of the entry in this page table
/// \arg flags The flags for the entry
void set(int i, page_table *p, uint16_t flags);
/// Check if the given entry represents a large or huge page
inline bool is_large_page(level l, int i) const {
return (l == level::pdp || l == level::pd) && (entries[i] & 0x80) == 0x80;
}
/// Check if the given entry represents a large or huge page
inline bool is_large_page(level l, int i) const {
return (l == level::pdp || l == level::pd) && (entries[i] & 0x80) == 0x80;
}
/// Check if the given entry is marked as present in the table
inline bool is_present(int i) const { return (entries[i] & 0x1) == 0x1; }
/// Check if the given entry is marked as present in the table
inline bool is_present(int i) const { return (entries[i] & 0x1) == 0x1; }
/// Check if the given entry represents a page (of any size)
inline bool is_page(level l, int i) const { return (l == level::pt) || is_large_page(l, i); }
/// Check if the given entry represents a page (of any size)
inline bool is_page(level l, int i) const { return (l == level::pt) || is_large_page(l, i); }
/// Free this page table and all resources it references
/// \arg l The level of this page table
void free(level l);
/// Free this page table and all resources it references
/// \arg l The level of this page table
void free(level l);
/// Print this table to the debug console.
void dump(level lvl = level::pml4, bool recurse = true);
/// Print this table to the debug console.
void dump(level lvl = level::pml4, bool recurse = true);
uint64_t entries[memory::table_entries];
uint64_t entries[memory::table_entries];
};
inline page_table::level operator+(page_table::level a, unsigned b) {
return static_cast<page_table::level>(static_cast<unsigned>(a) + b);
return static_cast<page_table::level>(static_cast<unsigned>(a) + b);
}
inline page_table::level operator-(page_table::level a, unsigned b) {
return static_cast<page_table::level>(static_cast<unsigned>(a) - b);
return static_cast<page_table::level>(static_cast<unsigned>(a) - b);
}
inline bool operator>(page_table::level a, page_table::level b) {
return static_cast<unsigned>(a) > static_cast<unsigned>(b);
return static_cast<unsigned>(a) > static_cast<unsigned>(b);
}
inline bool operator<(page_table::level a, page_table::level b) {
return static_cast<unsigned>(a) < static_cast<unsigned>(b);
return static_cast<unsigned>(a) < static_cast<unsigned>(b);
}
inline page_table::level& operator++(page_table::level& l) { l = l + 1; return l; }