The Pedigree Project 0.1
x64/state.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 "pedigree/kernel/processor/state.h"
22#include "pedigree/kernel/processor/types.h"
23
24static const char* X64InterruptStateRegisterName[18] = {
25 "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "r8", "r9",
26 "r10", "r11", "r12", "r13", "r14", "r15", "rsp", "rip", "rflags"};
27
28static const char* X64SyscallStateRegisterName[16] = {"rax", "rbx", "rdx", "rdi", "rsi", "rbp",
29 "r8", "r9", "r10", "r12", "r13", "r14",
30 "r15", "rsp", "rip", "rflags"};
31
33 return 18;
34}
35processor_register_t X64InterruptState::getRegister(size_t index) const {
36 if (index == 0)
37 return m_Rax;
38 if (index == 1)
39 return m_Rbx;
40 if (index == 2)
41 return m_Rcx;
42 if (index == 3)
43 return m_Rdx;
44 if (index == 4)
45 return m_Rdi;
46 if (index == 5)
47 return m_Rsi;
48 if (index == 6)
49 return m_Rbp;
50 if (index == 7)
51 return m_R8;
52 if (index == 8)
53 return m_R9;
54 if (index == 9)
55 return m_R10;
56 if (index == 10)
57 return m_R11;
58 if (index == 11)
59 return m_R12;
60 if (index == 12)
61 return m_R13;
62 if (index == 13)
63 return m_R14;
64 if (index == 14)
65 return m_R15;
66 if (index == 15)
67 return getStackPointer();
68 if (index == 16)
69 return m_Rip;
70 if (index == 17)
71 return m_Rflags;
72 return 0;
73}
74void X64InterruptState::setRegister(size_t index, uintptr_t value) {
75 if (index == 0)
76 m_Rax = value;
77 if (index == 1)
78 m_Rbx = value;
79 if (index == 2)
80 m_Rcx = value;
81 if (index == 3)
82 m_Rdx = value;
83 if (index == 4)
84 m_Rdi = value;
85 if (index == 5)
86 m_Rsi = value;
87 if (index == 6)
88 m_Rbp = value;
89 if (index == 7)
90 m_R8 = value;
91 if (index == 8)
92 m_R9 = value;
93 if (index == 9)
94 m_R10 = value;
95 if (index == 10)
96 m_R11 = value;
97 if (index == 11)
98 m_R12 = value;
99 if (index == 12)
100 m_R13 = value;
101 if (index == 13)
102 m_R14 = value;
103 if (index == 14)
104 m_R15 = value;
105 if (index == 15)
106 m_Rsp = value;
107 if (index == 16)
108 m_Rip = value;
109 if (index == 17)
110 m_Rflags = value;
111}
112const char* X64InterruptState::getRegisterName(size_t index) const {
113 return X64InterruptStateRegisterName[index];
114}
115
117 return 16;
118}
119processor_register_t X64SyscallState::getRegister(size_t index) const {
120 if (index == 0)
121 return m_Rax;
122 if (index == 1)
123 return m_Rbx;
124 if (index == 2)
125 return m_Rdx;
126 if (index == 3)
127 return m_Rdi;
128 if (index == 4)
129 return m_Rsi;
130 if (index == 5)
131 return m_Rbp;
132 if (index == 6)
133 return m_R8;
134 if (index == 7)
135 return m_R9;
136 if (index == 8)
137 return m_R10;
138 if (index == 9)
139 return m_R12;
140 if (index == 10)
141 return m_R13;
142 if (index == 11)
143 return m_R14;
144 if (index == 12)
145 return m_R15;
146 if (index == 13)
147 return m_Rsp;
148 if (index == 14)
149 return m_RipRcx;
150 if (index == 15)
151 return m_RFlagsR11;
152 return 0;
153}
154void X64SyscallState::setRegister(size_t index, uintptr_t value) {
155 if (index == 0)
156 m_Rax = value;
157 if (index == 1)
158 m_Rbx = value;
159 if (index == 2)
160 m_Rdx = value;
161 if (index == 3)
162 m_Rdi = value;
163 if (index == 4)
164 m_Rsi = value;
165 if (index == 5)
166 m_Rbp = value;
167 if (index == 6)
168 m_R8 = value;
169 if (index == 7)
170 m_R9 = value;
171 if (index == 8)
172 m_R10 = value;
173 if (index == 9)
174 m_R12 = value;
175 if (index == 10)
176 m_R13 = value;
177 if (index == 11)
178 m_R14 = value;
179 if (index == 12)
180 m_R15 = value;
181 if (index == 13)
182 m_Rsp = value;
183 if (index == 14)
184 m_RipRcx = value;
185 if (index == 15)
186 m_RFlagsR11 = value;
187}
188const char* X64SyscallState::getRegisterName(size_t index) const {
189 return X64SyscallStateRegisterName[index];
190}
191
193 const X64UserEntryMetadata& metadata) {
194 // Obtain the stack pointer.
195 uintptr_t* pStack = reinterpret_cast<uintptr_t*>(state.getStackPointer());
196
197 *--pStack = (userMode) ? 0x23 : 0x10; // SS
198 *--pStack = state.rsp; // RSP
199 *--pStack = 0x200; // RFLAGS - IF enabled.
200 *--pStack = (userMode) ? 0x1b : 0x08; // CS
201 *--pStack = state.rip; // RIP
202 *--pStack = 0; // Error code
203 *--pStack = 0; // Interrupt number
204 *--pStack = state.rax; // RAX
205 *--pStack = state.rbx; // RBX
206 *--pStack = state.rcx; // RCX
207 *--pStack = state.rdx; // RDX
208 *--pStack = state.rdi; // RDI
209 *--pStack = state.rsi; // RSI
210 *--pStack = state.rbp; // RBP
211 *--pStack = state.r8;
212 *--pStack = state.r9;
213 *--pStack = state.r10;
214 *--pStack = state.r11;
215 *--pStack = state.r12;
216 *--pStack = state.r13;
217 *--pStack = state.r14;
218 *--pStack = state.r15;
219
220 pStack -= sizeof(X64UserEntryMetadata) / sizeof(uintptr_t);
221 X64InterruptState* toRet = reinterpret_cast<X64InterruptState*>(pStack);
222 toRet->setUserEntryMetadata(metadata);
223
224 return toRet;
225}
226
227#if X64 && !HOSTED
228namespace {
229uint64_t installedUserTlsBase() {
230 uint32_t low, high;
231 asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(0xc0000100));
232 return (uint64_t(high) << 32) | low;
233}
234} // namespace
235void X64InterruptState::refreshUserTlsBase() {
236 pedigree_materialize_user_entry();
237 m_UserEntry.fsBase = installedUserTlsBase();
238 m_UserEntry.gsBase = Processor::getUserGsBase();
239}
240void X64SyscallState::refreshUserTlsBase() {
241 pedigree_materialize_user_entry();
242 m_UserEntry.fsBase = installedUserTlsBase();
243 m_UserEntry.gsBase = Processor::getUserGsBase();
244}
245#endif
size_t getRegisterCount() const
Definition x64/state.cc:32
uintptr_t getStackPointer() const
Definition x64/state.h:430
const char * getRegisterName(size_t index) const
Definition x64/state.cc:112
processor_register_t getRegister(size_t index) const
Definition x64/state.cc:35
uint64_t m_Rflags
Definition x64/state.h:191
static X64InterruptState * construct(class X64ProcessorState &state, bool userMode, const X64UserEntryMetadata &metadata)
Definition x64/state.cc:192
void setRegister(size_t index, uintptr_t value)
Definition x64/state.cc:74
uintptr_t getStackPointer() const
Definition x64/state.h:691
uint64_t m_Rsi
Definition x64/state.h:301
EXPORTED_PUBLIC processor_register_t getRegister(size_t index) const
Definition x64/state.cc:119
uint64_t m_RFlagsR11
Definition x64/state.h:313
uint64_t m_Rdi
Definition x64/state.h:303
uint64_t m_Rax
Definition x64/state.h:311
uint64_t m_R10
Definition x64/state.h:291
const char * getRegisterName(size_t index) const
Definition x64/state.cc:188
uint64_t m_Rsp
Definition x64/state.h:317
uint64_t m_Rdx
Definition x64/state.h:307
size_t getRegisterCount() const
Definition x64/state.cc:116
uint64_t m_RipRcx
Definition x64/state.h:315
uint64_t m_R9
Definition x64/state.h:293
uint64_t m_R12
Definition x64/state.h:289
uint64_t m_Rbp
Definition x64/state.h:297
uint64_t m_Rbx
Definition x64/state.h:309
uint64_t m_R14
Definition x64/state.h:285
uint64_t m_R13
Definition x64/state.h:287
uint64_t m_R15
Definition x64/state.h:283
uint64_t m_R8
Definition x64/state.h:295
EXPORTED_PUBLIC void setRegister(size_t index, uintptr_t value)
Definition x64/state.cc:154