xref: /openbmc/qemu/target/i386/emulate/x86.h (revision eebba0536a6302f5c55faa5286e5e59cb21036c3)
1*27458df8SWei Liu /*
2*27458df8SWei Liu  * Copyright (C) 2016 Veertu Inc,
3*27458df8SWei Liu  * Copyright (C) 2017 Veertu Inc,
4*27458df8SWei Liu  *
5*27458df8SWei Liu  * This program is free software; you can redistribute it and/or
6*27458df8SWei Liu  * modify it under the terms of the GNU Lesser General Public
7*27458df8SWei Liu  * License as published by the Free Software Foundation; either
8*27458df8SWei Liu  * version 2.1 of the License, or (at your option) any later version.
9*27458df8SWei Liu  *
10*27458df8SWei Liu  * This program is distributed in the hope that it will be useful,
11*27458df8SWei Liu  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*27458df8SWei Liu  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*27458df8SWei Liu  * Lesser General Public License for more details.
14*27458df8SWei Liu  *
15*27458df8SWei Liu  * You should have received a copy of the GNU Lesser General Public
16*27458df8SWei Liu  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
17*27458df8SWei Liu  */
18*27458df8SWei Liu 
19*27458df8SWei Liu #ifndef X86_EMU_DEFS_H
20*27458df8SWei Liu #define X86_EMU_DEFS_H
21*27458df8SWei Liu 
22*27458df8SWei Liu typedef struct x86_register {
23*27458df8SWei Liu     union {
24*27458df8SWei Liu         struct {
25*27458df8SWei Liu             uint64_t rrx;               /* full 64 bit */
26*27458df8SWei Liu         };
27*27458df8SWei Liu         struct {
28*27458df8SWei Liu             uint32_t erx;               /* low 32 bit part */
29*27458df8SWei Liu             uint32_t hi32_unused1;
30*27458df8SWei Liu         };
31*27458df8SWei Liu         struct {
32*27458df8SWei Liu             uint16_t rx;                /* low 16 bit part */
33*27458df8SWei Liu             uint16_t hi16_unused1;
34*27458df8SWei Liu             uint32_t hi32_unused2;
35*27458df8SWei Liu         };
36*27458df8SWei Liu         struct {
37*27458df8SWei Liu             uint8_t lx;                 /* low 8 bit part */
38*27458df8SWei Liu             uint8_t hx;                 /* high 8 bit */
39*27458df8SWei Liu             uint16_t hi16_unused2;
40*27458df8SWei Liu             uint32_t hi32_unused3;
41*27458df8SWei Liu         };
42*27458df8SWei Liu     };
43*27458df8SWei Liu } __attribute__ ((__packed__)) x86_register;
44*27458df8SWei Liu 
45*27458df8SWei Liu /* 16 bit Task State Segment */
46*27458df8SWei Liu typedef struct x86_tss_segment16 {
47*27458df8SWei Liu     uint16_t link;
48*27458df8SWei Liu     uint16_t sp0;
49*27458df8SWei Liu     uint16_t ss0;
50*27458df8SWei Liu     uint32_t sp1;
51*27458df8SWei Liu     uint16_t ss1;
52*27458df8SWei Liu     uint32_t sp2;
53*27458df8SWei Liu     uint16_t ss2;
54*27458df8SWei Liu     uint16_t ip;
55*27458df8SWei Liu     uint16_t flags;
56*27458df8SWei Liu     uint16_t ax;
57*27458df8SWei Liu     uint16_t cx;
58*27458df8SWei Liu     uint16_t dx;
59*27458df8SWei Liu     uint16_t bx;
60*27458df8SWei Liu     uint16_t sp;
61*27458df8SWei Liu     uint16_t bp;
62*27458df8SWei Liu     uint16_t si;
63*27458df8SWei Liu     uint16_t di;
64*27458df8SWei Liu     uint16_t es;
65*27458df8SWei Liu     uint16_t cs;
66*27458df8SWei Liu     uint16_t ss;
67*27458df8SWei Liu     uint16_t ds;
68*27458df8SWei Liu     uint16_t ldtr;
69*27458df8SWei Liu } __attribute__((packed)) x86_tss_segment16;
70*27458df8SWei Liu 
71*27458df8SWei Liu /* 32 bit Task State Segment */
72*27458df8SWei Liu typedef struct x86_tss_segment32 {
73*27458df8SWei Liu     uint32_t prev_tss;
74*27458df8SWei Liu     uint32_t esp0;
75*27458df8SWei Liu     uint32_t ss0;
76*27458df8SWei Liu     uint32_t esp1;
77*27458df8SWei Liu     uint32_t ss1;
78*27458df8SWei Liu     uint32_t esp2;
79*27458df8SWei Liu     uint32_t ss2;
80*27458df8SWei Liu     uint32_t cr3;
81*27458df8SWei Liu     uint32_t eip;
82*27458df8SWei Liu     uint32_t eflags;
83*27458df8SWei Liu     uint32_t eax;
84*27458df8SWei Liu     uint32_t ecx;
85*27458df8SWei Liu     uint32_t edx;
86*27458df8SWei Liu     uint32_t ebx;
87*27458df8SWei Liu     uint32_t esp;
88*27458df8SWei Liu     uint32_t ebp;
89*27458df8SWei Liu     uint32_t esi;
90*27458df8SWei Liu     uint32_t edi;
91*27458df8SWei Liu     uint32_t es;
92*27458df8SWei Liu     uint32_t cs;
93*27458df8SWei Liu     uint32_t ss;
94*27458df8SWei Liu     uint32_t ds;
95*27458df8SWei Liu     uint32_t fs;
96*27458df8SWei Liu     uint32_t gs;
97*27458df8SWei Liu     uint32_t ldt;
98*27458df8SWei Liu     uint16_t trap;
99*27458df8SWei Liu     uint16_t iomap_base;
100*27458df8SWei Liu } __attribute__ ((__packed__)) x86_tss_segment32;
101*27458df8SWei Liu 
102*27458df8SWei Liu /* 64 bit Task State Segment */
103*27458df8SWei Liu typedef struct x86_tss_segment64 {
104*27458df8SWei Liu     uint32_t unused;
105*27458df8SWei Liu     uint64_t rsp0;
106*27458df8SWei Liu     uint64_t rsp1;
107*27458df8SWei Liu     uint64_t rsp2;
108*27458df8SWei Liu     uint64_t unused1;
109*27458df8SWei Liu     uint64_t ist1;
110*27458df8SWei Liu     uint64_t ist2;
111*27458df8SWei Liu     uint64_t ist3;
112*27458df8SWei Liu     uint64_t ist4;
113*27458df8SWei Liu     uint64_t ist5;
114*27458df8SWei Liu     uint64_t ist6;
115*27458df8SWei Liu     uint64_t ist7;
116*27458df8SWei Liu     uint64_t unused2;
117*27458df8SWei Liu     uint16_t unused3;
118*27458df8SWei Liu     uint16_t iomap_base;
119*27458df8SWei Liu } __attribute__ ((__packed__)) x86_tss_segment64;
120*27458df8SWei Liu 
121*27458df8SWei Liu /* segment descriptors */
122*27458df8SWei Liu typedef struct x86_segment_descriptor {
123*27458df8SWei Liu     uint64_t    limit0:16;
124*27458df8SWei Liu     uint64_t    base0:16;
125*27458df8SWei Liu     uint64_t    base1:8;
126*27458df8SWei Liu     uint64_t    type:4;
127*27458df8SWei Liu     uint64_t    s:1;
128*27458df8SWei Liu     uint64_t    dpl:2;
129*27458df8SWei Liu     uint64_t    p:1;
130*27458df8SWei Liu     uint64_t    limit1:4;
131*27458df8SWei Liu     uint64_t    avl:1;
132*27458df8SWei Liu     uint64_t    l:1;
133*27458df8SWei Liu     uint64_t    db:1;
134*27458df8SWei Liu     uint64_t    g:1;
135*27458df8SWei Liu     uint64_t    base2:8;
136*27458df8SWei Liu } __attribute__ ((__packed__)) x86_segment_descriptor;
137*27458df8SWei Liu 
x86_segment_base(x86_segment_descriptor * desc)138*27458df8SWei Liu static inline uint32_t x86_segment_base(x86_segment_descriptor *desc)
139*27458df8SWei Liu {
140*27458df8SWei Liu     return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0);
141*27458df8SWei Liu }
142*27458df8SWei Liu 
x86_set_segment_base(x86_segment_descriptor * desc,uint32_t base)143*27458df8SWei Liu static inline void x86_set_segment_base(x86_segment_descriptor *desc,
144*27458df8SWei Liu                                         uint32_t base)
145*27458df8SWei Liu {
146*27458df8SWei Liu     desc->base2 = base >> 24;
147*27458df8SWei Liu     desc->base1 = (base >> 16) & 0xff;
148*27458df8SWei Liu     desc->base0 = base & 0xffff;
149*27458df8SWei Liu }
150*27458df8SWei Liu 
x86_segment_limit(x86_segment_descriptor * desc)151*27458df8SWei Liu static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc)
152*27458df8SWei Liu {
153*27458df8SWei Liu     uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0);
154*27458df8SWei Liu     if (desc->g) {
155*27458df8SWei Liu         return (limit << 12) | 0xfff;
156*27458df8SWei Liu     }
157*27458df8SWei Liu     return limit;
158*27458df8SWei Liu }
159*27458df8SWei Liu 
x86_set_segment_limit(x86_segment_descriptor * desc,uint32_t limit)160*27458df8SWei Liu static inline void x86_set_segment_limit(x86_segment_descriptor *desc,
161*27458df8SWei Liu                                          uint32_t limit)
162*27458df8SWei Liu {
163*27458df8SWei Liu     desc->limit0 = limit & 0xffff;
164*27458df8SWei Liu     desc->limit1 = limit >> 16;
165*27458df8SWei Liu }
166*27458df8SWei Liu 
167*27458df8SWei Liu typedef struct x86_call_gate {
168*27458df8SWei Liu     uint64_t offset0:16;
169*27458df8SWei Liu     uint64_t selector:16;
170*27458df8SWei Liu     uint64_t param_count:4;
171*27458df8SWei Liu     uint64_t reserved:3;
172*27458df8SWei Liu     uint64_t type:4;
173*27458df8SWei Liu     uint64_t dpl:1;
174*27458df8SWei Liu     uint64_t p:1;
175*27458df8SWei Liu     uint64_t offset1:16;
176*27458df8SWei Liu } __attribute__ ((__packed__)) x86_call_gate;
177*27458df8SWei Liu 
x86_call_gate_offset(x86_call_gate * gate)178*27458df8SWei Liu static inline uint32_t x86_call_gate_offset(x86_call_gate *gate)
179*27458df8SWei Liu {
180*27458df8SWei Liu     return (uint32_t)((gate->offset1 << 16) | gate->offset0);
181*27458df8SWei Liu }
182*27458df8SWei Liu 
183*27458df8SWei Liu #define GDT_SEL     0
184*27458df8SWei Liu #define LDT_SEL     1
185*27458df8SWei Liu 
186*27458df8SWei Liu typedef struct x86_segment_selector {
187*27458df8SWei Liu     union {
188*27458df8SWei Liu         uint16_t sel;
189*27458df8SWei Liu         struct {
190*27458df8SWei Liu             uint16_t rpl:2;
191*27458df8SWei Liu             uint16_t ti:1;
192*27458df8SWei Liu             uint16_t index:13;
193*27458df8SWei Liu         };
194*27458df8SWei Liu     };
195*27458df8SWei Liu } __attribute__ ((__packed__)) x86_segment_selector;
196*27458df8SWei Liu 
197*27458df8SWei Liu /* useful register access  macros */
198*27458df8SWei Liu #define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg])
199*27458df8SWei Liu 
200*27458df8SWei Liu #define RRX(cpu, reg)   (x86_reg(cpu, reg)->rrx)
201*27458df8SWei Liu #define RAX(cpu)        RRX(cpu, R_EAX)
202*27458df8SWei Liu #define RCX(cpu)        RRX(cpu, R_ECX)
203*27458df8SWei Liu #define RDX(cpu)        RRX(cpu, R_EDX)
204*27458df8SWei Liu #define RBX(cpu)        RRX(cpu, R_EBX)
205*27458df8SWei Liu #define RSP(cpu)        RRX(cpu, R_ESP)
206*27458df8SWei Liu #define RBP(cpu)        RRX(cpu, R_EBP)
207*27458df8SWei Liu #define RSI(cpu)        RRX(cpu, R_ESI)
208*27458df8SWei Liu #define RDI(cpu)        RRX(cpu, R_EDI)
209*27458df8SWei Liu #define R8(cpu)         RRX(cpu, R_R8)
210*27458df8SWei Liu #define R9(cpu)         RRX(cpu, R_R9)
211*27458df8SWei Liu #define R10(cpu)        RRX(cpu, R_R10)
212*27458df8SWei Liu #define R11(cpu)        RRX(cpu, R_R11)
213*27458df8SWei Liu #define R12(cpu)        RRX(cpu, R_R12)
214*27458df8SWei Liu #define R13(cpu)        RRX(cpu, R_R13)
215*27458df8SWei Liu #define R14(cpu)        RRX(cpu, R_R14)
216*27458df8SWei Liu #define R15(cpu)        RRX(cpu, R_R15)
217*27458df8SWei Liu 
218*27458df8SWei Liu #define ERX(cpu, reg)   (x86_reg(cpu, reg)->erx)
219*27458df8SWei Liu #define EAX(cpu)        ERX(cpu, R_EAX)
220*27458df8SWei Liu #define ECX(cpu)        ERX(cpu, R_ECX)
221*27458df8SWei Liu #define EDX(cpu)        ERX(cpu, R_EDX)
222*27458df8SWei Liu #define EBX(cpu)        ERX(cpu, R_EBX)
223*27458df8SWei Liu #define ESP(cpu)        ERX(cpu, R_ESP)
224*27458df8SWei Liu #define EBP(cpu)        ERX(cpu, R_EBP)
225*27458df8SWei Liu #define ESI(cpu)        ERX(cpu, R_ESI)
226*27458df8SWei Liu #define EDI(cpu)        ERX(cpu, R_EDI)
227*27458df8SWei Liu 
228*27458df8SWei Liu #define RX(cpu, reg)   (x86_reg(cpu, reg)->rx)
229*27458df8SWei Liu #define AX(cpu)        RX(cpu, R_EAX)
230*27458df8SWei Liu #define CX(cpu)        RX(cpu, R_ECX)
231*27458df8SWei Liu #define DX(cpu)        RX(cpu, R_EDX)
232*27458df8SWei Liu #define BP(cpu)        RX(cpu, R_EBP)
233*27458df8SWei Liu #define SP(cpu)        RX(cpu, R_ESP)
234*27458df8SWei Liu #define BX(cpu)        RX(cpu, R_EBX)
235*27458df8SWei Liu #define SI(cpu)        RX(cpu, R_ESI)
236*27458df8SWei Liu #define DI(cpu)        RX(cpu, R_EDI)
237*27458df8SWei Liu 
238*27458df8SWei Liu #define RL(cpu, reg)   (x86_reg(cpu, reg)->lx)
239*27458df8SWei Liu #define AL(cpu)        RL(cpu, R_EAX)
240*27458df8SWei Liu #define CL(cpu)        RL(cpu, R_ECX)
241*27458df8SWei Liu #define DL(cpu)        RL(cpu, R_EDX)
242*27458df8SWei Liu #define BL(cpu)        RL(cpu, R_EBX)
243*27458df8SWei Liu 
244*27458df8SWei Liu #define RH(cpu, reg)   (x86_reg(cpu, reg)->hx)
245*27458df8SWei Liu #define AH(cpu)        RH(cpu, R_EAX)
246*27458df8SWei Liu #define CH(cpu)        RH(cpu, R_ECX)
247*27458df8SWei Liu #define DH(cpu)        RH(cpu, R_EDX)
248*27458df8SWei Liu #define BH(cpu)        RH(cpu, R_EBX)
249*27458df8SWei Liu 
250*27458df8SWei Liu /* deal with GDT/LDT descriptors in memory */
251*27458df8SWei Liu bool x86_read_segment_descriptor(CPUState *cpu,
252*27458df8SWei Liu                                  struct x86_segment_descriptor *desc,
253*27458df8SWei Liu                                  x86_segment_selector sel);
254*27458df8SWei Liu bool x86_write_segment_descriptor(CPUState *cpu,
255*27458df8SWei Liu                                   struct x86_segment_descriptor *desc,
256*27458df8SWei Liu                                   x86_segment_selector sel);
257*27458df8SWei Liu 
258*27458df8SWei Liu bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
259*27458df8SWei Liu                         int gate);
260*27458df8SWei Liu 
261*27458df8SWei Liu /* helpers */
262*27458df8SWei Liu bool x86_is_protected(CPUState *cpu);
263*27458df8SWei Liu bool x86_is_real(CPUState *cpu);
264*27458df8SWei Liu bool x86_is_v8086(CPUState *cpu);
265*27458df8SWei Liu bool x86_is_long_mode(CPUState *cpu);
266*27458df8SWei Liu bool x86_is_long64_mode(CPUState *cpu);
267*27458df8SWei Liu bool x86_is_paging_mode(CPUState *cpu);
268*27458df8SWei Liu bool x86_is_pae_enabled(CPUState *cpu);
269*27458df8SWei Liu 
270*27458df8SWei Liu enum X86Seg;
271*27458df8SWei Liu target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg);
272*27458df8SWei Liu target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size,
273*27458df8SWei Liu                               enum X86Seg seg);
274*27458df8SWei Liu target_ulong linear_rip(CPUState *cpu, target_ulong rip);
275*27458df8SWei Liu 
rdtscp(void)276*27458df8SWei Liu static inline uint64_t rdtscp(void)
277*27458df8SWei Liu {
278*27458df8SWei Liu     uint64_t tsc;
279*27458df8SWei Liu     __asm__ __volatile__("rdtscp; "         /* serializing read of tsc */
280*27458df8SWei Liu                          "shl $32,%%rdx; "  /* shift higher 32 bits stored in rdx up */
281*27458df8SWei Liu                          "or %%rdx,%%rax"   /* and or onto rax */
282*27458df8SWei Liu                          : "=a"(tsc)        /* output to tsc variable */
283*27458df8SWei Liu                          :
284*27458df8SWei Liu                          : "%rcx", "%rdx"); /* rcx and rdx are clobbered */
285*27458df8SWei Liu 
286*27458df8SWei Liu     return tsc;
287*27458df8SWei Liu }
288*27458df8SWei Liu 
289*27458df8SWei Liu #endif
290