The Pedigree Project  0.1
ppc_common/PhysicalMemoryManager.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "PhysicalMemoryManager.h"
21 #include "../ppc32/VirtualAddressSpace.h"
22 #include "pedigree/kernel/Log.h"
23 #include "pedigree/kernel/panic.h"
24 #include "pedigree/kernel/processor/MemoryRegion.h"
25 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
26 
28 
30 {
32 }
33 
34 physical_uintptr_t PpcCommonPhysicalMemoryManager::allocatePage()
35 {
36  // If we're in initial mode we just return the next available page.
37  // If we're in normal mode we ask the pagestack for another page.
38  if (m_InitialMode)
39  return (m_NextPage += 0x1000);
40  else
41  return m_PageStack.allocate();
42 }
43 void PpcCommonPhysicalMemoryManager::freePage(physical_uintptr_t page)
44 {
45  // If we're in initial mode it's time to panic.
46  if (m_InitialMode)
47  panic("freePage called in initial mode!");
48  m_PageStack.free(page);
49 }
51  MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags,
52  physical_uintptr_t start)
53 {
54  // Allocate a specific physical memory region (always physically continuous)
55  if (start != static_cast<physical_uintptr_t>(-1))
56  {
57  if ((pageConstraints & continuous) != continuous)
58  panic("PhysicalMemoryManager::allocateRegion(): function misused");
59 
60  // Remove the memory from the range-lists (if desired/possible)
61  if ((pageConstraints & nonRamMemory) == nonRamMemory)
62  {
63  if (m_PhysicalRanges.allocateSpecific(
64  start, cPages * getPageSize()) == false)
65  if ((pageConstraints & force) != force)
66  return false;
67  }
68 
69  // Allocate the virtual address space
70  uintptr_t vAddress;
71  if (m_MemoryRegions.allocate(
72  cPages * PhysicalMemoryManager::getPageSize(), vAddress) ==
73  false)
74  {
75  WARNING("AllocateRegion: MemoryRegion allocation failed.");
76  return false;
77  }
78 
79  // Map the physical memory into the allocated space
80  VirtualAddressSpace &virtualAddressSpace =
82  for (size_t i = 0; i < cPages; i++)
83  if (virtualAddressSpace.map(
85  reinterpret_cast<void *>(
86  vAddress + i * PhysicalMemoryManager::getPageSize()),
87  Flags) == false)
88  {
89  m_MemoryRegions.free(
90  vAddress, cPages * PhysicalMemoryManager::getPageSize());
91  WARNING("AllocateRegion: VirtualAddressSpace::map failed.");
92  return false;
93  }
94 
95  // Set the memory-region's members
96  Region.m_VirtualAddress = reinterpret_cast<void *>(vAddress);
97  Region.m_PhysicalAddress = start;
98  Region.m_Size = cPages * PhysicalMemoryManager::getPageSize();
99 
100  // Add to the list of memory-regions
102  return true;
103  }
104  else
105  {
106  // Allocate the virtual address space
107  uintptr_t vAddress;
108  if (m_MemoryRegions.allocate(
109  cPages * PhysicalMemoryManager::getPageSize(), vAddress) ==
110  false)
111  {
112  WARNING("AllocateRegion: MemoryRegion allocation failed.");
113  return false;
114  }
115 
116  uint32_t start = 0;
117  VirtualAddressSpace &virtualAddressSpace =
119  // Map the physical memory into the allocated space
120  for (size_t i = 0; i < cPages; i++)
121  {
122  physical_uintptr_t page = m_PageStack.allocate();
123 
124  if (virtualAddressSpace.map(
125  page,
126  reinterpret_cast<void *>(
127  vAddress + i * PhysicalMemoryManager::getPageSize()),
128  Flags) == false)
129  {
130  WARNING("AllocateRegion: VirtualAddressSpace::map failed.");
131  return false;
132  }
133  }
134 
135  // Set the memory-region's members
136  Region.m_VirtualAddress = reinterpret_cast<void *>(vAddress);
137  Region.m_PhysicalAddress = start;
138  Region.m_Size = cPages * PhysicalMemoryManager::getPageSize();
139 
140  // Add to the list of memory-regions
142  return true;
143  }
144  return false;
145 }
146 
148  : m_PageStack(), m_InitialMode(true), m_NextPage(PMM_INITIAL_START),
149  m_PhysicalRanges(), m_MemoryRegions()
150 {
151 }
153 {
154 }
155 
156 void PpcCommonPhysicalMemoryManager::initialise(
157  Translations &translations, uintptr_t ramMax)
158 {
159  // Allocate every page that is currently in Translations.
160  for (uintptr_t i = 0; i < ramMax; i += getPageSize())
161  {
162  bool claimed = false;
163  for (unsigned int j = 0; j < translations.getNumTranslations(); j++)
164  {
165  Translations::Translation t = translations.getTranslation(j);
166  if ((i >= t.phys) && (i < t.phys + t.size))
167  {
168  claimed = true;
169  break;
170  }
171  }
172  if ((i >= PMM_INITIAL_START) && (i < m_NextPage))
173  claimed = true;
174  if (!claimed)
175  m_PageStack.free(i);
176  }
177 
178  // Initialise the free physical ranges. The physical ranges
179  // are designed to contain areas of physical address space not covered by
180  // other allocators (e.g. for PCI mapping), so we don't add anything below
181  // ramMax.
182  m_PhysicalRanges.free(ramMax, 0x100000000ULL - ramMax);
183  for (unsigned int i = 0; i < translations.getNumTranslations(); i++)
184  {
185  Translations::Translation t = translations.getTranslation(i);
186  // Normally we would check allocateSpecific for success, but it may fail
187  // as things like PCI address spaces can overlap (and RangeList can't
188  // deal with overlapping sections)
189  if (t.phys >= ramMax)
191  static_cast<uint64_t>(t.phys), t.size);
192  }
193 
194  // Initialise the range of virtual space for MemoryRegions
196  KERNEL_VIRTUAL_MEMORYREGION_ADDRESS, KERNEL_VIRTUAL_MEMORYREGION_SIZE);
197 
198  // ...And we're now in normal mode.
199  m_InitialMode = false;
200 }
201 
203 {
207  {
208  if (*it == pRegion)
209  {
210  size_t cPages =
212  uintptr_t start =
213  reinterpret_cast<uintptr_t>(pRegion->virtualAddress());
214  VirtualAddressSpace &virtualAddressSpace =
216  for (size_t i = 0; i < cPages; i++)
217  virtualAddressSpace.unmap(reinterpret_cast<void *>(
218  start + i * PhysicalMemoryManager::getPageSize()));
219  m_MemoryRegions.free(start, pRegion->size());
221  break;
222  }
223  }
224 }
225 
227  : m_Stack(0), m_StackMax(0), m_StackSize(0)
228 {
229 }
230 
232 {
233  if (m_StackSize == 0)
234  panic("No more physical pages left to allocate!");
235  return m_Stack[--m_StackSize];
236 }
237 
239  physical_uintptr_t physicalAddress)
240 {
241  if (m_StackMax <= m_StackSize)
242  {
243  m_StackMax += 0x1000;
244  physical_uintptr_t *oldStack = m_Stack;
245  m_Stack = new physical_uintptr_t[m_StackMax];
246  // Copy over the old stack
247  MemoryCopy(
248  reinterpret_cast<uint8_t *>(m_Stack),
249  reinterpret_cast<uint8_t *>(oldStack), m_StackSize);
250  // Free the old stack ... note that this will probably recurse into a
251  // call to 'free'!
252  delete[] oldStack;
253  }
255 }
void pushBack(const T &value)
Definition: Vector.h:270
virtual void unmap(void *virtualAddress)=0
Iterator end()
Definition: Vector.h:160
static PhysicalMemoryManager & instance()
A vector / dynamic array.
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
void * m_VirtualAddress
Definition: MemoryRegion.h:91
physical_uintptr_t m_PhysicalAddress
Definition: MemoryRegion.h:94
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
void free(T address, T length, bool merge=true)
Definition: RangeList.h:163
size_t m_Size
Definition: MemoryRegion.h:96
#define WARNING(text)
Definition: Log.h:78
uintptr_t physicalAddress(physical_uintptr_t address) PURE
Definition: utils.h:38
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
size_t size() const
Definition: MemoryRegion.cc:49
bool allocateSpecific(T address, T length)
Definition: RangeList.h:280
Implementation of the PhysicalMemoryManager for common ppc.
Translation getTranslation(size_t n)
Definition: Translation.cc:57
void * virtualAddress() const
Definition: MemoryRegion.cc:39
virtual void freePage(physical_uintptr_t page)
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)
void erase(size_t index)
Definition: Vector.h:350
size_t getNumTranslations()
Definition: Translation.cc:62