The Pedigree Project  0.1
x86_common/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 "PhysicalMemoryManager.h"
22 #include "pedigree/kernel/processor/ProcessorInformation.h"
23 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
24 #include "pedigree/kernel/processor/state.h"
25 #include "pedigree/kernel/processor/x86_common/ProcessorInformation.h"
26 #include "pedigree/kernel/utilities/Vector.h"
27 
28 #if defined(X86)
29 #include "../x86/VirtualAddressSpace.h"
30 #else
31 #include "../x64/VirtualAddressSpace.h"
32 #endif
33 
34 #include <machine/mach_pc/LocalApic.h>
35 #include <machine/mach_pc/Pc.h>
36 
38 {
40 #if defined(X86)
41  // Unmap the identity mapping of the first MBs
42  X86VirtualAddressSpace &KernelAddressSpace =
43  static_cast<X86VirtualAddressSpace &>(
45  *reinterpret_cast<uint32_t *>(KernelAddressSpace.m_PhysicalPageDirectory) =
46  0;
47  invalidate(0);
48 #else
49  // Unmap the identity mapping of the first MBs
50  X64VirtualAddressSpace &KernelAddressSpace =
51  static_cast<X64VirtualAddressSpace &>(
53  *reinterpret_cast<uint64_t *>(KernelAddressSpace.m_PhysicalPML4) = 0;
54  invalidate(0);
55 #endif
56 
58 }
59 
61 {
62  return 4;
63 }
64 
66  size_t nBpNumber, DebugFlags::FaultType &nFaultType, size_t &nLength,
67  bool &bEnabled)
68 {
69  uintptr_t nLinearAddress = 0;
70  switch (nBpNumber)
71  {
72  case 0:
73  asm volatile("mov %%db0, %0" : "=r"(nLinearAddress));
74  break;
75  case 1:
76  asm volatile("mov %%db1, %0" : "=r"(nLinearAddress));
77  break;
78  case 2:
79  asm volatile("mov %%db2, %0" : "=r"(nLinearAddress));
80  break;
81  case 3:
82  asm volatile("mov %%db3, %0" : "=r"(nLinearAddress));
83  break;
84  }
85 
86  uintptr_t nStatus;
87  asm volatile("mov %%db7, %0" : "=r"(nStatus));
88 
89  bEnabled = static_cast<bool>(
90  nStatus & (1 << (nBpNumber * 2 + 1))); // See intel manual 3b.
91  nFaultType = static_cast<DebugFlags::FaultType>(
92  (nStatus >> (nBpNumber * 4 + 16)) & 0x3);
93  switch ((nStatus >> (nBpNumber * 4 + 18)) & 0x3)
94  {
95  case 0:
96  nLength = 1;
97  break;
98  case 1:
99  nLength = 2;
100  break;
101  case 2:
102  nLength = 8;
103  break;
104  case 3:
105  nLength = 4;
106  break;
107  }
108 
109  return nLinearAddress;
110 }
111 
113  size_t nBpNumber, uintptr_t nLinearAddress,
114  DebugFlags::FaultType nFaultType, size_t nLength)
115 {
116  switch (nBpNumber)
117  {
118  case 0:
119  asm volatile("mov %0, %%db0" ::"r"(nLinearAddress));
120  break;
121  case 1:
122  asm volatile("mov %0, %%db1" ::"r"(nLinearAddress));
123  break;
124  case 2:
125  asm volatile("mov %0, %%db2" ::"r"(nLinearAddress));
126  break;
127  case 3:
128  asm volatile("mov %0, %%db3" ::"r"(nLinearAddress));
129  break;
130  }
131 
132  uintptr_t nStatus;
133  asm volatile("mov %%db7, %0" : "=r"(nStatus));
134 
135  size_t lengthField = 0;
136  switch (nLength)
137  {
138  case 1:
139  lengthField = 0;
140  break;
141  case 2:
142  lengthField = 1;
143  break;
144  case 8:
145  lengthField = 2;
146  break;
147  case 4:
148  lengthField = 3;
149  break;
150  }
151 
152  nStatus |= 1 << (nBpNumber * 2 + 1);
153  nStatus |= (nFaultType & 0x3) << (nBpNumber * 4 + 16);
154  nStatus |= (lengthField & 0x3) << (nBpNumber * 4 + 18);
155  asm volatile("mov %0, %%db7" ::"r"(nStatus));
156 }
157 
158 void Processor::disableDebugBreakpoint(size_t nBpNumber)
159 {
160  uintptr_t nStatus;
161  asm volatile("mov %%db7, %0" : "=r"(nStatus));
162 
163  nStatus &= ~(1 << (nBpNumber * 2 + 1));
164  asm volatile("mov %0, %%db7" ::"r"(nStatus));
165 }
166 
167 void Processor::setInterrupts(bool bEnable)
168 {
169  if (bEnable)
170  asm volatile("sti");
171  else
172  asm volatile("cli");
173 }
174 
176 {
177  size_t result;
178  asm volatile("pushf\n"
179  "pop %0\n"
180  "and $0x200, %0\n"
181  : "=r"(result));
182  return (result != 0);
183 }
184 
185 void Processor::setSingleStep(bool bEnable, InterruptState &state)
186 {
187  uintptr_t eflags = state.getFlags();
188  if (bEnable)
189  eflags |= 0x100;
190  else
191  eflags &= ~0x100;
192  state.setFlags(eflags);
193 }
194 
196 {
197  uint32_t eax, edx;
198  asm volatile("rdmsr" : "=a"(eax), "=d"(edx) : "c"(index));
199  return static_cast<uint64_t>(eax) | (static_cast<uint64_t>(edx) << 32);
200 }
201 
202 void Processor::writeMachineSpecificRegister(uint32_t index, uint64_t value)
203 {
204  uint32_t eax = value, edx = value >> 32;
205  asm volatile("wrmsr" ::"a"(eax), "d"(edx), "c"(index));
206 }
207 
208 void Processor::invalidate(void *pAddress)
209 {
210  asm volatile("invlpg (%0)" ::"a"(pAddress));
211 }
212 
214  uint32_t inEax, uint32_t inEcx, uint32_t &eax, uint32_t &ebx, uint32_t &ecx,
215  uint32_t &edx)
216 {
217  asm volatile("cpuid"
218  : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
219  : "a"(inEax), "c"(inEcx));
220 }
221 
222 #if defined(MULTIPROCESSOR)
224 {
225  if (m_Initialised < 2)
226  return 0;
227 
228  Pc &pc = Pc::instance();
229  uint8_t apicId = pc.getLocalApic().getId();
230 
231  for (size_t i = 0; i < m_ProcessorInformation.count(); i++)
232  if (m_ProcessorInformation[i]->m_LocalApicId == apicId)
233  return m_ProcessorInformation[i]->m_ProcessorId;
234 
235  return 0;
236 }
237 
238 ProcessorInformation &Processor::information()
239 {
240  if (m_Initialised < 2)
241  return m_SafeBspProcessorInformation;
242 
243  Pc &pc = Pc::instance();
244  uint8_t apicId = pc.getLocalApic().getId();
245 
246  for (size_t i = 0; i < m_ProcessorInformation.count(); i++)
247  if (m_ProcessorInformation[i]->m_LocalApicId == apicId)
248  return *m_ProcessorInformation[i];
249 
250  return m_SafeBspProcessorInformation;
251 }
252 
253 size_t Processor::getCount()
254 {
255  return m_ProcessorInformation.count();
256 }
257 #endif
258 
260 {
261  asm volatile("int $3");
262 }
263 
264 void Processor::halt()
265 {
266  asm volatile("hlt");
267 }
268 
269 void Processor::pause()
270 {
271  asm volatile("pause");
272 }
273 
274 void Processor::reset()
275 {
276  // Load null IDT for now
277  size_t zero = 0x0;
278  asm volatile("lidt %0; int $3" ::"m"(zero));
279 }
280 
282 {
283  bool bWasInterrupts = getInterrupts();
284  __asm__ __volatile__("sti; hlt");
285  if (!bWasInterrupts)
286  setInterrupts(false);
287 }
static uint64_t readMachineSpecificRegister(uint32_t index)
static void cpuid(uint32_t inEax, uint32_t inEcx, uint32_t &eax, uint32_t &ebx, uint32_t &ecx, uint32_t &edx)
static bool getInterrupts()
Definition: Pc.h:49
static uintptr_t getDebugBreakpoint(size_t nBpNumber, DebugFlags::FaultType &nFaultType, size_t &nLength, bool &bEnabled)
static void pause()
static void initialisationDone()
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
static ProcessorInformation & information()
Definition: Processor.cc:45
static void reset()
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 writeMachineSpecificRegister(uint32_t index, uint64_t value)
static void disableDebugBreakpoint(size_t nBpNumber)
static void haltUntilInterrupt()
static void setInterrupts(bool bEnable)
static void halt()
static size_t getCount()
Definition: Processor.cc:50
size_t ProcessorId
static void breakpoint()
static ProcessorId id()
Definition: Processor.cc:40
static ProcessorInformation m_ProcessorInformation
Definition: Processor.h:386
static size_t getDebugBreakpointCount()
static void invalidate(void *pAddress)