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