The Pedigree Project  0.1
armv7/Processor.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 "pedigree/kernel/processor/Processor.h"
21 #include "InterruptManager.h"
22 #include "PhysicalMemoryManager.h"
23 #include "VirtualAddressSpace.h"
24 #include "pedigree/kernel/Log.h"
25 #include "pedigree/kernel/process/initialiseMultitasking.h"
26 
28 {
29  // Initialise the physical memory-management
30  ArmV7PhysicalMemoryManager::instance().initialise(Info);
31 
32  // Initialise this processor's interrupt handling
34 
35  // Map in the base ELF file we loaded from
38 
39  uintptr_t mapBase = reinterpret_cast<uintptr_t>(Info.getModuleBase());
40  size_t mapLen = Info.getModuleCount();
41 
42  for (size_t i = 0; i < mapLen; i += 0x1000)
43  {
44  va.map(
45  mapBase + i, reinterpret_cast<void *>(mapBase + i),
47  }
48 
49  m_Initialised = 1;
50 }
51 
53 {
54 // Initialise multitasking
55 #ifdef THREADS
56  initialiseMultitasking();
57 #endif
58 
59  m_Initialised = 2;
60 }
61 
63 {
64  // Read the Main ID register
65  union
66  {
67  uint32_t data;
68 
69  struct
70  {
71  uint32_t revision : 4;
72  uint32_t partnum : 10;
73  uint32_t arch : 4;
74  uint32_t variant : 4;
75  char implementer;
76  } PACKED;
77  } mainID;
78  asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(mainID.data));
79 
80  // Grab the implementer of this chip
81  switch (mainID.implementer)
82  {
83  case 'A':
84  str += "ARM ";
85  break;
86  case 'D':
87  str += "DEC ";
88  break;
89  case 'M':
90  str += "Motorola/Freescale ";
91  break;
92  case 'Q':
93  str += "Qualcomm ";
94  break;
95  case 'V':
96  str += "Marvell ";
97  break;
98  case 'i':
99  str += "Intel ";
100  break;
101  default:
102  str += "Unknown ";
103  break;
104  }
105 
106  // Grab the architecture
107  switch (mainID.arch)
108  {
109  case 0x1:
110  str += "ARMv4 ";
111  break;
112  case 0x2:
113  str += "ARMv4T ";
114  break;
115  case 0x3:
116  str += "ARMv5 ";
117  break;
118  case 0x4:
119  str += "ARMv5T ";
120  break;
121  case 0x5:
122  str += "ARMv5TE ";
123  break;
124  case 0x6:
125  str += "ARMv5TEJ ";
126  break;
127  case 0x7:
128  str += "ARMv6 ";
129  break;
130  case 0xF:
131  str += "ARMv7 or above ";
132  break;
133  default:
134  str += "(unknown architecture) ";
135  break;
136  }
137 
138  // Append the part number
139  str += "(part number: ";
140  str.append(mainID.partnum);
141  str += ", revision maj=";
142 
143  // Append the revision
144  str.append(mainID.variant);
145  str += " min=";
146  str.append(mainID.revision);
147  str += ")";
148 }
149 
151 {
152  return 0;
153 }
154 
156  size_t nBpNumber, DebugFlags::FaultType &nFaultType, size_t &nLength,
157  bool &bEnabled)
158 {
160  return 0;
161 }
162 
164  size_t nBpNumber, uintptr_t nLinearAddress,
165  DebugFlags::FaultType nFaultType, size_t nLength)
166 {
168 }
169 
170 void Processor::disableDebugBreakpoint(size_t nBpNumber)
171 {
173 }
174 
175 void Processor::setInterrupts(bool bEnable)
176 {
177  bool bCurrent = getInterrupts();
178  if (bCurrent == bEnable)
179  return;
180 
182  if (m_Initialised >= 1) // Interrupts are only initialised at phase 1
183  {
184  uint32_t cpsr = 0;
185  asm volatile("MRS %0, cpsr" : "=r"(cpsr));
186  if (bEnable)
187  cpsr &= ~0x80;
188  else
189  cpsr |= 0x80;
190  asm volatile("MSR cpsr_c, %0" : : "r"(cpsr));
191  }
192 }
193 
195 {
197  if (m_Initialised >= 1) // Interrupts are only initialised at phase 1
198  {
199  uint32_t cpsr = 0;
200  asm volatile("MRS %0, cpsr" : "=r"(cpsr));
201  return !(cpsr & 0x80);
202  }
203  else
204  return false;
205 }
206 
207 void Processor::setSingleStep(bool bEnable, InterruptState &state)
208 {
210  ERROR("Single step unavailable on ARM.");
211 }
212 
214 {
215  const ArmV7VirtualAddressSpace &armAddressSpace =
216  static_cast<const ArmV7VirtualAddressSpace &>(AddressSpace);
217 
218  // Do we need to set a new page directory?
219  if (readTTBR0() != armAddressSpace.m_PhysicalPageDirectory)
220  {
221  // Set the new page directory
222  writeTTBR0(armAddressSpace.m_PhysicalPageDirectory);
223 
224  // Update the information in the ProcessorInformation structure
225  ProcessorInformation &processorInformation = Processor::information();
226  processorInformation.setVirtualAddressSpace(AddressSpace);
227  }
228 }
229 
230 physical_uintptr_t Processor::readTTBR0()
231 {
232  physical_uintptr_t ret = 0;
233  asm volatile("MRC p15,0,%0,c2,c0,0" : "=r"(ret));
234  return ret;
235 }
236 physical_uintptr_t Processor::readTTBR1()
237 {
238  physical_uintptr_t ret = 0;
239  asm volatile("MRC p15,0,%0,c2,c0,1" : "=r"(ret));
240  return ret;
241 }
242 physical_uintptr_t Processor::readTTBCR()
243 {
244  physical_uintptr_t ret = 0;
245  asm volatile("MRC p15,0,%0,c2,c0,2" : "=r"(ret));
246  return ret;
247 }
248 
249 void Processor::writeTTBR0(physical_uintptr_t value)
250 {
251  asm volatile("MCR p15,0,%0,c2,c0,0" : : "r"(value));
252 }
253 void Processor::writeTTBR1(physical_uintptr_t value)
254 {
255  asm volatile("MCR p15,0,%0,c2,c0,1" : : "r"(value));
256 }
257 void Processor::writeTTBCR(uint32_t value)
258 {
259  asm volatile("MCR p15,0,%0,c2,c0,2" : : "r"(value));
260 }
261 
262 void Processor::setTlsBase(uintptr_t newBase)
263 {
264  // Using the user read-only thread and process ID register to store the TLS
265  // base
266  asm volatile("MCR p15,0,%0,c13,c0,3" : : "r"(newBase));
267 }
Bootstrap structure passed to the kernel entry point.
static bool getInterrupts()
static void setTlsBase(uintptr_t newBase)
static uintptr_t getDebugBreakpoint(size_t nBpNumber, DebugFlags::FaultType &nFaultType, size_t &nLength, bool &bEnabled)
static void initialise2(const BootstrapStruct_t &Info) INITIALISATION_ONLY
second/last stage in the initialisation of the processor-specific interface
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
static ProcessorInformation & information()
Definition: Processor.cc:45
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
static void enableDebugBreakpoint(size_t nBpNumber, uintptr_t nLinearAddress, DebugFlags::FaultType nFaultType, size_t nLength)
static void setSingleStep(bool bEnable, InterruptState &state)
static size_t m_Initialised
Definition: Processor.h:371
static void initialise1(const BootstrapStruct_t &Info) INITIALISATION_ONLY
first stage in the initialisation of the processor-specific interface
static void disableDebugBreakpoint(size_t nBpNumber)
static void setInterrupts(bool bEnable)
static void identify(HugeStaticString &str)
#define ERROR(text)
Definition: Log.h:82
static size_t getDebugBreakpointCount()