blob: ae877f0022b816c0b5487f255612e816dccee2c8 [file] [log] [blame]
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -05001/*
2 * Copyright (C) 2016 Veertu Inc,
3 * Copyright (C) 2017 Veertu Inc,
4 *
5 * This program is free software; you can redistribute it and/or
Sergio Andres Gomez Del Real996feed2017-09-13 04:05:11 -05006 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -05009 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergio Andres Gomez Del Real996feed2017-09-13 04:05:11 -050012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -050014 *
Sergio Andres Gomez Del Real996feed2017-09-13 04:05:11 -050015 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -050017 */
18
Paolo Bonzinif9fea772017-10-03 15:36:05 +020019#ifndef HVF_X86_H
20#define HVF_X86_H 1
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -050021
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -050022#include "x86_gen.h"
23
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -050024typedef struct x86_register {
25 union {
26 struct {
27 uint64_t rrx; /* full 64 bit */
28 };
29 struct {
30 uint32_t erx; /* low 32 bit part */
31 uint32_t hi32_unused1;
32 };
33 struct {
34 uint16_t rx; /* low 16 bit part */
35 uint16_t hi16_unused1;
36 uint32_t hi32_unused2;
37 };
38 struct {
39 uint8_t lx; /* low 8 bit part */
40 uint8_t hx; /* high 8 bit */
41 uint16_t hi16_unused2;
42 uint32_t hi32_unused3;
43 };
44 };
45} __attribute__ ((__packed__)) x86_register;
46
47typedef enum x86_rflags {
48 RFLAGS_CF = (1L << 0),
49 RFLAGS_PF = (1L << 2),
50 RFLAGS_AF = (1L << 4),
51 RFLAGS_ZF = (1L << 6),
52 RFLAGS_SF = (1L << 7),
53 RFLAGS_TF = (1L << 8),
54 RFLAGS_IF = (1L << 9),
55 RFLAGS_DF = (1L << 10),
56 RFLAGS_OF = (1L << 11),
57 RFLAGS_IOPL = (3L << 12),
58 RFLAGS_NT = (1L << 14),
59 RFLAGS_RF = (1L << 16),
60 RFLAGS_VM = (1L << 17),
61 RFLAGS_AC = (1L << 18),
62 RFLAGS_VIF = (1L << 19),
63 RFLAGS_VIP = (1L << 20),
64 RFLAGS_ID = (1L << 21),
65} x86_rflags;
66
67/* rflags register */
68typedef struct x86_reg_flags {
69 union {
70 struct {
71 uint64_t rflags;
72 };
73 struct {
74 uint32_t eflags;
75 uint32_t hi32_unused1;
76 };
77 struct {
78 uint32_t cf:1;
79 uint32_t unused1:1;
80 uint32_t pf:1;
81 uint32_t unused2:1;
82 uint32_t af:1;
83 uint32_t unused3:1;
84 uint32_t zf:1;
85 uint32_t sf:1;
86 uint32_t tf:1;
87 uint32_t ief:1;
88 uint32_t df:1;
89 uint32_t of:1;
90 uint32_t iopl:2;
91 uint32_t nt:1;
92 uint32_t unused4:1;
93 uint32_t rf:1;
94 uint32_t vm:1;
95 uint32_t ac:1;
96 uint32_t vif:1;
97 uint32_t vip:1;
98 uint32_t id:1;
99 uint32_t unused5:10;
100 uint32_t hi32_unused2;
101 };
102 };
103} __attribute__ ((__packed__)) x86_reg_flags;
104
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500105typedef enum x86_reg_cr0 {
106 CR0_PE = (1L << 0),
107 CR0_MP = (1L << 1),
108 CR0_EM = (1L << 2),
109 CR0_TS = (1L << 3),
110 CR0_ET = (1L << 4),
111 CR0_NE = (1L << 5),
112 CR0_WP = (1L << 16),
113 CR0_AM = (1L << 18),
114 CR0_NW = (1L << 29),
115 CR0_CD = (1L << 30),
116 CR0_PG = (1L << 31),
117} x86_reg_cr0;
118
119typedef enum x86_reg_cr4 {
120 CR4_VME = (1L << 0),
121 CR4_PVI = (1L << 1),
122 CR4_TSD = (1L << 2),
123 CR4_DE = (1L << 3),
124 CR4_PSE = (1L << 4),
125 CR4_PAE = (1L << 5),
126 CR4_MSE = (1L << 6),
127 CR4_PGE = (1L << 7),
128 CR4_PCE = (1L << 8),
129 CR4_OSFXSR = (1L << 9),
130 CR4_OSXMMEXCPT = (1L << 10),
131 CR4_VMXE = (1L << 13),
132 CR4_SMXE = (1L << 14),
133 CR4_FSGSBASE = (1L << 16),
134 CR4_PCIDE = (1L << 17),
135 CR4_OSXSAVE = (1L << 18),
136 CR4_SMEP = (1L << 20),
137} x86_reg_cr4;
138
139/* 16 bit Task State Segment */
140typedef struct x86_tss_segment16 {
141 uint16_t link;
142 uint16_t sp0;
143 uint16_t ss0;
144 uint32_t sp1;
145 uint16_t ss1;
146 uint32_t sp2;
147 uint16_t ss2;
148 uint16_t ip;
149 uint16_t flags;
150 uint16_t ax;
151 uint16_t cx;
152 uint16_t dx;
153 uint16_t bx;
154 uint16_t sp;
155 uint16_t bp;
156 uint16_t si;
157 uint16_t di;
158 uint16_t es;
159 uint16_t cs;
160 uint16_t ss;
161 uint16_t ds;
162 uint16_t ldtr;
163} __attribute__((packed)) x86_tss_segment16;
164
165/* 32 bit Task State Segment */
166typedef struct x86_tss_segment32 {
167 uint32_t prev_tss;
168 uint32_t esp0;
169 uint32_t ss0;
170 uint32_t esp1;
171 uint32_t ss1;
172 uint32_t esp2;
173 uint32_t ss2;
174 uint32_t cr3;
175 uint32_t eip;
176 uint32_t eflags;
177 uint32_t eax;
178 uint32_t ecx;
179 uint32_t edx;
180 uint32_t ebx;
181 uint32_t esp;
182 uint32_t ebp;
183 uint32_t esi;
184 uint32_t edi;
185 uint32_t es;
186 uint32_t cs;
187 uint32_t ss;
188 uint32_t ds;
189 uint32_t fs;
190 uint32_t gs;
191 uint32_t ldt;
192 uint16_t trap;
193 uint16_t iomap_base;
194} __attribute__ ((__packed__)) x86_tss_segment32;
195
196/* 64 bit Task State Segment */
197typedef struct x86_tss_segment64 {
198 uint32_t unused;
199 uint64_t rsp0;
200 uint64_t rsp1;
201 uint64_t rsp2;
202 uint64_t unused1;
203 uint64_t ist1;
204 uint64_t ist2;
205 uint64_t ist3;
206 uint64_t ist4;
207 uint64_t ist5;
208 uint64_t ist6;
209 uint64_t ist7;
210 uint64_t unused2;
211 uint16_t unused3;
212 uint16_t iomap_base;
213} __attribute__ ((__packed__)) x86_tss_segment64;
214
215/* segment descriptors */
216typedef struct x86_segment_descriptor {
217 uint64_t limit0:16;
218 uint64_t base0:16;
219 uint64_t base1:8;
220 uint64_t type:4;
221 uint64_t s:1;
222 uint64_t dpl:2;
223 uint64_t p:1;
224 uint64_t limit1:4;
225 uint64_t avl:1;
226 uint64_t l:1;
227 uint64_t db:1;
228 uint64_t g:1;
229 uint64_t base2:8;
230} __attribute__ ((__packed__)) x86_segment_descriptor;
231
232static inline uint32_t x86_segment_base(x86_segment_descriptor *desc)
233{
234 return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0);
235}
236
237static inline void x86_set_segment_base(x86_segment_descriptor *desc,
238 uint32_t base)
239{
240 desc->base2 = base >> 24;
241 desc->base1 = (base >> 16) & 0xff;
242 desc->base0 = base & 0xffff;
243}
244
245static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc)
246{
247 uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0);
248 if (desc->g) {
249 return (limit << 12) | 0xfff;
250 }
251 return limit;
252}
253
254static inline void x86_set_segment_limit(x86_segment_descriptor *desc,
255 uint32_t limit)
256{
257 desc->limit0 = limit & 0xffff;
258 desc->limit1 = limit >> 16;
259}
260
261typedef struct x86_call_gate {
262 uint64_t offset0:16;
263 uint64_t selector:16;
264 uint64_t param_count:4;
265 uint64_t reserved:3;
266 uint64_t type:4;
267 uint64_t dpl:1;
268 uint64_t p:1;
269 uint64_t offset1:16;
270} __attribute__ ((__packed__)) x86_call_gate;
271
272static inline uint32_t x86_call_gate_offset(x86_call_gate *gate)
273{
274 return (uint32_t)((gate->offset1 << 16) | gate->offset0);
275}
276
277#define LDT_SEL 0
278#define GDT_SEL 1
279
280typedef struct x68_segment_selector {
281 union {
282 uint16_t sel;
283 struct {
284 uint16_t rpl:3;
285 uint16_t ti:1;
286 uint16_t index:12;
287 };
288 };
289} __attribute__ ((__packed__)) x68_segment_selector;
290
291typedef struct lazy_flags {
Paolo Bonziniff2de162017-10-03 15:17:37 +0200292 target_ulong result;
293 target_ulong auxbits;
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500294} lazy_flags;
295
296/* Definition of hvf_x86_state is here */
297struct HVFX86EmulatorState {
298 int interruptable;
299 uint64_t fetch_rip;
300 uint64_t rip;
301 struct x86_register regs[16];
302 struct x86_reg_flags rflags;
303 struct lazy_flags lflags;
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500304 uint8_t mmio_buf[4096];
305};
306
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500307/* useful register access macros */
308#define RIP(cpu) (cpu->hvf_emul->rip)
309#define EIP(cpu) ((uint32_t)cpu->hvf_emul->rip)
310#define RFLAGS(cpu) (cpu->hvf_emul->rflags.rflags)
311#define EFLAGS(cpu) (cpu->hvf_emul->rflags.eflags)
312
313#define RRX(cpu, reg) (cpu->hvf_emul->regs[reg].rrx)
Paolo Bonzini6701d812017-10-03 13:59:15 +0200314#define RAX(cpu) RRX(cpu, R_EAX)
315#define RCX(cpu) RRX(cpu, R_ECX)
316#define RDX(cpu) RRX(cpu, R_EDX)
317#define RBX(cpu) RRX(cpu, R_EBX)
318#define RSP(cpu) RRX(cpu, R_ESP)
319#define RBP(cpu) RRX(cpu, R_EBP)
320#define RSI(cpu) RRX(cpu, R_ESI)
321#define RDI(cpu) RRX(cpu, R_EDI)
322#define R8(cpu) RRX(cpu, R_R8)
323#define R9(cpu) RRX(cpu, R_R9)
324#define R10(cpu) RRX(cpu, R_R10)
325#define R11(cpu) RRX(cpu, R_R11)
326#define R12(cpu) RRX(cpu, R_R12)
327#define R13(cpu) RRX(cpu, R_R13)
328#define R14(cpu) RRX(cpu, R_R14)
329#define R15(cpu) RRX(cpu, R_R15)
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500330
331#define ERX(cpu, reg) (cpu->hvf_emul->regs[reg].erx)
Paolo Bonzini6701d812017-10-03 13:59:15 +0200332#define EAX(cpu) ERX(cpu, R_EAX)
333#define ECX(cpu) ERX(cpu, R_ECX)
334#define EDX(cpu) ERX(cpu, R_EDX)
335#define EBX(cpu) ERX(cpu, R_EBX)
336#define ESP(cpu) ERX(cpu, R_ESP)
337#define EBP(cpu) ERX(cpu, R_EBP)
338#define ESI(cpu) ERX(cpu, R_ESI)
339#define EDI(cpu) ERX(cpu, R_EDI)
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500340
341#define RX(cpu, reg) (cpu->hvf_emul->regs[reg].rx)
Paolo Bonzini6701d812017-10-03 13:59:15 +0200342#define AX(cpu) RX(cpu, R_EAX)
343#define CX(cpu) RX(cpu, R_ECX)
344#define DX(cpu) RX(cpu, R_EDX)
345#define BP(cpu) RX(cpu, R_EBP)
346#define SP(cpu) RX(cpu, R_ESP)
347#define BX(cpu) RX(cpu, R_EBX)
348#define SI(cpu) RX(cpu, R_ESI)
349#define DI(cpu) RX(cpu, R_EDI)
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500350
351#define RL(cpu, reg) (cpu->hvf_emul->regs[reg].lx)
Paolo Bonzini6701d812017-10-03 13:59:15 +0200352#define AL(cpu) RL(cpu, R_EAX)
353#define CL(cpu) RL(cpu, R_ECX)
354#define DL(cpu) RL(cpu, R_EDX)
355#define BL(cpu) RL(cpu, R_EBX)
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500356
357#define RH(cpu, reg) (cpu->hvf_emul->regs[reg].hx)
Paolo Bonzini6701d812017-10-03 13:59:15 +0200358#define AH(cpu) RH(cpu, R_EAX)
359#define CH(cpu) RH(cpu, R_ECX)
360#define DH(cpu) RH(cpu, R_EDX)
361#define BH(cpu) RH(cpu, R_EBX)
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500362
363/* deal with GDT/LDT descriptors in memory */
364bool x86_read_segment_descriptor(struct CPUState *cpu,
365 struct x86_segment_descriptor *desc,
366 x68_segment_selector sel);
367bool x86_write_segment_descriptor(struct CPUState *cpu,
368 struct x86_segment_descriptor *desc,
369 x68_segment_selector sel);
370
371bool x86_read_call_gate(struct CPUState *cpu, struct x86_call_gate *idt_desc,
372 int gate);
373
374/* helpers */
375bool x86_is_protected(struct CPUState *cpu);
376bool x86_is_real(struct CPUState *cpu);
377bool x86_is_v8086(struct CPUState *cpu);
378bool x86_is_long_mode(struct CPUState *cpu);
379bool x86_is_long64_mode(struct CPUState *cpu);
380bool x86_is_paging_mode(struct CPUState *cpu);
381bool x86_is_pae_enabled(struct CPUState *cpu);
382
Paolo Bonzini6701d812017-10-03 13:59:15 +0200383enum X86Seg;
Paolo Bonziniff2de162017-10-03 15:17:37 +0200384target_ulong linear_addr(struct CPUState *cpu, target_ulong addr, enum X86Seg seg);
385target_ulong linear_addr_size(struct CPUState *cpu, target_ulong addr, int size,
386 enum X86Seg seg);
387target_ulong linear_rip(struct CPUState *cpu, target_ulong rip);
Sergio Andres Gomez Del Realc97d6d22017-09-13 04:05:09 -0500388
389static inline uint64_t rdtscp(void)
390{
391 uint64_t tsc;
392 __asm__ __volatile__("rdtscp; " /* serializing read of tsc */
393 "shl $32,%%rdx; " /* shift higher 32 bits stored in rdx up */
394 "or %%rdx,%%rax" /* and or onto rax */
395 : "=a"(tsc) /* output to tsc variable */
396 :
397 : "%rcx", "%rdx"); /* rcx and rdx are clobbered */
398
399 return tsc;
400}
401
Paolo Bonzinif9fea772017-10-03 15:36:05 +0200402#endif