summaryrefslogtreecommitdiffhomepage
path: root/Private/Source/PageManager.cxx
blob: 95097f990939308376509b3adbb38245b05f3341 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/*
 *	========================================================
 *
 *	HCore
 * 	Copyright Mahrouss Logic, all rights reserved.
 *
 * 	========================================================
 */

#include <KernelKit/DebugOutput.hpp>
#include <NewKit/PageManager.hpp>

namespace HCore {
PTEWrapper::PTEWrapper(Boolean Rw, Boolean User, Boolean ExecDisable,
                       UIntPtr VirtAddr)
    : m_Rw(Rw),
      m_User(User),
      m_ExecDisable(ExecDisable),
      m_VirtAddr(VirtAddr),
      m_Cache(false),
      m_Shareable(false),
      m_Wt(false),
      m_Present(true),
      m_Accessed(false) {
  // special case for the null region.
  if (VirtAddr == 0) {
    m_Wt = false;
    m_Rw = false;
    m_Cache = false;
    m_Shareable = false;
  }
}

PTEWrapper::~PTEWrapper() {
  PTE *raw = reinterpret_cast<PTE *>(m_VirtAddr);

  MUST_PASS(raw);
  MUST_PASS(!raw->Accessed);

  if (raw->Present) raw->Present = false;
}

void PTEWrapper::FlushTLB(Ref<PageManager> &pm) {
  pm.Leak().FlushTLB(this->m_VirtAddr);
}

void PageManager::FlushTLB(UIntPtr VirtAddr) {
  if (VirtAddr == kBadAddress) return;

  flush_tlb(VirtAddr);
}

bool PTEWrapper::Reclaim() {
  if (!this->m_Present) {
    this->m_Present = true;
    return true;
  }

  return false;
}

PTEWrapper *PageManager::Request(Boolean Rw, Boolean User,
                                 Boolean ExecDisable) {
  PTEWrapper *PageTableEntry = reinterpret_cast<PTEWrapper *>(
      HCore::HAL::hal_alloc_page(sizeof(PTEWrapper), Rw, User));

  if (PageTableEntry == nullptr) {
    kcout << "PTEWrapper : Page table is nullptr!, ke_new_ke_heap failed!";
    return nullptr;
  }

  *PageTableEntry =
      PTEWrapper{Rw, User, ExecDisable, Detail::create_page_wrapper(Rw, User)};
  return PageTableEntry;
}

bool PageManager::Free(Ref<PTEWrapper *> &wrapper) {
  if (wrapper) {
    if (!Detail::page_disable(wrapper->VirtualAddress())) return false;

    this->FlushTLB(wrapper->VirtualAddress());
    return true;
  }

  return false;
}

const UIntPtr &PTEWrapper::VirtualAddress() { return m_VirtAddr; }

bool PTEWrapper::Shareable() {
  auto raw = reinterpret_cast<PTE *>(m_VirtAddr);

  if (raw->Present) {
    m_Shareable = raw->Shared;
    return m_Shareable;
  } else {
    kcout << "[PTEWrapper::Shareable] page is not present!";
    return false;
  }
}

bool PTEWrapper::Present() {
  auto raw = reinterpret_cast<PTE *>(m_VirtAddr);

  if (raw->Present) {
    m_Present = raw->Present;
    return m_Present;
  } else {
    kcout << "[PTEWrapper::Present] page is not present!";
    return false;
  }
}

bool PTEWrapper::Access() {
  auto raw = reinterpret_cast<PTE *>(m_VirtAddr);

  if (raw->Present) {
    m_Accessed = raw->Accessed;
  }

  return m_Accessed;
}
}  // namespace HCore