xref: /openbmc/qemu/target/i386/hvf/x86.h (revision f8436a16)
169e0a03cSPaolo Bonzini /*
269e0a03cSPaolo Bonzini  * Copyright (C) 2016 Veertu Inc,
369e0a03cSPaolo Bonzini  * Copyright (C) 2017 Veertu Inc,
469e0a03cSPaolo Bonzini  *
569e0a03cSPaolo Bonzini  * This program is free software; you can redistribute it and/or
669e0a03cSPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
769e0a03cSPaolo Bonzini  * License as published by the Free Software Foundation; either
88af82b8eSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
969e0a03cSPaolo Bonzini  *
1069e0a03cSPaolo Bonzini  * This program is distributed in the hope that it will be useful,
1169e0a03cSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1269e0a03cSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1369e0a03cSPaolo Bonzini  * Lesser General Public License for more details.
1469e0a03cSPaolo Bonzini  *
1569e0a03cSPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
1669e0a03cSPaolo Bonzini  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
1769e0a03cSPaolo Bonzini  */
1869e0a03cSPaolo Bonzini 
19f9fea777SPaolo Bonzini #ifndef HVF_X86_H
20177d9e0dSMarkus Armbruster #define HVF_X86_H
2169e0a03cSPaolo Bonzini 
2269e0a03cSPaolo Bonzini typedef struct x86_register {
2369e0a03cSPaolo Bonzini     union {
2469e0a03cSPaolo Bonzini         struct {
2569e0a03cSPaolo Bonzini             uint64_t rrx;               /* full 64 bit */
2669e0a03cSPaolo Bonzini         };
2769e0a03cSPaolo Bonzini         struct {
2869e0a03cSPaolo Bonzini             uint32_t erx;               /* low 32 bit part */
2969e0a03cSPaolo Bonzini             uint32_t hi32_unused1;
3069e0a03cSPaolo Bonzini         };
3169e0a03cSPaolo Bonzini         struct {
3269e0a03cSPaolo Bonzini             uint16_t rx;                /* low 16 bit part */
3369e0a03cSPaolo Bonzini             uint16_t hi16_unused1;
3469e0a03cSPaolo Bonzini             uint32_t hi32_unused2;
3569e0a03cSPaolo Bonzini         };
3669e0a03cSPaolo Bonzini         struct {
3769e0a03cSPaolo Bonzini             uint8_t lx;                 /* low 8 bit part */
3869e0a03cSPaolo Bonzini             uint8_t hx;                 /* high 8 bit */
3969e0a03cSPaolo Bonzini             uint16_t hi16_unused2;
4069e0a03cSPaolo Bonzini             uint32_t hi32_unused3;
4169e0a03cSPaolo Bonzini         };
4269e0a03cSPaolo Bonzini     };
4369e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x86_register;
4469e0a03cSPaolo Bonzini 
4569e0a03cSPaolo Bonzini /* 16 bit Task State Segment */
4669e0a03cSPaolo Bonzini typedef struct x86_tss_segment16 {
4769e0a03cSPaolo Bonzini     uint16_t link;
4869e0a03cSPaolo Bonzini     uint16_t sp0;
4969e0a03cSPaolo Bonzini     uint16_t ss0;
5069e0a03cSPaolo Bonzini     uint32_t sp1;
5169e0a03cSPaolo Bonzini     uint16_t ss1;
5269e0a03cSPaolo Bonzini     uint32_t sp2;
5369e0a03cSPaolo Bonzini     uint16_t ss2;
5469e0a03cSPaolo Bonzini     uint16_t ip;
5569e0a03cSPaolo Bonzini     uint16_t flags;
5669e0a03cSPaolo Bonzini     uint16_t ax;
5769e0a03cSPaolo Bonzini     uint16_t cx;
5869e0a03cSPaolo Bonzini     uint16_t dx;
5969e0a03cSPaolo Bonzini     uint16_t bx;
6069e0a03cSPaolo Bonzini     uint16_t sp;
6169e0a03cSPaolo Bonzini     uint16_t bp;
6269e0a03cSPaolo Bonzini     uint16_t si;
6369e0a03cSPaolo Bonzini     uint16_t di;
6469e0a03cSPaolo Bonzini     uint16_t es;
6569e0a03cSPaolo Bonzini     uint16_t cs;
6669e0a03cSPaolo Bonzini     uint16_t ss;
6769e0a03cSPaolo Bonzini     uint16_t ds;
6869e0a03cSPaolo Bonzini     uint16_t ldtr;
6969e0a03cSPaolo Bonzini } __attribute__((packed)) x86_tss_segment16;
7069e0a03cSPaolo Bonzini 
7169e0a03cSPaolo Bonzini /* 32 bit Task State Segment */
7269e0a03cSPaolo Bonzini typedef struct x86_tss_segment32 {
7369e0a03cSPaolo Bonzini     uint32_t prev_tss;
7469e0a03cSPaolo Bonzini     uint32_t esp0;
7569e0a03cSPaolo Bonzini     uint32_t ss0;
7669e0a03cSPaolo Bonzini     uint32_t esp1;
7769e0a03cSPaolo Bonzini     uint32_t ss1;
7869e0a03cSPaolo Bonzini     uint32_t esp2;
7969e0a03cSPaolo Bonzini     uint32_t ss2;
8069e0a03cSPaolo Bonzini     uint32_t cr3;
8169e0a03cSPaolo Bonzini     uint32_t eip;
8269e0a03cSPaolo Bonzini     uint32_t eflags;
8369e0a03cSPaolo Bonzini     uint32_t eax;
8469e0a03cSPaolo Bonzini     uint32_t ecx;
8569e0a03cSPaolo Bonzini     uint32_t edx;
8669e0a03cSPaolo Bonzini     uint32_t ebx;
8769e0a03cSPaolo Bonzini     uint32_t esp;
8869e0a03cSPaolo Bonzini     uint32_t ebp;
8969e0a03cSPaolo Bonzini     uint32_t esi;
9069e0a03cSPaolo Bonzini     uint32_t edi;
9169e0a03cSPaolo Bonzini     uint32_t es;
9269e0a03cSPaolo Bonzini     uint32_t cs;
9369e0a03cSPaolo Bonzini     uint32_t ss;
9469e0a03cSPaolo Bonzini     uint32_t ds;
9569e0a03cSPaolo Bonzini     uint32_t fs;
9669e0a03cSPaolo Bonzini     uint32_t gs;
9769e0a03cSPaolo Bonzini     uint32_t ldt;
9869e0a03cSPaolo Bonzini     uint16_t trap;
9969e0a03cSPaolo Bonzini     uint16_t iomap_base;
10069e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x86_tss_segment32;
10169e0a03cSPaolo Bonzini 
10269e0a03cSPaolo Bonzini /* 64 bit Task State Segment */
10369e0a03cSPaolo Bonzini typedef struct x86_tss_segment64 {
10469e0a03cSPaolo Bonzini     uint32_t unused;
10569e0a03cSPaolo Bonzini     uint64_t rsp0;
10669e0a03cSPaolo Bonzini     uint64_t rsp1;
10769e0a03cSPaolo Bonzini     uint64_t rsp2;
10869e0a03cSPaolo Bonzini     uint64_t unused1;
10969e0a03cSPaolo Bonzini     uint64_t ist1;
11069e0a03cSPaolo Bonzini     uint64_t ist2;
11169e0a03cSPaolo Bonzini     uint64_t ist3;
11269e0a03cSPaolo Bonzini     uint64_t ist4;
11369e0a03cSPaolo Bonzini     uint64_t ist5;
11469e0a03cSPaolo Bonzini     uint64_t ist6;
11569e0a03cSPaolo Bonzini     uint64_t ist7;
11669e0a03cSPaolo Bonzini     uint64_t unused2;
11769e0a03cSPaolo Bonzini     uint16_t unused3;
11869e0a03cSPaolo Bonzini     uint16_t iomap_base;
11969e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x86_tss_segment64;
12069e0a03cSPaolo Bonzini 
12169e0a03cSPaolo Bonzini /* segment descriptors */
12269e0a03cSPaolo Bonzini typedef struct x86_segment_descriptor {
12369e0a03cSPaolo Bonzini     uint64_t    limit0:16;
12469e0a03cSPaolo Bonzini     uint64_t    base0:16;
12569e0a03cSPaolo Bonzini     uint64_t    base1:8;
12669e0a03cSPaolo Bonzini     uint64_t    type:4;
12769e0a03cSPaolo Bonzini     uint64_t    s:1;
12869e0a03cSPaolo Bonzini     uint64_t    dpl:2;
12969e0a03cSPaolo Bonzini     uint64_t    p:1;
13069e0a03cSPaolo Bonzini     uint64_t    limit1:4;
13169e0a03cSPaolo Bonzini     uint64_t    avl:1;
13269e0a03cSPaolo Bonzini     uint64_t    l:1;
13369e0a03cSPaolo Bonzini     uint64_t    db:1;
13469e0a03cSPaolo Bonzini     uint64_t    g:1;
13569e0a03cSPaolo Bonzini     uint64_t    base2:8;
13669e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x86_segment_descriptor;
13769e0a03cSPaolo Bonzini 
x86_segment_base(x86_segment_descriptor * desc)13869e0a03cSPaolo Bonzini static inline uint32_t x86_segment_base(x86_segment_descriptor *desc)
13969e0a03cSPaolo Bonzini {
14069e0a03cSPaolo Bonzini     return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0);
14169e0a03cSPaolo Bonzini }
14269e0a03cSPaolo Bonzini 
x86_set_segment_base(x86_segment_descriptor * desc,uint32_t base)14369e0a03cSPaolo Bonzini static inline void x86_set_segment_base(x86_segment_descriptor *desc,
14469e0a03cSPaolo Bonzini                                         uint32_t base)
14569e0a03cSPaolo Bonzini {
14669e0a03cSPaolo Bonzini     desc->base2 = base >> 24;
14769e0a03cSPaolo Bonzini     desc->base1 = (base >> 16) & 0xff;
14869e0a03cSPaolo Bonzini     desc->base0 = base & 0xffff;
14969e0a03cSPaolo Bonzini }
15069e0a03cSPaolo Bonzini 
x86_segment_limit(x86_segment_descriptor * desc)15169e0a03cSPaolo Bonzini static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc)
15269e0a03cSPaolo Bonzini {
15369e0a03cSPaolo Bonzini     uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0);
15469e0a03cSPaolo Bonzini     if (desc->g) {
15569e0a03cSPaolo Bonzini         return (limit << 12) | 0xfff;
15669e0a03cSPaolo Bonzini     }
15769e0a03cSPaolo Bonzini     return limit;
15869e0a03cSPaolo Bonzini }
15969e0a03cSPaolo Bonzini 
x86_set_segment_limit(x86_segment_descriptor * desc,uint32_t limit)16069e0a03cSPaolo Bonzini static inline void x86_set_segment_limit(x86_segment_descriptor *desc,
16169e0a03cSPaolo Bonzini                                          uint32_t limit)
16269e0a03cSPaolo Bonzini {
16369e0a03cSPaolo Bonzini     desc->limit0 = limit & 0xffff;
16469e0a03cSPaolo Bonzini     desc->limit1 = limit >> 16;
16569e0a03cSPaolo Bonzini }
16669e0a03cSPaolo Bonzini 
16769e0a03cSPaolo Bonzini typedef struct x86_call_gate {
16869e0a03cSPaolo Bonzini     uint64_t offset0:16;
16969e0a03cSPaolo Bonzini     uint64_t selector:16;
17069e0a03cSPaolo Bonzini     uint64_t param_count:4;
17169e0a03cSPaolo Bonzini     uint64_t reserved:3;
17269e0a03cSPaolo Bonzini     uint64_t type:4;
17369e0a03cSPaolo Bonzini     uint64_t dpl:1;
17469e0a03cSPaolo Bonzini     uint64_t p:1;
17569e0a03cSPaolo Bonzini     uint64_t offset1:16;
17669e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x86_call_gate;
17769e0a03cSPaolo Bonzini 
x86_call_gate_offset(x86_call_gate * gate)17869e0a03cSPaolo Bonzini static inline uint32_t x86_call_gate_offset(x86_call_gate *gate)
17969e0a03cSPaolo Bonzini {
18069e0a03cSPaolo Bonzini     return (uint32_t)((gate->offset1 << 16) | gate->offset0);
18169e0a03cSPaolo Bonzini }
18269e0a03cSPaolo Bonzini 
183c6a89b45SJessica Clarke #define GDT_SEL     0
184c6a89b45SJessica Clarke #define LDT_SEL     1
18569e0a03cSPaolo Bonzini 
18669e0a03cSPaolo Bonzini typedef struct x68_segment_selector {
18769e0a03cSPaolo Bonzini     union {
18869e0a03cSPaolo Bonzini         uint16_t sel;
18969e0a03cSPaolo Bonzini         struct {
190c6a89b45SJessica Clarke             uint16_t rpl:2;
19169e0a03cSPaolo Bonzini             uint16_t ti:1;
192c6a89b45SJessica Clarke             uint16_t index:13;
19369e0a03cSPaolo Bonzini         };
19469e0a03cSPaolo Bonzini     };
19569e0a03cSPaolo Bonzini } __attribute__ ((__packed__)) x68_segment_selector;
19669e0a03cSPaolo Bonzini 
19769e0a03cSPaolo Bonzini /* useful register access  macros */
198167c6aefSRoman Bolshakov #define x86_reg(cpu, reg) ((x86_register *) &cpu->regs[reg])
199167c6aefSRoman Bolshakov 
200167c6aefSRoman Bolshakov #define RRX(cpu, reg)   (x86_reg(cpu, reg)->rrx)
2016701d81dSPaolo Bonzini #define RAX(cpu)        RRX(cpu, R_EAX)
2026701d81dSPaolo Bonzini #define RCX(cpu)        RRX(cpu, R_ECX)
2036701d81dSPaolo Bonzini #define RDX(cpu)        RRX(cpu, R_EDX)
2046701d81dSPaolo Bonzini #define RBX(cpu)        RRX(cpu, R_EBX)
2056701d81dSPaolo Bonzini #define RSP(cpu)        RRX(cpu, R_ESP)
2066701d81dSPaolo Bonzini #define RBP(cpu)        RRX(cpu, R_EBP)
2076701d81dSPaolo Bonzini #define RSI(cpu)        RRX(cpu, R_ESI)
2086701d81dSPaolo Bonzini #define RDI(cpu)        RRX(cpu, R_EDI)
2096701d81dSPaolo Bonzini #define R8(cpu)         RRX(cpu, R_R8)
2106701d81dSPaolo Bonzini #define R9(cpu)         RRX(cpu, R_R9)
2116701d81dSPaolo Bonzini #define R10(cpu)        RRX(cpu, R_R10)
2126701d81dSPaolo Bonzini #define R11(cpu)        RRX(cpu, R_R11)
2136701d81dSPaolo Bonzini #define R12(cpu)        RRX(cpu, R_R12)
2146701d81dSPaolo Bonzini #define R13(cpu)        RRX(cpu, R_R13)
2156701d81dSPaolo Bonzini #define R14(cpu)        RRX(cpu, R_R14)
2166701d81dSPaolo Bonzini #define R15(cpu)        RRX(cpu, R_R15)
21769e0a03cSPaolo Bonzini 
218167c6aefSRoman Bolshakov #define ERX(cpu, reg)   (x86_reg(cpu, reg)->erx)
2196701d81dSPaolo Bonzini #define EAX(cpu)        ERX(cpu, R_EAX)
2206701d81dSPaolo Bonzini #define ECX(cpu)        ERX(cpu, R_ECX)
2216701d81dSPaolo Bonzini #define EDX(cpu)        ERX(cpu, R_EDX)
2226701d81dSPaolo Bonzini #define EBX(cpu)        ERX(cpu, R_EBX)
2236701d81dSPaolo Bonzini #define ESP(cpu)        ERX(cpu, R_ESP)
2246701d81dSPaolo Bonzini #define EBP(cpu)        ERX(cpu, R_EBP)
2256701d81dSPaolo Bonzini #define ESI(cpu)        ERX(cpu, R_ESI)
2266701d81dSPaolo Bonzini #define EDI(cpu)        ERX(cpu, R_EDI)
22769e0a03cSPaolo Bonzini 
228167c6aefSRoman Bolshakov #define RX(cpu, reg)   (x86_reg(cpu, reg)->rx)
2296701d81dSPaolo Bonzini #define AX(cpu)        RX(cpu, R_EAX)
2306701d81dSPaolo Bonzini #define CX(cpu)        RX(cpu, R_ECX)
2316701d81dSPaolo Bonzini #define DX(cpu)        RX(cpu, R_EDX)
2326701d81dSPaolo Bonzini #define BP(cpu)        RX(cpu, R_EBP)
2336701d81dSPaolo Bonzini #define SP(cpu)        RX(cpu, R_ESP)
2346701d81dSPaolo Bonzini #define BX(cpu)        RX(cpu, R_EBX)
2356701d81dSPaolo Bonzini #define SI(cpu)        RX(cpu, R_ESI)
2366701d81dSPaolo Bonzini #define DI(cpu)        RX(cpu, R_EDI)
23769e0a03cSPaolo Bonzini 
238167c6aefSRoman Bolshakov #define RL(cpu, reg)   (x86_reg(cpu, reg)->lx)
2396701d81dSPaolo Bonzini #define AL(cpu)        RL(cpu, R_EAX)
2406701d81dSPaolo Bonzini #define CL(cpu)        RL(cpu, R_ECX)
2416701d81dSPaolo Bonzini #define DL(cpu)        RL(cpu, R_EDX)
2426701d81dSPaolo Bonzini #define BL(cpu)        RL(cpu, R_EBX)
24369e0a03cSPaolo Bonzini 
244167c6aefSRoman Bolshakov #define RH(cpu, reg)   (x86_reg(cpu, reg)->hx)
2456701d81dSPaolo Bonzini #define AH(cpu)        RH(cpu, R_EAX)
2466701d81dSPaolo Bonzini #define CH(cpu)        RH(cpu, R_ECX)
2476701d81dSPaolo Bonzini #define DH(cpu)        RH(cpu, R_EDX)
2486701d81dSPaolo Bonzini #define BH(cpu)        RH(cpu, R_EBX)
24969e0a03cSPaolo Bonzini 
25069e0a03cSPaolo Bonzini /* deal with GDT/LDT descriptors in memory */
251*f8436a16SPhilippe Mathieu-Daudé bool x86_read_segment_descriptor(CPUState *cpu,
25269e0a03cSPaolo Bonzini                                  struct x86_segment_descriptor *desc,
25369e0a03cSPaolo Bonzini                                  x68_segment_selector sel);
254*f8436a16SPhilippe Mathieu-Daudé bool x86_write_segment_descriptor(CPUState *cpu,
25569e0a03cSPaolo Bonzini                                   struct x86_segment_descriptor *desc,
25669e0a03cSPaolo Bonzini                                   x68_segment_selector sel);
25769e0a03cSPaolo Bonzini 
258*f8436a16SPhilippe Mathieu-Daudé bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc,
25969e0a03cSPaolo Bonzini                         int gate);
26069e0a03cSPaolo Bonzini 
26169e0a03cSPaolo Bonzini /* helpers */
262*f8436a16SPhilippe Mathieu-Daudé bool x86_is_protected(CPUState *cpu);
263*f8436a16SPhilippe Mathieu-Daudé bool x86_is_real(CPUState *cpu);
264*f8436a16SPhilippe Mathieu-Daudé bool x86_is_v8086(CPUState *cpu);
265*f8436a16SPhilippe Mathieu-Daudé bool x86_is_long_mode(CPUState *cpu);
266*f8436a16SPhilippe Mathieu-Daudé bool x86_is_long64_mode(CPUState *cpu);
267*f8436a16SPhilippe Mathieu-Daudé bool x86_is_paging_mode(CPUState *cpu);
268*f8436a16SPhilippe Mathieu-Daudé bool x86_is_pae_enabled(CPUState *cpu);
26969e0a03cSPaolo Bonzini 
2706701d81dSPaolo Bonzini enum X86Seg;
271*f8436a16SPhilippe Mathieu-Daudé target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg);
272*f8436a16SPhilippe Mathieu-Daudé target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size,
2736701d81dSPaolo Bonzini                               enum X86Seg seg);
274*f8436a16SPhilippe Mathieu-Daudé target_ulong linear_rip(CPUState *cpu, target_ulong rip);
27569e0a03cSPaolo Bonzini 
rdtscp(void)27669e0a03cSPaolo Bonzini static inline uint64_t rdtscp(void)
27769e0a03cSPaolo Bonzini {
27869e0a03cSPaolo Bonzini     uint64_t tsc;
27969e0a03cSPaolo Bonzini     __asm__ __volatile__("rdtscp; "         /* serializing read of tsc */
28069e0a03cSPaolo Bonzini                          "shl $32,%%rdx; "  /* shift higher 32 bits stored in rdx up */
28169e0a03cSPaolo Bonzini                          "or %%rdx,%%rax"   /* and or onto rax */
28269e0a03cSPaolo Bonzini                          : "=a"(tsc)        /* output to tsc variable */
28369e0a03cSPaolo Bonzini                          :
28469e0a03cSPaolo Bonzini                          : "%rcx", "%rdx"); /* rcx and rdx are clobbered */
28569e0a03cSPaolo Bonzini 
28669e0a03cSPaolo Bonzini     return tsc;
28769e0a03cSPaolo Bonzini }
28869e0a03cSPaolo Bonzini 
289f9fea777SPaolo Bonzini #endif
290