The Pedigree Project  0.1
x86/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 "../x86_common/PhysicalMemoryManager.h"
22 #include "InterruptManager.h"
23 #include "VirtualAddressSpace.h"
24 #include "gdt.h"
25 #include "pedigree/kernel/process/initialiseMultitasking.h"
26 #include "pedigree/kernel/processor/IoPortManager.h"
27 #include "pedigree/kernel/processor/NMFaultHandler.h"
28 #include "pedigree/kernel/processor/PageFaultHandler.h"
29 #include <SlabAllocator.h>
30 
31 // Multiprocessor headers
32 #if defined(MULTIPROCESSOR)
33 #include "../x86_common/Multiprocessor.h"
34 #endif
35 
36 #define PAT_UC 0x00
37 #define PAT_WC 0x01
38 #define PAT_WT 0x04
39 #define PAT_WP 0x05
40 #define PAT_WB 0x06
41 #define PAT_UCMINUS 0x07
42 
43 union pat
44 {
45  struct
46  {
47  uint32_t pa0 : 3;
48  uint32_t rsvd0 : 5;
49  uint32_t pa1 : 3;
50  uint32_t rsvd1 : 5;
51  uint32_t pa2 : 3;
52  uint32_t rsvd2 : 5;
53  uint32_t pa3 : 3;
54  uint32_t rsvd3 : 5;
55  uint32_t pa4 : 3;
56  uint32_t rsvd4 : 5;
57  uint32_t pa5 : 3;
58  uint32_t rsvd5 : 5;
59  uint32_t pa6 : 3;
60  uint32_t rsvd6 : 5;
61  uint32_t pa7 : 3;
62  uint32_t rsvd7 : 5;
63  } s;
64  uint64_t x;
65 };
66 
68 {
69  const X86VirtualAddressSpace &x86AddressSpace =
70  static_cast<const X86VirtualAddressSpace &>(AddressSpace);
71 
72  // Do we need to set a new page directory?
73  if (readCr3() != x86AddressSpace.m_PhysicalPageDirectory)
74  {
75  // Set the new page directory
76  asm volatile(
77  "mov %0, %%cr3" ::"r"(x86AddressSpace.m_PhysicalPageDirectory));
78 
79  // Update the information in the ProcessorInformation structure
80  ProcessorInformation &processorInformation = Processor::information();
81  processorInformation.setVirtualAddressSpace(AddressSpace);
82  }
83 }
84 
85 physical_uintptr_t Processor::readCr3()
86 {
87  physical_uintptr_t cr3;
88  asm volatile("mov %%cr3, %0" : "=r"(cr3));
89  return cr3;
90 }
91 
93 {
94  // Initialise this processor's interrupt handling
96 
98 
99  // Initialise the physical memory-management
100  X86CommonPhysicalMemoryManager &physicalMemoryManager =
102  physicalMemoryManager.initialise(Info);
103 
104  // Initialise the I/O Manager
105  IoPortManager &ioPortManager = IoPortManager::instance();
106  ioPortManager.initialise(0, 0x10000);
107 
109 
111  // Write PAT MSR.
112  // MSR 0x277
113 
114  /*
115  PAT Entry
116  Memory Type Following Power-up or Reset
117  PAT0 WB
118  PAT1 WT
119  PAT2 UC-
120  PAT3 UC
121  PAT4 WB
122  PAT5 WT
123  PAT6 UC-
124  PAT7 UC
125  */
126  //
127  uint32_t pat_lo, pat_hi;
128  asm volatile("rdmsr" : "=a"(pat_lo), "=d"(pat_hi) : "c"(0x277));
129 
130  union pat p;
131  p.x = pat_lo | (static_cast<uint64_t>(pat_hi) << 32ULL);
132  p.s.pa0 = PAT_WB;
133  p.s.pa1 =
134  PAT_WC; // Redefine PWT in all page entries to mean WC instead of WT.
135  p.s.pa2 = PAT_UCMINUS;
136  p.s.pa3 = PAT_UC;
137  p.s.pa4 = PAT_WB;
138  p.s.pa5 = PAT_WT; // PWT|PAT == WT.
139  p.s.pa6 = PAT_UCMINUS;
140  p.s.pa7 = PAT_UC;
141  pat_lo = static_cast<uint32_t>(p.x);
142  pat_hi = static_cast<uint32_t>(p.x >> 32ULL);
143 
144  asm volatile("wrmsr" ::"a"(pat_lo), "d"(pat_hi), "c"(0x277));
145 
146  m_Initialised = 1;
147 }
148 
150 {
151  m_nProcessors = 1;
152 #if defined(MULTIPROCESSOR)
153  m_nProcessors = Multiprocessor::initialise1();
154 #endif
155 
156  // Initialise the GDT
157  X86GdtManager::instance().initialise(m_nProcessors);
159 
160  initialiseMultitasking();
161 
163 
164  m_Initialised = 2;
165 
166 #if defined(MULTIPROCESSOR)
167  if (m_nProcessors != 1)
169 #endif
170 }
171 
173 {
174  uint32_t eax, ebx, ecx, edx;
175  char ident[13];
176  cpuid(0, 0, eax, ebx, ecx, edx);
177  MemoryCopy(ident, &ebx, 4);
178  MemoryCopy(&ident[4], &edx, 4);
179  MemoryCopy(&ident[8], &ecx, 4);
180  ident[12] = 0;
181  str = ident;
182 }
183 
184 void Processor::setTlsBase(uintptr_t newBase)
185 {
187 
188  // Reload FS/GS
189  uint16_t newseg =
190  newBase ? Processor::information().getTlsSelector() | 3 : 0x23;
191  asm volatile("mov %0, %%bx; mov %%bx, %%fs; mov %%bx, %%gs" ::"r"(newseg)
192  : "ebx");
193 }
Bootstrap structure passed to the kernel entry point.
static void initialiseProcessor() INITIALISATION_ONLY
Definition: x86/gdt.cc:86
static void setTlsBase(uintptr_t newBase)
static void initialise2(const BootstrapStruct_t &Info) INITIALISATION_ONLY
second/last stage in the initialisation of the processor-specific interface
static IoPortManager & instance()
Definition: IoPortManager.h:44
static ProcessorInformation & information()
Definition: Processor.cc:45
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
void setTlsBase(uintptr_t base)
Definition: x86/gdt.cc:119
Manages hardware I/O port (de)allocations.
Definition: IoPortManager.h:38
static PageFaultHandler & instance()
static size_t initialise1() INITIALISATION_ONLY
void initialise(io_port_t ioPortBase, size_t size) INITIALISATION_ONLY
static void initialise1(const BootstrapStruct_t &Info) INITIALISATION_ONLY
first stage in the initialisation of the processor-specific interface
void initialise(size_t processorCount) INITIALISATION_ONLY
Definition: x86/gdt.cc:30
static void initialise2() INITIALISATION_ONLY
static void initialiseProcessor() INITIALISATION_ONLY
static NMFaultHandler & instance()
static void setInterrupts(bool bEnable)
static void identify(HugeStaticString &str)
void initialise(const BootstrapStruct_t &Info) INITIALISATION_ONLY
Implementation of the PhysicalMemoryManager for common x86.
static X86GdtManager & instance()
Definition: x86/gdt.h:35