1c97d6d2cSSergio Andres Gomez Del Real /* 2c97d6d2cSSergio Andres Gomez Del Real * Copyright (C) 2016 Veertu Inc, 3c97d6d2cSSergio Andres Gomez Del Real * Copyright (C) 2017 Veertu Inc, 4c97d6d2cSSergio Andres Gomez Del Real * 5c97d6d2cSSergio Andres Gomez Del Real * This program is free software; you can redistribute it and/or 6996feed4SSergio Andres Gomez Del Real * modify it under the terms of the GNU Lesser General Public 7996feed4SSergio Andres Gomez Del Real * License as published by the Free Software Foundation; either 88af82b8eSChetan Pant * version 2.1 of the License, or (at your option) any later version. 9c97d6d2cSSergio Andres Gomez Del Real * 10c97d6d2cSSergio Andres Gomez Del Real * This program is distributed in the hope that it will be useful, 11c97d6d2cSSergio Andres Gomez Del Real * but WITHOUT ANY WARRANTY; without even the implied warranty of 12996feed4SSergio Andres Gomez Del Real * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13996feed4SSergio Andres Gomez Del Real * Lesser General Public License for more details. 14c97d6d2cSSergio Andres Gomez Del Real * 15996feed4SSergio Andres Gomez Del Real * You should have received a copy of the GNU Lesser General Public 16996feed4SSergio Andres Gomez Del Real * License along with this program; if not, see <http://www.gnu.org/licenses/>. 17c97d6d2cSSergio Andres Gomez Del Real */ 18c97d6d2cSSergio Andres Gomez Del Real 19*fb8ebeddSWei Liu #ifndef X86_EMU_DEFS_H 20*fb8ebeddSWei Liu #define X86_EMU_DEFS_H 21c97d6d2cSSergio Andres Gomez Del Real 22c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_register { 23c97d6d2cSSergio Andres Gomez Del Real union { 24c97d6d2cSSergio Andres Gomez Del Real struct { 25c97d6d2cSSergio Andres Gomez Del Real uint64_t rrx; /* full 64 bit */ 26c97d6d2cSSergio Andres Gomez Del Real }; 27c97d6d2cSSergio Andres Gomez Del Real struct { 28c97d6d2cSSergio Andres Gomez Del Real uint32_t erx; /* low 32 bit part */ 29c97d6d2cSSergio Andres Gomez Del Real uint32_t hi32_unused1; 30c97d6d2cSSergio Andres Gomez Del Real }; 31c97d6d2cSSergio Andres Gomez Del Real struct { 32c97d6d2cSSergio Andres Gomez Del Real uint16_t rx; /* low 16 bit part */ 33c97d6d2cSSergio Andres Gomez Del Real uint16_t hi16_unused1; 34c97d6d2cSSergio Andres Gomez Del Real uint32_t hi32_unused2; 35c97d6d2cSSergio Andres Gomez Del Real }; 36c97d6d2cSSergio Andres Gomez Del Real struct { 37c97d6d2cSSergio Andres Gomez Del Real uint8_t lx; /* low 8 bit part */ 38c97d6d2cSSergio Andres Gomez Del Real uint8_t hx; /* high 8 bit */ 39c97d6d2cSSergio Andres Gomez Del Real uint16_t hi16_unused2; 40c97d6d2cSSergio Andres Gomez Del Real uint32_t hi32_unused3; 41c97d6d2cSSergio Andres Gomez Del Real }; 42c97d6d2cSSergio Andres Gomez Del Real }; 43c97d6d2cSSergio Andres Gomez Del Real } __attribute__ ((__packed__)) x86_register; 44c97d6d2cSSergio Andres Gomez Del Real 45c97d6d2cSSergio Andres Gomez Del Real /* 16 bit Task State Segment */ 46c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_tss_segment16 { 47c97d6d2cSSergio Andres Gomez Del Real uint16_t link; 48c97d6d2cSSergio Andres Gomez Del Real uint16_t sp0; 49c97d6d2cSSergio Andres Gomez Del Real uint16_t ss0; 50c97d6d2cSSergio Andres Gomez Del Real uint32_t sp1; 51c97d6d2cSSergio Andres Gomez Del Real uint16_t ss1; 52c97d6d2cSSergio Andres Gomez Del Real uint32_t sp2; 53c97d6d2cSSergio Andres Gomez Del Real uint16_t ss2; 54c97d6d2cSSergio Andres Gomez Del Real uint16_t ip; 55c97d6d2cSSergio Andres Gomez Del Real uint16_t flags; 56c97d6d2cSSergio Andres Gomez Del Real uint16_t ax; 57c97d6d2cSSergio Andres Gomez Del Real uint16_t cx; 58c97d6d2cSSergio Andres Gomez Del Real uint16_t dx; 59c97d6d2cSSergio Andres Gomez Del Real uint16_t bx; 60c97d6d2cSSergio Andres Gomez Del Real uint16_t sp; 61c97d6d2cSSergio Andres Gomez Del Real uint16_t bp; 62c97d6d2cSSergio Andres Gomez Del Real uint16_t si; 63c97d6d2cSSergio Andres Gomez Del Real uint16_t di; 64c97d6d2cSSergio Andres Gomez Del Real uint16_t es; 65c97d6d2cSSergio Andres Gomez Del Real uint16_t cs; 66c97d6d2cSSergio Andres Gomez Del Real uint16_t ss; 67c97d6d2cSSergio Andres Gomez Del Real uint16_t ds; 68c97d6d2cSSergio Andres Gomez Del Real uint16_t ldtr; 69c97d6d2cSSergio Andres Gomez Del Real } __attribute__((packed)) x86_tss_segment16; 70c97d6d2cSSergio Andres Gomez Del Real 71c97d6d2cSSergio Andres Gomez Del Real /* 32 bit Task State Segment */ 72c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_tss_segment32 { 73c97d6d2cSSergio Andres Gomez Del Real uint32_t prev_tss; 74c97d6d2cSSergio Andres Gomez Del Real uint32_t esp0; 75c97d6d2cSSergio Andres Gomez Del Real uint32_t ss0; 76c97d6d2cSSergio Andres Gomez Del Real uint32_t esp1; 77c97d6d2cSSergio Andres Gomez Del Real uint32_t ss1; 78c97d6d2cSSergio Andres Gomez Del Real uint32_t esp2; 79c97d6d2cSSergio Andres Gomez Del Real uint32_t ss2; 80c97d6d2cSSergio Andres Gomez Del Real uint32_t cr3; 81c97d6d2cSSergio Andres Gomez Del Real uint32_t eip; 82c97d6d2cSSergio Andres Gomez Del Real uint32_t eflags; 83c97d6d2cSSergio Andres Gomez Del Real uint32_t eax; 84c97d6d2cSSergio Andres Gomez Del Real uint32_t ecx; 85c97d6d2cSSergio Andres Gomez Del Real uint32_t edx; 86c97d6d2cSSergio Andres Gomez Del Real uint32_t ebx; 87c97d6d2cSSergio Andres Gomez Del Real uint32_t esp; 88c97d6d2cSSergio Andres Gomez Del Real uint32_t ebp; 89c97d6d2cSSergio Andres Gomez Del Real uint32_t esi; 90c97d6d2cSSergio Andres Gomez Del Real uint32_t edi; 91c97d6d2cSSergio Andres Gomez Del Real uint32_t es; 92c97d6d2cSSergio Andres Gomez Del Real uint32_t cs; 93c97d6d2cSSergio Andres Gomez Del Real uint32_t ss; 94c97d6d2cSSergio Andres Gomez Del Real uint32_t ds; 95c97d6d2cSSergio Andres Gomez Del Real uint32_t fs; 96c97d6d2cSSergio Andres Gomez Del Real uint32_t gs; 97c97d6d2cSSergio Andres Gomez Del Real uint32_t ldt; 98c97d6d2cSSergio Andres Gomez Del Real uint16_t trap; 99c97d6d2cSSergio Andres Gomez Del Real uint16_t iomap_base; 100c97d6d2cSSergio Andres Gomez Del Real } __attribute__ ((__packed__)) x86_tss_segment32; 101c97d6d2cSSergio Andres Gomez Del Real 102c97d6d2cSSergio Andres Gomez Del Real /* 64 bit Task State Segment */ 103c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_tss_segment64 { 104c97d6d2cSSergio Andres Gomez Del Real uint32_t unused; 105c97d6d2cSSergio Andres Gomez Del Real uint64_t rsp0; 106c97d6d2cSSergio Andres Gomez Del Real uint64_t rsp1; 107c97d6d2cSSergio Andres Gomez Del Real uint64_t rsp2; 108c97d6d2cSSergio Andres Gomez Del Real uint64_t unused1; 109c97d6d2cSSergio Andres Gomez Del Real uint64_t ist1; 110c97d6d2cSSergio Andres Gomez Del Real uint64_t ist2; 111c97d6d2cSSergio Andres Gomez Del Real uint64_t ist3; 112c97d6d2cSSergio Andres Gomez Del Real uint64_t ist4; 113c97d6d2cSSergio Andres Gomez Del Real uint64_t ist5; 114c97d6d2cSSergio Andres Gomez Del Real uint64_t ist6; 115c97d6d2cSSergio Andres Gomez Del Real uint64_t ist7; 116c97d6d2cSSergio Andres Gomez Del Real uint64_t unused2; 117c97d6d2cSSergio Andres Gomez Del Real uint16_t unused3; 118c97d6d2cSSergio Andres Gomez Del Real uint16_t iomap_base; 119c97d6d2cSSergio Andres Gomez Del Real } __attribute__ ((__packed__)) x86_tss_segment64; 120c97d6d2cSSergio Andres Gomez Del Real 121c97d6d2cSSergio Andres Gomez Del Real /* segment descriptors */ 122c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_segment_descriptor { 123c97d6d2cSSergio Andres Gomez Del Real uint64_t limit0:16; 124c97d6d2cSSergio Andres Gomez Del Real uint64_t base0:16; 125c97d6d2cSSergio Andres Gomez Del Real uint64_t base1:8; 126c97d6d2cSSergio Andres Gomez Del Real uint64_t type:4; 127c97d6d2cSSergio Andres Gomez Del Real uint64_t s:1; 128c97d6d2cSSergio Andres Gomez Del Real uint64_t dpl:2; 129c97d6d2cSSergio Andres Gomez Del Real uint64_t p:1; 130c97d6d2cSSergio Andres Gomez Del Real uint64_t limit1:4; 131c97d6d2cSSergio Andres Gomez Del Real uint64_t avl:1; 132c97d6d2cSSergio Andres Gomez Del Real uint64_t l:1; 133c97d6d2cSSergio Andres Gomez Del Real uint64_t db:1; 134c97d6d2cSSergio Andres Gomez Del Real uint64_t g:1; 135c97d6d2cSSergio Andres Gomez Del Real uint64_t base2:8; 136c97d6d2cSSergio Andres Gomez Del Real } __attribute__ ((__packed__)) x86_segment_descriptor; 137c97d6d2cSSergio Andres Gomez Del Real 138c97d6d2cSSergio Andres Gomez Del Real static inline uint32_t x86_segment_base(x86_segment_descriptor *desc) 139c97d6d2cSSergio Andres Gomez Del Real { 140c97d6d2cSSergio Andres Gomez Del Real return (uint32_t)((desc->base2 << 24) | (desc->base1 << 16) | desc->base0); 141c97d6d2cSSergio Andres Gomez Del Real } 142c97d6d2cSSergio Andres Gomez Del Real 143c97d6d2cSSergio Andres Gomez Del Real static inline void x86_set_segment_base(x86_segment_descriptor *desc, 144c97d6d2cSSergio Andres Gomez Del Real uint32_t base) 145c97d6d2cSSergio Andres Gomez Del Real { 146c97d6d2cSSergio Andres Gomez Del Real desc->base2 = base >> 24; 147c97d6d2cSSergio Andres Gomez Del Real desc->base1 = (base >> 16) & 0xff; 148c97d6d2cSSergio Andres Gomez Del Real desc->base0 = base & 0xffff; 149c97d6d2cSSergio Andres Gomez Del Real } 150c97d6d2cSSergio Andres Gomez Del Real 151c97d6d2cSSergio Andres Gomez Del Real static inline uint32_t x86_segment_limit(x86_segment_descriptor *desc) 152c97d6d2cSSergio Andres Gomez Del Real { 153c97d6d2cSSergio Andres Gomez Del Real uint32_t limit = (uint32_t)((desc->limit1 << 16) | desc->limit0); 154c97d6d2cSSergio Andres Gomez Del Real if (desc->g) { 155c97d6d2cSSergio Andres Gomez Del Real return (limit << 12) | 0xfff; 156c97d6d2cSSergio Andres Gomez Del Real } 157c97d6d2cSSergio Andres Gomez Del Real return limit; 158c97d6d2cSSergio Andres Gomez Del Real } 159c97d6d2cSSergio Andres Gomez Del Real 160c97d6d2cSSergio Andres Gomez Del Real static inline void x86_set_segment_limit(x86_segment_descriptor *desc, 161c97d6d2cSSergio Andres Gomez Del Real uint32_t limit) 162c97d6d2cSSergio Andres Gomez Del Real { 163c97d6d2cSSergio Andres Gomez Del Real desc->limit0 = limit & 0xffff; 164c97d6d2cSSergio Andres Gomez Del Real desc->limit1 = limit >> 16; 165c97d6d2cSSergio Andres Gomez Del Real } 166c97d6d2cSSergio Andres Gomez Del Real 167c97d6d2cSSergio Andres Gomez Del Real typedef struct x86_call_gate { 168c97d6d2cSSergio Andres Gomez Del Real uint64_t offset0:16; 169c97d6d2cSSergio Andres Gomez Del Real uint64_t selector:16; 170c97d6d2cSSergio Andres Gomez Del Real uint64_t param_count:4; 171c97d6d2cSSergio Andres Gomez Del Real uint64_t reserved:3; 172c97d6d2cSSergio Andres Gomez Del Real uint64_t type:4; 173c97d6d2cSSergio Andres Gomez Del Real uint64_t dpl:1; 174c97d6d2cSSergio Andres Gomez Del Real uint64_t p:1; 175c97d6d2cSSergio Andres Gomez Del Real uint64_t offset1:16; 176c97d6d2cSSergio Andres Gomez Del Real } __attribute__ ((__packed__)) x86_call_gate; 177c97d6d2cSSergio Andres Gomez Del Real 178c97d6d2cSSergio Andres Gomez Del Real static inline uint32_t x86_call_gate_offset(x86_call_gate *gate) 179c97d6d2cSSergio Andres Gomez Del Real { 180c97d6d2cSSergio Andres Gomez Del Real return (uint32_t)((gate->offset1 << 16) | gate->offset0); 181c97d6d2cSSergio Andres Gomez Del Real } 182c97d6d2cSSergio Andres Gomez Del Real 183c6a89b45SJessica Clarke #define GDT_SEL 0 184c6a89b45SJessica Clarke #define LDT_SEL 1 185c97d6d2cSSergio Andres Gomez Del Real 18625409172SWei Liu typedef struct x86_segment_selector { 187c97d6d2cSSergio Andres Gomez Del Real union { 188c97d6d2cSSergio Andres Gomez Del Real uint16_t sel; 189c97d6d2cSSergio Andres Gomez Del Real struct { 190c6a89b45SJessica Clarke uint16_t rpl:2; 191c97d6d2cSSergio Andres Gomez Del Real uint16_t ti:1; 192c6a89b45SJessica Clarke uint16_t index:13; 193c97d6d2cSSergio Andres Gomez Del Real }; 194c97d6d2cSSergio Andres Gomez Del Real }; 19525409172SWei Liu } __attribute__ ((__packed__)) x86_segment_selector; 196c97d6d2cSSergio Andres Gomez Del Real 197c97d6d2cSSergio Andres Gomez Del Real /* 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) 217c97d6d2cSSergio Andres Gomez Del Real 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) 227c97d6d2cSSergio Andres Gomez Del Real 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) 237c97d6d2cSSergio Andres Gomez Del Real 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) 243c97d6d2cSSergio Andres Gomez Del Real 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) 249c97d6d2cSSergio Andres Gomez Del Real 250c97d6d2cSSergio Andres Gomez Del Real /* deal with GDT/LDT descriptors in memory */ 251f8436a16SPhilippe Mathieu-Daudé bool x86_read_segment_descriptor(CPUState *cpu, 252c97d6d2cSSergio Andres Gomez Del Real struct x86_segment_descriptor *desc, 25325409172SWei Liu x86_segment_selector sel); 254f8436a16SPhilippe Mathieu-Daudé bool x86_write_segment_descriptor(CPUState *cpu, 255c97d6d2cSSergio Andres Gomez Del Real struct x86_segment_descriptor *desc, 25625409172SWei Liu x86_segment_selector sel); 257c97d6d2cSSergio Andres Gomez Del Real 258f8436a16SPhilippe Mathieu-Daudé bool x86_read_call_gate(CPUState *cpu, struct x86_call_gate *idt_desc, 259c97d6d2cSSergio Andres Gomez Del Real int gate); 260c97d6d2cSSergio Andres Gomez Del Real 261c97d6d2cSSergio Andres Gomez Del Real /* helpers */ 262f8436a16SPhilippe Mathieu-Daudé bool x86_is_protected(CPUState *cpu); 263f8436a16SPhilippe Mathieu-Daudé bool x86_is_real(CPUState *cpu); 264f8436a16SPhilippe Mathieu-Daudé bool x86_is_v8086(CPUState *cpu); 265f8436a16SPhilippe Mathieu-Daudé bool x86_is_long_mode(CPUState *cpu); 266f8436a16SPhilippe Mathieu-Daudé bool x86_is_long64_mode(CPUState *cpu); 267f8436a16SPhilippe Mathieu-Daudé bool x86_is_paging_mode(CPUState *cpu); 268f8436a16SPhilippe Mathieu-Daudé bool x86_is_pae_enabled(CPUState *cpu); 269c97d6d2cSSergio Andres Gomez Del Real 2706701d81dSPaolo Bonzini enum X86Seg; 271f8436a16SPhilippe Mathieu-Daudé target_ulong linear_addr(CPUState *cpu, target_ulong addr, enum X86Seg seg); 272f8436a16SPhilippe Mathieu-Daudé target_ulong linear_addr_size(CPUState *cpu, target_ulong addr, int size, 2736701d81dSPaolo Bonzini enum X86Seg seg); 274f8436a16SPhilippe Mathieu-Daudé target_ulong linear_rip(CPUState *cpu, target_ulong rip); 275c97d6d2cSSergio Andres Gomez Del Real 276c97d6d2cSSergio Andres Gomez Del Real static inline uint64_t rdtscp(void) 277c97d6d2cSSergio Andres Gomez Del Real { 278c97d6d2cSSergio Andres Gomez Del Real uint64_t tsc; 279c97d6d2cSSergio Andres Gomez Del Real __asm__ __volatile__("rdtscp; " /* serializing read of tsc */ 280c97d6d2cSSergio Andres Gomez Del Real "shl $32,%%rdx; " /* shift higher 32 bits stored in rdx up */ 281c97d6d2cSSergio Andres Gomez Del Real "or %%rdx,%%rax" /* and or onto rax */ 282c97d6d2cSSergio Andres Gomez Del Real : "=a"(tsc) /* output to tsc variable */ 283c97d6d2cSSergio Andres Gomez Del Real : 284c97d6d2cSSergio Andres Gomez Del Real : "%rcx", "%rdx"); /* rcx and rdx are clobbered */ 285c97d6d2cSSergio Andres Gomez Del Real 286c97d6d2cSSergio Andres Gomez Del Real return tsc; 287c97d6d2cSSergio Andres Gomez Del Real } 288c97d6d2cSSergio Andres Gomez Del Real 289f9fea777SPaolo Bonzini #endif 290