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 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 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 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 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 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 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