The Pedigree Project  0.1
Translation.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 "Translation.h"
21 #include "pedigree/kernel/Log.h"
22 #include "pedigree/kernel/machine/openfirmware/Device.h"
23 #include "pedigree/kernel/machine/openfirmware/OpenFirmware.h"
24 #include "pedigree/kernel/panic.h"
25 
26 Translations::Translations() : m_nTranslations(0)
27 {
28  // Get the current translations list.
29  OFDevice chosen(OpenFirmware::instance().findDevice("/chosen"));
30  OFDevice mmu(chosen.getProperty("mmu"));
31 
32  if (mmu.getProperty(
33  "translations", m_pTranslations,
34  sizeof(Translation) * NUM_TRANSLATIONS) == -1)
35  {
36  // We have to panic, because otherwise Processor would try to change
37  // page tables with no translation entries in!
38  panic("Translations not detected correctly");
39  return;
40  }
41 
42  m_nTranslations =
43  mmu.getPropertyLength("translations") / sizeof(Translation);
44  for (unsigned int i = 0; i < m_nTranslations; i++)
45  {
46  NOTICE(
47  "T: " << Hex << m_pTranslations[i].virt << ", "
48  << m_pTranslations[i].phys << ", " << m_pTranslations[i].size
49  << ", " << m_pTranslations[i].mode);
50  }
51 }
52 
53 Translations::~Translations()
54 {
55 }
56 
58 {
59  return m_pTranslations[n];
60 }
61 
63 {
64  return m_nTranslations;
65 }
66 
68  uint32_t virt, uint32_t phys, uint32_t size, uint32_t mode)
69 {
70  m_pTranslations[m_nTranslations].virt = virt;
71  m_pTranslations[m_nTranslations].phys = phys;
72  m_pTranslations[m_nTranslations].size = size;
73  m_pTranslations[m_nTranslations].mode = mode;
74  m_nTranslations++;
75  if (m_nTranslations >= NUM_TRANSLATIONS)
76  panic("Too many translations!");
77 }
78 
80 uint32_t Translations::findFreePhysicalMemory(uint32_t size, uint32_t align)
81 {
82  // Quickly grab the SDR1 value so that we don't accidentally overwrite it.
83  uint32_t sdr1;
84  asm volatile("mfsdr1 %0" : "=r"(sdr1));
85  sdr1 &= 0xFFFFF000;
86 
87  // For every page on an 'align' boundary...
88  for (uint32_t i = 0x000000; i < 0xFFFFFFFF - align; i += align)
89  {
90  uint32_t addr = i;
91  // Is this address taken?
92  bool taken = false;
93 
94  for (unsigned int j = 0; j < m_nTranslations; j++)
95  {
96  // We're looking for the two regions to be disjoint.
97  // Start address in our range?
98  if ((m_pTranslations[j].phys >= addr) &&
99  (m_pTranslations[j].phys < addr + size))
100  {
101  taken = true;
102  break;
103  }
104  // End address in our range?
105  uint32_t end = m_pTranslations[j].phys + m_pTranslations[j].size;
106  if ((end >= addr) && (end < addr + size))
107  {
108  taken = true;
109  break;
110  }
111  }
112  // Check SDR1
113  if ((sdr1 >= addr && sdr1 < addr + size) ||
114  ((sdr1 + 0x1000000) >= addr && (sdr1 + 0x1000000) < (addr + size)))
115  taken = true;
116  if (!taken)
117  return addr;
118  }
119  return 0;
120 }
121 
122 void Translations::removeRange(uintptr_t start, uintptr_t end)
123 {
124  bool removed = true;
125  while (removed)
126  {
127  removed = false;
128  for (unsigned int i = 0; i < m_nTranslations; i++)
129  {
130  if (m_pTranslations[i].virt >= start &&
131  m_pTranslations[i].virt < end)
132  {
133  // Remove this translation.
134  removed = true;
135  for (; i < m_nTranslations; i++)
136  m_pTranslations[i] = m_pTranslations[i + 1];
137  m_nTranslations--;
138  // Start again.
139  break;
140  }
141  }
142  }
143 }
void removeRange(uintptr_t start, uintptr_t end)
Definition: Translation.cc:122
static OpenFirmware & instance()
Definition: OpenFirmware.h:45
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
Translation getTranslation(size_t n)
Definition: Translation.cc:57
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
void addTranslation(uint32_t virt, uint32_t phys, uint32_t size, uint32_t mode)
Definition: Translation.cc:67
uint32_t findFreePhysicalMemory(uint32_t size, uint32_t align=0x100000)
Definition: Translation.cc:80
size_t getNumTranslations()
Definition: Translation.cc:62