File:  [Qemu by Fabrice Bellard] / qemu / target-i386 / svm.h
Revision 1.1: download - view: text, annotated - select for diffs
Tue Apr 24 16:49:26 2018 UTC (3 years, 7 months ago) by root
CVS tags: MAIN, HEAD
Initial revision

    1: #ifndef __SVM_H
    2: #define __SVM_H
    3: 
    4: enum {
    5:         /* We shift all the intercept bits so we can OR them with the
    6:            TB flags later on */
    7: 	INTERCEPT_INTR = HF_HIF_SHIFT,
    8: 	INTERCEPT_NMI,
    9: 	INTERCEPT_SMI,
   10: 	INTERCEPT_INIT,
   11: 	INTERCEPT_VINTR,
   12: 	INTERCEPT_SELECTIVE_CR0,
   13: 	INTERCEPT_STORE_IDTR,
   14: 	INTERCEPT_STORE_GDTR,
   15: 	INTERCEPT_STORE_LDTR,
   16: 	INTERCEPT_STORE_TR,
   17: 	INTERCEPT_LOAD_IDTR,
   18: 	INTERCEPT_LOAD_GDTR,
   19: 	INTERCEPT_LOAD_LDTR,
   20: 	INTERCEPT_LOAD_TR,
   21: 	INTERCEPT_RDTSC,
   22: 	INTERCEPT_RDPMC,
   23: 	INTERCEPT_PUSHF,
   24: 	INTERCEPT_POPF,
   25: 	INTERCEPT_CPUID,
   26: 	INTERCEPT_RSM,
   27: 	INTERCEPT_IRET,
   28: 	INTERCEPT_INTn,
   29: 	INTERCEPT_INVD,
   30: 	INTERCEPT_PAUSE,
   31: 	INTERCEPT_HLT,
   32: 	INTERCEPT_INVLPG,
   33: 	INTERCEPT_INVLPGA,
   34: 	INTERCEPT_IOIO_PROT,
   35: 	INTERCEPT_MSR_PROT,
   36: 	INTERCEPT_TASK_SWITCH,
   37: 	INTERCEPT_FERR_FREEZE,
   38: 	INTERCEPT_SHUTDOWN,
   39: 	INTERCEPT_VMRUN,
   40: 	INTERCEPT_VMMCALL,
   41: 	INTERCEPT_VMLOAD,
   42: 	INTERCEPT_VMSAVE,
   43: 	INTERCEPT_STGI,
   44: 	INTERCEPT_CLGI,
   45: 	INTERCEPT_SKINIT,
   46: 	INTERCEPT_RDTSCP,
   47: 	INTERCEPT_ICEBP,
   48: 	INTERCEPT_WBINVD,
   49: };
   50: /* This is not really an intercept but rather a placeholder to
   51:    show that we are in an SVM (just like a hidden flag, but keeps the
   52:    TBs clean) */
   53: #define INTERCEPT_SVM 63
   54: #define INTERCEPT_SVM_MASK (1ULL << INTERCEPT_SVM)
   55: 
   56: struct __attribute__ ((__packed__)) vmcb_control_area {
   57: 	uint16_t intercept_cr_read;
   58: 	uint16_t intercept_cr_write;
   59: 	uint16_t intercept_dr_read;
   60: 	uint16_t intercept_dr_write;
   61: 	uint32_t intercept_exceptions;
   62: 	uint64_t intercept;
   63: 	uint8_t reserved_1[44];
   64: 	uint64_t iopm_base_pa;
   65: 	uint64_t msrpm_base_pa;
   66: 	uint64_t tsc_offset;
   67: 	uint32_t asid;
   68: 	uint8_t tlb_ctl;
   69: 	uint8_t reserved_2[3];
   70: 	uint32_t int_ctl;
   71: 	uint32_t int_vector;
   72: 	uint32_t int_state;
   73: 	uint8_t reserved_3[4];
   74: 	uint32_t exit_code;
   75: 	uint32_t exit_code_hi;
   76: 	uint64_t exit_info_1;
   77: 	uint64_t exit_info_2;
   78: 	uint32_t exit_int_info;
   79: 	uint32_t exit_int_info_err;
   80: 	uint64_t nested_ctl;
   81: 	uint8_t reserved_4[16];
   82: 	uint32_t event_inj;
   83: 	uint32_t event_inj_err;
   84: 	uint64_t nested_cr3;
   85: 	uint64_t lbr_ctl;
   86: 	uint8_t reserved_5[832];
   87: };
   88: 
   89: 
   90: #define TLB_CONTROL_DO_NOTHING 0
   91: #define TLB_CONTROL_FLUSH_ALL_ASID 1
   92: 
   93: #define V_TPR_MASK 0x0f
   94: 
   95: #define V_IRQ_SHIFT 8
   96: #define V_IRQ_MASK (1 << V_IRQ_SHIFT)
   97: 
   98: #define V_INTR_PRIO_SHIFT 16
   99: #define V_INTR_PRIO_MASK (0x0f << V_INTR_PRIO_SHIFT)
  100: 
  101: #define V_IGN_TPR_SHIFT 20
  102: #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
  103: 
  104: #define V_INTR_MASKING_SHIFT 24
  105: #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
  106: 
  107: #define SVM_INTERRUPT_SHADOW_MASK 1
  108: 
  109: #define SVM_IOIO_STR_SHIFT 2
  110: #define SVM_IOIO_REP_SHIFT 3
  111: #define SVM_IOIO_SIZE_SHIFT 4
  112: #define SVM_IOIO_ASIZE_SHIFT 7
  113: 
  114: #define SVM_IOIO_TYPE_MASK 1
  115: #define SVM_IOIO_STR_MASK (1 << SVM_IOIO_STR_SHIFT)
  116: #define SVM_IOIO_REP_MASK (1 << SVM_IOIO_REP_SHIFT)
  117: #define SVM_IOIO_SIZE_MASK (7 << SVM_IOIO_SIZE_SHIFT)
  118: #define SVM_IOIO_ASIZE_MASK (7 << SVM_IOIO_ASIZE_SHIFT)
  119: 
  120: struct __attribute__ ((__packed__)) vmcb_seg {
  121: 	uint16_t selector;
  122: 	uint16_t attrib;
  123: 	uint32_t limit;
  124: 	uint64_t base;
  125: };
  126: 
  127: struct __attribute__ ((__packed__)) vmcb_save_area {
  128: 	struct vmcb_seg es;
  129: 	struct vmcb_seg cs;
  130: 	struct vmcb_seg ss;
  131: 	struct vmcb_seg ds;
  132: 	struct vmcb_seg fs;
  133: 	struct vmcb_seg gs;
  134: 	struct vmcb_seg gdtr;
  135: 	struct vmcb_seg ldtr;
  136: 	struct vmcb_seg idtr;
  137: 	struct vmcb_seg tr;
  138: 	uint8_t reserved_1[43];
  139: 	uint8_t cpl;
  140: 	uint8_t reserved_2[4];
  141: 	uint64_t efer;
  142: 	uint8_t reserved_3[112];
  143: 	uint64_t cr4;
  144: 	uint64_t cr3;
  145: 	uint64_t cr0;
  146: 	uint64_t dr7;
  147: 	uint64_t dr6;
  148: 	uint64_t rflags;
  149: 	uint64_t rip;
  150: 	uint8_t reserved_4[88];
  151: 	uint64_t rsp;
  152: 	uint8_t reserved_5[24];
  153: 	uint64_t rax;
  154: 	uint64_t star;
  155: 	uint64_t lstar;
  156: 	uint64_t cstar;
  157: 	uint64_t sfmask;
  158: 	uint64_t kernel_gs_base;
  159: 	uint64_t sysenter_cs;
  160: 	uint64_t sysenter_esp;
  161: 	uint64_t sysenter_eip;
  162: 	uint64_t cr2;
  163: 	/* qemu: cr8 added to reuse this as hsave */
  164: 	uint64_t cr8;
  165: 	uint8_t reserved_6[32 - 8]; /* originally 32 */
  166: 	uint64_t g_pat;
  167: 	uint64_t dbgctl;
  168: 	uint64_t br_from;
  169: 	uint64_t br_to;
  170: 	uint64_t last_excp_from;
  171: 	uint64_t last_excp_to;
  172: };
  173: 
  174: struct __attribute__ ((__packed__)) vmcb {
  175: 	struct vmcb_control_area control;
  176: 	struct vmcb_save_area save;
  177: };
  178: 
  179: #define SVM_CPUID_FEATURE_SHIFT 2
  180: #define SVM_CPUID_FUNC 0x8000000a
  181: 
  182: #define MSR_EFER_SVME_MASK (1ULL << 12)
  183: 
  184: #define SVM_SELECTOR_S_SHIFT 4
  185: #define SVM_SELECTOR_DPL_SHIFT 5
  186: #define SVM_SELECTOR_P_SHIFT 7
  187: #define SVM_SELECTOR_AVL_SHIFT 8
  188: #define SVM_SELECTOR_L_SHIFT 9
  189: #define SVM_SELECTOR_DB_SHIFT 10
  190: #define SVM_SELECTOR_G_SHIFT 11
  191: 
  192: #define SVM_SELECTOR_TYPE_MASK (0xf)
  193: #define SVM_SELECTOR_S_MASK (1 << SVM_SELECTOR_S_SHIFT)
  194: #define SVM_SELECTOR_DPL_MASK (3 << SVM_SELECTOR_DPL_SHIFT)
  195: #define SVM_SELECTOR_P_MASK (1 << SVM_SELECTOR_P_SHIFT)
  196: #define SVM_SELECTOR_AVL_MASK (1 << SVM_SELECTOR_AVL_SHIFT)
  197: #define SVM_SELECTOR_L_MASK (1 << SVM_SELECTOR_L_SHIFT)
  198: #define SVM_SELECTOR_DB_MASK (1 << SVM_SELECTOR_DB_SHIFT)
  199: #define SVM_SELECTOR_G_MASK (1 << SVM_SELECTOR_G_SHIFT)
  200: 
  201: #define SVM_SELECTOR_WRITE_MASK (1 << 1)
  202: #define SVM_SELECTOR_READ_MASK SVM_SELECTOR_WRITE_MASK
  203: #define SVM_SELECTOR_CODE_MASK (1 << 3)
  204: 
  205: #define INTERCEPT_CR0_MASK 1
  206: #define INTERCEPT_CR3_MASK (1 << 3)
  207: #define INTERCEPT_CR4_MASK (1 << 4)
  208: 
  209: #define INTERCEPT_DR0_MASK 1
  210: #define INTERCEPT_DR1_MASK (1 << 1)
  211: #define INTERCEPT_DR2_MASK (1 << 2)
  212: #define INTERCEPT_DR3_MASK (1 << 3)
  213: #define INTERCEPT_DR4_MASK (1 << 4)
  214: #define INTERCEPT_DR5_MASK (1 << 5)
  215: #define INTERCEPT_DR6_MASK (1 << 6)
  216: #define INTERCEPT_DR7_MASK (1 << 7)
  217: 
  218: #define SVM_EVTINJ_VEC_MASK 0xff
  219: 
  220: #define SVM_EVTINJ_TYPE_SHIFT 8
  221: #define SVM_EVTINJ_TYPE_MASK (7 << SVM_EVTINJ_TYPE_SHIFT)
  222: 
  223: #define SVM_EVTINJ_TYPE_INTR (0 << SVM_EVTINJ_TYPE_SHIFT)
  224: #define SVM_EVTINJ_TYPE_NMI (2 << SVM_EVTINJ_TYPE_SHIFT)
  225: #define SVM_EVTINJ_TYPE_EXEPT (3 << SVM_EVTINJ_TYPE_SHIFT)
  226: #define SVM_EVTINJ_TYPE_SOFT (4 << SVM_EVTINJ_TYPE_SHIFT)
  227: 
  228: #define SVM_EVTINJ_VALID (1 << 31)
  229: #define SVM_EVTINJ_VALID_ERR (1 << 11)
  230: 
  231: #define SVM_EXITINTINFO_VEC_MASK SVM_EVTINJ_VEC_MASK
  232: 
  233: #define	SVM_EXITINTINFO_TYPE_INTR SVM_EVTINJ_TYPE_INTR
  234: #define	SVM_EXITINTINFO_TYPE_NMI SVM_EVTINJ_TYPE_NMI
  235: #define	SVM_EXITINTINFO_TYPE_EXEPT SVM_EVTINJ_TYPE_EXEPT
  236: #define	SVM_EXITINTINFO_TYPE_SOFT SVM_EVTINJ_TYPE_SOFT
  237: 
  238: #define SVM_EXITINTINFO_VALID SVM_EVTINJ_VALID
  239: #define SVM_EXITINTINFO_VALID_ERR SVM_EVTINJ_VALID_ERR
  240: 
  241: #define	SVM_EXIT_READ_CR0 	0x000
  242: #define	SVM_EXIT_READ_CR3 	0x003
  243: #define	SVM_EXIT_READ_CR4 	0x004
  244: #define	SVM_EXIT_READ_CR8 	0x008
  245: #define	SVM_EXIT_WRITE_CR0 	0x010
  246: #define	SVM_EXIT_WRITE_CR3 	0x013
  247: #define	SVM_EXIT_WRITE_CR4 	0x014
  248: #define	SVM_EXIT_WRITE_CR8 	0x018
  249: #define	SVM_EXIT_READ_DR0 	0x020
  250: #define	SVM_EXIT_READ_DR1 	0x021
  251: #define	SVM_EXIT_READ_DR2 	0x022
  252: #define	SVM_EXIT_READ_DR3 	0x023
  253: #define	SVM_EXIT_READ_DR4 	0x024
  254: #define	SVM_EXIT_READ_DR5 	0x025
  255: #define	SVM_EXIT_READ_DR6 	0x026
  256: #define	SVM_EXIT_READ_DR7 	0x027
  257: #define	SVM_EXIT_WRITE_DR0 	0x030
  258: #define	SVM_EXIT_WRITE_DR1 	0x031
  259: #define	SVM_EXIT_WRITE_DR2 	0x032
  260: #define	SVM_EXIT_WRITE_DR3 	0x033
  261: #define	SVM_EXIT_WRITE_DR4 	0x034
  262: #define	SVM_EXIT_WRITE_DR5 	0x035
  263: #define	SVM_EXIT_WRITE_DR6 	0x036
  264: #define	SVM_EXIT_WRITE_DR7 	0x037
  265: #define SVM_EXIT_EXCP_BASE      0x040
  266: #define SVM_EXIT_INTR		0x060
  267: #define SVM_EXIT_NMI		0x061
  268: #define SVM_EXIT_SMI		0x062
  269: #define SVM_EXIT_INIT		0x063
  270: #define SVM_EXIT_VINTR		0x064
  271: #define SVM_EXIT_CR0_SEL_WRITE	0x065
  272: #define SVM_EXIT_IDTR_READ	0x066
  273: #define SVM_EXIT_GDTR_READ	0x067
  274: #define SVM_EXIT_LDTR_READ	0x068
  275: #define SVM_EXIT_TR_READ	0x069
  276: #define SVM_EXIT_IDTR_WRITE	0x06a
  277: #define SVM_EXIT_GDTR_WRITE	0x06b
  278: #define SVM_EXIT_LDTR_WRITE	0x06c
  279: #define SVM_EXIT_TR_WRITE	0x06d
  280: #define SVM_EXIT_RDTSC		0x06e
  281: #define SVM_EXIT_RDPMC		0x06f
  282: #define SVM_EXIT_PUSHF		0x070
  283: #define SVM_EXIT_POPF		0x071
  284: #define SVM_EXIT_CPUID		0x072
  285: #define SVM_EXIT_RSM		0x073
  286: #define SVM_EXIT_IRET		0x074
  287: #define SVM_EXIT_SWINT		0x075
  288: #define SVM_EXIT_INVD		0x076
  289: #define SVM_EXIT_PAUSE		0x077
  290: #define SVM_EXIT_HLT		0x078
  291: #define SVM_EXIT_INVLPG		0x079
  292: #define SVM_EXIT_INVLPGA	0x07a
  293: #define SVM_EXIT_IOIO		0x07b
  294: #define SVM_EXIT_MSR		0x07c
  295: #define SVM_EXIT_TASK_SWITCH	0x07d
  296: #define SVM_EXIT_FERR_FREEZE	0x07e
  297: #define SVM_EXIT_SHUTDOWN	0x07f
  298: #define SVM_EXIT_VMRUN		0x080
  299: #define SVM_EXIT_VMMCALL	0x081
  300: #define SVM_EXIT_VMLOAD		0x082
  301: #define SVM_EXIT_VMSAVE		0x083
  302: #define SVM_EXIT_STGI		0x084
  303: #define SVM_EXIT_CLGI		0x085
  304: #define SVM_EXIT_SKINIT		0x086
  305: #define SVM_EXIT_RDTSCP		0x087
  306: #define SVM_EXIT_ICEBP		0x088
  307: #define SVM_EXIT_WBINVD		0x089
  308: /* only included in documentation, maybe wrong */
  309: #define SVM_EXIT_MONITOR	0x08a
  310: #define SVM_EXIT_MWAIT		0x08b
  311: #define SVM_EXIT_NPF  		0x400
  312: 
  313: #define SVM_EXIT_ERR		-1
  314: 
  315: #define SVM_CR0_SELECTIVE_MASK (1 << 3 | 1) /* TS and MP */
  316: 
  317: #define SVM_VMLOAD ".byte 0x0f, 0x01, 0xda"
  318: #define SVM_VMRUN  ".byte 0x0f, 0x01, 0xd8"
  319: #define SVM_VMSAVE ".byte 0x0f, 0x01, 0xdb"
  320: #define SVM_CLGI   ".byte 0x0f, 0x01, 0xdd"
  321: #define SVM_STGI   ".byte 0x0f, 0x01, 0xdc"
  322: #define SVM_INVLPGA ".byte 0x0f, 0x01, 0xdf"
  323: 
  324: /* function references */
  325: 
  326: void helper_stgi();
  327: void vmexit(uint64_t exit_code, uint64_t exit_info_1);
  328: int svm_check_intercept_param(uint32_t type, uint64_t param);
  329: static inline int svm_check_intercept(unsigned int type) {
  330:     return svm_check_intercept_param(type, 0);
  331: }
  332: 
  333: 
  334: #define INTERCEPTED(mask) (env->intercept & mask)
  335: #define INTERCEPTEDw(var, mask) (env->intercept ## var & mask)
  336: #define INTERCEPTEDl(var, mask) (env->intercept ## var & mask)
  337: 
  338: #define SVM_LOAD_SEG(addr, seg_index, seg) \
  339:     cpu_x86_load_seg_cache(env, \
  340:                     R_##seg_index, \
  341:                     lduw_phys(addr + offsetof(struct vmcb, save.seg.selector)),\
  342:                     ldq_phys(addr + offsetof(struct vmcb, save.seg.base)),\
  343:                     ldl_phys(addr + offsetof(struct vmcb, save.seg.limit)),\
  344:                     vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg.attrib)), ldq_phys(addr + offsetof(struct vmcb, save.seg.base)), ldl_phys(addr + offsetof(struct vmcb, save.seg.limit))))
  345: 
  346: #define SVM_LOAD_SEG2(addr, seg_qemu, seg_vmcb) \
  347:     env->seg_qemu.selector  = lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector)); \
  348:     env->seg_qemu.base      = ldq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base)); \
  349:     env->seg_qemu.limit     = ldl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit)); \
  350:     env->seg_qemu.flags     = vmcb2cpu_attrib(lduw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib)), env->seg_qemu.base, env->seg_qemu.limit)
  351: 
  352: #define SVM_SAVE_SEG(addr, seg_qemu, seg_vmcb) \
  353:     stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.selector), env->seg_qemu.selector); \
  354:     stq_phys(addr + offsetof(struct vmcb, save.seg_vmcb.base), env->seg_qemu.base); \
  355:     stl_phys(addr + offsetof(struct vmcb, save.seg_vmcb.limit), env->seg_qemu.limit); \
  356:     stw_phys(addr + offsetof(struct vmcb, save.seg_vmcb.attrib), cpu2vmcb_attrib(env->seg_qemu.flags))
  357: 
  358: #endif

unix.superglobalmegacorp.com